tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bus_dmamap_sync() for USB
Hi,
attached is a patch that adds bus_dmamap_sync() calls for uhci, ohci and ehci.
I've tested uhci and ehci on amd64 (both intel and add-on VIA ehci) and
sgimips (add-on VIA ehci). ohci has been tested on amd64 and macppc
(both with the build-in USB controller). All tests have been done with
USB keyboard/mouse, USB umass key and umodem. This patch, along with the
one in PR port-i386/38935, fix the race condition that cause
"host controller process error" and "host controller halted" errors when
umodem@uhci is under heavy use.
Michael Lorenz reported issues with this on uhci/ehci in a sgimips O2,
but I couldn't reproduce it. It may be an issue with his add-on adapter.
If noone object I'll commit this in the next few days.
--
Manuel Bouyer, LIP6, Universite Paris VI.
Manuel.Bouyer%lip6.fr@localhost
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: ehci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ehci.c,v
retrieving revision 1.137
diff -u -r1.137 ehci.c
--- ehci.c 16 Jun 2008 10:29:41 -0000 1.137
+++ ehci.c 23 Jun 2008 16:09:36 -0000
@@ -437,6 +437,8 @@
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
sqh->sqtd = NULL;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/* Point the frame list at the last level (128ms). */
for (i = 0; i < sc->sc_flsize; i++) {
@@ -448,6 +450,8 @@
sc->sc_islots[EHCI_IQHIDX(EHCI_IPOLLRATES - 1,
i)].sqh->physaddr);
}
+ usb_syncmem(&sc->sc_fldma, 0, sc->sc_flsize * sizeof(ehci_link_t),
+ BUS_DMASYNC_PREWRITE);
/* Allocate dummy QH that starts the async list. */
sqh = ehci_alloc_sqh(sc);
@@ -467,6 +471,8 @@
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
sqh->sqtd = NULL;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef EHCI_DEBUG
if (ehcidebug) {
ehci_dump_sqh(sqh);
@@ -699,10 +705,21 @@
* is a an error somewhere in the middle, or whether there was a
* short packet (SPD and not ACTIVE).
*/
+ usb_syncmem(&lsqtd->dma,
+ lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(lsqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) {
DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = le32toh(sqtd->qtd.qtd_status);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
/* If there's an active QTD the xfer isn't done. */
if (status & EHCI_QTD_ACTIVE)
break;
@@ -715,6 +732,9 @@
}
DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
ex, ex->sqtdstart));
+ usb_syncmem(&lsqtd->dma,
+ lsqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD);
return;
}
done:
@@ -767,6 +787,8 @@
lsqtd = ex->sqtdend;
actlen = 0;
for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd; sqtd=sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
nstatus = le32toh(sqtd->qtd.qtd_status);
if (nstatus & EHCI_QTD_ACTIVE)
break;
@@ -1232,7 +1254,14 @@
stop = 0;
for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) {
ehci_dump_sqtd(sqtd);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_next),
+ sizeof(sqtd->qtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_next),
+ sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
}
if (sqtd)
printf("dump aborted, too many TDs\n");
@@ -1241,8 +1270,12 @@
void
ehci_dump_sqtd(ehci_soft_qtd_t *sqtd)
{
+ usb_syncmem(&sqtd->dma, sqtd->offs,
+ sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
ehci_dump_qtd(&sqtd->qtd);
+ usb_syncmem(&sqtd->dma, sqtd->offs,
+ sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD);
}
void
@@ -1273,6 +1306,8 @@
ehci_qh_t *qh = &sqh->qh;
u_int32_t endp, endphub;
+ usb_syncmem(&sqh->dma, sqh->offs,
+ sizeof(sqh->qh), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
endp = le32toh(qh->qh_endp);
@@ -1293,6 +1328,8 @@
printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
printf("Overlay qTD:\n");
ehci_dump_qtd(&qh->qh_qtd);
+ usb_syncmem(&sqh->dma, sqh->offs,
+ sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
}
#ifdef DIAGNOSTIC
@@ -1393,6 +1430,8 @@
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(0);
+ usb_syncmem(&sqh->dma, sqh->offs,
+ sizeof(sqh->qh), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
epipe->sqh = sqh;
switch (xfertype) {
@@ -1459,10 +1498,16 @@
{
SPLUSBCHECK;
+ usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE);
sqh->next = head->next;
sqh->qh.qh_link = head->qh.qh_link;
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE);
head->next = sqh;
head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH);
+ usb_syncmem(&head->dma, head->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE);
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -1486,8 +1531,12 @@
;
if (p == NULL)
panic("ehci_rem_qh: ED not found");
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE);
p->next = sqh->next;
p->qh.qh_link = sqh->qh.qh_link;
+ usb_syncmem(&p->dma, p->offs + offsetof(ehci_qh_t, qh_link),
+ sizeof(p->qh.qh_link), BUS_DMASYNC_PREWRITE);
ehci_sync_hc(sc);
}
@@ -1499,20 +1548,32 @@
u_int32_t status;
/* Save toggle bit and ping status. */
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = sqh->qh.qh_qtd.qtd_status &
htole32(EHCI_QTD_TOGGLE_MASK |
EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE));
/* Set HALTED to make hw leave it alone. */
sqh->qh.qh_qtd.qtd_status =
htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sqh->qh.qh_curqtd = 0;
sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
sqh->qh.qh_qtd.qtd_altnext = 0;
for (i = 0; i < EHCI_QTD_NBUFFERS; i++)
sqh->qh.qh_qtd.qtd_buffer[i] = 0;
sqh->sqtd = sqtd;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Set !HALTED && !ACTIVE to start execution, preserve some fields */
sqh->qh.qh_qtd.qtd_status = status;
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/*
@@ -2183,6 +2244,8 @@
offs = i * EHCI_SQH_SIZE;
sqh = KERNADDR(&dma, offs);
sqh->physaddr = DMAADDR(&dma, offs);
+ sqh->dma = dma;
+ sqh->offs = offs;
sqh->next = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
@@ -2225,6 +2288,8 @@
offs = i * EHCI_SQTD_SIZE;
sqtd = KERNADDR(&dma, offs);
sqtd->physaddr = DMAADDR(&dma, offs);
+ sqtd->dma = dma;
+ sqtd->offs = offs;
sqtd->nextqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd;
}
@@ -2285,6 +2350,9 @@
*sp = cur;
if (cur == NULL)
goto nomem;
+
+ usb_syncmem(dma, 0, alen,
+ rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
for (;;) {
dataphyspage = EHCI_PAGE(dataphys);
/* The EHCI hardware can handle at most 5 pages. */
@@ -2359,6 +2427,7 @@
htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen));
cur->xfer = xfer;
cur->len = curlen;
+
DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n",
dataphys, dataphys + curlen));
/* adjust the toggle based on the number of packets in this
@@ -2369,11 +2438,15 @@
}
if (next == NULL)
break;
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
dataphys += curlen;
cur = next;
}
cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
*ep = cur;
epipe->nexttoggle = tog;
@@ -2490,10 +2563,27 @@
s = splusb();
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
+
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
qhstatus = sqh->qh.qh_qtd.qtd_status;
sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
+ usb_syncmem(&sqtd->dma,
+ sqtd->offs + offsetof(ehci_qtd_t, qtd_status),
+ sizeof(sqtd->qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if (sqtd == exfer->sqtdend)
break;
}
@@ -2523,6 +2613,11 @@
* any of them.
*/
s = splusb(); /* XXX why? */
+
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_curqtd),
+ sizeof(sqh->qh.qh_curqtd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd));
hit = 0;
for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
@@ -2535,7 +2630,15 @@
if (hit && sqtd != NULL) {
DPRINTFN(1,("ehci_abort_xfer: cur=0x%08x\n", sqtd->physaddr));
sqh->qh.qh_curqtd = htole32(sqtd->physaddr); /* unlink qTDs */
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_curqtd),
+ sizeof(sqh->qh.qh_curqtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sqh->qh.qh_qtd.qtd_status = qhstatus;
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(ehci_qh_t, qh_qtd.qtd_status),
+ sizeof(sqh->qh.qh_qtd.qtd_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
} else {
DPRINTFN(1,("ehci_abort_xfer: no hit\n"));
}
@@ -2640,7 +2743,10 @@
{
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = xfer->pipe->device->bus->hci_private;
- /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+ struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
+ usb_device_request_t *req = &xfer->request;
+ int len = UGETW(req->wLength);
+ int rd = req->bmRequestType & UT_READ;
DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer));
@@ -2653,6 +2759,11 @@
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req,
+ BUS_DMASYNC_POSTWRITE);
+ if (len)
+ usb_syncmem(&xfer->dmabuf, 0, len,
+ rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen));
@@ -2741,11 +2852,14 @@
end->nextqtd = stat;
end->qtd.qtd_next =
end->qtd.qtd_altnext = htole32(stat->physaddr);
+ usb_syncmem(&end->dma, end->offs, sizeof(end->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
} else {
next = stat;
}
memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req);
+ usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
/* Clear toggle */
setup->qtd.qtd_status = htole32(
@@ -2761,6 +2875,8 @@
setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
setup->xfer = xfer;
setup->len = sizeof *req;
+ usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
stat->qtd.qtd_status = htole32(
EHCI_QTD_ACTIVE |
@@ -2775,6 +2891,8 @@
stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
stat->xfer = xfer;
stat->len = 0;
+ usb_syncmem(&stat->dma, stat->offs, sizeof(stat->qtd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -2795,7 +2913,7 @@
/* Insert qTD in QH list. */
s = splusb();
- ehci_set_qh_qtd(sqh, setup);
+ ehci_set_qh_qtd(sqh, setup); /* also does usb_syncmem(sqh) */
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
ehci_timeout, xfer);
@@ -2928,7 +3046,7 @@
#endif
s = splusb();
- ehci_set_qh_qtd(sqh, data);
+ ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
ehci_timeout, xfer);
@@ -2984,7 +3102,9 @@
{
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = xfer->pipe->device->bus->hci_private;
- /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+ struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
+ int endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+ int rd = UE_GET_DIR(endpt) == UE_DIR_IN;
DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
@@ -2992,6 +3112,8 @@
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
@@ -3098,7 +3220,7 @@
#endif
s = splusb();
- ehci_set_qh_qtd(sqh, data);
+ ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
ehci_timeout, xfer);
@@ -3170,6 +3292,8 @@
xfer->length = len;
endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+ usb_syncmem(&xfer->dmabuf, 0, len,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
sqh = epipe->sqh;
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
@@ -3192,7 +3316,7 @@
#endif
s = splusb();
- ehci_set_qh_qtd(sqh, data);
+ ehci_set_qh_qtd(sqh, data); /* also does usb_syncmem(sqh) */
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_callout(xfer->timeout_handle,
mstohz(xfer->timeout), ehci_timeout, xfer);
@@ -3203,6 +3327,10 @@
} else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
+ isread = UE_GET_DIR(endpt) == UE_DIR_IN;
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
#undef exfer
}
Index: ehcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ehcivar.h,v
retrieving revision 1.30
diff -u -r1.30 ehcivar.h
--- ehcivar.h 28 Apr 2008 20:23:58 -0000 1.30
+++ ehcivar.h 23 Jun 2008 16:09:36 -0000
@@ -33,6 +33,8 @@
ehci_qtd_t qtd;
struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */
ehci_physaddr_t physaddr;
+ usb_dma_t dma; /* qTD's DMA infos */
+ int offs; /* qTD's offset in usb_dma_t */
usbd_xfer_handle xfer;
LIST_ENTRY(ehci_soft_qtd) hnext;
u_int16_t len;
@@ -45,6 +47,8 @@
struct ehci_soft_qh *next;
struct ehci_soft_qtd *sqtd;
ehci_physaddr_t physaddr;
+ usb_dma_t dma; /* QH's DMA infos */
+ int offs; /* QH's offset in usb_dma_t */
int islot;
} ehci_soft_qh_t;
#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) /
EHCI_QH_ALIGN * EHCI_QH_ALIGN)
Index: ohci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
retrieving revision 1.194
diff -u -r1.194 ohci.c
--- ohci.c 4 Jun 2008 12:38:58 -0000 1.194
+++ ohci.c 23 Jun 2008 16:09:36 -0000
@@ -420,6 +420,8 @@
offs = i * OHCI_SED_SIZE;
sed = KERNADDR(&dma, offs);
sed->physaddr = DMAADDR(&dma, offs);
+ sed->dma = dma;
+ sed->offs = offs;
sed->next = sc->sc_freeeds;
sc->sc_freeeds = sed;
}
@@ -458,6 +460,8 @@
offs = i * OHCI_STD_SIZE;
std = KERNADDR(&dma, offs);
std->physaddr = DMAADDR(&dma, offs);
+ std->dma = dma;
+ std->offs = offs;
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
}
@@ -506,6 +510,8 @@
cur = sp;
dataphys = DMAADDR(dma, 0);
dataphysend = OHCI_PAGE(dataphys + len - 1);
+ usb_syncmem(dma, 0, len,
+ rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
tdflags = HTOO32(
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
(flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
@@ -546,6 +552,8 @@
cur->len = curlen;
cur->flags = OHCI_ADD_LEN;
cur->xfer = xfer;
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
dataphys, dataphys + curlen - 1));
if (len == 0)
@@ -571,6 +579,8 @@
cur->len = 0;
cur->flags = 0;
cur->xfer = xfer;
+ usb_syncmem(&cur->dma, cur->offs, sizeof(cur->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
}
*ep = cur;
@@ -615,6 +625,8 @@
offs = i * OHCI_SITD_SIZE;
sitd = KERNADDR(&dma, offs);
sitd->physaddr = DMAADDR(&dma, offs);
+ sitd->dma = dma;
+ sitd->offs = offs;
sitd->nextitd = sc->sc_freeitds;
sc->sc_freeitds = sitd;
}
@@ -724,6 +736,9 @@
goto bad2;
}
sc->sc_bulk_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+ usb_syncmem(&sc->sc_bulk_head->dma, sc->sc_bulk_head->offs,
+ sizeof(sc->sc_bulk_head->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate dummy ED that starts the isochronous list. */
sc->sc_isoc_head = ohci_alloc_sed(sc);
@@ -732,6 +747,9 @@
goto bad3;
}
sc->sc_isoc_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+ usb_syncmem(&sc->sc_isoc_head->dma, sc->sc_isoc_head->offs,
+ sizeof(sc->sc_isoc_head->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate all the dummy EDs that make up the interrupt tree. */
for (i = 0; i < OHCI_NO_EDS; i++) {
@@ -751,6 +769,8 @@
psed= sc->sc_isoc_head;
sed->next = psed;
sed->ed.ed_nexted = HTOO32(psed->physaddr);
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/*
* Fill HCCA interrupt table. The bit reversal is to get
@@ -759,6 +779,8 @@
for (i = 0; i < OHCI_NO_INTRS; i++)
sc->sc_hcca->hcca_interrupt_table[revbits[i]] =
HTOO32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr);
+ usb_syncmem(&sc->sc_hccadma, 0, OHCI_HCCA_SIZE,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef OHCI_DEBUG
if (ohcidebug > 15) {
@@ -1268,8 +1290,14 @@
sc->sc_bus.intr_context++;
s = splhardusb();
+ usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head),
+ sizeof(sc->sc_hcca->hcca_done_head),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
done = O32TOH(sc->sc_hcca->hcca_done_head) & ~OHCI_DONE_INTRS;
sc->sc_hcca->hcca_done_head = 0;
+ usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head),
+ sizeof(sc->sc_hcca->hcca_done_head),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_WDH);
sc->sc_eintrs |= OHCI_WDH;
OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH);
@@ -1279,6 +1307,8 @@
for (sdone = NULL, sidone = NULL; done != 0; ) {
std = ohci_hash_find_td(sc, done);
if (std != NULL) {
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
std->dnext = sdone;
done = O32TOH(std->td.td_nexttd);
sdone = std;
@@ -1287,6 +1317,8 @@
}
sitd = ohci_hash_find_itd(sc, done);
if (sitd != NULL) {
+ usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sitd->dnext = sidone;
done = O32TOH(sitd->itd.itd_nextitd);
sidone = sitd;
@@ -1469,6 +1501,10 @@
void
ohci_device_ctrl_done(usbd_xfer_handle xfer)
{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+ int len = UGETW(xfer->request.wLength);
+ int isread = (xfer->request.bmRequestType & UT_READ);
+
DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer));
#ifdef DIAGNOSTIC
@@ -1476,6 +1512,11 @@
panic("ohci_device_ctrl_done: not a request");
}
#endif
+ if (len)
+ usb_syncmem(&xfer->dmabuf, 0, len,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ usb_syncmem(&opipe->u.ctl.reqdma, 0,
+ sizeof(usb_device_request_t), BUS_DMASYNC_POSTWRITE);
}
void
@@ -1485,11 +1526,15 @@
ohci_softc_t *sc = opipe->pipe.device->bus->hci_private;
ohci_soft_ed_t *sed = opipe->sed;
ohci_soft_td_t *data, *tail;
+ int isread =
+ (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) ==
UE_DIR_IN);
DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
if (xfer->pipe->repeat) {
data = opipe->tail.td;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
@@ -1512,10 +1557,16 @@
data->len = xfer->length;
data->xfer = xfer;
data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ usb_syncmem(&data->dma, data->offs, sizeof(data->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
xfer->hcpriv = data;
xfer->actlen = 0;
sed->ed.ed_tailp = HTOO32(tail->physaddr);
+ usb_syncmem(&sed->dma,
+ sed->offs + offsetof(ohci_ed_t, ed_tailp),
+ sizeof(sed->ed.ed_tailp),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
opipe->tail.td = tail;
}
}
@@ -1523,8 +1574,13 @@
void
ohci_device_bulk_done(usbd_xfer_handle xfer)
{
+ int isread =
+ (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) ==
UE_DIR_IN);
+
DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
}
void
@@ -1669,10 +1725,17 @@
during the setup of the control pipe in usbd_new_device(). */
/* XXX This only needs to be done once, but it's too early in open. */
/* XXXX Should not touch ED here! */
+
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_flags = HTOO32(
(O32TOH(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
next = stat;
@@ -1688,9 +1751,14 @@
/* Start toggle at 1 and then use the carried toggle. */
std->td.td_flags &= HTOO32(~OHCI_TD_TOGGLE_MASK);
std->td.td_flags |= HTOO32(OHCI_TD_TOGGLE_1);
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(ohci_td_t, td_flags),
+ sizeof(std->td.td_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req);
+ usb_syncmem(&opipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
setup->td.td_flags = HTOO32(OHCI_TD_SETUP | OHCI_TD_NOCC |
OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
@@ -1702,6 +1770,8 @@
setup->xfer = xfer;
setup->flags = 0;
xfer->hcpriv = setup;
+ usb_syncmem(&setup->dma, setup->offs, sizeof(setup->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
stat->td.td_flags = HTOO32(
(isread ? OHCI_TD_OUT : OHCI_TD_IN) |
@@ -1713,6 +1783,8 @@
stat->flags = OHCI_CALL_DONE;
stat->len = 0;
stat->xfer = xfer;
+ usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef OHCI_DEBUG
if (ohcidebug > 5) {
@@ -1725,6 +1797,10 @@
/* Insert ED in schedule */
s = splusb();
sed->ed.ed_tailp = HTOO32(tail->physaddr);
+ usb_syncmem(&sed->dma,
+ sed->offs + offsetof(ohci_ed_t, ed_tailp),
+ sizeof(sed->ed.ed_tailp),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
opipe->tail.td = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
@@ -1766,10 +1842,19 @@
DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head));
SPLUSBCHECK;
+ usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(head->ed.ed_nexted),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->next = head->next;
sed->ed.ed_nexted = head->ed.ed_nexted;
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(sed->ed.ed_nexted),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
head->next = sed;
head->ed.ed_nexted = HTOO32(sed->physaddr);
+ usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(head->ed.ed_nexted),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/*
@@ -1787,8 +1872,14 @@
;
if (p == NULL)
panic("ohci_rem_ed: ED not found");
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(sed->ed.ed_nexted),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
p->next = sed->next;
p->ed.ed_nexted = sed->ed.ed_nexted;
+ usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(p->ed.ed_nexted),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
/*
@@ -1926,6 +2017,8 @@
"\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
sbuf, sizeof(sbuf));
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
"nexttd=0x%08lx be=0x%08lx\n",
std, (u_long)std->physaddr, sbuf,
@@ -1942,6 +2035,8 @@
{
int i;
+ usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
"bp0=0x%08lx next=0x%08lx be=0x%08lx\n",
sitd, (u_long)sitd->physaddr,
@@ -1970,6 +2065,8 @@
{
char sbuf[128], sbuf2[128];
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
bitmask_snprintf((u_int32_t)O32TOH(sed->ed.ed_flags),
"\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
sbuf, sizeof(sbuf));
@@ -2057,6 +2154,8 @@
fmt |
OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
sed->ed.ed_headp = sed->ed.ed_tailp = HTOO32(tdphys);
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
switch (xfertype) {
case UE_CONTROL:
@@ -2209,7 +2308,13 @@
usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
splx(s);
DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/*
* Step 2: Wait until we know hardware has finished any possible
@@ -2263,6 +2368,10 @@
DPRINTFN(1,("ohci_abort_xfer: set hd=0x%08x, tl=0x%08x\n",
(int)p->physaddr, (int)O32TOH(sed->ed.ed_tailp)));
sed->ed.ed_headp = HTOO32(p->physaddr); /* unlink TDs */
+ usb_syncmem(&sed->dma,
+ sed->offs + offsetof(ohci_ed_t, ed_headp),
+ sizeof(sed->ed.ed_headp),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
} else {
DPRINTFN(1,("ohci_abort_xfer: no hit\n"));
}
@@ -2270,7 +2379,13 @@
/*
* Step 4: Turn on hardware again.
*/
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/*
* Step 5: Execute callback.
@@ -2867,6 +2982,8 @@
opipe->u.bulk.isread = isread;
opipe->u.bulk.length = len;
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
/* Update device address */
sed->ed.ed_flags = HTOO32(
(O32TOH(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |
@@ -2881,6 +2998,9 @@
tail->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1));
tail->flags |= OHCI_CALL_DONE;
tail = tail->nexttd; /* point at sentinel */
+ usb_syncmem(&tail->dma, tail->offs + offsetof(ohci_td_t, td_flags),
+ sizeof(tail->td.td_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if (err)
return (err);
@@ -2909,6 +3029,8 @@
sed->ed.ed_tailp = HTOO32(tail->physaddr);
opipe->tail.td = tail;
sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_callout(xfer->timeout_handle, mstohz(xfer->timeout),
@@ -3013,6 +3135,8 @@
data->len = len;
data->xfer = xfer;
data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ usb_syncmem(&data->dma, data->offs, sizeof(data->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
xfer->hcpriv = data;
#ifdef OHCI_DEBUG
@@ -3025,9 +3149,13 @@
/* Insert ED in schedule */
s = splusb();
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_tailp = HTOO32(tail->physaddr);
opipe->tail.td = tail;
sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#if 0
/*
@@ -3074,7 +3202,12 @@
DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
pipe, nslots, pos));
s = splusb();
+ usb_syncmem(&sed->dma, sed->offs,
+ sizeof(sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
(O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
usb_delay_ms(&sc->sc_bus, 2);
@@ -3087,6 +3220,9 @@
#endif
p->next = sed->next;
p->ed.ed_nexted = sed->ed.ed_nexted;
+ usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted),
+ sizeof(p->ed.ed_nexted),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
splx(s);
for (j = 0; j < nslots; j++)
@@ -3144,9 +3280,18 @@
s = splusb();
hsed = sc->sc_eds[best];
sed->next = hsed->next;
+ usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(hsed->ed.ed_flags),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_nexted = hsed->ed.ed_nexted;
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
hsed->next = sed;
hsed->ed.ed_nexted = HTOO32(sed->physaddr);
+ usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(hsed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
splx(s);
for (j = 0; j < nslots; j++)
@@ -3245,6 +3390,8 @@
sitd->itd.itd_be = HTOO32(bp0 + offs - 1);
sitd->xfer = xfer;
sitd->flags = 0;
+ usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sitd = nsitd;
iso->next = iso->next + ncur;
@@ -3273,6 +3420,8 @@
sitd->itd.itd_be = HTOO32(bp0 + offs - 1);
sitd->xfer = xfer;
sitd->flags = OHCI_CALL_DONE;
+ usb_syncmem(&sitd->dma, sitd->offs, sizeof(sitd->itd),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
iso->next = iso->next + ncur;
iso->inuse += nframes;
@@ -3291,9 +3440,14 @@
#endif
s = splusb();
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_tailp = HTOO32(nsitd->physaddr);
opipe->tail.itd = nsitd;
sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
splx(s);
#ifdef OHCI_DEBUG
@@ -3353,7 +3507,12 @@
xfer->status = USBD_CANCELLED;
sed = opipe->sed;
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
+ usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags),
+ sizeof(sed->ed.ed_flags),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sitd = xfer->hcpriv;
#ifdef DIAGNOSTIC
@@ -3381,6 +3540,8 @@
sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */
sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
+ usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
splx(s);
}
Index: ohcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohcivar.h,v
retrieving revision 1.44
diff -u -r1.44 ohcivar.h
--- ohcivar.h 28 Apr 2008 20:23:59 -0000 1.44
+++ ohcivar.h 23 Jun 2008 16:09:36 -0000
@@ -35,6 +35,8 @@
ohci_ed_t ed;
struct ohci_soft_ed *next;
ohci_physaddr_t physaddr;
+ usb_dma_t dma;
+ int offs;
} ohci_soft_ed_t;
#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) /
OHCI_ED_ALIGN * OHCI_ED_ALIGN)
#define OHCI_SED_CHUNK 128
@@ -45,6 +47,8 @@
struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */
struct ohci_soft_td *dnext; /* next in done list */
ohci_physaddr_t physaddr;
+ usb_dma_t dma;
+ int offs;
LIST_ENTRY(ohci_soft_td) hnext;
usbd_xfer_handle xfer;
u_int16_t len;
@@ -61,6 +65,8 @@
struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */
struct ohci_soft_itd *dnext; /* next in done list */
ohci_physaddr_t physaddr;
+ usb_dma_t dma;
+ int offs;
LIST_ENTRY(ohci_soft_itd) hnext;
usbd_xfer_handle xfer;
u_int16_t flags;
Index: uhci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v
retrieving revision 1.222
diff -u -r1.222 uhci.c
--- uhci.c 16 Jun 2008 10:29:41 -0000 1.222
+++ uhci.c 23 Jun 2008 16:09:36 -0000
@@ -390,6 +390,10 @@
for (; pqh->hlink != sqh; pqh = pqh->hlink) {
#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
+ usb_syncmem(&pqh->dma,
+ pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(pqh->qh.qh_hlink),
+ BUS_DMASYNC_POSTWRITE);
if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) {
printf("uhci_find_prev_qh: QH not found\n");
return (NULL);
@@ -458,6 +462,8 @@
std->td.td_status = htole32(0); /* inactive */
std->td.td_token = htole32(0);
std->td.td_buffer = htole32(0);
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate the dummy QH marking the end and used for looping the QHs.*/
lsqh = uhci_alloc_sqh(sc);
@@ -468,6 +474,8 @@
lsqh->elink = std;
lsqh->qh.qh_elink = htole32(std->physaddr | UHCI_PTR_TD);
sc->sc_last_qh = lsqh;
+ usb_syncmem(&lsqh->dma, lsqh->offs, sizeof(lsqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate the dummy QH where bulk traffic will be queued. */
bsqh = uhci_alloc_sqh(sc);
@@ -478,6 +486,8 @@
bsqh->elink = NULL;
bsqh->qh.qh_elink = htole32(UHCI_PTR_T);
sc->sc_bulk_start = sc->sc_bulk_end = bsqh;
+ usb_syncmem(&bsqh->dma, bsqh->offs, sizeof(bsqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate dummy QH where high speed control traffic will be queued. */
chsqh = uhci_alloc_sqh(sc);
@@ -488,6 +498,8 @@
chsqh->elink = NULL;
chsqh->qh.qh_elink = htole32(UHCI_PTR_T);
sc->sc_hctl_start = sc->sc_hctl_end = chsqh;
+ usb_syncmem(&chsqh->dma, chsqh->offs, sizeof(chsqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/* Allocate dummy QH where control traffic will be queued. */
clsqh = uhci_alloc_sqh(sc);
@@ -498,6 +510,8 @@
clsqh->elink = NULL;
clsqh->qh.qh_elink = htole32(UHCI_PTR_T);
sc->sc_lctl_start = sc->sc_lctl_end = clsqh;
+ usb_syncmem(&clsqh->dma, clsqh->offs, sizeof(clsqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
/*
* Make all (virtual) frame list pointers point to the interrupt
@@ -514,10 +528,14 @@
std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */
std->td.td_token = htole32(0);
std->td.td_buffer = htole32(0);
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sqh->hlink = clsqh;
sqh->qh.qh_hlink = htole32(clsqh->physaddr | UHCI_PTR_QH);
sqh->elink = NULL;
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sc->sc_vframes[i].htd = std;
sc->sc_vframes[i].etd = std;
sc->sc_vframes[i].hqh = sqh;
@@ -527,6 +545,10 @@
j += UHCI_VFRAMELIST_COUNT)
sc->sc_pframes[j] = htole32(std->physaddr);
}
+ usb_syncmem(&sc->sc_dma, 0,
+ UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
+ BUS_DMASYNC_PREWRITE);
+
LIST_INIT(&sc->sc_intrhead);
@@ -814,6 +836,9 @@
{
char sbuf[128], sbuf2[128];
+
+ usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
"token=0x%08lx buffer=0x%08lx\n",
p, (long)p->physaddr,
@@ -838,14 +863,19 @@
UHCI_TD_GET_ENDPT(le32toh(p->td.td_token)),
UHCI_TD_GET_DT(le32toh(p->td.td_token)),
UHCI_TD_GET_MAXLEN(le32toh(p->td.td_token))));
+ usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+ BUS_DMASYNC_PREREAD);
}
void
uhci_dump_qh(uhci_soft_qh_t *sqh)
{
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh,
(int)sqh->physaddr, le32toh(sqh->qh.qh_hlink),
le32toh(sqh->qh.qh_elink)));
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
}
@@ -887,10 +917,13 @@
*/
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (sqh->hlink != NULL && !(le32toh(sqh->qh.qh_hlink) & UHCI_PTR_T))
uhci_dump_qhs(sqh->hlink);
else
DPRINTF(("No QH\n"));
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), BUS_DMASYNC_PREREAD);
if (sqh->elink != NULL && !(le32toh(sqh->qh.qh_elink) & UHCI_PTR_T))
uhci_dump_tds(sqh->elink);
@@ -902,6 +935,7 @@
uhci_dump_tds(uhci_soft_td_t *std)
{
uhci_soft_td_t *td;
+ int stop;
for(td = std; td != NULL; td = td->link.std) {
uhci_dump_td(td);
@@ -911,8 +945,14 @@
* printing the free list in case the queue/TD has
* already been moved there (seatbelt).
*/
- if (le32toh(td->td.td_link) & UHCI_PTR_T ||
- le32toh(td->td.td_link) == 0)
+ usb_syncmem(&td->dma, td->offs + offsetof(uhci_td_t, td_link),
+ sizeof(td->td.td_link),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+ stop = (le32toh(td->td.td_link) & UHCI_PTR_T ||
+ le32toh(td->td.td_link) == 0);
+ usb_syncmem(&td->dma, td->offs + offsetof(uhci_td_t, td_link),
+ sizeof(td->td.td_link), BUS_DMASYNC_PREREAD);
+ if (stop)
break;
}
}
@@ -1044,6 +1084,10 @@
/* Note, we don't loop back the soft pointer. */
sc->sc_last_qh->qh.qh_hlink =
htole32(sc->sc_hctl_start->physaddr | UHCI_PTR_QH);
+ usb_syncmem(&sc->sc_last_qh->dma,
+ sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sc->sc_last_qh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
}
}
@@ -1056,6 +1100,10 @@
if (--sc->sc_loops == 0) {
DPRINTFN(5,("uhci_end_loop: remove\n"));
sc->sc_last_qh->qh.qh_hlink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sc->sc_last_qh->dma,
+ sc->sc_last_qh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sc->sc_last_qh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
}
}
@@ -1069,11 +1117,18 @@
DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh));
eqh = sc->sc_hctl_end;
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink),
+ BUS_DMASYNC_POSTWRITE);
sqh->hlink = eqh->hlink;
sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE);
eqh->hlink = sqh;
eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
sc->sc_hctl_end = sqh;
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE);
#ifdef UHCI_CTL_LOOP
uhci_add_loop(sc);
#endif
@@ -1098,15 +1153,32 @@
* at the last used TD.
* In this case we set the T bit and wait a little for the HC
* to stop looking at the TD.
+ * Note that if the TD chain is large enough, the controller
+ * may still be looking at the chain at the end of this function.
+ * uhci_free_std_chain() will make sure the controller stops
+ * looking at it quickly, but until then we should not change
+ * sqh->hlink.
*/
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
delay(UHCI_QH_REMOVE_DELAY);
}
pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh);
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(pqh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
delay(UHCI_QH_REMOVE_DELAY);
if (sc->sc_hctl_end == sqh)
sc->sc_hctl_end = pqh;
@@ -1122,10 +1194,16 @@
DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh));
eqh = sc->sc_lctl_end;
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
sqh->hlink = eqh->hlink;
sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE);
eqh->hlink = sqh;
eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE);
sc->sc_lctl_end = sqh;
}
@@ -1139,13 +1217,25 @@
DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh));
/* See comment in uhci_remove_hs_ctrl() */
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
delay(UHCI_QH_REMOVE_DELAY);
}
pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh);
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(pqh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
delay(UHCI_QH_REMOVE_DELAY);
if (sc->sc_lctl_end == sqh)
sc->sc_lctl_end = pqh;
@@ -1161,10 +1251,16 @@
DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh));
eqh = sc->sc_bulk_end;
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
sqh->hlink = eqh->hlink;
sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
+ BUS_DMASYNC_PREWRITE);
eqh->hlink = sqh;
eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE);
sc->sc_bulk_end = sqh;
uhci_add_loop(sc);
}
@@ -1180,13 +1276,24 @@
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
uhci_rem_loop(sc);
/* See comment in uhci_remove_hs_ctrl() */
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
delay(UHCI_QH_REMOVE_DELAY);
}
pqh = uhci_find_prev_qh(sc->sc_bulk_start, sqh);
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sqh->qh.qh_hlink), BUS_DMASYNC_POSTWRITE);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(pqh->qh.qh_hlink), BUS_DMASYNC_PREWRITE);
delay(UHCI_QH_REMOVE_DELAY);
if (sc->sc_bulk_end == sqh)
sc->sc_bulk_end = pqh;
@@ -1354,10 +1461,21 @@
* is an error somewhere in the middle, or whether there was a
* short packet (SPD and not ACTIVE).
*/
+ usb_syncmem(&lstd->dma,
+ lstd->offs + offsetof(uhci_td_t, td_status),
+ sizeof(lstd->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) {
DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii));
for (std = ii->stdstart; std != lstd; std = std->link.std) {
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = le32toh(std->td.td_status);
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status), BUS_DMASYNC_PREREAD);
/* If there's an active TD the xfer isn't done. */
if (status & UHCI_TD_ACTIVE)
break;
@@ -1365,6 +1483,10 @@
if (status & UHCI_TD_STALLED)
goto done;
/* We want short packets, and it is short: it's done */
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_token),
+ sizeof(std->td.td_token),
+ BUS_DMASYNC_POSTWRITE);
if ((status & UHCI_TD_SPD) &&
UHCI_TD_GET_ACTLEN(status) <
UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)))
@@ -1372,6 +1494,10 @@
}
DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n",
ii, ii->stdstart));
+ usb_syncmem(&lstd->dma,
+ lstd->offs + offsetof(uhci_td_t, td_status),
+ sizeof(lstd->td.td_status),
+ BUS_DMASYNC_PREREAD);
return;
}
done:
@@ -1429,6 +1555,10 @@
#endif
if (++n >= UHCI_VFRAMELIST_COUNT)
n = 0;
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
status = le32toh(std->td.td_status);
len = UHCI_TD_GET_ACTLEN(status);
xfer->frlengths[i] = len;
@@ -1450,6 +1580,8 @@
/* The transfer is done, compute actual length and status. */
actlen = 0;
for (std = ii->stdstart; std != NULL; std = std->link.std) {
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
nstatus = le32toh(std->td.td_status);
if (nstatus & UHCI_TD_ACTIVE)
break;
@@ -1665,6 +1797,8 @@
offs = i * UHCI_STD_SIZE;
std = KERNADDR(&dma, offs);
std->physaddr = DMAADDR(&dma, offs);
+ std->dma = dma;
+ std->offs = offs;
std->link.std = sc->sc_freetds;
sc->sc_freetds = std;
}
@@ -1708,6 +1842,8 @@
offs = i * UHCI_SQH_SIZE;
sqh = KERNADDR(&dma, offs);
sqh->physaddr = DMAADDR(&dma, offs);
+ sqh->dma = dma;
+ sqh->offs = offs;
sqh->hlink = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
@@ -1731,6 +1867,26 @@
{
uhci_soft_td_t *p;
+ /*
+ * to avoid race condition with the controller which may be looking
+ * at this chain, we need to first invalidate all links, and
+ * then wait for the controller to move to another queue
+ */
+ for (p = std; p != stdend; p = p->link.std) {
+ usb_syncmem(&p->dma,
+ p->offs + offsetof(uhci_td_t, td_link),
+ sizeof(p->td.td_link),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+ if ((p->td.td_link & UHCI_PTR_T) == 0) {
+ p->td.td_link = UHCI_PTR_T;
+ usb_syncmem(&p->dma,
+ p->offs + offsetof(uhci_td_t, td_link),
+ sizeof(p->td.td_link),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ }
+ }
+ delay(UHCI_QH_REMOVE_DELAY);
+
for (; std != stdend; std = p) {
p = std->link.std;
uhci_free_std(sc, std);
@@ -1778,6 +1934,8 @@
status |= UHCI_TD_LS;
if (flags & USBD_SHORT_XFER_OK)
status |= UHCI_TD_SPD;
+ usb_syncmem(dma, 0, len,
+ rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
for (i = ntd; i >= 0; i--) {
p = uhci_alloc_std(sc);
if (p == NULL) {
@@ -1802,6 +1960,8 @@
htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
UHCI_TD_OUT(l, endpt, addr, tog));
p->td.td_buffer = htole32(DMAADDR(dma, i * maxp));
+ usb_syncmem(&p->dma, p->offs, sizeof(p->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
tog ^= 1;
}
*sp = lastp;
@@ -1876,6 +2036,11 @@
if (err)
return (err);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
+ usb_syncmem(&dataend->dma,
+ dataend->offs + offsetof(uhci_td_t, td_status),
+ sizeof(dataend->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
#ifdef UHCI_DEBUG
if (uhcidebug > 8) {
@@ -1897,6 +2062,7 @@
sqh->elink = data;
sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD);
+ /* uhci_add_bulk() will do usb_syncmem(sqh) */
s = splusb();
uhci_add_bulk(sc, sqh);
@@ -1992,8 +2158,17 @@
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, uhci_timeout, ii);
DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii));
- for (std = ii->stdstart; std != NULL; std = std->link.std)
+ for (std = ii->stdstart; std != NULL; std = std->link.std) {
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ }
splx(s);
/*
@@ -2132,6 +2307,10 @@
if (err)
return (err);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
+ usb_syncmem(&dataend->dma,
+ dataend->offs + offsetof(uhci_td_t, td_status),
+ sizeof(dataend->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef UHCI_DEBUG
if (uhcidebug > 10) {
@@ -2159,6 +2338,10 @@
sqh = upipe->u.intr.qhs[i];
sqh->elink = data;
sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
uhci_add_intr_info(sc, ii);
xfer->status = USBD_IN_PROGRESS;
@@ -2272,12 +2455,17 @@
next = data;
dataend->link.std = stat;
dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF |
UHCI_PTR_TD);
+ usb_syncmem(&dataend->dma,
+ dataend->offs + offsetof(uhci_td_t, td_link),
+ sizeof(dataend->td.td_link),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
} else {
next = stat;
}
upipe->u.ctl.length = len;
memcpy(KERNADDR(&upipe->u.ctl.reqdma, 0), req, sizeof *req);
+ usb_syncmem(&upipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE);
setup->link.std = next;
setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD);
@@ -2285,6 +2473,8 @@
UHCI_TD_ACTIVE);
setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr));
setup->td.td_buffer = htole32(DMAADDR(&upipe->u.ctl.reqdma, 0));
+ usb_syncmem(&setup->dma, setup->offs, sizeof(setup->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
stat->link.std = NULL;
stat->td.td_link = htole32(UHCI_PTR_T);
@@ -2294,6 +2484,8 @@
htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) :
UHCI_TD_IN (0, endpt, addr, 1));
stat->td.td_buffer = htole32(0);
+ usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef UHCI_DEBUG
if (uhcidebug > 10) {
@@ -2315,6 +2507,7 @@
sqh->elink = setup;
sqh->qh.qh_elink = htole32(setup->physaddr | UHCI_PTR_TD);
+ /* uhci_add_?s_ctrl() will do usb_syncmem(sqh) */
s = splusb();
if (dev->speed == USB_SPEED_LOW)
@@ -2393,8 +2586,9 @@
uhci_softc_t *sc = dev->bus->hci_private;
struct iso *iso = &upipe->u.iso;
uhci_soft_td_t *std;
- u_int32_t buf, len, status;
+ u_int32_t buf, len, status, offs;
int s, i, next, nframes;
+ int rd = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) ==
UE_DIR_IN;
DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
"nframes=%d\n",
@@ -2425,6 +2619,7 @@
UXFER(xfer)->curframe = next;
buf = DMAADDR(&xfer->dmabuf, 0);
+ offs = 0;
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
UHCI_TD_ACTIVE |
UHCI_TD_IOS);
@@ -2436,11 +2631,15 @@
next = 0;
len = xfer->frlengths[i];
std->td.td_buffer = htole32(buf);
+ usb_syncmem(&xfer->dmabuf, offs, len,
+ rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
if (i == nframes - 1)
status |= UHCI_TD_IOC;
std->td.td_status = htole32(status);
std->td.td_token &= htole32(~UHCI_TD_MAXLEN_MASK);
std->td.td_token |= htole32(UHCI_TD_SET_MAXLEN(len));
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef UHCI_DEBUG
if (uhcidebug > 5) {
DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i));
@@ -2448,6 +2647,7 @@
}
#endif
buf += len;
+ offs += len;
}
iso->next = next;
iso->inuse += xfer->nframes;
@@ -2531,7 +2731,19 @@
maxlen = 0;
for (i = 0; i < nframes; i++) {
std = stds[n];
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_token),
+ sizeof(std->td.td_token),
+ BUS_DMASYNC_POSTWRITE);
len = UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token));
if (len > maxlen)
maxlen = len;
@@ -2569,8 +2781,18 @@
*/
iso = &upipe->u.iso;
- for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++)
- iso->stds[i]->td.td_status &= htole32(~UHCI_TD_ACTIVE);
+ for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
+ std = iso->stds[i];
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
+ std->td.td_status &= htole32(~UHCI_TD_ACTIVE);
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_status),
+ sizeof(std->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ }
usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */
s = splusb();
@@ -2587,7 +2809,15 @@
return;
}
vstd->link = std->link;
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_link),
+ sizeof(std->td.td_link),
+ BUS_DMASYNC_POSTWRITE);
vstd->td.td_link = std->td.td_link;
+ usb_syncmem(&vstd->dma,
+ vstd->offs + offsetof(uhci_td_t, td_link),
+ sizeof(vstd->td.td_link),
+ BUS_DMASYNC_PREWRITE);
uhci_free_std(sc, std);
}
splx(s);
@@ -2623,6 +2853,8 @@
goto bad;
std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */
std->td.td_token = htole32(token);
+ usb_syncmem(&std->dma, std->offs, sizeof(std->td),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
iso->stds[i] = std;
}
@@ -2631,10 +2863,22 @@
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
std = iso->stds[i];
vstd = sc->sc_vframes[i].htd;
+ usb_syncmem(&vstd->dma,
+ vstd->offs + offsetof(uhci_td_t, td_link),
+ sizeof(vstd->td.td_link),
+ BUS_DMASYNC_POSTWRITE);
std->link = vstd->link;
std->td.td_link = vstd->td.td_link;
+ usb_syncmem(&std->dma,
+ std->offs + offsetof(uhci_td_t, td_link),
+ sizeof(std->td.td_link),
+ BUS_DMASYNC_PREWRITE);
vstd->link.std = std;
vstd->td.td_link = htole32(std->physaddr | UHCI_PTR_TD);
+ usb_syncmem(&vstd->dma,
+ vstd->offs + offsetof(uhci_td_t, td_link),
+ sizeof(vstd->td.td_link),
+ BUS_DMASYNC_PREWRITE);
}
splx(s);
@@ -2654,6 +2898,10 @@
uhci_device_isoc_done(usbd_xfer_handle xfer)
{
uhci_intr_info_t *ii = &UXFER(xfer)->iinfo;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+ int i, offs;
+ int rd = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) ==
UE_DIR_IN;
+
DPRINTFN(4, ("uhci_isoc_done: length=%d, busy_free=0x%08x\n",
xfer->actlen, xfer->busy_free));
@@ -2676,9 +2924,24 @@
#endif
/* Turn off the interrupt since it is active even if the TD is not. */
+ usb_syncmem(&ii->stdend->dma,
+ ii->stdend->offs + offsetof(uhci_td_t, td_status),
+ sizeof(ii->stdend->td.td_status),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
ii->stdend->td.td_status &= htole32(~UHCI_TD_IOC);
+ usb_syncmem(&ii->stdend->dma,
+ ii->stdend->offs + offsetof(uhci_td_t, td_status),
+ sizeof(ii->stdend->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
uhci_del_intr_info(ii); /* remove from active list */
+
+ offs = 0;
+ for (i = 0; i < xfer->nframes; i++) {
+ usb_syncmem(&xfer->dmabuf, offs, xfer->frlengths[i],
+ rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ offs += xfer->frlengths[i];
+ }
}
void
@@ -2688,7 +2951,7 @@
uhci_softc_t *sc = ii->sc;
struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_soft_qh_t *sqh;
- int i, npoll;
+ int i, npoll, isread;
DPRINTFN(5, ("uhci_device_intr_done: length=%d\n", xfer->actlen));
@@ -2697,9 +2960,17 @@
sqh = upipe->u.intr.qhs[i];
sqh->elink = NULL;
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
uhci_free_std_chain(sc, ii->stdstart, NULL);
+ isread = UE_GET_DIR(upipe->pipe.endpoint->edesc->bEndpointAddress) ==
UE_DIR_IN;
+ usb_syncmem(&xfer->dmabuf, 0, xfer->length,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+
/* XXX Wasteful. */
if (xfer->pipe->repeat) {
uhci_soft_td_t *data, *dataend;
@@ -2711,6 +2982,10 @@
upipe->u.intr.isread, xfer->flags,
&xfer->dmabuf, &data, &dataend);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
+ usb_syncmem(&dataend->dma,
+ dataend->offs + offsetof(uhci_td_t, td_status),
+ sizeof(dataend->td.td_status),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
#ifdef UHCI_DEBUG
if (uhcidebug > 10) {
@@ -2732,6 +3007,10 @@
sqh = upipe->u.intr.qhs[i];
sqh->elink = data;
sqh->qh.qh_elink = htole32(data->physaddr |
UHCI_PTR_TD);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
}
xfer->status = USBD_IN_PROGRESS;
/* The ii is already on the examined list, just leave it. */
@@ -2749,6 +3028,8 @@
uhci_intr_info_t *ii = &UXFER(xfer)->iinfo;
uhci_softc_t *sc = ii->sc;
struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+ int len = UGETW(xfer->request.wLength);
+ int isread = (xfer->request.bmRequestType & UT_READ);
#ifdef DIAGNOSTIC
if (!(xfer->rqflags & URQ_REQUEST))
@@ -2768,6 +3049,13 @@
if (upipe->u.ctl.length != 0)
uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
+ if (len) {
+ usb_syncmem(&xfer->dmabuf, 0, len,
+ isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ }
+ usb_syncmem(&upipe->u.ctl.reqdma, 0,
+ sizeof(usb_device_request_t), BUS_DMASYNC_POSTWRITE);
+
DPRINTFN(5, ("uhci_device_ctrl_done: length=%d\n", xfer->actlen));
}
@@ -2804,10 +3092,19 @@
DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", sqh->pos, sqh));
eqh = vf->eqh;
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink),
+ BUS_DMASYNC_POSTWRITE);
sqh->hlink = eqh->hlink;
sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sqh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
eqh->hlink = sqh;
eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH);
+ usb_syncmem(&eqh->dma, eqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(eqh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
vf->eqh = sqh;
vf->bandwidth++;
}
@@ -2822,14 +3119,28 @@
DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", sqh->pos, sqh));
/* See comment in uhci_remove_ctrl() */
+
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
delay(UHCI_QH_REMOVE_DELAY);
}
pqh = uhci_find_prev_qh(vf->hqh, sqh);
+ usb_syncmem(&sqh->dma, sqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(sqh->qh.qh_hlink),
+ BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ usb_syncmem(&pqh->dma, pqh->offs + offsetof(uhci_qh_t, qh_hlink),
+ sizeof(pqh->qh.qh_hlink),
+ BUS_DMASYNC_PREWRITE);
delay(UHCI_QH_REMOVE_DELAY);
if (vf->eqh == sqh)
vf->eqh = pqh;
@@ -2877,6 +3188,10 @@
upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc);
sqh->elink = NULL;
sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ usb_syncmem(&sqh->dma,
+ sqh->offs + offsetof(uhci_qh_t, qh_elink),
+ sizeof(sqh->qh.qh_elink),
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
sqh->pos = MOD(i * ival + bestoffs);
}
#undef MOD
Index: uhcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhcivar.h,v
retrieving revision 1.44
diff -u -r1.44 uhcivar.h
--- uhcivar.h 28 Apr 2008 20:23:59 -0000 1.44
+++ uhcivar.h 23 Jun 2008 16:09:36 -0000
@@ -87,6 +87,8 @@
uhci_td_t td; /* The real TD, must be first */
uhci_soft_td_qh_t link; /* soft version of the td_link field */
uhci_physaddr_t physaddr; /* TD's physical address. */
+ usb_dma_t dma; /* TD's DMA infos */
+ int offs; /* TD's offset in usb_dma_t */
};
/*
* Make the size such that it is a multiple of UHCI_TD_ALIGN. This way
@@ -106,6 +108,8 @@
uhci_soft_td_t *elink; /* soft version of qh_elink */
uhci_physaddr_t physaddr; /* QH's physical address. */
int pos; /* Timeslot position */
+ usb_dma_t dma; /* QH's DMA infos */
+ int offs; /* QH's offset in usb_dma_t */
};
/* See comment about UHCI_STD_SIZE. */
#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) /
UHCI_QH_ALIGN * UHCI_QH_ALIGN)
Index: usb_mem.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_mem.c,v
retrieving revision 1.36
diff -u -r1.36 usb_mem.c
--- usb_mem.c 21 May 2008 17:19:44 -0000 1.36
+++ usb_mem.c 23 Jun 2008 16:09:36 -0000
@@ -287,6 +287,13 @@
DPRINTFN(5, ("usb_freemem: frag=%p\n", f));
}
+void
+usb_syncmem(usb_dma_t *p, bus_addr_t offset, bus_size_t len, int ops)
+{
+ bus_dmamap_sync(p->block->tag, p->block->map, p->offs + offset,
+ len, ops);
+}
+
#ifdef __NetBSD__
usbd_status
Index: usb_mem.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_mem.h,v
retrieving revision 1.26
diff -u -r1.26 usb_mem.h
--- usb_mem.h 21 May 2008 17:19:44 -0000 1.26
+++ usb_mem.h 23 Jun 2008 16:09:36 -0000
@@ -52,6 +52,7 @@
usbd_status usb_allocmem(usbd_bus_handle,size_t,size_t, usb_dma_t *);
void usb_freemem(usbd_bus_handle, usb_dma_t *);
+void usb_syncmem(usb_dma_t *, bus_addr_t, bus_size_t, int ops);
#ifdef __NetBSD__
struct extent;
Home |
Main Index |
Thread Index |
Old Index