version 1.54, 2004/01/17 13:15:05 |
version 1.55, 2004/06/22 05:25:10 |
Line 109 int ehcidebug = 0; |
|
Line 109 int ehcidebug = 0; |
|
|
|
struct ehci_pipe { |
struct ehci_pipe { |
struct usbd_pipe pipe; |
struct usbd_pipe pipe; |
|
int nexttoggle; |
|
|
ehci_soft_qh_t *sqh; |
ehci_soft_qh_t *sqh; |
union { |
union { |
ehci_soft_qtd_t *qtd; |
ehci_soft_qtd_t *qtd; |
Line 748 ehci_idone(struct ehci_xfer *ex) |
|
Line 750 ehci_idone(struct ehci_xfer *ex) |
|
if (sqtd != NULL) { |
if (sqtd != NULL) { |
if (!(xfer->rqflags & URQ_REQUEST)) |
if (!(xfer->rqflags & URQ_REQUEST)) |
printf("ehci_idone: need toggle update\n"); |
printf("ehci_idone: need toggle update\n"); |
#if 0 |
epipe->nexttoggle = EHCI_QTD_GET_TOGGLE(status); |
epipe->nexttoggle = EHCI_TD_GET_DT(le32toh(std->td.td_token)); |
|
#endif |
|
} |
} |
|
|
status &= EHCI_QTD_STATERRS; |
status &= EHCI_QTD_STATERRS; |
Line 1058 ehci_device_clear_toggle(usbd_pipe_handl |
|
Line 1058 ehci_device_clear_toggle(usbd_pipe_handl |
|
if (ehcidebug) |
if (ehcidebug) |
usbd_dump_pipe(pipe); |
usbd_dump_pipe(pipe); |
#endif |
#endif |
epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE); |
epipe->nexttoggle = 0; |
} |
} |
|
|
Static void |
Static void |
Line 1217 ehci_open(usbd_pipe_handle pipe) |
|
Line 1217 ehci_open(usbd_pipe_handle pipe) |
|
if (sc->sc_dying) |
if (sc->sc_dying) |
return (USBD_IOERROR); |
return (USBD_IOERROR); |
|
|
|
epipe->nexttoggle = 0; |
|
|
if (addr == sc->sc_addr) { |
if (addr == sc->sc_addr) { |
switch (ed->bEndpointAddress) { |
switch (ed->bEndpointAddress) { |
case USB_CONTROL_ENDPOINT: |
case USB_CONTROL_ENDPOINT: |
Line 1246 ehci_open(usbd_pipe_handle pipe) |
|
Line 1248 ehci_open(usbd_pipe_handle pipe) |
|
sqh->qh.qh_endp = htole32( |
sqh->qh.qh_endp = htole32( |
EHCI_QH_SET_ADDR(addr) | |
EHCI_QH_SET_ADDR(addr) | |
EHCI_QH_SET_ENDPT(ed->bEndpointAddress) | |
EHCI_QH_SET_ENDPT(ed->bEndpointAddress) | |
EHCI_QH_SET_EPS(speed) | /* XXX */ |
EHCI_QH_SET_EPS(speed) | |
/* XXX EHCI_QH_DTC ? */ |
EHCI_QH_DTC | |
EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) | |
EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) | |
(speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ? |
(speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ? |
EHCI_QH_CTL : 0) | |
EHCI_QH_CTL : 0) | |
Line 2100 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
Line 2102 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
ehci_soft_qtd_t *next, *cur; |
ehci_soft_qtd_t *next, *cur; |
ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys; |
ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys; |
u_int32_t qtdstatus; |
u_int32_t qtdstatus; |
int len, curlen; |
int len, curlen, mps; |
int i; |
int i, tog; |
usb_dma_t *dma = &xfer->dmabuf; |
usb_dma_t *dma = &xfer->dmabuf; |
|
|
DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); |
DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); |
Line 2109 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
Line 2111 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
len = alen; |
len = alen; |
dataphys = DMAADDR(dma, 0); |
dataphys = DMAADDR(dma, 0); |
dataphyslastpage = EHCI_PAGE(dataphys + len - 1); |
dataphyslastpage = EHCI_PAGE(dataphys + len - 1); |
|
#if 0 |
|
printf("status=%08x toggle=%d\n", epipe->sqh->qh.qh_qtd.qtd_status, |
|
epipe->nexttoggle); |
|
#endif |
qtdstatus = htole32( |
qtdstatus = htole32( |
EHCI_QTD_ACTIVE | |
EHCI_QTD_ACTIVE | |
EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | |
EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | |
EHCI_QTD_SET_CERR(3) |
EHCI_QTD_SET_CERR(3) |
/* IOC set below */ |
/* IOC set below */ |
/* BYTES set below */ |
/* BYTES set below */ |
/* XXX Data toggle */ |
|
); |
); |
|
mps = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); |
|
tog = epipe->nexttoggle; |
|
if (tog) |
|
qtdstatus |= EHCI_QTD_TOGGLE; |
|
|
cur = ehci_alloc_sqtd(sc); |
cur = ehci_alloc_sqtd(sc); |
*sp = cur; |
*sp = cur; |
Line 2144 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
Line 2153 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
curlen = len; |
curlen = len; |
} |
} |
#endif |
#endif |
|
|
/* XXX true for EHCI? */ |
|
/* the length must be a multiple of the max size */ |
/* the length must be a multiple of the max size */ |
curlen -= curlen % UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); |
curlen -= curlen % mps; |
DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, " |
DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, " |
"curlen=%d\n", curlen)); |
"curlen=%d\n", curlen)); |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
Line 2192 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
Line 2199 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
cur->len = curlen; |
cur->len = curlen; |
DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n", |
DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n", |
dataphys, dataphys + curlen)); |
dataphys, dataphys + curlen)); |
|
/* adjust the toggle based on the number of packets in this |
|
qtd */ |
|
if (((curlen + mps - 1) / mps) & 1) { |
|
tog ^= 1; |
|
qtdstatus ^= EHCI_QTD_TOGGLE; |
|
} |
if (len == 0) |
if (len == 0) |
break; |
break; |
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); |
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); |
Line 2200 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
Line 2213 ehci_alloc_sqtd_chain(struct ehci_pipe * |
|
} |
} |
cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC); |
cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC); |
*ep = cur; |
*ep = cur; |
|
epipe->nexttoggle = tog; |
|
|
DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n", |
DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n", |
*sp, *ep)); |
*sp, *ep)); |
Line 2515 ehci_device_request(usbd_xfer_handle xfe |
|
Line 2529 ehci_device_request(usbd_xfer_handle xfe |
|
* This needs to go away since it slows down control transfers. |
* This needs to go away since it slows down control transfers. |
* Removing it entails: |
* Removing it entails: |
* - fill the QH only once with addr & wMaxPacketSize |
* - fill the QH only once with addr & wMaxPacketSize |
* - put the correct data toggles in the qtds and set DTC |
|
*/ |
*/ |
/* ehci_sync_hc(sc); */ |
/* ehci_sync_hc(sc); */ |
/* Update device address and length since they may have changed. */ |
/* Update device address and length since they may have changed. */ |
/* XXX This only needs to be done once, but it's too early in open. */ |
/* XXX This only needs to be done once, but it's too early in open. */ |
/* XXXX Should not touch ED here! */ |
/* XXXX Should not touch ED here! */ |
sqh->qh.qh_endp = |
sqh->qh.qh_endp = |
(sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QG_MPLMASK))) | |
(sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QH_MPLMASK))) | |
htole32( |
htole32( |
EHCI_QH_SET_ADDR(addr) | |
EHCI_QH_SET_ADDR(addr) | |
/* EHCI_QH_DTC | */ |
|
EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)) |
EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)) |
); |
); |
/* Clear toggle */ |
|
sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE); |
|
|
|
/* Set up data transaction */ |
/* Set up data transaction */ |
if (len != 0) { |
if (len != 0) { |
ehci_soft_qtd_t *end; |
ehci_soft_qtd_t *end; |
|
|
|
/* Start toggle at 1. */ |
|
epipe->nexttoggle = 1; |
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, |
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, |
&next, &end); |
&next, &end); |
if (err) |
if (err) |
Line 2542 ehci_device_request(usbd_xfer_handle xfe |
|
Line 2554 ehci_device_request(usbd_xfer_handle xfe |
|
end->nextqtd = stat; |
end->nextqtd = stat; |
end->qtd.qtd_next = |
end->qtd.qtd_next = |
end->qtd.qtd_altnext = htole32(stat->physaddr); |
end->qtd.qtd_altnext = htole32(stat->physaddr); |
/* Start toggle at 1. */ |
|
/*next->qtd.td_flags |= htole32(EHCI_QTD_TOGGLE);*/ |
|
} else { |
} else { |
next = stat; |
next = stat; |
} |
} |
|
|
memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req); |
memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req); |
|
|
|
/* Clear toggle */ |
|
sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE); |
setup->qtd.qtd_status = htole32( |
setup->qtd.qtd_status = htole32( |
EHCI_QTD_ACTIVE | |
EHCI_QTD_ACTIVE | |
EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | |
EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | |
Line 2567 ehci_device_request(usbd_xfer_handle xfe |
|
Line 2579 ehci_device_request(usbd_xfer_handle xfe |
|
EHCI_QTD_ACTIVE | |
EHCI_QTD_ACTIVE | |
EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | |
EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | |
EHCI_QTD_SET_CERR(3) | |
EHCI_QTD_SET_CERR(3) | |
|
EHCI_QTD_TOGGLE | |
EHCI_QTD_IOC |
EHCI_QTD_IOC |
); |
); |
stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */ |
stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */ |