summaryrefslogtreecommitdiff
path: root/sys/dev/usb/ohci.c
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-08-15 18:58:59 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-08-15 18:58:59 +0000
commit7e39b3e00cd3ccd0b07addb9ef65831475e736c1 (patch)
tree5c3cee704d4d1180d7b1d7cb48f68519db061291 /sys/dev/usb/ohci.c
parent34bf829dcf646f92caf4b5016e3ccb92dd3b611b (diff)
Sync with NetBSD.
Implement timeouts and abort requests. Compute length of short transfers correctly.
Diffstat (limited to 'sys/dev/usb/ohci.c')
-rw-r--r--sys/dev/usb/ohci.c317
1 files changed, 220 insertions, 97 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index b92435c9176..eead92f1ebc 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.2 1999/08/13 08:55:57 fgsch Exp $ */
+/* $OpenBSD: ohci.c,v 1.3 1999/08/15 18:58:58 fgsch Exp $ */
/* $NetBSD: ohci.c,v 1.33 1999/06/30 06:44:23 augustss Exp $ */
/*
@@ -112,7 +112,8 @@ void ohci_poll __P((struct usbd_bus *));
void ohci_waitintr __P((ohci_softc_t *, usbd_request_handle));
void ohci_rhsc __P((ohci_softc_t *, usbd_request_handle));
void ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t));
-void ohci_ii_done __P((ohci_softc_t *, usbd_request_handle));
+void ohci_idone __P((ohci_softc_t *, usbd_request_handle));
+void ohci_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_ctrl_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_intr_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_bulk_done __P((ohci_softc_t *, usbd_request_handle));
@@ -156,6 +157,10 @@ int ohci_str __P((usb_string_descriptor_t *, int, char *));
void ohci_timeout __P((void *));
void ohci_rhsc_able __P((ohci_softc_t *, int));
+void ohci_close_pipe __P((usbd_pipe_handle pipe,
+ ohci_soft_ed_t *head));
+void ohci_abort_request __P((usbd_request_handle reqh));
+
#ifdef USB_DEBUG
ohci_softc_t *thesc;
void ohci_dumpregs __P((ohci_softc_t *));
@@ -169,7 +174,7 @@ void ohci_dump_ed __P((ohci_soft_ed_t *));
#define OREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r))
#define OREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r))
#elif defined(__FreeBSD__)
-#define OWRITE4(sc, r, x) *(u_int32_t *) ((sc)->sc_iobase + (r)) = x
+#define OWRITE4(sc, r, x) (*(u_int32_t *) ((sc)->sc_iobase + (r)) = (x))
#define OREAD4(sc, r) (*(u_int32_t *) ((sc)->sc_iobase + (r)))
#define OREAD2(sc, r) (*(u_int16_t *) ((sc)->sc_iobase + (r)))
#endif
@@ -394,6 +399,7 @@ ohci_init(sc)
goto bad1;
}
sc->sc_ctrl_head->ed->ed_flags |= LE(OHCI_ED_SKIP);
+
sc->sc_bulk_head = ohci_alloc_sed(sc);
if (!sc->sc_bulk_head) {
r = USBD_NOMEM;
@@ -611,7 +617,7 @@ ohci_intr(p)
ohci_physaddr_t done;
/* In case the interrupt occurs before initialization has completed. */
- if (sc == NULL || sc->sc_hcca == NULL) { /* NWH added sc==0 */
+ if (sc == NULL || sc->sc_hcca == NULL) {
#ifdef DIAGNOSTIC
printf("ohci_intr: sc->sc_hcca == NULL\n");
#endif
@@ -741,31 +747,21 @@ ohci_process_done(sc, done)
DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n",
std, reqh, reqh->hcpriv));
cc = OHCI_TD_GET_CC(LE(std->td->td_flags));
- if (cc == OHCI_CC_NO_ERROR) {
- if (std->td->td_cbp == 0)
- len = std->len;
- else
- len = LE(std->td->td_be) -
- LE(std->td->td_cbp) + 1;
- /*
- * Only do a callback on the last stage of a transfer.
- * Others have hcpriv = 0.
- */
- if ((reqh->pipe->endpoint->edesc->bmAttributes &
- UE_XFERTYPE) == UE_CONTROL) {
- /* For a control transfer the length is in
- * the xfer stage */
- if (reqh->hcpriv == std) {
- reqh->status = USBD_NORMAL_COMPLETION;
- ohci_ii_done(sc, reqh);
- } else
- reqh->actlen = len;
- } else {
- if (reqh->hcpriv == std) {
- reqh->actlen = len;
- reqh->status = USBD_NORMAL_COMPLETION;
- ohci_ii_done(sc, reqh);
- }
+ if (reqh->status == USBD_CANCELLED ||
+ reqh->status == USBD_TIMEOUT) {
+ DPRINTF(("ohci_process_done: cancel/timeout %p\n",
+ reqh));
+ ohci_idone(sc, reqh);
+ } else if (cc == OHCI_CC_NO_ERROR) {
+ len = std->len;
+ if (std->td->td_cbp != 0)
+ len -= LE(std->td->td_be) -
+ LE(std->td->td_cbp) + 1;
+ if (std->flags & OHCI_SET_LEN)
+ reqh->actlen = len;
+ if (std->flags & OHCI_CALL_DONE) {
+ reqh->status = USBD_NORMAL_COMPLETION;
+ ohci_idone(sc, reqh);
}
} else {
ohci_soft_td_t *p, *n;
@@ -792,7 +788,7 @@ ohci_process_done(sc, done)
reqh->status = USBD_STALLED;
else
reqh->status = USBD_IOERROR;
- ohci_ii_done(sc, reqh);
+ ohci_idone(sc, reqh);
}
ohci_hash_rem_td(sc, std);
ohci_free_std(sc, std);
@@ -800,25 +796,38 @@ ohci_process_done(sc, done)
}
void
-ohci_ii_done(sc, reqh)
+ohci_idone(sc, reqh)
+ ohci_softc_t *sc;
+ usbd_request_handle reqh;
+{
+ ohci_done(sc, reqh);
+ if (reqh->pipe->intrreqh != reqh)
+ usb_start_next(reqh->pipe);
+}
+
+void
+ohci_done(sc, reqh)
ohci_softc_t *sc;
usbd_request_handle reqh;
{
+#ifdef DIAGNOSTIC
+ if (!reqh->hcpriv)
+ printf("ohci_done: reqh=%p, no hcpriv\n", reqh);
+#endif
+ reqh->hcpriv = 0;
+
switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
ohci_ctrl_done(sc, reqh);
- usb_start_next(reqh->pipe);
break;
case UE_INTERRUPT:
ohci_intr_done(sc, reqh);
break;
case UE_BULK:
ohci_bulk_done(sc, reqh);
- usb_start_next(reqh->pipe);
break;
case UE_ISOCHRONOUS:
printf("ohci_process_done: ISO done?\n");
- usb_start_next(reqh->pipe);
break;
}
@@ -868,7 +877,7 @@ ohci_intr_done(sc, reqh)
dma = &opipe->u.intr.datadma;
memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
- if (reqh->pipe->repeat) {
+ if (reqh->pipe->intrreqh == reqh) {
xfer = opipe->tail;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
if (!tail) {
@@ -888,7 +897,7 @@ ohci_intr_done(sc, reqh)
xfer->td->td_be = LE(LE(xfer->td->td_cbp) + reqh->length - 1);
xfer->len = reqh->length;
xfer->reqh = reqh;
-
+ xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
reqh->hcpriv = xfer;
ohci_hash_add_td(sc, xfer);
@@ -896,7 +905,6 @@ ohci_intr_done(sc, reqh)
opipe->tail = tail;
} else {
usb_freemem(sc->sc_dmatag, dma);
- usb_start_next(reqh->pipe);
}
}
@@ -913,12 +921,10 @@ ohci_bulk_done(sc, reqh)
DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n",
reqh, reqh->actlen));
- if (len != 0) {
- dma = &opipe->u.bulk.datadma;
- if (opipe->u.bulk.isread)
- memcpy(reqh->buffer, KERNADDR(dma), len);
- usb_freemem(sc->sc_dmatag, dma);
- }
+ dma = &opipe->u.bulk.datadma;
+ if (opipe->u.bulk.isread)
+ memcpy(reqh->buffer, KERNADDR(dma), len);
+ usb_freemem(sc->sc_dmatag, dma);
usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
@@ -957,7 +963,7 @@ ohci_rhsc(sc, reqh)
reqh->status = USBD_NORMAL_COMPLETION;
reqh->xfercb(reqh);
- if (!reqh->pipe->repeat) {
+ if (reqh->pipe->intrreqh != reqh) {
sc->sc_intrreqh = 0;
usb_freemem(sc->sc_dmatag, &opipe->u.intr.datadma);
usb_start_next(reqh->pipe);
@@ -997,7 +1003,7 @@ ohci_waitintr(sc, reqh)
/* Timeout */
DPRINTF(("ohci_waitintr: timeout\n"));
reqh->status = USBD_TIMEOUT;
- ohci_ii_done(sc, reqh);
+ ohci_idone(sc, reqh);
/* XXX should free TD */
}
@@ -1081,10 +1087,14 @@ ohci_device_request(reqh)
xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
+ xfer->flags = OHCI_SET_LEN;
next = xfer;
- } else
+ stat->flags = OHCI_CALL_DONE;
+ } else {
next = stat;
+ stat->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
+ }
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
if (!isread && len != 0)
@@ -1098,6 +1108,8 @@ ohci_device_request(reqh)
setup->td->td_be = LE(LE(setup->td->td_cbp) + sizeof *req - 1);
setup->len = 0; /* XXX The number of byte we count */
setup->reqh = reqh;
+ setup->flags = 0;
+ reqh->hcpriv = setup;
stat->td->td_flags = LE(
(isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
@@ -1109,8 +1121,6 @@ ohci_device_request(reqh)
stat->len = 0;
stat->reqh = reqh;
- reqh->hcpriv = stat;
-
#if USB_DEBUG
if (ohcidebug > 5) {
printf("ohci_device_request:\n");
@@ -1268,7 +1278,7 @@ ohci_dump_td(std)
printf("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx "
"nexttd=0x%08lx be=0x%08lx\n",
std, (u_long)std->physaddr,
- (u_long)LE(std->td->td_flags),
+ (int)LE(std->td->td_flags),
"\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
OHCI_TD_GET_DI(LE(std->td->td_flags)),
OHCI_TD_GET_EC(LE(std->td->td_flags)),
@@ -1287,7 +1297,7 @@ ohci_dump_ed(sed)
OHCI_ED_GET_FA(LE(sed->ed->ed_flags)),
OHCI_ED_GET_EN(LE(sed->ed->ed_flags)),
OHCI_ED_GET_MAXP(LE(sed->ed->ed_flags)),
- (u_long)LE(sed->ed->ed_flags),
+ (int)LE(sed->ed->ed_flags),
"\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
(u_long)LE(sed->ed->ed_tailp),
(u_long)LE(sed->ed->ed_headp), "\20\1HALT\2CARRY",
@@ -1379,6 +1389,113 @@ ohci_open(pipe)
}
/*
+ * Close a reqular pipe.
+ * Assumes that there are no pending transactions.
+ */
+void
+ohci_close_pipe(pipe, head)
+ usbd_pipe_handle pipe;
+ ohci_soft_ed_t *head;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
+ ohci_soft_ed_t *sed = opipe->sed;
+ int s;
+
+ s = splusb();
+#ifdef DIAGNOSTIC
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) !=
+ (sed->ed->ed_headp & LE(OHCI_TAILMASK))) {
+ ohci_physaddr_t td = sed->ed->ed_headp;
+ ohci_soft_td_t *std;
+ for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]);
+ std != 0;
+ std = LIST_NEXT(std, hnext))
+ if (std->physaddr == td)
+ break;
+ printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
+ "tl=0x%x pipe=%p, std=%p\n", sed,
+ (int)LE(sed->ed->ed_headp), (int)LE(sed->ed->ed_tailp),
+ pipe, std);
+ usb_delay_ms(&sc->sc_bus, 2);
+ if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) !=
+ (sed->ed->ed_headp & LE(OHCI_TAILMASK)))
+ printf("ohci_close_pipe: pipe still not empty\n");
+ }
+#endif
+ ohci_rem_ed(sed, head);
+ splx(s);
+ ohci_free_std(sc, opipe->tail);
+ ohci_free_sed(sc, opipe->sed);
+}
+
+/*
+ * Abort a device request.
+ * If this routine is called at splusb() it guarantees that the request
+ * will be removed from the hardware scheduling and that the callback
+ * for it will be called with USBD_CANCELLED status.
+ * It's impossible to guarantee that the requested transfer will not
+ * have happened since the hardware runs concurrently.
+ * If the transaction has already happened we rely on the ordinary
+ * interrupt processing to process it.
+ */
+void
+ohci_abort_request(reqh)
+ usbd_request_handle reqh;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ usbd_device_handle dev = opipe->pipe.device;
+ ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+ ohci_soft_ed_t *sed;
+ ohci_soft_td_t *p, *n;
+ int s;
+
+ DPRINTF(("ohci_abort_request: reqh=%p pipe=%p\n", reqh, opipe));
+ s = splusb();
+
+ reqh->status = USBD_CANCELLED; /* mark as cancelled */
+
+ if (!reqh->hcpriv) {
+ /* Not scheduled */
+ reqh->xfercb(reqh);
+ return;
+ }
+
+ sed = opipe->sed;
+ DPRINTFN(1,("ohci_abort_request: stop ed=%p\n", sed));
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
+ delay(10); /* give HC hardware a little time */
+
+ /* if already processed by hardware let interrupt routine handle it */
+ if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) ==
+ (sed->ed->ed_headp & LE(OHCI_TAILMASK))) {
+ DPRINTF(("ohci_abort_request: request processed\n"));
+ usb_delay_ms(dev->bus, 2);
+ } else {
+ p = reqh->hcpriv;
+#ifdef DIAGNOSTIC
+ if (!p) {
+ printf("ohci_abort_request: hcpriv==0\n");
+ return;
+ }
+#endif
+ ohci_done(sc, reqh);
+ for (; p->reqh == reqh; p = n) {
+ n = p->nexttd;
+ ohci_hash_rem_td(sc, p);
+ ohci_free_std(sc, p);
+ }
+ DPRINTFN(2,("ohci_abort_request: set hd=%x, tl=%x\n",
+ (int)LE(p->physaddr), (int)LE(sed->ed->ed_tailp)));
+ sed->ed->ed_headp = p->physaddr; /* unlink TDs */
+ }
+
+ sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */
+ splx(s);
+}
+
+/*
* Data structures and routines to emulate the root hub.
*/
usb_device_descriptor_t ohci_devd = {
@@ -1784,6 +1901,7 @@ ohci_root_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
DPRINTF(("ohci_root_ctrl_close\n"));
+ /* Nothing to do. */
}
usbd_status
@@ -1840,9 +1958,10 @@ ohci_root_intr_close(pipe)
usbd_pipe_handle pipe;
{
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
- sc->sc_intrreqh = 0;
DPRINTF(("ohci_root_intr_close\n"));
+
+ sc->sc_intrreqh = 0;
}
/************************/
@@ -1890,9 +2009,8 @@ void
ohci_device_ctrl_abort(reqh)
usbd_request_handle reqh;
{
- /* XXX inactivate */
- usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is donw */
- /* XXX call done */
+ DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh));
+ ohci_abort_request(reqh);
}
/* Close a device control pipe. */
@@ -1900,20 +2018,10 @@ void
ohci_device_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
- ohci_soft_ed_t *sed = opipe->sed;
- int s;
- s = splusb();
- sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
- if ((LE(sed->ed->ed_tailp) & OHCI_TAILMASK) != LE(sed->ed->ed_headp))
- usb_delay_ms(&sc->sc_bus, 2);
- ohci_rem_ed(sed, sc->sc_ctrl_head);
- splx(s);
- ohci_free_std(sc, opipe->tail);
- ohci_free_sed(sc, opipe->sed);
- /* XXX free other resources */
+ DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
+ ohci_close_pipe(pipe, sc->sc_ctrl_head);
}
/************************/
@@ -1948,17 +2056,23 @@ ohci_device_bulk_start(reqh)
usbd_status r;
int s, len, isread;
+#ifdef DIAGNOSTIC
if (reqh->isreq) {
/* XXX panic */
- printf("ohci_device_bulk_transfer: a request\n");
+ printf("ohci_device_bulk_start: a request\n");
return (USBD_INVAL);
}
+#endif
len = reqh->length;
dmap = &opipe->u.bulk.datadma;
isread = reqh->pipe->endpoint->edesc->bEndpointAddress & UE_IN;
sed = opipe->sed;
+ DPRINTFN(4,("ohci_device_bulk_start: reqh=%p len=%d isread=%d "
+ "flags=%d endpt=%d\n", reqh, len, isread, reqh->flags,
+ reqh->pipe->endpoint->edesc->bEndpointAddress));
+
opipe->u.bulk.isread = isread;
opipe->u.bulk.length = len;
@@ -1990,23 +2104,46 @@ ohci_device_bulk_start(reqh)
xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
-
+ xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
reqh->hcpriv = xfer;
if (!isread)
memcpy(KERNADDR(dmap), reqh->buffer, len);
+ DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
+ "td_cbp=0x%08x td_be=0x%08x\n",
+ (int)LE(sed->ed->ed_flags), (int)LE(xfer->td->td_flags),
+ (int)LE(xfer->td->td_cbp), (int)LE(xfer->td->td_be)));
+
+#ifdef USB_DEBUG
+ if (ohcidebug > 4) {
+ ohci_dump_ed(sed);
+ ohci_dump_tds(xfer);
+ }
+#endif
+
/* Insert ED in schedule */
s = splusb();
ohci_hash_add_td(sc, xfer);
sed->ed->ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
- sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); /* XXX why */
+ sed->ed->ed_flags &= LE(~OHCI_ED_SKIP);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
if (reqh->timeout && !sc->sc_bus.use_polling) {
usb_timeout(ohci_timeout, reqh,
MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
}
+
+#ifdef USB_DEBUG
+ if (ohcidebug > 5) {
+ delay(5000);
+ printf("ohci_device_intr_transfer: status=%x\n",
+ OREAD4(sc, OHCI_COMMAND_STATUS));
+ ohci_dump_ed(sed);
+ ohci_dump_tds(xfer);
+ }
+#endif
+
splx(s);
return (USBD_IN_PROGRESS);
@@ -2017,37 +2154,25 @@ ohci_device_bulk_start(reqh)
return (r);
}
-/* Abort a device bulk request. */
void
ohci_device_bulk_abort(reqh)
usbd_request_handle reqh;
{
-#if 0
- sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
- if ((LE(sed->ed->ed_tailp) & OHCI_TAILMASK) != LE(sed->ed->ed_headp))
- usb_delay_ms(reqh->pipe->device->bus, 2);
-#endif
- /* XXX inactivate */
- usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
- /* XXX call done */
+ DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh));
+ ohci_abort_request(reqh);
}
-/* Close a device bulk pipe. */
+/*
+ * Close a device bulk pipe.
+ */
void
ohci_device_bulk_close(pipe)
usbd_pipe_handle pipe;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
- usbd_device_handle dev = opipe->pipe.device;
- ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
- int s;
+ ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
- s = splusb();
- ohci_rem_ed(opipe->sed, sc->sc_bulk_head);
- splx(s);
- ohci_free_std(sc, opipe->tail);
- ohci_free_sed(sc, opipe->sed);
- /* XXX free other resources */
+ DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
+ ohci_close_pipe(pipe, sc->sc_bulk_head);
}
/************************/
@@ -2117,7 +2242,7 @@ ohci_device_intr_start(reqh)
xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
-
+ xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
reqh->hcpriv = xfer;
#if USB_DEBUG
@@ -2165,13 +2290,11 @@ void
ohci_device_intr_abort(reqh)
usbd_request_handle reqh;
{
- /* XXX inactivate */
- usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
- if (reqh->pipe->repeat) {
+ if (reqh->pipe->intrreqh == reqh) {
DPRINTF(("ohci_device_intr_abort: remove\n"));
- reqh->pipe->repeat = 0;
- ohci_intr_done((ohci_softc_t *)reqh->pipe->device->bus, reqh);
+ reqh->pipe->intrreqh = 0;
}
+ ohci_abort_request(reqh);
}
/* Close a device interrupt pipe. */
@@ -2191,7 +2314,8 @@ ohci_device_intr_close(pipe)
pipe, nslots, pos));
s = splusb();
sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
- if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) != sed->ed->ed_headp)
+ if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) !=
+ (sed->ed->ed_headp & LE(OHCI_TAILMASK)))
usb_delay_ms(&sc->sc_bus, 2);
for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
@@ -2207,7 +2331,6 @@ ohci_device_intr_close(pipe)
ohci_free_std(sc, opipe->tail);
ohci_free_sed(sc, opipe->sed);
- /* XXX free other resources */
}
usbd_status