Do abort of transfers in a sane way. Fixes PR 8041.
This commit is contained in:
parent
3954583ce7
commit
d2db832909
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: uhci.c,v 1.32 1999/07/12 05:22:50 augustss Exp $ */
|
/* $NetBSD: uhci.c,v 1.33 1999/08/02 19:30:34 augustss Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -147,7 +147,9 @@ usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *,
|
||||||
void uhci_timo __P((void *));
|
void uhci_timo __P((void *));
|
||||||
void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle));
|
void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle));
|
||||||
void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *));
|
void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *));
|
||||||
void uhci_ii_done __P((uhci_intr_info_t *, int));
|
void uhci_ii_done __P((uhci_intr_info_t *));
|
||||||
|
void uhci_ii_finish __P((uhci_intr_info_t *));
|
||||||
|
void uhci_abort_req __P((usbd_request_handle, usbd_status status));
|
||||||
void uhci_timeout __P((void *));
|
void uhci_timeout __P((void *));
|
||||||
void uhci_wakeup_ctrl __P((void *, int, int, void *, int));
|
void uhci_wakeup_ctrl __P((void *, int, int, void *, int));
|
||||||
void uhci_lock_frames __P((uhci_softc_t *));
|
void uhci_lock_frames __P((uhci_softc_t *));
|
||||||
|
@ -813,27 +815,36 @@ uhci_check_intr(sc, ii)
|
||||||
usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
|
usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
|
||||||
upipe = (struct uhci_pipe *)ii->reqh->pipe;
|
upipe = (struct uhci_pipe *)ii->reqh->pipe;
|
||||||
upipe->pipe.endpoint->toggle = upipe->nexttoggle;
|
upipe->pipe.endpoint->toggle = upipe->nexttoggle;
|
||||||
uhci_ii_done(ii, 0);
|
uhci_ii_done(ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uhci_ii_done(ii, timo)
|
uhci_ii_done(ii)
|
||||||
uhci_intr_info_t *ii;
|
uhci_intr_info_t *ii;
|
||||||
int timo;
|
|
||||||
{
|
{
|
||||||
usbd_request_handle reqh = ii->reqh;
|
usbd_request_handle reqh = ii->reqh;
|
||||||
uhci_soft_td_t *std;
|
uhci_soft_td_t *std;
|
||||||
u_int32_t status;
|
u_int32_t status;
|
||||||
int actlen;
|
int actlen;
|
||||||
|
|
||||||
DPRINTFN(10, ("uhci_ii_done: ii=%p ready %d\n", ii, timo));
|
#ifdef USB_DEBUG
|
||||||
|
DPRINTFN(10, ("uhci_ii_done: ii=%p ready\n", ii));
|
||||||
|
if (uhcidebug > 10)
|
||||||
|
uhci_dump_tds(ii->stdstart);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (reqh->status == USBD_CANCELLED ||
|
||||||
|
reqh->status == USBD_TIMEOUT) {
|
||||||
|
DPRINTF(("uhci_ii_done: aborted reqh=%p\n", reqh));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
{
|
{
|
||||||
int s = splhigh();
|
int s = splhigh();
|
||||||
if (ii->isdone) {
|
if (ii->isdone) {
|
||||||
splx(s);
|
splx(s);
|
||||||
printf("uhci_ii_done: is done!\n");
|
printf("uhci_ii_done: ii=%p is done!\n", ii);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ii->isdone = 1;
|
ii->isdone = 1;
|
||||||
|
@ -842,7 +853,6 @@ uhci_ii_done(ii, timo)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The transfer is done, compute actual length and status. */
|
/* The transfer is done, compute actual length and status. */
|
||||||
/* XXX Should stop at first inactive to get toggle right. */
|
|
||||||
/* XXX Is this correct for control xfers? */
|
/* XXX Is this correct for control xfers? */
|
||||||
actlen = 0;
|
actlen = 0;
|
||||||
for (std = ii->stdstart; std; std = std->td->link.std) {
|
for (std = ii->stdstart; std; std = std->td->link.std) {
|
||||||
|
@ -872,14 +882,16 @@ uhci_ii_done(ii, timo)
|
||||||
} else {
|
} else {
|
||||||
reqh->status = USBD_NORMAL_COMPLETION;
|
reqh->status = USBD_NORMAL_COMPLETION;
|
||||||
}
|
}
|
||||||
if (timo) {
|
uhci_ii_finish(ii);
|
||||||
/* We got a timeout. Make sure transaction is not active. */
|
}
|
||||||
reqh->status = USBD_TIMEOUT;
|
|
||||||
for (std = ii->stdstart; std != 0; std = std->td->link.std)
|
void
|
||||||
std->td->td_status &= ~UHCI_TD_ACTIVE;
|
uhci_ii_finish(ii)
|
||||||
/* XXX should we wait 1 ms */
|
uhci_intr_info_t *ii;
|
||||||
}
|
{
|
||||||
DPRINTFN(5, ("uhci_ii_done: calling handler ii=%p\n", ii));
|
usbd_request_handle reqh = ii->reqh;
|
||||||
|
|
||||||
|
DPRINTFN(5, ("uhci_ii_finish: calling handler ii=%p\n", ii));
|
||||||
|
|
||||||
switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
|
switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
|
||||||
case UE_CONTROL:
|
case UE_CONTROL:
|
||||||
|
@ -911,12 +923,9 @@ uhci_timeout(addr)
|
||||||
void *addr;
|
void *addr;
|
||||||
{
|
{
|
||||||
uhci_intr_info_t *ii = addr;
|
uhci_intr_info_t *ii = addr;
|
||||||
int s;
|
|
||||||
|
|
||||||
DPRINTF(("uhci_timeout: ii=%p\n", ii));
|
DPRINTF(("uhci_timeout: ii=%p\n", ii));
|
||||||
s = splusb();
|
uhci_abort_req(ii->reqh, USBD_TIMEOUT);
|
||||||
uhci_ii_done(ii, 1);
|
|
||||||
splx(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -953,7 +962,7 @@ uhci_waitintr(sc, reqh)
|
||||||
ii = LIST_NEXT(ii, list))
|
ii = LIST_NEXT(ii, list))
|
||||||
;
|
;
|
||||||
if (ii)
|
if (ii)
|
||||||
uhci_ii_done(ii, 1);
|
uhci_ii_done(ii);
|
||||||
else
|
else
|
||||||
panic("uhci_waitintr: lost intr_info\n");
|
panic("uhci_waitintr: lost intr_info\n");
|
||||||
}
|
}
|
||||||
|
@ -1153,10 +1162,10 @@ uhci_free_std_chain(sc, std, stdend)
|
||||||
}
|
}
|
||||||
|
|
||||||
usbd_status
|
usbd_status
|
||||||
uhci_alloc_std_chain(upipe, sc, len, rd, spd, dma, sp, ep)
|
uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
|
||||||
struct uhci_pipe *upipe;
|
struct uhci_pipe *upipe;
|
||||||
uhci_softc_t *sc;
|
uhci_softc_t *sc;
|
||||||
int len, rd, spd;
|
int len, rd, shortok;
|
||||||
usb_dma_t *dma;
|
usb_dma_t *dma;
|
||||||
uhci_soft_td_t **sp, **ep;
|
uhci_soft_td_t **sp, **ep;
|
||||||
{
|
{
|
||||||
|
@ -1167,9 +1176,9 @@ uhci_alloc_std_chain(upipe, sc, len, rd, spd, dma, sp, ep)
|
||||||
int addr = upipe->pipe.device->address;
|
int addr = upipe->pipe.device->address;
|
||||||
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
|
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
|
||||||
|
|
||||||
DPRINTFN(15, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
|
DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
|
||||||
"spd=%d\n", addr, UE_GET_ADDR(endpt), len,
|
"shortok=%d\n", addr, UE_GET_ADDR(endpt), len,
|
||||||
upipe->pipe.device->lowspeed, spd));
|
upipe->pipe.device->lowspeed, shortok));
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
*sp = *ep = 0;
|
*sp = *ep = 0;
|
||||||
DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
|
DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
|
||||||
|
@ -1188,10 +1197,10 @@ uhci_alloc_std_chain(upipe, sc, len, rd, spd, dma, sp, ep)
|
||||||
lastp = 0;
|
lastp = 0;
|
||||||
lastlink = UHCI_PTR_T;
|
lastlink = UHCI_PTR_T;
|
||||||
ntd--;
|
ntd--;
|
||||||
status = UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE;
|
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
|
||||||
if (upipe->pipe.device->lowspeed)
|
if (upipe->pipe.device->lowspeed)
|
||||||
status |= UHCI_TD_LS;
|
status |= UHCI_TD_LS;
|
||||||
if (spd)
|
if (shortok)
|
||||||
status |= UHCI_TD_SPD;
|
status |= UHCI_TD_SPD;
|
||||||
for (i = ntd; i >= 0; i--) {
|
for (i = ntd; i >= 0; i--) {
|
||||||
p = uhci_alloc_std(sc);
|
p = uhci_alloc_std(sc);
|
||||||
|
@ -1219,7 +1228,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, spd, dma, sp, ep)
|
||||||
}
|
}
|
||||||
*sp = lastp;
|
*sp = lastp;
|
||||||
/*upipe->pipe.endpoint->toggle = tog;*/
|
/*upipe->pipe.endpoint->toggle = tog;*/
|
||||||
DPRINTFN(10, ("uhci_alloc_std_chain: oldtog=%d newtog=%d\n",
|
DPRINTFN(10, ("uhci_alloc_std_chain: oldtog=%d nexttog=%d\n",
|
||||||
upipe->pipe.endpoint->toggle, upipe->nexttoggle));
|
upipe->pipe.endpoint->toggle, upipe->nexttoggle));
|
||||||
return (USBD_NORMAL_COMPLETION);
|
return (USBD_NORMAL_COMPLETION);
|
||||||
}
|
}
|
||||||
|
@ -1284,7 +1293,7 @@ uhci_device_bulk_start(reqh)
|
||||||
memcpy(KERNADDR(dmap), reqh->buffer, len);
|
memcpy(KERNADDR(dmap), reqh->buffer, len);
|
||||||
|
|
||||||
#ifdef USB_DEBUG
|
#ifdef USB_DEBUG
|
||||||
if (uhcidebug > 10) {
|
if (uhcidebug > 8) {
|
||||||
printf("uhci_device_bulk_transfer: xfer(1)\n");
|
printf("uhci_device_bulk_transfer: xfer(1)\n");
|
||||||
uhci_dump_tds(xfer);
|
uhci_dump_tds(xfer);
|
||||||
}
|
}
|
||||||
|
@ -1336,9 +1345,33 @@ void
|
||||||
uhci_device_bulk_abort(reqh)
|
uhci_device_bulk_abort(reqh)
|
||||||
usbd_request_handle reqh;
|
usbd_request_handle reqh;
|
||||||
{
|
{
|
||||||
/* XXX inactivate */
|
DPRINTF(("uhci_device_bulk_abort:\n"));
|
||||||
usb_delay_ms(reqh->pipe->device->bus, 1);/* make sure it is done */
|
uhci_abort_req(reqh, USBD_CANCELLED);
|
||||||
/* XXX call done */
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uhci_abort_req(reqh, status)
|
||||||
|
usbd_request_handle reqh;
|
||||||
|
usbd_status status;
|
||||||
|
{
|
||||||
|
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
|
||||||
|
uhci_intr_info_t *ii = upipe->iinfo;
|
||||||
|
uhci_soft_td_t *std;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
/* Make interrupt routine ignore it, */
|
||||||
|
reqh->status = USBD_CANCELLED;
|
||||||
|
|
||||||
|
/* make hardware ignore it, */
|
||||||
|
for (std = ii->stdstart; std != 0; std = std->td->link.std)
|
||||||
|
std->td->td_status &= ~UHCI_TD_ACTIVE;
|
||||||
|
/* make sure hardware has completed, */
|
||||||
|
usb_delay_ms(reqh->pipe->device->bus, 1);
|
||||||
|
|
||||||
|
/* and call final part of interrupt handler. */
|
||||||
|
s = splusb();
|
||||||
|
uhci_ii_finish(ii);
|
||||||
|
splx(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a device bulk pipe. */
|
/* Close a device bulk pipe. */
|
||||||
|
@ -1491,9 +1524,8 @@ void
|
||||||
uhci_device_ctrl_abort(reqh)
|
uhci_device_ctrl_abort(reqh)
|
||||||
usbd_request_handle reqh;
|
usbd_request_handle reqh;
|
||||||
{
|
{
|
||||||
/* XXX inactivate */
|
DPRINTF(("uhci_device_ctrl_abort:\n"));
|
||||||
usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
|
uhci_abort_req(reqh, USBD_CANCELLED);
|
||||||
/* XXX call done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a device control pipe. */
|
/* Close a device control pipe. */
|
||||||
|
@ -1729,7 +1761,7 @@ void
|
||||||
uhci_device_isoc_abort(reqh)
|
uhci_device_isoc_abort(reqh)
|
||||||
usbd_request_handle reqh;
|
usbd_request_handle reqh;
|
||||||
{
|
{
|
||||||
/* XXX Can't abort a single request. */
|
/* XXX Can't abort this. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue