PERFORCE change 113175 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Jan 19 21:15:59 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=113175
Change 113175 by hselasky at hselasky_mini_itx on 2007/01/19 21:15:07
Add missing "bus_dmamap_sync()" calls to the USB host controller
drivers. Optimize the USB code with regard to "bus_dmamap_sync()".
calls.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/ehci.c#16 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci.h#7 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#12 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#14 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.h#6 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#12 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#15 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.h#6 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#11 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#25 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#28 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/ehci.c#16 (text+ko) ====
@@ -101,12 +101,14 @@
extern struct usbd_pipe_methods ehci_root_ctrl_methods;
extern struct usbd_pipe_methods ehci_root_intr_methods;
-#define PHYSADDR(sc,what) \
- ((sc)->sc_physaddr + POINTER_TO_UNSIGNED(&(((struct ehci_softc *)0)->what)))
+#define SC_HW_PHYSADDR(sc,what) \
+ ((sc)->sc_hw_page.physaddr + \
+ POINTER_TO_UNSIGNED(&(((struct ehci_hw_softc *)0)->what)))
usbd_status
ehci_init(ehci_softc_t *sc)
{
+ struct ehci_hw_softc *hw_ptr;
u_int32_t version, sparams, cparams, hcr;
u_int i;
u_int16_t x;
@@ -116,6 +118,8 @@
mtx_lock(&sc->sc_bus.mtx);
+ hw_ptr = sc->sc_hw_ptr;
+
DPRINTF(("start\n"));
LIST_INIT(&sc->sc_interrupt_list_head);
@@ -193,26 +197,31 @@
sc->sc_eintrs = EHCI_NORMAL_INTRS;
+ usbd_page_sync(&(sc->sc_hw_page), BUS_DMASYNC_PREWRITE);
+
for(i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++)
{
- sc->sc_hw.intr_start[i].qh_self =
- htole32(PHYSADDR(sc,sc_hw.intr_start[i])|EHCI_LINK_QH);
+ hw_ptr->intr_start[i].qh_self =
+ htole32(SC_HW_PHYSADDR(sc,intr_start[i])|EHCI_LINK_QH);
- sc->sc_hw.intr_start[i].qh_endp =
+ hw_ptr->intr_start[i].qh_endp =
htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH));
- sc->sc_hw.intr_start[i].qh_endphub =
+ hw_ptr->intr_start[i].qh_endphub =
htole32(EHCI_QH_SET_MULT(1));
- sc->sc_hw.intr_start[i].qh_curqtd = 0;
+ hw_ptr->intr_start[i].qh_curqtd = 0;
- sc->sc_hw.intr_start[i].qh_qtd.qtd_next =
+ hw_ptr->intr_start[i].qh_qtd.qtd_next =
htole32(EHCI_LINK_TERMINATE);
- sc->sc_hw.intr_start[i].qh_qtd.qtd_altnext =
+ hw_ptr->intr_start[i].qh_qtd.qtd_altnext =
htole32(EHCI_LINK_TERMINATE);
- sc->sc_hw.intr_start[i].qh_qtd.qtd_status =
+ hw_ptr->intr_start[i].qh_qtd.qtd_status =
htole32(EHCI_QTD_HALTED);
+ hw_ptr->intr_start[i].page =
+ &(sc->sc_hw_page);
+
sc->sc_intr_p_last[i] =
- &sc->sc_hw.intr_start[i];
+ &(hw_ptr->intr_start[i]);
}
/*
@@ -230,43 +239,49 @@
/* the next QH has half the
* poll interval
*/
- sc->sc_hw.intr_start[x].qh_link =
- sc->sc_hw.intr_start[y].qh_self;
+ hw_ptr->intr_start[x].qh_link =
+ hw_ptr->intr_start[y].qh_self;
x++;
}
bit >>= 1;
}
/* the last (1ms) QH terminates */
- sc->sc_hw.intr_start[0].qh_link = htole32(EHCI_LINK_TERMINATE);
+ hw_ptr->intr_start[0].qh_link = htole32(EHCI_LINK_TERMINATE);
for(i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++)
{
/* initialize full speed isochronous */
- sc->sc_hw.isoc_fs_start[i].sitd_self =
- htole32(PHYSADDR(sc,sc_hw.isoc_fs_start[i])|EHCI_LINK_SITD);
+ hw_ptr->isoc_fs_start[i].sitd_self =
+ htole32(SC_HW_PHYSADDR(sc,isoc_fs_start[i])|EHCI_LINK_SITD);
- sc->sc_hw.isoc_fs_start[i].sitd_back =
+ hw_ptr->isoc_fs_start[i].sitd_back =
htole32(EHCI_LINK_TERMINATE);
- sc->sc_hw.isoc_fs_start[i].sitd_next =
- sc->sc_hw.intr_start[i|(EHCI_VIRTUAL_FRAMELIST_COUNT/2)].qh_self;
+ hw_ptr->isoc_fs_start[i].sitd_next =
+ hw_ptr->intr_start[i|(EHCI_VIRTUAL_FRAMELIST_COUNT/2)].qh_self;
+
+ hw_ptr->isoc_fs_start[i].page =
+ &(sc->sc_hw_page);
sc->sc_isoc_fs_p_last[i] =
- &sc->sc_hw.isoc_fs_start[i];
+ &(hw_ptr->isoc_fs_start[i]);
/* initialize high speed isochronous */
- sc->sc_hw.isoc_hs_start[i].itd_self =
- htole32(PHYSADDR(sc,sc_hw.isoc_hs_start[i])|EHCI_LINK_ITD);
+ hw_ptr->isoc_hs_start[i].itd_self =
+ htole32(SC_HW_PHYSADDR(sc,isoc_hs_start[i])|EHCI_LINK_ITD);
+
+ hw_ptr->isoc_hs_start[i].itd_next =
+ hw_ptr->isoc_fs_start[i].sitd_self;
- sc->sc_hw.isoc_hs_start[i].itd_next =
- sc->sc_hw.isoc_fs_start[i].sitd_self;
+ hw_ptr->isoc_hs_start[i].page =
+ &(sc->sc_hw_page);
sc->sc_isoc_hs_p_last[i] =
- &sc->sc_hw.isoc_hs_start[i];
+ &(hw_ptr->isoc_hs_start[i]);
}
/*
@@ -276,43 +291,49 @@
*/
for(i = 0; i < EHCI_FRAMELIST_COUNT; i++)
{
- sc->sc_hw.pframes[i] = sc->sc_hw.isoc_hs_start
+ hw_ptr->pframes[i] = hw_ptr->isoc_hs_start
[i & (EHCI_VIRTUAL_FRAMELIST_COUNT-1)].itd_self;
}
/* setup sync list pointer */
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, PHYSADDR(sc,sc_hw.pframes[0]));
+ EOWRITE4(sc, EHCI_PERIODICLISTBASE, SC_HW_PHYSADDR(sc,pframes[0]));
/* init dummy QH that starts the async list */
- sc->sc_hw.async_start.qh_self =
- htole32(PHYSADDR(sc,sc_hw.async_start)|EHCI_LINK_QH);
+ hw_ptr->async_start.qh_self =
+ htole32(SC_HW_PHYSADDR(sc,async_start)|EHCI_LINK_QH);
/* fill the QH */
- sc->sc_hw.async_start.qh_endp =
+ hw_ptr->async_start.qh_endp =
htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL);
- sc->sc_hw.async_start.qh_endphub = htole32(EHCI_QH_SET_MULT(1));
- sc->sc_hw.async_start.qh_link = sc->sc_hw.async_start.qh_self;
- sc->sc_hw.async_start.qh_curqtd = 0;
+ hw_ptr->async_start.qh_endphub = htole32(EHCI_QH_SET_MULT(1));
+ hw_ptr->async_start.qh_link = hw_ptr->async_start.qh_self;
+ hw_ptr->async_start.qh_curqtd = 0;
/* fill the overlay qTD */
- sc->sc_hw.async_start.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
- sc->sc_hw.async_start.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
- sc->sc_hw.async_start.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
+ hw_ptr->async_start.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
+ hw_ptr->async_start.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ hw_ptr->async_start.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
+
+ /* fill the page pointer */
+ hw_ptr->async_start.page =
+ &(sc->sc_hw_page);
sc->sc_async_p_last =
- &sc->sc_hw.async_start;
+ &(hw_ptr->async_start);
+
+ usbd_page_sync(&(sc->sc_hw_page), BUS_DMASYNC_POSTWRITE);
#ifdef USB_DEBUG
if(ehcidebug)
{
- ehci_dump_sqh(&sc->sc_hw.async_start);
+ ehci_dump_sqh(&(hw_ptr->async_start));
}
#endif
/* setup async list pointer */
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, PHYSADDR(sc,sc_hw.async_start)|EHCI_LINK_QH);
+ EOWRITE4(sc, EHCI_ASYNCLISTADDR, SC_HW_PHYSADDR(sc,async_start)|EHCI_LINK_QH);
/* enable interrupts */
@@ -451,8 +472,8 @@
/* restore things in case the bios doesn't */
EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
- EOWRITE4(sc, EHCI_PERIODICLISTBASE, PHYSADDR(sc,sc_hw.pframes[0]));
- EOWRITE4(sc, EHCI_ASYNCLISTADDR, PHYSADDR(sc,sc_hw.async_start)|EHCI_LINK_QH);
+ EOWRITE4(sc, EHCI_PERIODICLISTBASE, SC_HW_PHYSADDR(sc,pframes[0]));
+ EOWRITE4(sc, EHCI_ASYNCLISTADDR, SC_HW_PHYSADDR(sc,async_start)|EHCI_LINK_QH);
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
@@ -661,25 +682,28 @@
return;
}
-static void
+static uint8_t
ehci_dump_sqtd(ehci_qtd_t *sqtd)
{
+ uint8_t temp;
+ usbd_page_sync(sqtd->page, BUS_DMASYNC_PREREAD);
printf("QTD(%p) at 0x%08x:\n", sqtd, le32toh(sqtd->qtd_self));
ehci_dump_qtd(sqtd);
- return;
+ temp = (sqtd->qtd_next & htole32(EHCI_LINK_TERMINATE)) ? 1 : 0;
+ usbd_page_sync(sqtd->page, BUS_DMASYNC_POSTREAD);
+ return temp;
}
static void
ehci_dump_sqtds(ehci_qtd_t *sqtd)
{
u_int16_t i;
- u_int32_t stop;
+ uint8_t stop;
stop = 0;
for(i = 0; sqtd && (i < 20) && !stop; sqtd = sqtd->obj_next, i++)
{
- ehci_dump_sqtd(sqtd);
- stop = sqtd->qtd_next & htole32(EHCI_LINK_TERMINATE);
+ stop = ehci_dump_sqtd(sqtd);
}
if(sqtd)
{
@@ -693,6 +717,7 @@
{
u_int32_t endp, endphub;
+ usbd_page_sync(qh->page, BUS_DMASYNC_PREREAD);
printf("QH(%p) at 0x%08x:\n", qh, le32toh(qh->qh_self) & ~0x1F);
printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
endp = le32toh(qh->qh_endp);
@@ -713,12 +738,14 @@
printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
printf("Overlay qTD:\n");
ehci_dump_qtd((void *)&qh->qh_qtd);
+ usbd_page_sync(qh->page, BUS_DMASYNC_POSTREAD);
return;
}
static void
ehci_dump_sitd(ehci_sitd_t *sitd)
{
+ usbd_page_sync(sitd->page, BUS_DMASYNC_PREREAD);
printf("SITD(%p) at 0x%08x\n", sitd, le32toh(sitd->sitd_self) & ~0x1F);
printf(" next=0x%08x\n", le32toh(sitd->sitd_next));
printf(" portaddr=0x%08x dir=%s addr=%d endpt=0x%x port=0x%x huba=0x%x\n",
@@ -739,12 +766,14 @@
le32toh(sitd->sitd_bp[1]),
le32toh(sitd->sitd_bp_hi[0]),
le32toh(sitd->sitd_bp_hi[1]));
+ usbd_page_sync(sitd->page, BUS_DMASYNC_POSTREAD);
return;
}
static void
ehci_dump_itd(ehci_itd_t *itd)
{
+ usbd_page_sync(itd->page, BUS_DMASYNC_PREREAD);
printf("ITD(%p) at 0x%08x\n", itd, le32toh(itd->itd_self) & ~0x1F);
printf(" next=0x%08x\n", le32toh(itd->itd_next));
printf(" status[0]=0x%08x; <%s>\n", le32toh(itd->itd_status[0]),
@@ -786,6 +815,7 @@
le32toh(itd->itd_bp_hi[4]),
le32toh(itd->itd_bp_hi[5]),
le32toh(itd->itd_bp_hi[6]));
+ usbd_page_sync(itd->page, BUS_DMASYNC_POSTREAD);
return;
}
@@ -829,17 +859,24 @@
/* (sc->sc_bus.mtx) must be locked */
+ usbd_page_sync(std->page, BUS_DMASYNC_PREWRITE);
+
std->next = last->next;
std->sitd_next = last->sitd_next;
std->prev = last;
+ usbd_page_sync(std->page, BUS_DMASYNC_POSTWRITE);
+ usbd_page_sync(last->page, BUS_DMASYNC_PREWRITE);
+
/* the last->next->prev is never followed:
* std->next->prev = std;
*/
last->next = std;
last->sitd_next = std->sitd_self;
+ usbd_page_sync(last->page, BUS_DMASYNC_POSTWRITE);
+
return(std);
}
@@ -851,16 +888,24 @@
/* (sc->sc_bus.mtx) must be locked */
+ usbd_page_sync(std->page, BUS_DMASYNC_PREWRITE);
+
std->next = last->next;
std->itd_next = last->itd_next;
std->prev = last;
+ usbd_page_sync(std->page, BUS_DMASYNC_POSTWRITE);
+ usbd_page_sync(last->page, BUS_DMASYNC_PREWRITE);
+
/* the last->next->prev is never followed:
* std->next->prev = std;
*/
last->next = std;
last->itd_next = std->itd_self;
+
+ usbd_page_sync(last->page, BUS_DMASYNC_POSTWRITE);
+
return(std);
}
@@ -872,11 +917,16 @@
/* (sc->sc_bus.mtx) must be locked */
+ usbd_page_sync(sqh->page, BUS_DMASYNC_PREWRITE);
+
sqh->next = last->next;
sqh->qh_link = last->qh_link;
sqh->prev = last;
-
+
+ usbd_page_sync(sqh->page, BUS_DMASYNC_POSTWRITE);
+ usbd_page_sync(last->page, BUS_DMASYNC_PREWRITE);
+
/* the last->next->prev is never followed:
* sqh->next->prev = sqh;
*/
@@ -884,6 +934,8 @@
last->next = sqh;
last->qh_link = sqh->qh_self;
+ usbd_page_sync(last->page, BUS_DMASYNC_POSTWRITE);
+
#ifdef USB_DEBUG
if(ehcidebug > 5)
{
@@ -902,9 +954,13 @@
/* (sc->sc_bus.mtx) must be locked */
+ usbd_page_sync(std->prev->page, BUS_DMASYNC_PREWRITE);
+
std->prev->next = std->next;
std->prev->sitd_next = std->sitd_next;
+ usbd_page_sync(std->prev->page, BUS_DMASYNC_POSTWRITE);
+
if(std->next)
{
std->next->prev = std->prev;
@@ -920,9 +976,13 @@
/* (sc->sc_bus.mtx) must be locked */
+ usbd_page_sync(std->prev->page, BUS_DMASYNC_PREWRITE);
+
std->prev->next = std->next;
std->prev->itd_next = std->itd_next;
+ usbd_page_sync(std->prev->page, BUS_DMASYNC_POSTWRITE);
+
if(std->next)
{
std->next->prev = std->prev;
@@ -941,14 +1001,20 @@
/* only remove if not removed from a queue */
if(sqh->prev)
{
+ usbd_page_sync(sqh->prev->page, BUS_DMASYNC_PREWRITE);
+
sqh->prev->next = sqh->next;
sqh->prev->qh_link = sqh->qh_link;
+ usbd_page_sync(sqh->prev->page, BUS_DMASYNC_POSTWRITE);
+
if(sqh->next)
{
sqh->next->prev = sqh->prev;
}
+ usbd_page_sync(sqh->page, BUS_DMASYNC_PREWRITE);
+
/* set the Terminate-bit in the e_next of the QH,
* in case the transferred packet was short so
* that the QH still points at the last used TD
@@ -956,6 +1022,8 @@
sqh->qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE);
+ usbd_page_sync(sqh->page, BUS_DMASYNC_POSTWRITE);
+
last = ((last == sqh) ? sqh->prev : last);
sqh->prev = 0;
@@ -971,6 +1039,7 @@
{
u_int32_t status = 0;
u_int32_t actlen = 0;
+ uint32_t qtd_next;
u_int16_t len;
ehci_qtd_t *td = xfer->td_transfer_first;
@@ -987,17 +1056,21 @@
/* the transfer is done, compute actual length and status */
for (;
td != NULL;
- td = ((td == xfer->td_transfer_last) ? NULL : td->obj_next))
+ td = td->obj_next)
{
- if(td->qtd_status & htole32(EHCI_QTD_ACTIVE))
- {
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
+
+ status = le32toh(td->qtd_status);
+ qtd_next = le32toh(td->qtd_next);
+
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
+
+ if (status & EHCI_QTD_ACTIVE) {
break;
}
- status = le32toh(td->qtd_status);
-
/* halt is ok if descriptor is last, and complete */
- if((td->qtd_next == htole32(EHCI_LINK_TERMINATE)) &&
+ if((qtd_next == EHCI_LINK_TERMINATE) &&
(EHCI_QTD_GET_BYTES(status) == 0))
{
status &= ~EHCI_QTD_HALTED;
@@ -1009,6 +1082,11 @@
{
actlen += td->len - len;
}
+
+ if (((void *)td) == xfer->td_transfer_last) {
+ td = NULL;
+ break;
+ }
}
/* if there are left over TDs
@@ -1030,11 +1108,8 @@
xfer->actlen = actlen;
- status &= EHCI_QTD_STATERRS;
-
#ifdef USB_DEBUG
- if(status == EHCI_QTD_HALTED)
- {
+ if (status & EHCI_QTD_STATERRS) {
DPRINTFN(10,
("error, addr=%d, endpt=0x%02x, "
"status=%s%s%s%s%s%s%s%s\n",
@@ -1050,10 +1125,9 @@
(status & EHCI_QTD_PINGSTATE) ? "-PING" : ""));
}
#endif
-
- ehci_device_done(xfer,
- (status == 0) ? USBD_NORMAL_COMPLETION :
- (status == EHCI_QTD_HALTED) ? USBD_STALLED : USBD_IOERROR);
+ ehci_device_done(xfer, (status & EHCI_QTD_HALTED) ?
+ USBD_STALLED :
+ USBD_NORMAL_COMPLETION);
return;
}
@@ -1063,7 +1137,7 @@
static u_int8_t
ehci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
{
- DPRINTFN(15, ("xfer=%p\n", xfer));
+ uint32_t status;
if(xfer->usb_thread != ctd)
{
@@ -1073,13 +1147,21 @@
goto done;
}
+ DPRINTFN(12, ("xfer=%p checking transfer\n", xfer));
+
if(xfer->pipe->methods == &ehci_device_isoc_fs_methods)
{
ehci_sitd_t *td = xfer->td_transfer_last;
/* isochronous full speed transfer */
- if(!(td->sitd_status & htole32(EHCI_SITD_ACTIVE)))
- {
+
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
+
+ status = le32toh(td->sitd_status);
+
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
+
+ if (!(status & EHCI_SITD_ACTIVE)) {
ehci_device_done(xfer, USBD_NORMAL_COMPLETION);
goto transferred;
}
@@ -1089,70 +1171,71 @@
ehci_itd_t *td = xfer->td_transfer_last;
/* isochronous high speed transfer */
- if((!(td->itd_status[0] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[1] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[2] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[3] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[4] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[5] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[6] & htole32(EHCI_ITD_ACTIVE))) &&
- (!(td->itd_status[7] & htole32(EHCI_ITD_ACTIVE))))
- {
+
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
+
+ status = ((!(td->itd_status[0] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[1] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[2] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[3] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[4] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[5] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[6] & htole32(EHCI_ITD_ACTIVE))) &&
+ (!(td->itd_status[7] & htole32(EHCI_ITD_ACTIVE))));
+
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
+
+ if (status) {
ehci_device_done(xfer, USBD_NORMAL_COMPLETION);
goto transferred;
}
}
else
{
- ehci_qtd_t *td = xfer->td_transfer_last;
+ ehci_qtd_t *td;
/* non-isochronous transfer */
- if(td->qtd_status & htole32(EHCI_QTD_ACTIVE))
+
+ /* check whether there is an error somewhere
+ * in the middle, or whether there was a short
+ * packet (SPD and not ACTIVE)
+ */
+ for (td = xfer->td_transfer_cache;
+ td != NULL;
+ td = td->obj_next)
{
- /*
- * if the last TD is still active we need to
- * check whether there is an error somewhere
- * in the middle, or whether there was a short
- * packet (SPD and not ACTIVE)
- */
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
- DPRINTFN(12, ("xfer=%p active\n", xfer));
+ status = le32toh(td->qtd_status);
- for(td = xfer->td_transfer_cache;
- td != NULL;
- td = ((td == xfer->td_transfer_last) ? NULL : td->obj_next))
- {
- u_int32_t status;
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
- status = le32toh(td->qtd_status);
+ /* if there is an active TD
+ * the transfer isn't done
+ */
+ if (status & EHCI_QTD_ACTIVE) {
+ /* update cache */
+ xfer->td_transfer_cache = td;
+ goto done;
+ }
- /* if there's an active TD
- * the transfer isn't done
- */
- if(status & EHCI_QTD_ACTIVE)
- {
- DPRINTFN(12, ("xfer=%p is still "
- "active\n", xfer));
- /* update cache */
- xfer->td_transfer_cache = td;
- goto done;
- }
+ /* any kind of error makes
+ * the transfer done
+ */
+ if (status & EHCI_QTD_HALTED) {
+ break;
+ }
- /* any kind of error makes
- * the transfer done
- */
- if(status & EHCI_QTD_HALTED)
- {
- break;
- }
+ /* a short packet also makes
+ * the transfer done
+ */
+ if (EHCI_QTD_GET_BYTES(status)) {
+ break;
+ }
- /* we want short packets,
- * and if it is short: it's done
- */
- if(EHCI_QTD_GET_BYTES(status) != 0)
- {
- break;
- }
+ if (((void *)td) == xfer->td_transfer_last) {
+ td = NULL;
+ break;
}
}
ehci_non_isoc_done(xfer);
@@ -1160,6 +1243,7 @@
}
done:
+ DPRINTFN(12, ("xfer=%p is still active\n", xfer));
return 0;
transferred:
@@ -1431,6 +1515,8 @@
u_int32_t average = (EHCI_PAGE_SIZE - (EHCI_PAGE_SIZE %
xfer->max_packet_size));
u_int32_t qtd_status;
+ uint32_t qh_endp;
+ uint32_t qh_endphub;
u_int32_t buf_offset;
u_int32_t len = xfer->length;
u_int32_t c_error =
@@ -1464,6 +1550,8 @@
*/
xfer->pipe->toggle_next = 1;
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
+
/* SETUP message */
td->qtd_status = c_error | htole32
@@ -1486,6 +1574,15 @@
len -= sizeof(usb_device_request_t);
td_last = td;
td = td->obj_next;
+
+ if (td) {
+ /* link the last TD with the next one */
+ td_last->qtd_next = td->qtd_self;
+ /* short transfers should terminate the transfer: */
+ td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ }
+
+ usbd_page_sync(td_last->page, BUS_DMASYNC_POSTWRITE);
}
else
{
@@ -1549,14 +1646,8 @@
"than there is in the buffer!", __FUNCTION__);
}
- /* link in last TD */
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
- if (td_last) {
- td_last->qtd_next = td->qtd_self;
- /* short transfers should terminate the transfer: */
- td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
- }
-
/* fill out current TD */
td->qtd_status =
@@ -1590,15 +1681,20 @@
len -= average;
td_last = td;
td = td->obj_next;
+
+ if (td) {
+ /* link the last TD with the next one */
+ td_last->qtd_next = td->qtd_self;
+ /* short transfers should terminate the transfer: */
+ td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ }
+
+ usbd_page_sync(td_last->page, BUS_DMASYNC_POSTWRITE);
}
if(xfer->pipe->methods == &ehci_device_ctrl_methods)
{
- /* link in last TD */
-
- td_last->qtd_next = td->qtd_self;
- /* short transfers should terminate the transfer: */
- td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
/* STATUS message */
@@ -1619,12 +1715,19 @@
td->len = 0;
td_last = td;
+
+ usbd_page_sync(td_last->page, BUS_DMASYNC_POSTWRITE);
}
+ usbd_page_sync(td_last->page, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
+
+ /* the last TD terminates the transfer: */
td_last->qtd_next = htole32(EHCI_LINK_TERMINATE);
td_last->qtd_altnext = htole32(EHCI_LINK_TERMINATE);
td_last->qtd_status |= htole32(EHCI_QTD_IOC);
+ usbd_page_sync(td_last->page, BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
+
/* must have at least one frame! */
xfer->td_transfer_last = td_last;
@@ -1640,9 +1743,11 @@
qh = xfer->qh_start;
+ usbd_page_sync(qh->page, BUS_DMASYNC_PREWRITE);
+
/* the "qh_link" field is filled when the QH is added */
- qh->qh_endp = htole32
+ qh_endp =
(EHCI_QH_SET_ADDR(xfer->address) |
EHCI_QH_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
EHCI_QH_DTC |
@@ -1652,14 +1757,15 @@
switch (xfer->udev->speed) {
case USB_SPEED_LOW:
- qh->qh_endp |= htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_LOW)|
- EHCI_QH_CTL);
+ qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_LOW)|
+ EHCI_QH_CTL);
break;
case USB_SPEED_FULL:
- qh->qh_endp |= htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_FULL)|
- EHCI_QH_CTL); break;
+ qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_FULL)|
+ EHCI_QH_CTL);
+ break;
case USB_SPEED_HIGH:
- qh->qh_endp |= htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH));
+ qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH));
break;
default:
panic("%s: bad device speed %d!", __FUNCTION__, xfer->udev->speed);
@@ -1668,16 +1774,18 @@
if(xfer->pipe->methods != &ehci_device_ctrl_methods)
{
- qh->qh_endp &= htole32(~EHCI_QH_CTL);
+ qh_endp &= ~EHCI_QH_CTL;
}
- qh->qh_endphub = htole32
+ qh->qh_endp = htole32(qh_endp);
+
+ qh_endphub =
(EHCI_QH_SET_MULT(xfer->max_packet_count & 3)|
EHCI_QH_SET_CMASK(0xf0));
if(xfer->udev->myhsport)
{
- qh->qh_endphub |= htole32
+ qh_endphub |=
(EHCI_QH_SET_HUBA(xfer->udev->myhsport->parent->address)|
EHCI_QH_SET_PORT(xfer->udev->myhsport->portno));
}
@@ -1685,9 +1793,10 @@
if(xfer->pipe->methods == &ehci_device_intr_methods)
{
/* execute the transfer one time per 1ms */
- qh->qh_endphub |= htole32(EHCI_QH_SET_SMASK(0x04));
+ qh_endphub |= EHCI_QH_SET_SMASK(0x04);
}
+ qh->qh_endphub = htole32(qh_endphub);
qh->qh_curqtd = htole32(0);
/* fill the overlay qTD */
@@ -1698,6 +1807,8 @@
qh->qh_qtd.qtd_next = td->qtd_self;
qh->qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE);
+ usbd_page_sync(qh->page, BUS_DMASYNC_POSTWRITE);
+
EHCI_APPEND_QH(qh, *qh_last);
return;
}
@@ -1744,6 +1855,7 @@
{
u_int32_t nframes = xfer->nframes;
u_int32_t actlen = 0;
+ uint32_t status;
u_int16_t *plen = xfer->frlengths;
u_int16_t len = 0;
u_int8_t need_delay = 0;
@@ -1773,13 +1885,16 @@
ehci_dump_sitd(td);
}
#endif
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
+ status = le32toh(td->sitd_status);
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
+
/* check for active transfers */
- if(td->sitd_status & htole32(EHCI_SITD_ACTIVE))
- {
+ if (status & EHCI_SITD_ACTIVE) {
need_delay = 1;
}
- len = EHCI_SITD_GET_LEN(le32toh(td->sitd_status));
+ len = EHCI_SITD_GET_LEN(status);
if(*plen >= len)
{
@@ -1810,6 +1925,7 @@
{
u_int32_t nframes = xfer->nframes;
u_int32_t actlen = 0;
+ uint32_t status;
u_int16_t *plen = xfer->frlengths;
u_int16_t len = 0;
u_int8_t td_no = 0;
@@ -1840,12 +1956,16 @@
ehci_dump_itd(td);
}
#endif
- if(td->itd_status[td_no] & htole32(EHCI_ITD_ACTIVE))
- {
+
+ usbd_page_sync(td->page, BUS_DMASYNC_PREREAD);
+ status = le32toh(td->itd_status[td_no]);
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTREAD);
+
+ if (status & EHCI_ITD_ACTIVE) {
need_delay = 1;
}
- len = EHCI_ITD_GET_LEN(le32toh(td->itd_status[td_no]));
+ len = EHCI_ITD_GET_LEN(status);
if(*plen >= len)
{
@@ -2277,6 +2397,8 @@
for(td = xfer->td_start; td; td = td->obj_next)
{
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
+
td->sitd_portaddr = sitd_portaddr;
/* TODO: make some kind of automatic SMASK/CMASK selection
@@ -2303,6 +2425,8 @@
EHCI_SITD_SET_CMASK(0xF8));
}
td->sitd_back = htole32(EHCI_LINK_TERMINATE);
+
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTWRITE);
}
return;
}
@@ -2321,6 +2445,7 @@
ehci_softc_t *sc = xfer->usb_sc;
u_int32_t buf_offset;
u_int32_t nframes;
+ uint32_t temp;
u_int16_t *plen;
#ifdef USB_DEBUG
u_int8_t once = 1;
@@ -2401,18 +2526,22 @@
*plen = xfer->max_frame_size;
}
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
+
td->sitd_bp[0] = htole32(buf_res.physaddr);
buf_offset += *plen;
usbd_get_page(&(xfer->buf_data), buf_offset, &buf_res);
- td->sitd_bp[1] = htole32(buf_res.physaddr & (~0xFFF));
+ temp = buf_res.physaddr & (~0xFFF);
if(UE_GET_DIR(xfer->endpoint) == UE_DIR_OUT)
{
- td->sitd_bp[1] |= htole32(1); /* T-count == 1 */
+ temp |= 1; /* T-count == 1*/
}
+ td->sitd_bp[1] = htole32(temp);
+
if(nframes == 0)
{
td->sitd_status = htole32
@@ -2426,6 +2555,8 @@
(EHCI_SITD_ACTIVE|
EHCI_SITD_SET_LEN(*plen));
}
+ usbd_page_sync(td->page, BUS_DMASYNC_POSTWRITE);
+
#ifdef USB_DEBUG
if(ehcidebug > 15)
{
@@ -2488,11 +2619,14 @@
ehci_device_isoc_hs_open(struct usbd_xfer *xfer)
{
ehci_itd_t *td;
+ uint32_t temp;
/* initialize all TD's */
for(td = xfer->td_start; td; td = td->obj_next)
{
+ usbd_page_sync(td->page, BUS_DMASYNC_PREWRITE);
+
/* set TD inactive */
td->itd_status[0] = 0;
td->itd_status[1] = 0;
@@ -2508,18 +2642,21 @@
(EHCI_ITD_SET_ADDR(xfer->address)|
EHCI_ITD_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)));
- /* set maximum packet size */
- td->itd_bp[1] = htole32
- (EHCI_ITD_SET_MPL(xfer->max_packet_size & 0x7FF));
+ temp = EHCI_ITD_SET_MPL(xfer->max_packet_size & 0x7FF);
/* set direction */
if(UE_GET_DIR(xfer->endpoint) == UE_DIR_IN)
{
- td->itd_bp[1] |= htole32(EHCI_ITD_SET_DIR_IN);
+ temp |= EHCI_ITD_SET_DIR_IN;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list