--- src/sys/bus/usb/ehci.c 2005/09/04 04:27:57 1.13 +++ src/sys/bus/usb/ehci.c 2005/09/04 04:46:12 1.14 @@ -211,7 +211,7 @@ Static void ehci_device_isoc_done(usbd_ Static void ehci_device_clear_toggle(usbd_pipe_handle pipe); Static void ehci_noop(usbd_pipe_handle pipe); -Static int ehci_str(usb_string_descriptor_t *, int, char *); +Static int ehci_str(usb_string_descriptor_t *, int, const char *); Static void ehci_pcd(ehci_softc_t *, usbd_xfer_handle); Static void ehci_pcd_able(ehci_softc_t *, int); Static void ehci_pcd_enable(void *); @@ -333,7 +333,7 @@ Static struct usbd_pipe_methods ehci_dev usbd_status ehci_init(ehci_softc_t *sc) { - u_int32_t version, sparams, cparams, hcr; + u_int32_t vers, sparams, cparams, hcr; u_int i; usbd_status err; ehci_soft_qh_t *sqh; @@ -345,9 +345,9 @@ ehci_init(ehci_softc_t *sc) sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); - version = EREAD2(sc, EHCI_HCIVERSION); + vers = EREAD2(sc, EHCI_HCIVERSION); printf("%s: EHCI version %x.%x\n", USBDEVNAME(sc->sc_bus.bdev), - version >> 8, version & 0xff); + vers >> 8, vers & 0xff); sparams = EREAD4(sc, EHCI_HCSPARAMS); DPRINTF(("ehci_init: sparams=0x%x\n", sparams)); @@ -1493,7 +1493,7 @@ Static usb_hub_descriptor_t ehci_hubd = }; Static int -ehci_str( usb_string_descriptor_t *p, int l, char *s) +ehci_str( usb_string_descriptor_t *p, int l, const char *s) { int i; @@ -2120,6 +2120,7 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * int i, tog; int offset; usb_dma_t *dma = &xfer->dmabuf; + u_int16_t flags = xfer->flags; DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); @@ -2127,10 +2128,6 @@ ehci_alloc_sqtd_chain(struct ehci_pipe * len = alen; dataphys = DMAADDR(dma, 0); dataphyslastpage = EHCI_PAGE(DMAADDR(dma, len - 1)); -#if 0 -printf("status=%08x toggle=%d\n", epipe->sqh->qh.qh_qtd.qtd_status, - epipe->nexttoggle); -#endif qtdstatus = EHCI_QTD_ACTIVE | EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | EHCI_QTD_SET_CERR(3) @@ -2190,7 +2187,7 @@ printf("status=%08x toggle=%d\n", epipe- "curlen=%d\n", curlen)); #ifdef DIAGNOSTIC if (curlen == 0) - panic("ehci_alloc_std: curlen == 0"); + panic("ehci_alloc_sqtd_chain: curlen == 0"); #endif } DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x " @@ -2199,7 +2196,15 @@ printf("status=%08x toggle=%d\n", epipe- len, curlen)); len -= curlen; - if (len != 0) { + /* + * Allocate another transfer if there's more data left, + * or if force last short transfer flag is set and we're + * allocating a multiple of the max packet size. + */ + if (len != 0 || + ((flags & USBD_FORCE_SHORT_XFER) && + (curlen % mps) == 0 && !rd && curlen != 0) + ) { next = ehci_alloc_sqtd(sc); if (next == NULL) goto nomem; @@ -2209,7 +2214,8 @@ printf("status=%08x toggle=%d\n", epipe- nextphys = EHCI_NULL; } - for (i = 0; i * EHCI_PAGE_SIZE < curlen; i++) { + for (i = 0; i * EHCI_PAGE_SIZE < + curlen + EHCI_PAGE_OFFSET(dataphys); i++) { ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE; if (i != 0) /* use offset only in first buffer */ a = EHCI_PAGE(a); @@ -2236,7 +2242,7 @@ printf("status=%08x toggle=%d\n", epipe- tog ^= 1; qtdstatus ^= EHCI_QTD_TOGGLE_MASK; } - if (len == 0) + if (next == NULL) break; DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); offset += curlen;