From owner-p4-projects@FreeBSD.ORG Fri Jan 19 21:15:59 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D4A8116A406; Fri, 19 Jan 2007 21:15:58 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9947A16A402 for ; Fri, 19 Jan 2007 21:15:58 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 8748713C45A for ; Fri, 19 Jan 2007 21:15:58 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id l0JLFwdx088827 for ; Fri, 19 Jan 2007 21:15:58 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id l0JLFwFI088824 for perforce@freebsd.org; Fri, 19 Jan 2007 21:15:58 GMT (envelope-from hselasky@FreeBSD.org) Date: Fri, 19 Jan 2007 21:15:58 GMT Message-Id: <200701192115.l0JLFwFI088824@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 113175 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Jan 2007 21:15:59 -0000 http://perforce.freebsd.org/chv.cgi?CH=113175 Change 113175 by hselasky@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) <<<