summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/TODO4
-rw-r--r--sys/dev/usb/ohci.c439
-rw-r--r--sys/dev/usb/ohcireg.h6
-rw-r--r--sys/dev/usb/ohcivar.h13
-rw-r--r--sys/dev/usb/ugen.c50
-rw-r--r--sys/dev/usb/uhci.c514
-rw-r--r--sys/dev/usb/uhcireg.h16
-rw-r--r--sys/dev/usb/uhcivar.h46
-rw-r--r--sys/dev/usb/uhid.c15
-rw-r--r--sys/dev/usb/uhub.c27
-rw-r--r--sys/dev/usb/usb.h12
-rw-r--r--sys/dev/usb/usb_mem.c16
-rw-r--r--sys/dev/usb/usb_mem.h8
-rw-r--r--sys/dev/usb/usb_subr.c114
-rw-r--r--sys/dev/usb/usbdi.c164
-rw-r--r--sys/dev/usb/usbdi.h13
-rw-r--r--sys/dev/usb/usbdi_util.c11
-rw-r--r--sys/dev/usb/usbdi_util.h4
-rw-r--r--sys/dev/usb/usbdivar.h14
19 files changed, 765 insertions, 721 deletions
diff --git a/sys/dev/usb/TODO b/sys/dev/usb/TODO
index d4b43d3a58e..7c5458c7eb5 100644
--- a/sys/dev/usb/TODO
+++ b/sys/dev/usb/TODO
@@ -24,3 +24,7 @@ memory allocator from an interrupt context.
Move memory allocation and copying to HC independent code.
Use a TD chain in ohci.c to allow transfers > 8K.
+
+Document device driver API.
+
+Document HC driver API.
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 503d1a50e33..7892a19c232 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.4 1999/08/19 08:18:38 fgsch Exp $ */
+/* $OpenBSD: ohci.c,v 1.5 1999/08/27 09:00:28 fgsch Exp $ */
/* $NetBSD: ohci.c,v 1.33 1999/06/30 06:44:23 augustss Exp $ */
/*
@@ -65,8 +65,8 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
-#include <dev/usb/usb_quirks.h>
#include <dev/usb/usb_mem.h>
+#include <dev/usb/usb_quirks.h>
#include <dev/usb/ohcireg.h>
#include <dev/usb/ohcivar.h>
@@ -108,11 +108,6 @@ 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_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));
usbd_status ohci_device_request __P((usbd_request_handle reqh));
void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *));
@@ -130,21 +125,26 @@ usbd_status ohci_root_intr_transfer __P((usbd_request_handle));
usbd_status ohci_root_intr_start __P((usbd_request_handle));
void ohci_root_intr_abort __P((usbd_request_handle));
void ohci_root_intr_close __P((usbd_pipe_handle));
+void ohci_root_intr_done __P((usbd_request_handle));
usbd_status ohci_device_ctrl_transfer __P((usbd_request_handle));
usbd_status ohci_device_ctrl_start __P((usbd_request_handle));
void ohci_device_ctrl_abort __P((usbd_request_handle));
void ohci_device_ctrl_close __P((usbd_pipe_handle));
+void ohci_device_ctrl_done __P((usbd_request_handle));
usbd_status ohci_device_bulk_transfer __P((usbd_request_handle));
usbd_status ohci_device_bulk_start __P((usbd_request_handle));
void ohci_device_bulk_abort __P((usbd_request_handle));
void ohci_device_bulk_close __P((usbd_pipe_handle));
+void ohci_device_bulk_done __P((usbd_request_handle));
usbd_status ohci_device_intr_transfer __P((usbd_request_handle));
usbd_status ohci_device_intr_start __P((usbd_request_handle));
void ohci_device_intr_abort __P((usbd_request_handle));
void ohci_device_intr_close __P((usbd_pipe_handle));
+void ohci_device_intr_done __P((usbd_request_handle));
+
usbd_status ohci_device_setintr __P((ohci_softc_t *sc,
struct ohci_pipe *pipe, int ival));
@@ -155,7 +155,9 @@ 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));
+void ohci_abort_req __P((usbd_request_handle reqh,
+ usbd_status status));
+void ohci_abort_req_end __P((void *));
void ohci_device_clear_toggle __P((usbd_pipe_handle pipe));
void ohci_noop __P((usbd_pipe_handle pipe));
@@ -216,6 +218,7 @@ struct usbd_methods ohci_root_ctrl_methods = {
ohci_root_ctrl_close,
ohci_noop,
0,
+ 0,
};
struct usbd_methods ohci_root_intr_methods = {
@@ -224,6 +227,7 @@ struct usbd_methods ohci_root_intr_methods = {
ohci_root_intr_abort,
ohci_root_intr_close,
ohci_noop,
+ ohci_root_intr_done,
0,
};
@@ -233,6 +237,7 @@ struct usbd_methods ohci_device_ctrl_methods = {
ohci_device_ctrl_abort,
ohci_device_ctrl_close,
ohci_noop,
+ ohci_device_ctrl_done,
0,
};
@@ -242,6 +247,7 @@ struct usbd_methods ohci_device_intr_methods = {
ohci_device_intr_abort,
ohci_device_intr_close,
ohci_device_clear_toggle,
+ ohci_device_intr_done,
0,
};
@@ -251,6 +257,7 @@ struct usbd_methods ohci_device_bulk_methods = {
ohci_device_bulk_abort,
ohci_device_bulk_close,
ohci_device_clear_toggle,
+ ohci_device_bulk_done,
0,
};
@@ -265,30 +272,23 @@ ohci_alloc_sed(sc)
if (!sc->sc_freeeds) {
DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
- sed = malloc(sizeof(ohci_soft_ed_t) * OHCI_ED_CHUNK,
- M_USBHC, M_NOWAIT);
- if (!sed)
- return 0;
- r = usb_allocmem(sc->sc_dmatag, OHCI_ED_SIZE * OHCI_ED_CHUNK,
+ r = usb_allocmem(sc->sc_dmatag, OHCI_SED_SIZE * OHCI_SED_CHUNK,
OHCI_ED_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION) {
- free(sed, M_USBHC);
- return 0;
- }
- for(i = 0; i < OHCI_ED_CHUNK; i++, sed++) {
- offs = i * OHCI_ED_SIZE;
+ if (r != USBD_NORMAL_COMPLETION)
+ return (0);
+ for(i = 0; i < OHCI_SED_CHUNK; i++) {
+ offs = i * OHCI_SED_SIZE;
+ sed = (ohci_soft_ed_t *)((char *)KERNADDR(&dma) +offs);
sed->physaddr = DMAADDR(&dma) + offs;
- sed->ed = (ohci_ed_t *)
- ((char *)KERNADDR(&dma) + offs);
sed->next = sc->sc_freeeds;
sc->sc_freeeds = sed;
}
}
sed = sc->sc_freeeds;
sc->sc_freeeds = sed->next;
- memset(sed->ed, 0, OHCI_ED_SIZE);
+ memset(&sed->ed, 0, sizeof(ohci_ed_t));
sed->next = 0;
- return sed;
+ return (sed);
}
void
@@ -311,28 +311,21 @@ ohci_alloc_std(sc)
if (!sc->sc_freetds) {
DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
- std = malloc(sizeof(ohci_soft_td_t) * OHCI_TD_CHUNK,
- M_USBHC, M_NOWAIT);
- if (!std)
- return 0;
- r = usb_allocmem(sc->sc_dmatag, OHCI_TD_SIZE * OHCI_TD_CHUNK,
+ r = usb_allocmem(sc->sc_dmatag, OHCI_STD_SIZE * OHCI_STD_CHUNK,
OHCI_TD_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION) {
- free(std, M_USBHC);
- return 0;
- }
- for(i = 0; i < OHCI_TD_CHUNK; i++, std++) {
- offs = i * OHCI_TD_SIZE;
+ if (r != USBD_NORMAL_COMPLETION)
+ return (0);
+ for(i = 0; i < OHCI_STD_CHUNK; i++) {
+ offs = i * OHCI_STD_SIZE;
+ std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
std->physaddr = DMAADDR(&dma) + offs;
- std->td = (ohci_td_t *)
- ((char *)KERNADDR(&dma) + offs);
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
}
}
std = sc->sc_freetds;
sc->sc_freetds = std->nexttd;
- memset(std->td, 0, OHCI_TD_SIZE);
+ memset(&std->td, 0, sizeof(ohci_td_t));
std->nexttd = 0;
return (std);
}
@@ -359,7 +352,7 @@ ohci_init(sc)
DPRINTF(("ohci_init: start\n"));
rev = OREAD4(sc, OHCI_REVISION);
#if defined(__OpenBSD__)
- printf(", version %d.%d%s",
+ printf(" version %d.%d%s",
#else
printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev),
#endif
@@ -397,14 +390,14 @@ ohci_init(sc)
r = USBD_NOMEM;
goto bad1;
}
- sc->sc_ctrl_head->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ 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;
goto bad2;
}
- sc->sc_bulk_head->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
/* Allocate all the dummy EDs that make up the interrupt tree. */
for (i = 0; i < OHCI_NO_EDS; i++) {
@@ -417,11 +410,11 @@ ohci_init(sc)
}
/* All ED fields are set to 0. */
sc->sc_eds[i] = sed;
- sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
if (i != 0) {
psed = sc->sc_eds[(i-1) / 2];
sed->next = psed;
- sed->ed->ed_nexted = LE(psed->physaddr);
+ sed->ed.ed_nexted = LE(psed->physaddr);
}
}
/*
@@ -728,7 +721,7 @@ ohci_process_done(sc, done)
DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done));
/* Reverse the done list. */
- for (sdone = 0; done; done = LE(std->td->td_nexttd)) {
+ for (sdone = 0; done; done = LE(std->td.td_nexttd)) {
std = ohci_hash_find_td(sc, done);
std->dnext = sdone;
sdone = std;
@@ -745,30 +738,32 @@ ohci_process_done(sc, done)
reqh = std->reqh;
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));
+ cc = OHCI_TD_GET_CC(LE(std->td.td_flags));
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
if (reqh->status == USBD_CANCELLED ||
reqh->status == USBD_TIMEOUT) {
DPRINTF(("ohci_process_done: cancel/timeout %p\n",
reqh));
- ohci_idone(sc, reqh);
+ /* Handled by abort routine. */
+ continue;
} 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->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);
+ usb_transfer_complete(reqh);
}
} else {
ohci_soft_td_t *p, *n;
struct ohci_pipe *opipe =
(struct ohci_pipe *)reqh->pipe;
DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n",
- OHCI_TD_GET_CC(LE(std->td->td_flags)),
- ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td->td_flags))]));
+ OHCI_TD_GET_CC(LE(std->td.td_flags)),
+ ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))]));
/*
* Endpoint is halted. First unlink all the TDs
* belonging to the failed transfer, and then restart
@@ -780,14 +775,14 @@ ohci_process_done(sc, done)
ohci_free_std(sc, p);
}
/* clear halt */
- opipe->sed->ed->ed_headp = LE(p->physaddr);
+ opipe->sed->ed.ed_headp = LE(p->physaddr);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (cc == OHCI_CC_STALL)
reqh->status = USBD_STALLED;
else
reqh->status = USBD_IOERROR;
- ohci_idone(sc, reqh);
+ usb_transfer_complete(reqh);
}
ohci_hash_rem_td(sc, std);
ohci_free_std(sc, std);
@@ -795,65 +790,22 @@ ohci_process_done(sc, done)
}
void
-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;
-{
- usbd_pipe_handle pipe = reqh->pipe;
-
-#ifdef DIAGNOSTIC
- if (!reqh->hcpriv)
- printf("ohci_done: reqh=%p, no hcpriv\n", reqh);
-#endif
- reqh->hcpriv = 0;
-
- switch (pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- ohci_ctrl_done(sc, reqh);
- break;
- case UE_INTERRUPT:
- ohci_intr_done(sc, reqh);
- break;
- case UE_BULK:
- ohci_bulk_done(sc, reqh);
- break;
- case UE_ISOCHRONOUS:
- printf("ohci_process_done: ISO done?\n");
- break;
- }
-
- /* Remove request from queue. */
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
-
- /* And finally execute callback. */
- reqh->xfercb(reqh);
-}
-
-void
-ohci_ctrl_done(sc, reqh)
- ohci_softc_t *sc;
+ohci_device_ctrl_done(reqh)
usbd_request_handle reqh;
{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
u_int len = opipe->u.ctl.length;
usb_dma_t *dma;
DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh));
+#ifdef DIAGNOSTIC
if (!reqh->isreq) {
panic("ohci_ctrl_done: not a request\n");
- return;
}
+#endif
+ reqh->hcpriv = 0;
if (len != 0) {
dma = &opipe->u.ctl.datadma;
@@ -861,15 +813,14 @@ ohci_ctrl_done(sc, reqh)
memcpy(reqh->buffer, KERNADDR(dma), len);
usb_freemem(sc->sc_dmatag, dma);
}
- usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
void
-ohci_intr_done(sc, reqh)
- ohci_softc_t *sc;
+ohci_device_intr_done(reqh)
usbd_request_handle reqh;
{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
usb_dma_t *dma;
ohci_soft_ed_t *sed = opipe->sed;
ohci_soft_td_t *xfer, *tail;
@@ -878,10 +829,12 @@ ohci_intr_done(sc, reqh)
DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n",
reqh, reqh->actlen));
+ reqh->hcpriv = 0;
+
dma = &opipe->u.intr.datadma;
memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
- if (reqh->pipe->intrreqh == reqh) {
+ if (reqh->pipe->repeat) {
xfer = opipe->tail;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
if (!tail) {
@@ -890,22 +843,22 @@ ohci_intr_done(sc, reqh)
}
tail->reqh = 0;
- xfer->td->td_flags = LE(
+ xfer->td.td_flags = LE(
OHCI_TD_IN | OHCI_TD_NOCC |
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
if (reqh->flags & USBD_SHORT_XFER_OK)
- xfer->td->td_flags |= LE(OHCI_TD_R);
- xfer->td->td_cbp = LE(DMAADDR(dma));
+ xfer->td.td_flags |= LE(OHCI_TD_R);
+ xfer->td.td_cbp = LE(DMAADDR(dma));
xfer->nexttd = tail;
- xfer->td->td_nexttd = LE(tail->physaddr);
- xfer->td->td_be = LE(LE(xfer->td->td_cbp) + reqh->length - 1);
+ xfer->td.td_nexttd = LE(tail->physaddr);
+ 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);
- sed->ed->ed_tailp = LE(tail->physaddr);
+ sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
} else {
usb_freemem(sc->sc_dmatag, dma);
@@ -913,23 +866,23 @@ ohci_intr_done(sc, reqh)
}
void
-ohci_bulk_done(sc, reqh)
- ohci_softc_t *sc;
+ohci_device_bulk_done(reqh)
usbd_request_handle reqh;
{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
u_int len = opipe->u.bulk.length;
usb_dma_t *dma;
-
DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n",
reqh, reqh->actlen));
+ reqh->hcpriv = 0;
+
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);
}
void
@@ -965,13 +918,21 @@ ohci_rhsc(sc, reqh)
DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
reqh->actlen = reqh->length;
reqh->status = USBD_NORMAL_COMPLETION;
- reqh->xfercb(reqh);
- if (reqh->pipe->intrreqh != reqh) {
- sc->sc_intrreqh = 0;
+ usb_transfer_complete(reqh);
+}
+
+void
+ohci_root_intr_done(reqh)
+ usbd_request_handle reqh;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
+
+ reqh->hcpriv = 0;
+
+ if (!reqh->pipe->repeat)
usb_freemem(sc->sc_dmatag, &opipe->u.intr.datadma);
- usb_start_next(reqh->pipe);
- }
}
/*
@@ -1007,7 +968,7 @@ ohci_waitintr(sc, reqh)
/* Timeout */
DPRINTF(("ohci_waitintr: timeout\n"));
reqh->status = USBD_TIMEOUT;
- ohci_idone(sc, reqh);
+ usb_transfer_complete(reqh);
/* XXX should free TD */
}
@@ -1066,8 +1027,8 @@ ohci_device_request(reqh)
/* 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. */
- sed->ed->ed_flags = LE(
- (LE(sed->ed->ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
+ sed->ed.ed_flags = LE(
+ (LE(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
@@ -1081,14 +1042,14 @@ ohci_device_request(reqh)
r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
if (r != USBD_NORMAL_COMPLETION)
goto bad4;
- xfer->td->td_flags = LE(
+ xfer->td.td_flags = LE(
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
(reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
- xfer->td->td_cbp = LE(DMAADDR(dmap));
+ xfer->td.td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = stat;
- xfer->td->td_nexttd = LE(stat->physaddr);
- xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
+ xfer->td.td_nexttd = LE(stat->physaddr);
+ xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
xfer->flags = OHCI_SET_LEN;
@@ -1104,24 +1065,24 @@ ohci_device_request(reqh)
if (!isread && len != 0)
memcpy(KERNADDR(dmap), reqh->buffer, len);
- setup->td->td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
+ setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
- setup->td->td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma));
+ setup->td.td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma));
setup->nexttd = next;
- setup->td->td_nexttd = LE(next->physaddr);
- setup->td->td_be = LE(LE(setup->td->td_cbp) + sizeof *req - 1);
+ setup->td.td_nexttd = LE(next->physaddr);
+ 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(
+ stat->td.td_flags = LE(
(isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
- stat->td->td_cbp = 0;
+ stat->td.td_cbp = 0;
stat->nexttd = tail;
- stat->td->td_nexttd = LE(tail->physaddr);
- stat->td->td_be = 0;
+ stat->td.td_nexttd = LE(tail->physaddr);
+ stat->td.td_be = 0;
stat->len = 0;
stat->reqh = reqh;
@@ -1139,7 +1100,7 @@ ohci_device_request(reqh)
if (len != 0)
ohci_hash_add_td(sc, xfer);
ohci_hash_add_td(sc, stat);
- sed->ed->ed_tailp = LE(tail->physaddr);
+ sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (reqh->timeout && !sc->sc_bus.use_polling) {
@@ -1179,9 +1140,9 @@ ohci_add_ed(sed, head)
ohci_soft_ed_t *head;
{
sed->next = head->next;
- sed->ed->ed_nexted = head->ed->ed_nexted;
+ sed->ed.ed_nexted = head->ed.ed_nexted;
head->next = sed;
- head->ed->ed_nexted = LE(sed->physaddr);
+ head->ed.ed_nexted = LE(sed->physaddr);
}
/*
@@ -1200,7 +1161,7 @@ ohci_rem_ed(sed, head)
if (!p)
panic("ohci_rem_ed: ED not found\n");
p->next = sed->next;
- p->ed->ed_nexted = sed->ed->ed_nexted;
+ p->ed.ed_nexted = sed->ed.ed_nexted;
}
/*
@@ -1254,16 +1215,10 @@ void
ohci_timeout(addr)
void *addr;
{
-#if 0
- usbd_request_handle *reqh = addr;
- int s;
+ usbd_request_handle reqh = addr;
DPRINTF(("ohci_timeout: reqh=%p\n", reqh));
- s = splusb();
- /* XXX need to inactivate TD before calling interrupt routine */
- ohci_XXX_done(reqh);
- splx(s);
-#endif
+ ohci_abort_req(reqh, USBD_TIMEOUT);
}
#ifdef USB_DEBUG
@@ -1282,13 +1237,13 @@ 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,
- (int)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)),
- OHCI_TD_GET_CC(LE(std->td->td_flags)),
- (u_long)LE(std->td->td_cbp),
- (u_long)LE(std->td->td_nexttd), (u_long)LE(std->td->td_be));
+ OHCI_TD_GET_DI(LE(std->td.td_flags)),
+ OHCI_TD_GET_EC(LE(std->td.td_flags)),
+ OHCI_TD_GET_CC(LE(std->td.td_flags)),
+ (u_long)LE(std->td.td_cbp),
+ (u_long)LE(std->td.td_nexttd), (u_long)LE(std->td.td_be));
}
void
@@ -1298,14 +1253,14 @@ ohci_dump_ed(sed)
printf("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
"headp=%b nexted=0x%08lx\n",
sed, (u_long)sed->physaddr,
- 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)),
- (int)LE(sed->ed->ed_flags),
+ 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)),
+ (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",
- (u_long)LE(sed->ed->ed_nexted));
+ (u_long)LE(sed->ed.ed_tailp),
+ (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY",
+ (u_long)LE(sed->ed.ed_nexted));
}
#endif
@@ -1345,7 +1300,7 @@ ohci_open(pipe)
goto bad1;
opipe->sed = sed;
opipe->tail = std;
- sed->ed->ed_flags = LE(
+ sed->ed.ed_flags = LE(
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_EN(ed->bEndpointAddress) |
OHCI_ED_DIR_TD |
@@ -1353,7 +1308,7 @@ ohci_open(pipe)
((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ?
OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) |
OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
- sed->ed->ed_headp = sed->ed->ed_tailp = LE(std->physaddr);
+ sed->ed.ed_headp = sed->ed.ed_tailp = LE(std->physaddr);
switch (ed->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
@@ -1408,10 +1363,10 @@ ohci_close_pipe(pipe, head)
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;
+ 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;
@@ -1420,11 +1375,11 @@ ohci_close_pipe(pipe, head)
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),
+ (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)))
+ 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
@@ -1445,57 +1400,65 @@ ohci_close_pipe(pipe, head)
* interrupt processing to process it.
*/
void
-ohci_abort_request(reqh)
+ohci_abort_req(reqh, status)
usbd_request_handle reqh;
+ usbd_status status;
{
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();
+ DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe));
- reqh->status = USBD_CANCELLED; /* mark as cancelled */
+ reqh->status = status;
- if (!reqh->hcpriv) {
- /* Not scheduled */
- reqh->xfercb(reqh);
- return;
- }
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
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);
+ DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed));
+ sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
+
+ if (curproc) {
+ usb_delay_ms(opipe->pipe.device->bus, 1);
+ ohci_abort_req_end(reqh);
} else {
- p = reqh->hcpriv;
+ timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+ }
+}
+
+void
+ohci_abort_req_end(v)
+ void *v;
+{
+ usbd_request_handle reqh = v;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
+ ohci_soft_ed_t *sed;
+ ohci_soft_td_t *p, *n;
+ int s;
+
+ s = splusb();
+
+ p = reqh->hcpriv;
#ifdef DIAGNOSTIC
- if (!p) {
- printf("ohci_abort_request: hcpriv==0\n");
- return;
- }
+ if (!p) {
+ printf("ohci_abort_req: 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 */
+ for (; p->reqh == reqh; p = n) {
+ n = p->nexttd;
+ ohci_hash_rem_td(sc, p);
+ ohci_free_std(sc, p);
}
- sed->ed->ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */
+ sed = opipe->sed;
+ DPRINTFN(2,("ohci_abort_req: 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 */
+
+ usb_transfer_complete(reqh);
+
splx(s);
}
@@ -1885,10 +1848,8 @@ ohci_root_ctrl_start(reqh)
reqh->actlen = totlen;
r = USBD_NORMAL_COMPLETION;
ret:
- SIMPLEQ_REMOVE_HEAD(&reqh->pipe->queue, reqh, next);
reqh->status = r;
- reqh->xfercb(reqh);
- usb_start_next(reqh->pipe);
+ usb_transfer_complete(reqh);
return (USBD_IN_PROGRESS);
}
@@ -2015,7 +1976,7 @@ ohci_device_ctrl_abort(reqh)
usbd_request_handle reqh;
{
DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh));
- ohci_abort_request(reqh);
+ ohci_abort_req(reqh, USBD_CANCELLED);
}
/* Close a device control pipe. */
@@ -2037,7 +1998,7 @@ ohci_device_clear_toggle(pipe)
{
struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
- opipe->sed->ed->ed_tailp &= LE(~OHCI_TOGGLECARRY);
+ opipe->sed->ed.ed_tailp &= LE(~OHCI_TOGGLECARRY);
}
void
@@ -2108,20 +2069,20 @@ ohci_device_bulk_start(reqh)
tail->reqh = 0;
/* Update device address */
- sed->ed->ed_flags = LE(
- (LE(sed->ed->ed_flags) & ~OHCI_ED_ADDRMASK) |
+ sed->ed.ed_flags = LE(
+ (LE(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |
OHCI_ED_SET_FA(addr));
/* Set up data transaction */
xfer = opipe->tail;
- xfer->td->td_flags = LE(
+ xfer->td.td_flags = LE(
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY |
(reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
- xfer->td->td_cbp = LE(DMAADDR(dmap));
+ xfer->td.td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = tail;
- xfer->td->td_nexttd = LE(tail->physaddr);
- xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
+ xfer->td.td_nexttd = LE(tail->physaddr);
+ 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;
@@ -2132,8 +2093,8 @@ ohci_device_bulk_start(reqh)
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)));
+ (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) {
@@ -2145,9 +2106,9 @@ ohci_device_bulk_start(reqh)
/* Insert ED in schedule */
s = splusb();
ohci_hash_add_td(sc, xfer);
- sed->ed->ed_tailp = LE(tail->physaddr);
+ sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
- sed->ed->ed_flags &= LE(~OHCI_ED_SKIP);
+ 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,
@@ -2179,7 +2140,7 @@ ohci_device_bulk_abort(reqh)
usbd_request_handle reqh;
{
DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh));
- ohci_abort_request(reqh);
+ ohci_abort_req(reqh, USBD_CANCELLED);
}
/*
@@ -2251,15 +2212,15 @@ ohci_device_intr_start(reqh)
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
- xfer->td->td_flags = LE(
+ xfer->td.td_flags = LE(
OHCI_TD_IN | OHCI_TD_NOCC |
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
if (reqh->flags & USBD_SHORT_XFER_OK)
- xfer->td->td_flags |= LE(OHCI_TD_R);
- xfer->td->td_cbp = LE(DMAADDR(dmap));
+ xfer->td.td_flags |= LE(OHCI_TD_R);
+ xfer->td.td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = tail;
- xfer->td->td_nexttd = LE(tail->physaddr);
- xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
+ xfer->td.td_nexttd = LE(tail->physaddr);
+ 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;
@@ -2276,15 +2237,9 @@ ohci_device_intr_start(reqh)
/* Insert ED in schedule */
s = splusb();
ohci_hash_add_td(sc, xfer);
- sed->ed->ed_tailp = LE(tail->physaddr);
+ sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
-#if 0
- if (reqh->timeout && !sc->sc_bus.use_polling) {
- usb_timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
- }
-#endif
- sed->ed->ed_flags &= LE(~OHCI_ED_SKIP);
+ sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
#ifdef USB_DEBUG
if (ohcidebug > 5) {
@@ -2314,7 +2269,7 @@ ohci_device_intr_abort(reqh)
DPRINTF(("ohci_device_intr_abort: remove\n"));
reqh->pipe->intrreqh = 0;
}
- ohci_abort_request(reqh);
+ ohci_abort_req(reqh, USBD_CANCELLED);
}
/* Close a device interrupt pipe. */
@@ -2333,9 +2288,9 @@ ohci_device_intr_close(pipe)
DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
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 & LE(OHCI_TAILMASK)))
+ sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
+ 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)
@@ -2343,7 +2298,7 @@ ohci_device_intr_close(pipe)
if (!p)
panic("ohci_device_intr_close: ED not found\n");
p->next = sed->next;
- p->ed->ed_nexted = sed->ed->ed_nexted;
+ p->ed.ed_nexted = sed->ed.ed_nexted;
splx(s);
for (j = 0; j < nslots; j++)
@@ -2404,9 +2359,9 @@ ohci_device_setintr(sc, opipe, ival)
s = splusb();
hsed = sc->sc_eds[best];
sed->next = hsed->next;
- sed->ed->ed_nexted = hsed->ed->ed_nexted;
+ sed->ed.ed_nexted = hsed->ed.ed_nexted;
hsed->next = sed;
- hsed->ed->ed_nexted = LE(sed->physaddr);
+ hsed->ed.ed_nexted = LE(sed->physaddr);
splx(s);
for (j = 0; j < nslots; j++)
diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h
index 877a0db6bd0..d054fd5a56a 100644
--- a/sys/dev/usb/ohcireg.h
+++ b/sys/dev/usb/ohcireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohcireg.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */
+/* $OpenBSD: ohcireg.h,v 1.2 1999/08/27 09:00:28 fgsch Exp $ */
/* $NetBSD: ohcireg.h,v 1.7 1998/12/10 23:16:47 augustss Exp $ */
/*
@@ -165,7 +165,7 @@ typedef struct {
ohci_physaddr_t ed_headp;
ohci_physaddr_t ed_nexted;
} ohci_ed_t;
-#define OHCI_ED_SIZE 16
+/* #define OHCI_ED_SIZE 16 */
#define OHCI_ED_ALIGN 16
typedef struct {
@@ -188,7 +188,7 @@ typedef struct {
ohci_physaddr_t td_nexttd; /* Next TD */
ohci_physaddr_t td_be; /* Buffer End */
} ohci_td_t;
-#define OHCI_TD_SIZE 16
+/* #define OHCI_TD_SIZE 16 */
#define OHCI_TD_ALIGN 16
#define OHCI_CC_NO_ERROR 0
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index 601619a4199..ffa75a6b072 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohcivar.h,v 1.3 1999/08/19 08:18:38 fgsch Exp $ */
+/* $OpenBSD: ohcivar.h,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */
/* $NetBSD: ohcivar.h,v 1.6 1999/08/14 14:49:31 augustss Exp $ */
/*
@@ -39,26 +39,27 @@
*/
typedef struct ohci_soft_ed {
- ohci_ed_t *ed;
+ ohci_ed_t ed;
struct ohci_soft_ed *next;
ohci_physaddr_t physaddr;
} ohci_soft_ed_t;
-#define OHCI_ED_CHUNK 256
+#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) / OHCI_ED_ALIGN * OHCI_ED_ALIGN)
+#define OHCI_SED_CHUNK 128
typedef struct ohci_soft_td {
- ohci_td_t *td;
+ ohci_td_t td;
struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */
struct ohci_soft_td *dnext; /* next in done list */
ohci_physaddr_t physaddr;
LIST_ENTRY(ohci_soft_td) hnext;
- /*ohci_soft_ed_t *sed;*/
usbd_request_handle reqh;
u_int16_t len;
u_int16_t flags;
#define OHCI_CALL_DONE 0x0001
#define OHCI_SET_LEN 0x0002
} ohci_soft_td_t;
-#define OHCI_TD_CHUNK 256
+#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
+#define OHCI_STD_CHUNK 128
#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 968078fc9bb..62e9d262951 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ugen.c,v 1.2 1999/08/16 22:08:48 fgsch Exp $ */
-/* $NetBSD: ugen.c,v 1.13 1999/08/02 19:32:56 augustss Exp $ */
+/* $OpenBSD: ugen.c,v 1.3 1999/08/27 09:00:28 fgsch Exp $ */
+/* $NetBSD: ugen.c,v 1.18 1999/08/23 22:55:14 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -86,6 +86,7 @@ struct ugen_endpoint {
struct clist q;
struct selinfo rsel;
void *ibuf;
+ u_int32_t timeout;
};
#define UGEN_CHUNK 128 /* chunk size for read */
@@ -287,6 +288,7 @@ ugenopen(dev, flag, mode, p)
continue;
sce = &sc->sc_endpoints[endpt][dir];
sce->state = 0;
+ sce->timeout = USBD_NO_TIMEOUT;
DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
sc, endpt, dir, sce));
edesc = sce->edesc;
@@ -469,10 +471,12 @@ ugen_do_read(sc, endpt, uio, flag)
reqh, sce->pipeh,
sce->state & UGEN_SHORT_OK ?
USBD_SHORT_XFER_OK : 0,
- buf, &tn, "ugenrb");
+ sce->timeout, buf, &tn, "ugenrb");
if (r != USBD_NORMAL_COMPLETION) {
if (r == USBD_INTERRUPTED)
error = EINTR;
+ else if (r == USBD_TIMEOUT)
+ error = ETIMEDOUT;
else
error = EIO;
break;
@@ -515,7 +519,7 @@ ugen_do_write(sc, endpt, uio, flag)
int flag;
{
struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
- size_t n;
+ u_int32_t n;
int error = 0;
char buf[UGEN_BBSIZE];
usbd_request_handle reqh;
@@ -546,8 +550,8 @@ ugen_do_write(sc, endpt, uio, flag)
if (error)
break;
DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
- r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
- &n, "ugenwb");
+ r = usbd_bulk_transfer(reqh, sce->pipeh, 0,
+ sce->timeout, buf, &n,"ugenwb");
if (r != USBD_NORMAL_COMPLETION) {
if (r == USBD_INTERRUPTED)
error = EINTR;
@@ -586,6 +590,17 @@ ugen_activate(self, act)
struct device *self;
enum devact act;
{
+ struct ugen_softc *sc = (struct ugen_softc *)self;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
return (0);
}
@@ -642,10 +657,7 @@ ugenintr(reqh, addr, status)
{
struct ugen_endpoint *sce = addr;
/*struct ugen_softc *sc = sce->sc;*/
- usbd_private_handle priv;
- void *buffer;
u_int32_t count;
- usbd_status xstatus;
u_char *ibuf;
if (status == USBD_CANCELLED)
@@ -657,11 +669,11 @@ ugenintr(reqh, addr, status)
return;
}
- (void)usbd_get_request_status(reqh, &priv, &buffer, &count, &xstatus);
+ usbd_get_request_status(reqh, 0, 0, &count, 0);
ibuf = sce->ibuf;
DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n",
- reqh, xstatus, count));
+ reqh, status, count));
DPRINTFN(5, (" data = %02x %02x %02x\n",
ibuf[0], ibuf[1], ibuf[2]));
@@ -816,7 +828,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
sce = &sc->sc_endpoints[endpt][IN];
#ifdef DIAGNOSTIC
if (!sce->pipeh) {
- printf("ugenioctl: no pipe\n");
+ printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
return (EIO);
}
#endif
@@ -825,6 +837,16 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
else
sce->state &= ~UGEN_SHORT_OK;
return (0);
+ case USB_SET_TIMEOUT:
+ sce = &sc->sc_endpoints[endpt][IN];
+#ifdef DIAGNOSTIC
+ if (!sce->pipeh) {
+ printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n");
+ return (EIO);
+ }
+#endif
+ sce->timeout = *(int *)addr;
+ return (0);
default:
break;
}
@@ -956,11 +978,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
uio.uio_segflg = UIO_USERSPACE;
uio.uio_rw = UIO_READ;
uio.uio_procp = p;
-#if defined(__OpenBSD__)
error = uiomove((caddr_t)cdesc, len, &uio);
-#else
- error = uiomove(cdesc, len, &uio);
-#endif
free(cdesc, M_TEMP);
return (error);
}
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 9296c686491..6f523d43cfd 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhci.c,v 1.3 1999/08/19 08:18:38 fgsch Exp $ */
-/* $NetBSD: uhci.c,v 1.34 1999/08/02 23:35:55 augustss Exp $ */
+/* $OpenBSD: uhci.c,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */
+/* $NetBSD: uhci.c,v 1.43 1999/08/22 23:41:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -66,6 +66,7 @@
#include <machine/bus_pio.h>
#endif
#include <machine/bus.h>
+#include <machine/endian.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -90,6 +91,16 @@ struct cfdriver uhci_cd = {
};
#endif
+/*
+ * The UHCI controller is little endian, so on big endian machines
+ * the data strored in memory needs to be swapped.
+ */
+#if BYTE_ORDER == BIG_ENDIAN
+#define LE(x) (bswap32(x))
+#else
+#define LE(x) (x)
+#endif
+
struct uhci_pipe {
struct usbd_pipe pipe;
uhci_intr_info_t *iinfo;
@@ -158,8 +169,8 @@ void uhci_timo __P((void *));
void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle));
void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *));
void uhci_idone __P((uhci_intr_info_t *));
-void uhci_done __P((uhci_intr_info_t *));
void uhci_abort_req __P((usbd_request_handle, usbd_status status));
+void uhci_abort_req_end __P((void *v));
void uhci_timeout __P((void *));
void uhci_wakeup_ctrl __P((void *, int, int, void *, int));
void uhci_lock_frames __P((uhci_softc_t *));
@@ -176,42 +187,47 @@ usbd_status uhci_device_ctrl_transfer __P((usbd_request_handle));
usbd_status uhci_device_ctrl_start __P((usbd_request_handle));
void uhci_device_ctrl_abort __P((usbd_request_handle));
void uhci_device_ctrl_close __P((usbd_pipe_handle));
+void uhci_device_ctrl_done __P((usbd_request_handle));
+
usbd_status uhci_device_intr_transfer __P((usbd_request_handle));
usbd_status uhci_device_intr_start __P((usbd_request_handle));
void uhci_device_intr_abort __P((usbd_request_handle));
void uhci_device_intr_close __P((usbd_pipe_handle));
+void uhci_device_intr_done __P((usbd_request_handle));
+
usbd_status uhci_device_bulk_transfer __P((usbd_request_handle));
usbd_status uhci_device_bulk_start __P((usbd_request_handle));
void uhci_device_bulk_abort __P((usbd_request_handle));
void uhci_device_bulk_close __P((usbd_pipe_handle));
+void uhci_device_bulk_done __P((usbd_request_handle));
+
usbd_status uhci_device_isoc_transfer __P((usbd_request_handle));
usbd_status uhci_device_isoc_start __P((usbd_request_handle));
void uhci_device_isoc_abort __P((usbd_request_handle));
void uhci_device_isoc_close __P((usbd_pipe_handle));
+void uhci_device_isoc_done __P((usbd_request_handle));
usbd_status uhci_device_isoc_setbuf __P((usbd_pipe_handle, u_int, u_int));
usbd_status uhci_root_ctrl_transfer __P((usbd_request_handle));
usbd_status uhci_root_ctrl_start __P((usbd_request_handle));
void uhci_root_ctrl_abort __P((usbd_request_handle));
void uhci_root_ctrl_close __P((usbd_pipe_handle));
+
usbd_status uhci_root_intr_transfer __P((usbd_request_handle));
usbd_status uhci_root_intr_start __P((usbd_request_handle));
void uhci_root_intr_abort __P((usbd_request_handle));
void uhci_root_intr_close __P((usbd_pipe_handle));
+void uhci_root_intr_done __P((usbd_request_handle));
usbd_status uhci_open __P((usbd_pipe_handle));
void uhci_poll __P((struct usbd_bus *));
usbd_status uhci_device_request __P((usbd_request_handle reqh));
-void uhci_ctrl_done __P((uhci_intr_info_t *ii));
-void uhci_bulk_done __P((uhci_intr_info_t *ii));
void uhci_add_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *));
void uhci_remove_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *));
usbd_status uhci_device_setintr __P((uhci_softc_t *sc,
struct uhci_pipe *pipe, int ival));
-void uhci_intr_done __P((uhci_intr_info_t *ii));
-void uhci_isoc_done __P((uhci_intr_info_t *ii));
void uhci_device_clear_toggle __P((usbd_pipe_handle pipe));
void uhci_noop __P((usbd_pipe_handle pipe));
@@ -246,6 +262,7 @@ struct usbd_methods uhci_root_ctrl_methods = {
uhci_root_ctrl_close,
uhci_noop,
0,
+ 0,
};
struct usbd_methods uhci_root_intr_methods = {
@@ -254,6 +271,7 @@ struct usbd_methods uhci_root_intr_methods = {
uhci_root_intr_abort,
uhci_root_intr_close,
uhci_noop,
+ uhci_root_intr_done,
0,
};
@@ -263,6 +281,7 @@ struct usbd_methods uhci_device_ctrl_methods = {
uhci_device_ctrl_abort,
uhci_device_ctrl_close,
uhci_noop,
+ uhci_device_ctrl_done,
0,
};
@@ -272,6 +291,7 @@ struct usbd_methods uhci_device_intr_methods = {
uhci_device_intr_abort,
uhci_device_intr_close,
uhci_device_clear_toggle,
+ uhci_device_intr_done,
0,
};
@@ -281,6 +301,7 @@ struct usbd_methods uhci_device_bulk_methods = {
uhci_device_bulk_abort,
uhci_device_bulk_close,
uhci_device_clear_toggle,
+ uhci_device_bulk_done,
0,
};
@@ -290,6 +311,7 @@ struct usbd_methods uhci_device_isoc_methods = {
uhci_device_isoc_abort,
uhci_device_isoc_close,
uhci_noop,
+ uhci_device_isoc_done,
uhci_device_isoc_setbuf,
};
@@ -331,23 +353,23 @@ uhci_init(sc)
return (r);
sc->sc_pframes = KERNADDR(&sc->sc_dma);
UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */
- UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list */
+ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/
/* Allocate the dummy QH where bulk traffic will be queued. */
bsqh = uhci_alloc_sqh(sc);
if (!bsqh)
return (USBD_NOMEM);
- bsqh->qh->qh_hlink = UHCI_PTR_T; /* end of QH chain */
- bsqh->qh->qh_elink = UHCI_PTR_T;
+ bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */
+ bsqh->qh.qh_elink = LE(UHCI_PTR_T);
sc->sc_bulk_start = sc->sc_bulk_end = bsqh;
/* Allocate the dummy QH where control traffic will be queued. */
csqh = uhci_alloc_sqh(sc);
if (!csqh)
return (USBD_NOMEM);
- csqh->qh->hlink = bsqh;
- csqh->qh->qh_hlink = bsqh->physaddr | UHCI_PTR_Q;
- csqh->qh->qh_elink = UHCI_PTR_T;
+ csqh->hlink = bsqh;
+ csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q);
+ csqh->qh.qh_elink = LE(UHCI_PTR_T);
sc->sc_ctl_start = sc->sc_ctl_end = csqh;
/*
@@ -360,15 +382,15 @@ uhci_init(sc)
sqh = uhci_alloc_sqh(sc);
if (!std || !sqh)
return (USBD_NOMEM);
- std->td->link.sqh = sqh;
- std->td->td_link = sqh->physaddr | UHCI_PTR_Q;
- std->td->td_status = UHCI_TD_IOS; /* iso, inactive */
- std->td->td_token = 0;
- std->td->td_buffer = 0;
- sqh->qh->hlink = csqh;
- sqh->qh->qh_hlink = csqh->physaddr | UHCI_PTR_Q;
- sqh->qh->elink = 0;
- sqh->qh->qh_elink = UHCI_PTR_T;
+ std->link.sqh = sqh;
+ std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q);
+ std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
+ std->td.td_token = LE(0);
+ std->td.td_buffer = LE(0);
+ sqh->hlink = csqh;
+ sqh->qh.qh_hlink = LE(csqh->physaddr | UHCI_PTR_Q);
+ sqh->elink = 0;
+ sqh->qh.qh_elink = LE(UHCI_PTR_T);
sc->sc_vframes[i].htd = std;
sc->sc_vframes[i].etd = std;
sc->sc_vframes[i].hqh = sqh;
@@ -376,7 +398,7 @@ uhci_init(sc)
for (j = i;
j < UHCI_FRAMELIST_COUNT;
j += UHCI_VFRAMELIST_COUNT)
- sc->sc_pframes[j] = std->physaddr;
+ sc->sc_pframes[j] = LE(std->physaddr);
}
LIST_INIT(&sc->sc_intrhead);
@@ -402,9 +424,9 @@ uhci_init(sc)
/*
* Handle suspend/resume.
*
- * Must use delay() here since we are called from an interrupt
- * context, but since we are close to being inactive anyway
- * it doesn't matter.
+ * We need to switch to polling mode here, because this routine is
+ * called from an intterupt context. This is all right since we
+ * are almost suspended anyway.
*/
void
uhci_power(why, v)
@@ -429,9 +451,10 @@ uhci_power(why, v)
if (sc->sc_has_timo)
usb_untimeout(uhci_timo, sc->sc_has_timo,
sc->sc_has_timo->timo_handle);
+ sc->sc_bus.use_polling = 1;
uhci_run(sc, 0); /* stop the controller */
UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
- delay(USB_RESUME_WAIT * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
sc->sc_suspend = why;
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
} else {
@@ -444,12 +467,13 @@ uhci_power(why, v)
if (cmd & UHCI_CMD_RS)
uhci_run(sc, 0); /* in case BIOS has started it */
UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
- delay(USB_RESUME_DELAY * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */
uhci_run(sc, 1); /* and start traffic again */
- delay(USB_RESUME_RECOVERY * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
+ sc->sc_bus.use_polling = 0;
if (sc->sc_has_timo)
usb_timeout(uhci_timo, sc->sc_has_timo,
sc->sc_ival, sc->sc_has_timo->timo_handle);
@@ -489,25 +513,25 @@ uhci_dump_td(p)
printf("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
"token=0x%08lx buffer=0x%08lx\n",
p, (long)p->physaddr,
- (long)p->td->td_link,
- (long)p->td->td_status,
- (long)p->td->td_token,
- (long)p->td->td_buffer);
+ (long)LE(p->td.td_link),
+ (long)LE(p->td.td_status),
+ (long)LE(p->td.td_token),
+ (long)LE(p->td.td_buffer));
if (uhci_longtd)
printf(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,"
"D=%d,maxlen=%d\n",
- (int)p->td->td_link,
+ (int)LE(p->td.td_link),
"\20\1T\2Q\3VF",
- (int)p->td->td_status,
+ (int)LE(p->td.td_status),
"\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
"STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
- UHCI_TD_GET_ERRCNT(p->td->td_status),
- UHCI_TD_GET_ACTLEN(p->td->td_status),
- UHCI_TD_GET_PID(p->td->td_token),
- UHCI_TD_GET_DEVADDR(p->td->td_token),
- UHCI_TD_GET_ENDPT(p->td->td_token),
- UHCI_TD_GET_DT(p->td->td_token),
- UHCI_TD_GET_MAXLEN(p->td->td_token));
+ UHCI_TD_GET_ERRCNT(LE(p->td.td_status)),
+ UHCI_TD_GET_ACTLEN(LE(p->td.td_status)),
+ UHCI_TD_GET_PID(LE(p->td.td_token)),
+ UHCI_TD_GET_DEVADDR(LE(p->td.td_token)),
+ UHCI_TD_GET_ENDPT(LE(p->td.td_token)),
+ UHCI_TD_GET_DT(LE(p->td.td_token)),
+ UHCI_TD_GET_MAXLEN(LE(p->td.td_token)));
}
void
@@ -515,7 +539,7 @@ uhci_dump_qh(p)
uhci_soft_qh_t *p;
{
printf("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, (int)p->physaddr,
- p->qh->qh_hlink, p->qh->qh_elink);
+ LE(p->qh.qh_hlink), LE(p->qh.qh_elink));
}
@@ -528,7 +552,7 @@ uhci_dump()
uhci_dumpregs(sc);
printf("intrs=%d\n", sc->sc_intrs);
printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link);
- uhci_dump_qh(sc->sc_ctl_start->qh->hlink);
+ uhci_dump_qh(sc->sc_ctl_start->qh.hlink);
}
#endif
@@ -538,7 +562,7 @@ uhci_dump_tds(std)
{
uhci_soft_td_t *p;
- for(p = std; p; p = p->td->link.std)
+ for(p = std; p; p = p->link.std)
uhci_dump_td(p);
}
#endif
@@ -560,27 +584,36 @@ uhci_timo(addr)
DPRINTFN(15, ("uhci_timo\n"));
+ usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
+
p = KERNADDR(&upipe->u.intr.datadma);
p[0] = 0;
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<1;
if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<2;
+ if (p[0] == 0)
+ /* No change, try again in a while */
+ return;
+
+ reqh->actlen = 1;
+ reqh->status = USBD_NORMAL_COMPLETION;
s = splusb();
+ reqh->hcpriv = 0;
+ usb_transfer_complete(reqh);
+ splx(s);
+}
+
+void
+uhci_root_intr_done(reqh)
+ usbd_request_handle reqh;
+{
+ usbd_pipe_handle pipe = reqh->pipe;
+ uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
+
if (!reqh->pipe->repeat)
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
- if (p[0] != 0) {
- reqh->actlen = 1;
- reqh->status = USBD_NORMAL_COMPLETION;
- reqh->xfercb(reqh);
- }
- if (reqh->pipe->repeat) {
- usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
- } else {
usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma);
- usb_start_next(reqh->pipe);
- }
- splx(s);
}
@@ -641,14 +674,14 @@ uhci_add_ctrl(sc, sqh)
uhci_softc_t *sc;
uhci_soft_qh_t *sqh;
{
- uhci_qh_t *eqh;
+ uhci_soft_qh_t *eqh;
DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh));
- eqh = sc->sc_ctl_end->qh;
- sqh->qh->hlink = eqh->hlink;
- sqh->qh->qh_hlink = eqh->qh_hlink;
- eqh->hlink = sqh;
- eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q;
+ eqh = sc->sc_ctl_end;
+ sqh->hlink = eqh->hlink;
+ sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ eqh->hlink = sqh;
+ eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
sc->sc_ctl_end = sqh;
}
@@ -661,17 +694,17 @@ uhci_remove_ctrl(sc, sqh)
uhci_soft_qh_t *pqh;
DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh));
- for (pqh = sc->sc_ctl_start; pqh->qh->hlink != sqh; pqh=pqh->qh->hlink)
+ for (pqh = sc->sc_ctl_start; pqh->hlink != sqh; pqh=pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
- if (pqh->qh->qh_hlink & UHCI_PTR_T) {
+ if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
printf("uhci_remove_ctrl: QH not found\n");
return;
}
#else
;
#endif
- pqh->qh->hlink = sqh->qh->hlink;
- pqh->qh->qh_hlink = sqh->qh->qh_hlink;
+ pqh->hlink = sqh->hlink;
+ pqh->qh.qh_hlink = sqh->qh.qh_hlink;
if (sc->sc_ctl_end == sqh)
sc->sc_ctl_end = pqh;
}
@@ -682,14 +715,14 @@ uhci_add_bulk(sc, sqh)
uhci_softc_t *sc;
uhci_soft_qh_t *sqh;
{
- uhci_qh_t *eqh;
+ uhci_soft_qh_t *eqh;
DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh));
- eqh = sc->sc_bulk_end->qh;
- sqh->qh->hlink = eqh->hlink;
- sqh->qh->qh_hlink = eqh->qh_hlink;
- eqh->hlink = sqh;
- eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q;
+ eqh = sc->sc_bulk_end;
+ sqh->hlink = eqh->hlink;
+ sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ eqh->hlink = sqh;
+ eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
sc->sc_bulk_end = sqh;
}
@@ -702,19 +735,17 @@ uhci_remove_bulk(sc, sqh)
uhci_soft_qh_t *pqh;
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
- for (pqh = sc->sc_bulk_start;
- pqh->qh->hlink != sqh;
- pqh = pqh->qh->hlink)
+ for (pqh = sc->sc_bulk_start; pqh->hlink != sqh; pqh = pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
- if (pqh->qh->qh_hlink & UHCI_PTR_T) {
+ if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
printf("uhci_remove_bulk: QH not found\n");
return;
}
#else
;
#endif
- pqh->qh->hlink = sqh->qh->hlink;
- pqh->qh->qh_hlink = sqh->qh->qh_hlink;
+ pqh->hlink = sqh->hlink;
+ pqh->qh.qh_hlink = sqh->qh.qh_hlink;
if (sc->sc_bulk_end == sqh)
sc->sc_bulk_end = pqh;
}
@@ -792,7 +823,6 @@ uhci_check_intr(sc, ii)
uhci_softc_t *sc;
uhci_intr_info_t *ii;
{
- struct uhci_pipe *upipe;
uhci_soft_td_t *std, *lstd;
u_int32_t status;
@@ -817,10 +847,10 @@ uhci_check_intr(sc, ii)
* is a an error somewhere in the middle, or whether there was a
* short packet (SPD and not ACTIVE).
*/
- if (lstd->td->td_status & UHCI_TD_ACTIVE) {
+ if (LE(lstd->td.td_status) & UHCI_TD_ACTIVE) {
DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
- for (std = ii->stdstart; std != lstd; std = std->td->link.std){
- status = std->td->td_status;
+ for (std = ii->stdstart; std != lstd; std = std->link.std){
+ status = LE(std->td.td_status);
if ((status & UHCI_TD_STALLED) ||
(status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) ==
UHCI_TD_SPD)
@@ -832,7 +862,6 @@ uhci_check_intr(sc, ii)
}
done:
usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
- upipe = (struct uhci_pipe *)ii->reqh->pipe;
uhci_idone(ii);
}
@@ -874,16 +903,17 @@ uhci_idone(ii)
/* The transfer is done, compute actual length and status. */
/* XXX Is this correct for control xfers? */
actlen = 0;
- for (std = ii->stdstart; std; std = std->td->link.std) {
- status = std->td->td_status;
+ for (std = ii->stdstart; std; std = std->link.std) {
+ status = LE(std->td.td_status);
if (status & UHCI_TD_ACTIVE)
break;
- if (UHCI_TD_GET_PID(std->td->td_token) != UHCI_TD_PID_SETUP)
+ if (UHCI_TD_GET_PID(LE(std->td.td_token)) !=
+ UHCI_TD_PID_SETUP)
actlen += UHCI_TD_GET_ACTLEN(status);
}
/* If there are left over TDs we need to update the toggle. */
if (std)
- upipe->nexttoggle = UHCI_TD_GET_DT(std->td->td_token);
+ upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token));
status &= UHCI_TD_ERROR;
DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n",
@@ -905,41 +935,8 @@ uhci_idone(ii)
} else {
reqh->status = USBD_NORMAL_COMPLETION;
}
-
- uhci_done(ii);
- if (ii->reqh->pipe->intrreqh != ii->reqh)
- usb_start_next(ii->reqh->pipe);
-}
-
-void
-uhci_done(ii)
- uhci_intr_info_t *ii;
-{
- usbd_request_handle reqh = ii->reqh;
- usbd_pipe_handle pipe = reqh->pipe;
-
- DPRINTFN(5, ("uhci_ii_finish: calling handler ii=%p\n", ii));
-
- switch (pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- uhci_ctrl_done(ii);
- break;
- case UE_ISOCHRONOUS:
- uhci_isoc_done(ii);
- break;
- case UE_BULK:
- uhci_bulk_done(ii);
- break;
- case UE_INTERRUPT:
- uhci_intr_done(ii);
- break;
- }
-
- /* Remove request from queue. */
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
-
- /* And finally execute callback. */
- reqh->xfercb(reqh);
+ reqh->hcpriv = ii;
+ usb_transfer_complete(reqh);
}
/*
@@ -988,10 +985,11 @@ uhci_waitintr(sc, reqh)
ii && ii->reqh != reqh;
ii = LIST_NEXT(ii, list))
;
- if (ii)
- uhci_idone(ii);
- else
+#ifdef DIAGNOSTIC
+ if (!ii)
panic("uhci_waitintr: lost intr_info\n");
+#endif
+ uhci_idone(ii);
}
void
@@ -1067,32 +1065,26 @@ uhci_alloc_std(sc)
{
uhci_soft_td_t *std;
usbd_status r;
- int i;
+ int i, offs;
usb_dma_t dma;
if (!sc->sc_freetds) {
DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
- std = malloc(sizeof(uhci_soft_td_t) * UHCI_TD_CHUNK,
- M_USBHC, M_NOWAIT);
- if (!std)
- return (0);
- r = usb_allocmem(sc->sc_dmatag, UHCI_TD_SIZE * UHCI_TD_CHUNK,
+ r = usb_allocmem(sc->sc_dmatag, UHCI_STD_SIZE * UHCI_STD_CHUNK,
UHCI_TD_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION) {
- free(std, M_USBHC);
+ if (r != USBD_NORMAL_COMPLETION)
return (0);
- }
- for(i = 0; i < UHCI_TD_CHUNK; i++, std++) {
- std->physaddr = DMAADDR(&dma) + i * UHCI_TD_SIZE;
- std->td = (uhci_td_t *)
- ((char *)KERNADDR(&dma) + i * UHCI_TD_SIZE);
- std->td->link.std = sc->sc_freetds;
+ for(i = 0; i < UHCI_STD_CHUNK; i++) {
+ offs = i * UHCI_STD_SIZE;
+ std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
+ std->physaddr = DMAADDR(&dma) + offs;
+ std->link.std = sc->sc_freetds;
sc->sc_freetds = std;
}
}
std = sc->sc_freetds;
- sc->sc_freetds = std->td->link.std;
- memset(std->td, 0, UHCI_TD_SIZE);
+ sc->sc_freetds = std->link.std;
+ memset(&std->td, 0, sizeof(uhci_td_t));
return std;
}
@@ -1103,13 +1095,13 @@ uhci_free_std(sc, std)
{
#ifdef DIAGNOSTIC
#define TD_IS_FREE 0x12345678
- if (std->td->td_token == TD_IS_FREE) {
+ if (LE(std->td.td_token) == TD_IS_FREE) {
printf("uhci_free_std: freeing free TD %p\n", std);
return;
}
- std->td->td_token = TD_IS_FREE;
+ std->td.td_token = LE(TD_IS_FREE);
#endif
- std->td->link.std = sc->sc_freetds;
+ std->link.std = sc->sc_freetds;
sc->sc_freetds = std;
}
@@ -1124,28 +1116,21 @@ uhci_alloc_sqh(sc)
if (!sc->sc_freeqhs) {
DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
- sqh = malloc(sizeof(uhci_soft_qh_t) * UHCI_QH_CHUNK,
- M_USBHC, M_NOWAIT);
- if (!sqh)
- return 0;
- r = usb_allocmem(sc->sc_dmatag, UHCI_QH_SIZE * UHCI_QH_CHUNK,
+ r = usb_allocmem(sc->sc_dmatag, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
UHCI_QH_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION) {
- free(sqh, M_USBHC);
+ if (r != USBD_NORMAL_COMPLETION)
return 0;
- }
- for(i = 0; i < UHCI_QH_CHUNK; i++, sqh++) {
- offs = i * UHCI_QH_SIZE;
+ for(i = 0; i < UHCI_SQH_CHUNK; i++) {
+ offs = i * UHCI_SQH_SIZE;
+ sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs);
sqh->physaddr = DMAADDR(&dma) + offs;
- sqh->qh = (uhci_qh_t *)
- ((char *)KERNADDR(&dma) + offs);
- sqh->qh->hlink = sc->sc_freeqhs;
+ sqh->hlink = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
}
sqh = sc->sc_freeqhs;
- sc->sc_freeqhs = sqh->qh->hlink;
- memset(sqh->qh, 0, UHCI_QH_SIZE);
+ sc->sc_freeqhs = sqh->hlink;
+ memset(&sqh->qh, 0, sizeof(uhci_qh_t));
return (sqh);
}
@@ -1154,7 +1139,7 @@ uhci_free_sqh(sc, sqh)
uhci_softc_t *sc;
uhci_soft_qh_t *sqh;
{
- sqh->qh->hlink = sc->sc_freeqhs;
+ sqh->hlink = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
@@ -1183,7 +1168,7 @@ uhci_free_std_chain(sc, std, stdend)
uhci_soft_td_t *p;
for (; std != stdend; std = p) {
- p = std->td->link.std;
+ p = std->link.std;
uhci_free_std(sc, std);
}
}
@@ -1217,6 +1202,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
return (USBD_INVAL);
}
ntd = (len + maxp - 1) / maxp;
+ DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
tog = upipe->nexttoggle;
if (ntd % 2 == 0)
tog ^= 1;
@@ -1235,11 +1221,11 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
uhci_free_std_chain(sc, lastp, 0);
return (USBD_NOMEM);
}
- p->td->link.std = lastp;
- p->td->td_link = lastlink;
+ p->link.std = lastp;
+ p->td.td_link = LE(lastlink);
lastp = p;
lastlink = p->physaddr;
- p->td->td_status = status;
+ p->td.td_status = LE(status);
if (i == ntd) {
/* last TD */
l = len % maxp;
@@ -1247,10 +1233,10 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
*ep = p;
} else
l = maxp;
- p->td->td_token =
- rd ? UHCI_TD_IN (l, endpt, addr, tog) :
- UHCI_TD_OUT(l, endpt, addr, tog);
- p->td->td_buffer = DMAADDR(dma) + i * maxp;
+ p->td.td_token =
+ LE(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
+ UHCI_TD_OUT(l, endpt, addr, tog));
+ p->td.td_buffer = LE(DMAADDR(dma) + i * maxp);
tog ^= 1;
}
*sp = lastp;
@@ -1327,7 +1313,7 @@ uhci_device_bulk_start(reqh)
dmap, &xfer, &xferend);
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
- xferend->td->td_status |= UHCI_TD_IOC;
+ xferend->td.td_status |= LE(UHCI_TD_IOC);
if (!isread && len != 0)
memcpy(KERNADDR(dmap), reqh->buffer, len);
@@ -1347,8 +1333,8 @@ uhci_device_bulk_start(reqh)
ii->isdone = 0;
#endif
- sqh->qh->elink = xfer;
- sqh->qh->qh_elink = xfer->physaddr;
+ sqh->elink = xfer;
+ sqh->qh.qh_elink = LE(xfer->physaddr);
sqh->intr_info = ii;
s = splusb();
@@ -1397,20 +1383,39 @@ uhci_abort_req(reqh, 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;
+ reqh->status = status;
+
+ /* don't timeout, */
+ usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
/* make hardware ignore it, */
- for (std = ii->stdstart; std != 0; std = std->td->link.std)
- std->td->td_status &= ~UHCI_TD_ACTIVE;
+ for (std = ii->stdstart; std != 0; std = std->link.std)
+ std->td.td_status &= LE(~UHCI_TD_ACTIVE);
+
+ reqh->hcpriv = ii;
+
/* make sure hardware has completed, */
- usb_delay_ms(reqh->pipe->device->bus, 1);
+ if (curproc) {
+ usb_delay_ms(reqh->pipe->device->bus, 1);
+ /* and call final part of interrupt handler. */
+ uhci_abort_req_end(reqh);
+ } else {
+ /* We have no process context, so we can't use tsleep(). */
+ timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+ }
+}
+
+void
+uhci_abort_req_end(v)
+ void *v;
+{
+ usbd_request_handle reqh = v;
+ int s;
- /* and call final part of interrupt handler. */
s = splusb();
- uhci_done(ii);
+ usb_transfer_complete(reqh);
splx(s);
}
@@ -1514,7 +1519,7 @@ uhci_device_intr_start(reqh)
dmap, &xfer, &xferend);
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
- xferend->td->td_status |= UHCI_TD_IOC;
+ xferend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
@@ -1537,8 +1542,8 @@ uhci_device_intr_start(reqh)
upipe->u.intr.qhs[0]));
for (i = 0; i < upipe->u.intr.npoll; i++) {
sqh = upipe->u.intr.qhs[i];
- sqh->qh->elink = xfer;
- sqh->qh->qh_elink = xfer->physaddr;
+ sqh->elink = xfer;
+ sqh->qh.qh_elink = LE(xfer->physaddr);
}
splx(s);
@@ -1676,8 +1681,8 @@ uhci_device_request(reqh)
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
next = xfer;
- xferend->td->link.std = stat;
- xferend->td->td_link = stat->physaddr;
+ xferend->link.std = stat;
+ xferend->td.td_link = LE(stat->physaddr);
} else {
next = stat;
}
@@ -1687,27 +1692,25 @@ uhci_device_request(reqh)
if (!isread && len != 0)
memcpy(KERNADDR(dmap), reqh->buffer, len);
- setup->td->link.std = next;
- setup->td->td_link = next->physaddr;
- setup->td->td_status = UHCI_TD_SET_ERRCNT(2) | ls | UHCI_TD_ACTIVE;
- setup->td->td_token = UHCI_TD_SETUP(sizeof *req, endpt, addr);
- setup->td->td_buffer = DMAADDR(&upipe->u.ctl.reqdma);
-
- stat->td->link.std = 0;
- stat->td->td_link = UHCI_PTR_T;
- stat->td->td_status = UHCI_TD_SET_ERRCNT(2) | ls |
- UHCI_TD_ACTIVE | UHCI_TD_IOC;
- stat->td->td_token =
- isread ? UHCI_TD_OUT(0, endpt, addr, 1) :
- UHCI_TD_IN (0, endpt, addr, 1);
- stat->td->td_buffer = 0;
+ setup->link.std = next;
+ setup->td.td_link = LE(next->physaddr);
+ setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
+ setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
+ setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
+
+ stat->link.std = 0;
+ stat->td.td_link = LE(UHCI_PTR_T);
+ stat->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls |
+ UHCI_TD_ACTIVE | UHCI_TD_IOC);
+ stat->td.td_token =
+ LE(isread ? UHCI_TD_OUT(0, endpt, addr, 1) :
+ UHCI_TD_IN (0, endpt, addr, 1));
+ stat->td.td_buffer = LE(0);
#ifdef USB_DEBUG
if (uhcidebug > 20) {
- printf("uhci_device_request: setup\n");
- uhci_dump_td(setup);
- printf("uhci_device_request: stat\n");
- uhci_dump_td(stat);
+ printf("uhci_device_request: before transfer\n");
+ uhci_dump_tds(setup);
}
#endif
@@ -1719,8 +1722,8 @@ uhci_device_request(reqh)
ii->isdone = 0;
#endif
- sqh->qh->elink = setup;
- sqh->qh->qh_elink = setup->physaddr;
+ sqh->elink = setup;
+ sqh->qh.qh_elink = LE(setup->physaddr);
sqh->intr_info = ii;
s = splusb();
@@ -1736,20 +1739,20 @@ uhci_device_request(reqh)
printf("uhci_enter_ctl_q: follow from [0]\n");
for (std = sc->sc_vframes[0].htd, link = 0;
(link & UHCI_PTR_Q) == 0;
- std = std->td->link.std) {
- link = std->td->td_link;
+ std = std->link.std) {
+ link = LE(std->td.td_link);
uhci_dump_td(std);
}
for (sxqh = xqh = (uhci_soft_qh_t *)std;
xqh;
- xqh = (maxqh++ == 5 || xqh->qh->hlink==sxqh ||
- xqh->qh->hlink==xqh ? NULL : xqh->qh->hlink)) {
+ xqh = (maxqh++ == 5 || xqh->hlink==sxqh ||
+ xqh->hlink==xqh ? NULL : xqh->hlink)) {
uhci_dump_qh(xqh);
uhci_dump_qh(sxqh);
}
printf("Enqueued QH:\n");
uhci_dump_qh(sqh);
- uhci_dump_tds(sqh->qh->elink);
+ uhci_dump_tds(sqh->elink);
}
#endif
if (reqh->timeout && !sc->sc_bus.use_polling) {
@@ -1818,7 +1821,7 @@ uhci_device_isoc_close(pipe)
iso = &upipe->u.iso;
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++)
- iso->stds[i]->td->td_status &= ~UHCI_TD_ACTIVE;
+ iso->stds[i]->td.td_status &= LE(~UHCI_TD_ACTIVE);
usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */
uhci_lock_frames(sc);
@@ -1827,8 +1830,8 @@ uhci_device_isoc_close(pipe)
std = iso->stds[i];
for (vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
- vstd && vstd->td->link.std != std;
- vstd = vstd->td->link.std)
+ vstd && vstd->link.std != std;
+ vstd = vstd->link.std)
;
if (!vstd) {
/*panic*/
@@ -1836,8 +1839,8 @@ uhci_device_isoc_close(pipe)
uhci_unlock_frames(sc);
return;
}
- vstd->td->link = std->td->link;
- vstd->td->td_link = std->td->td_link;
+ vstd->link = std->link;
+ vstd->td.td_link = std->td.td_link;
uhci_free_std(sc, std);
}
uhci_unlock_frames(sc);
@@ -1907,17 +1910,17 @@ uhci_device_isoc_setbuf(pipe, bufsize, nbuf)
uhci_soft_td_t *std, *vstd;
std = iso->stds[i];
- std->td->td_status = UHCI_TD_IOS; /* iso, inactive */
- std->td->td_token =
- rd ? UHCI_TD_IN (0, endpt, addr, 0) :
- UHCI_TD_OUT(0, endpt, addr, 0);
- std->td->td_buffer = DMAADDR(&iso->bufs[i % nbuf]);
+ std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
+ std->td.td_token =
+ LE(rd ? UHCI_TD_IN (0, endpt, addr, 0) :
+ UHCI_TD_OUT(0, endpt, addr, 0));
+ std->td.td_buffer = LE(DMAADDR(&iso->bufs[i % nbuf]));
vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
- std->td->link = vstd->td->link;
- std->td->td_link = vstd->td->td_link;
- vstd->td->link.std = std;
- vstd->td->td_link = std->physaddr;
+ std->link = vstd->link;
+ std->td.td_link = vstd->td.td_link;
+ vstd->link.std = std;
+ vstd->td.td_link = LE(std->physaddr);
}
uhci_unlock_frames(sc);
@@ -1935,17 +1938,18 @@ uhci_device_isoc_setbuf(pipe, bufsize, nbuf)
}
void
-uhci_isoc_done(ii)
- uhci_intr_info_t *ii;
+uhci_device_isoc_done(reqh)
+ usbd_request_handle reqh;
{
+ /*uhci_intr_info_t *ii = v;*/
}
void
-uhci_intr_done(ii)
- uhci_intr_info_t *ii;
+uhci_device_intr_done(reqh)
+ usbd_request_handle reqh;
{
+ uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
- usbd_request_handle reqh = ii->reqh;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
usb_dma_t *dma;
uhci_soft_qh_t *sqh;
@@ -1958,8 +1962,8 @@ uhci_intr_done(ii)
npoll = upipe->u.intr.npoll;
for(i = 0; i < npoll; i++) {
sqh = upipe->u.intr.qhs[i];
- sqh->qh->elink = 0;
- sqh->qh->qh_elink = UHCI_PTR_T;
+ sqh->elink = 0;
+ sqh->qh.qh_elink = LE(UHCI_PTR_T);
}
uhci_free_std_chain(sc, ii->stdstart, 0);
@@ -1971,7 +1975,7 @@ uhci_intr_done(ii)
uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
reqh->flags & USBD_SHORT_XFER_OK,
dma, &xfer, &xferend);
- xferend->td->td_status |= UHCI_TD_IOC;
+ xferend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
@@ -1988,8 +1992,8 @@ uhci_intr_done(ii)
#endif
for (i = 0; i < npoll; i++) {
sqh = upipe->u.intr.qhs[i];
- sqh->qh->elink = xfer;
- sqh->qh->qh_elink = xfer->physaddr;
+ sqh->elink = xfer;
+ sqh->qh.qh_elink = LE(xfer->physaddr);
}
} else {
usb_freemem(sc->sc_dmatag, dma);
@@ -1999,15 +2003,14 @@ uhci_intr_done(ii)
/* Deallocate request data structures */
void
-uhci_ctrl_done(ii)
- uhci_intr_info_t *ii;
+uhci_device_ctrl_done(reqh)
+ usbd_request_handle reqh;
{
+ uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
- usbd_request_handle reqh = ii->reqh;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
u_int len = upipe->u.ctl.length;
usb_dma_t *dma;
- uhci_td_t *htd = ii->stdstart->td;
#ifdef DIAGNOSTIC
if (!reqh->isreq)
@@ -2022,7 +2025,7 @@ uhci_ctrl_done(ii)
dma = &upipe->u.ctl.datadma;
if (reqh->request.bmRequestType & UT_READ)
memcpy(reqh->buffer, KERNADDR(dma), len);
- uhci_free_std_chain(sc, htd->link.std, ii->stdend);
+ uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
usb_freemem(sc->sc_dmatag, dma);
}
DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen));
@@ -2030,11 +2033,11 @@ uhci_ctrl_done(ii)
/* Deallocate request data structures */
void
-uhci_bulk_done(ii)
- uhci_intr_info_t *ii;
+uhci_device_bulk_done(reqh)
+ usbd_request_handle reqh;
{
+ uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
- usbd_request_handle reqh = ii->reqh;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
u_int datalen = upipe->u.bulk.length;
usb_dma_t *dma;
@@ -2061,14 +2064,14 @@ uhci_add_intr(sc, n, sqh)
uhci_soft_qh_t *sqh;
{
struct uhci_vframe *vf = &sc->sc_vframes[n];
- uhci_qh_t *eqh;
+ uhci_soft_qh_t *eqh;
DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", n, sqh));
- eqh = vf->eqh->qh;
- sqh->qh->hlink = eqh->hlink;
- sqh->qh->qh_hlink = eqh->qh_hlink;
- eqh->hlink = sqh;
- eqh->qh_hlink = sqh->physaddr | UHCI_PTR_Q;
+ eqh = vf->eqh;
+ sqh->hlink = eqh->hlink;
+ sqh->qh.qh_hlink = eqh->qh.qh_hlink;
+ eqh->hlink = sqh;
+ eqh->qh.qh_hlink = LE(sqh->physaddr | UHCI_PTR_Q);
vf->eqh = sqh;
vf->bandwidth++;
}
@@ -2085,17 +2088,17 @@ uhci_remove_intr(sc, n, sqh)
DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", n, sqh));
- for (pqh = vf->hqh; pqh->qh->hlink != sqh; pqh = pqh->qh->hlink)
+ for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
- if (pqh->qh->qh_hlink & UHCI_PTR_T) {
+ if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
printf("uhci_remove_intr: QH not found\n");
return;
}
#else
;
#endif
- pqh->qh->hlink = sqh->qh->hlink;
- pqh->qh->qh_hlink = sqh->qh->qh_hlink;
+ pqh->hlink = sqh->hlink;
+ pqh->qh.qh_hlink = sqh->qh.qh_hlink;
if (vf->eqh == sqh)
vf->eqh = pqh;
vf->bandwidth--;
@@ -2144,8 +2147,8 @@ uhci_device_setintr(sc, upipe, ival)
upipe->iinfo->stdstart = 0;
for(i = 0; i < npoll; i++) {
upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc);
- sqh->qh->elink = 0;
- sqh->qh->qh_elink = UHCI_PTR_T;
+ sqh->elink = 0;
+ sqh->qh.qh_elink = LE(UHCI_PTR_T);
sqh->pos = MOD(i * ival + bestoffs);
sqh->intr_info = upipe->iinfo;
}
@@ -2658,10 +2661,9 @@ uhci_root_ctrl_start(reqh)
reqh->actlen = totlen;
r = USBD_NORMAL_COMPLETION;
ret:
- SIMPLEQ_REMOVE_HEAD(&reqh->pipe->queue, reqh, next);
reqh->status = r;
- reqh->xfercb(reqh);
- usb_start_next(reqh->pipe);
+ reqh->hcpriv = 0;
+ usb_transfer_complete(reqh);
return (USBD_IN_PROGRESS);
}
diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h
index 29ac0b6607d..a49c9c31c3c 100644
--- a/sys/dev/usb/uhcireg.h
+++ b/sys/dev/usb/uhcireg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhcireg.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */
-/* $NetBSD: uhcireg.h,v 1.6 1999/04/03 19:01:20 augustss Exp $ */
+/* $OpenBSD: uhcireg.h,v 1.2 1999/08/27 09:00:29 fgsch Exp $ */
+/* $NetBSD: uhcireg.h,v 1.7 1999/08/22 23:19:57 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -116,11 +116,6 @@ typedef u_int32_t uhci_physaddr_t;
#define UHCI_PTR_Q 0x00000002
#define UHCI_PTR_VF 0x00000004
-typedef union {
- struct uhci_soft_qh *sqh;
- struct uhci_soft_td *std;
-} uhci_soft_td_qh_t;
-
/*
* The Queue Heads and Transfer Descriptors and accessed
* by both the CPU and the USB controller which runs
@@ -166,10 +161,7 @@ typedef struct {
#define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff)
#define UHCI_TD_MAXLEN_MASK 0xffe00000
u_int32_t td_buffer;
- uhci_soft_td_qh_t link; /* soft version of the td_link field */
- /* padding to 32 bytes */
} uhci_td_t;
-#define UHCI_TD_SIZE 32
#define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED)
@@ -185,10 +177,6 @@ typedef struct {
typedef struct {
uhci_physaddr_t qh_hlink;
uhci_physaddr_t qh_elink;
- struct uhci_soft_qh *hlink; /* soft version of qh_hlink */
- struct uhci_soft_td *elink; /* soft version of qh_elink */
- /* padding to 32 bytes */
} uhci_qh_t;
-#define UHCI_QH_SIZE 32
#endif /* _DEV_PCI_UHCIREG_H_ */
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index d81af2589af..6e3215ba2e3 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhcivar.h,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */
-/* $NetBSD: uhcivar.h,v 1.7 1999/06/26 08:30:18 augustss Exp $ */
+/* $OpenBSD: uhcivar.h,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */
+/* $NetBSD: uhcivar.h,v 1.12 1999/08/22 23:41:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -56,6 +56,11 @@
typedef struct uhci_soft_qh uhci_soft_qh_t;
typedef struct uhci_soft_td uhci_soft_td_t;
+typedef union {
+ struct uhci_soft_qh *sqh;
+ struct uhci_soft_td *std;
+} uhci_soft_td_qh_t;
+
/*
* An interrupt info struct contains the information needed to
* execute a requested routine when the controller generates an
@@ -81,28 +86,34 @@ typedef struct uhci_intr_info {
* Extra information that we need for a TD.
*/
struct uhci_soft_td {
- uhci_td_t *td; /* The real TD */
- uhci_physaddr_t physaddr; /* and its physical address. */
+ uhci_td_t td; /* The real TD, must be first */
+ uhci_soft_td_qh_t link; /* soft version of the td_link field */
+ uhci_physaddr_t physaddr; /* TD's physical address. */
};
-#define UHCI_TD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/
+/*
+ * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way
+ * we can pack a number of soft TD together and have the real TS well
+ * aligned.
+ * NOTE: Minimum size is 32 bytes.
+ */
+#define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN)
+#define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/
/*
* Extra information that we need for a QH.
*/
struct uhci_soft_qh {
- uhci_qh_t *qh; /* The real QH */
- uhci_physaddr_t physaddr; /* and its physical address. */
+ uhci_qh_t qh; /* The real QH, must be first */
+ uhci_soft_qh_t *hlink; /* soft version of qh_hlink */
+ uhci_soft_td_t *elink; /* soft version of qh_elink */
+ uhci_physaddr_t physaddr; /* QH's physical address. */
int pos; /* Timeslot position */
uhci_intr_info_t *intr_info; /* Who to call on completion. */
+/* XXX should try to shrink with 4 bytes to fit into 32 bytes */
};
-#define UHCI_QH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
-
-/* Only used for buffer free list. */
-struct uhci_buffer {
- struct uhci_buffer *next;
-};
-#define UHCI_BUFFER_SIZE 64
-#define UHCI_BUFFER_CHUNK 64 /*(PAGE_SIZE / UHCI_BUFFER_SIZE)*/
+/* See comment about UHCI_STD_SIZE. */
+#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN)
+#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
/*
* Information about an entry in the virtial frame list.
@@ -137,7 +148,6 @@ typedef struct uhci_softc {
uhci_soft_td_t *sc_freetds;
uhci_soft_qh_t *sc_freeqhs;
- struct uhci_buffer *sc_freebuffers;
u_int8_t sc_addr; /* device address */
u_int8_t sc_conf; /* device configuration */
@@ -157,10 +167,6 @@ typedef struct uhci_softc {
#define UHCI_HAS_LOCK 1
#define UHCI_WANT_LOCK 2
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- usb_dma_t *sc_mallocs;
-#endif
-
char sc_vendor[16];
int sc_id_vendor;
} uhci_softc_t;
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index c8069545114..74feaaca1d7 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhid.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */
-/* $NetBSD: uhid.c,v 1.18 1999/06/30 06:44:23 augustss Exp $ */
+/* $OpenBSD: uhid.c,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */
+/* $NetBSD: uhid.c,v 1.21 1999/08/23 22:55:14 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -243,6 +243,17 @@ uhid_activate(self, act)
struct device *self;
enum devact act;
{
+ struct uhid_softc *sc = (struct uhid_softc *)self;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
return (0);
}
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index af333fa22e4..fd80037ef55 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhub.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */
-/* $NetBSD: uhub.c,v 1.18 1999/06/30 06:44:23 augustss Exp $ */
+/* $OpenBSD: uhub.c,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */
+/* $NetBSD: uhub.c,v 1.23 1999/08/23 22:55:14 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -63,7 +63,6 @@
#define DPRINTF(x) if (usbdebug) logprintf x
#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
extern int usbdebug;
-extern char *usbd_error_strs[];
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -127,8 +126,8 @@ USB_ATTACH(uhub)
r = usbd_set_config_index(dev, 0, 1);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("%s: configuration failed, error=%d(%s)\n",
- USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ DPRINTF(("%s: configuration failed, error=%s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
USB_ATTACH_ERROR_RETURN;
}
@@ -152,8 +151,8 @@ USB_ATTACH(uhub)
r = usbd_do_request(dev, &req, &hubdesc);
}
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("%s: getting hub descriptor failed, error=%d(%s)\n",
- USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ DPRINTF(("%s: getting hub descriptor failed, error=%s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
USB_ATTACH_ERROR_RETURN;
}
@@ -328,8 +327,8 @@ uhub_explore(dev)
r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("uhub_explore: get port status failed, "
- "error=%d(%s)\n",
- r, usbd_error_strs[r]));
+ "error=%s\n",
+ usbd_errstr(r)));
continue;
}
status = UGETW(up->status.wPortStatus);
@@ -403,7 +402,7 @@ uhub_explore(dev)
/* XXX retry a few times? */
if (r != USBD_NORMAL_COMPLETION) {
DPRINTFN(-1,("uhub_explore: usb_new_device failed, "
- "error=%d(%s)\n", r, usbd_error_strs[r]));
+ "error=%s\n", usbd_errstr(r)));
/* Avoid addressing problems by disabling. */
/* usbd_reset_port(dev, port, &up->status); */
/* XXX
@@ -492,6 +491,14 @@ uhub_activate(self, act)
struct device *self;
enum devact act;
{
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ break;
+ }
return (0);
}
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index a466a7bae82..e0a1e6ca5f2 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.h,v 1.2 1999/08/19 08:18:39 fgsch Exp $ */
+/* $OpenBSD: usb.h,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */
/* $NetBSD: usb.h,v 1.27 1999/08/18 07:55:19 augustss Exp $ */
/*
@@ -45,9 +45,7 @@
#include <sys/types.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/ioctl.h>
-#endif
-#if defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(_KERNEL)
#include <dev/usb/usb_port.h>
#endif /* _KERNEL */
@@ -223,6 +221,7 @@ typedef struct {
#define UE_ADDR 0x0f
#define UE_GET_ADDR(a) ((a) & UE_ADDR)
#define UE_GET_IN(a) (((a) >> 7) & 1)
+#define UE_GET_DIR(a) ((a) & 0x80)
uByte bmAttributes;
#define UE_XFERTYPE 0x03
#define UE_CONTROL 0x00
@@ -356,8 +355,10 @@ typedef struct {
#define USUBCLASS_UFI 4
#define USUBCLASS_SFF8070I 5
#define USUBCLASS_SCSI 6
-#define UPROTO_MASS_CBI_C 0
-#define UPROTO_MASS_CBI_NC 1
+#define UPROTO_MASS_CBI_I 0
+#define UPROTO_MASS_CBI 1
+#define UPROTO_MASS_BULK 80
+#define UPROTO_MASS_BULK2 2
#define UCLASS_HUB 9
#define USUBCLASS_HUB 0
#define UCLASS_DATA 10
@@ -509,6 +510,7 @@ struct usb_device_stats {
#define USB_DO_REQUEST _IOWR('U', 111, struct usb_ctl_request)
#define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info)
#define USB_SET_SHORT_XFER _IOW ('U', 113, int)
+#define USB_SET_TIMEOUT _IOW ('U', 114, int)
/* Modem device */
#define USB_GET_CM_OVER_DATA _IOR ('U', 130, int)
diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c
index 805877dcbae..fee0b823a82 100644
--- a/sys/dev/usb/usb_mem.c
+++ b/sys/dev/usb/usb_mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_mem.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */
+/* $OpenBSD: usb_mem.c,v 1.4 1999/08/27 09:00:29 fgsch Exp $ */
/* $NetBSD: usb_mem.c,v 1.9 1999/08/16 20:19:55 augustss Exp $ */
/*
@@ -64,7 +64,7 @@
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) logprintf x
#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
-extern int usbdebug;
+int usbdebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -83,12 +83,14 @@ struct usb_frag_dma {
usbd_status usb_block_allocmem
__P((bus_dma_tag_t, size_t, size_t, usb_dma_block_t **));
+#if 0
void usb_block_real_freemem __P((usb_dma_block_t *));
+#endif
void usb_block_freemem __P((usb_dma_block_t *));
-LIST_HEAD(, usb_block_dma) usb_blk_freelist =
+LIST_HEAD(, usb_dma_block) usb_blk_freelist =
LIST_HEAD_INITIALIZER(usb_blk_freelist);
-/* XXX should have different free list for different tags */
+/* XXX should have different free list for different tags (for speed) */
LIST_HEAD(, usb_frag_dma) usb_frag_freelist =
LIST_HEAD_INITIALIZER(usb_frag_freelist);
@@ -107,8 +109,8 @@ usb_block_allocmem(tag, size, align, dmap)
#ifdef DIAGNOSTIC
if (!curproc) {
- printf("usb_block_allocmem: in interrupt context, size=%u\n",
- size);
+ printf("usb_block_allocmem: in interrupt context, size=%lu\n",
+ (unsigned long) size);
}
#endif
@@ -173,6 +175,7 @@ free:
return (USBD_NOMEM);
}
+#if 0
void
usb_block_real_freemem(p)
usb_dma_block_t *p;
@@ -189,6 +192,7 @@ usb_block_real_freemem(p)
bus_dmamem_free(p->tag, p->segs, p->nsegs);
free(p, M_USB);
}
+#endif
/*
* Do not free the memory unconditionally since we might be called
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index 041127807bb..9c5ae8f435c 100644
--- a/sys/dev/usb/usb_mem.h
+++ b/sys/dev/usb/usb_mem.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_mem.h,v 1.1 1999/08/13 05:28:04 fgsch Exp $ */
+/* $OpenBSD: usb_mem.h,v 1.2 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usb_mem.h,v 1.4 1999/01/09 12:16:54 augustss Exp $ */
/*
@@ -39,7 +39,7 @@
*/
#if defined(__NetBSD__) || defined(__OpenBSD__)
-typedef struct usb_block_dma {
+typedef struct usb_dma_block {
bus_dma_tag_t tag;
bus_dmamap_t map;
caddr_t kaddr;
@@ -48,11 +48,11 @@ typedef struct usb_block_dma {
size_t size;
size_t align;
int fullblock;
- LIST_ENTRY(usb_block_dma) next;
+ LIST_ENTRY(usb_dma_block) next;
} usb_dma_block_t;
typedef struct {
- usb_dma_block_t *block;
+ struct usb_dma_block *block;
u_int offs;
} usb_dma_t;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index a26022ee9ad..981663dd903 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_subr.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.4 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usb_subr.c,v 1.38 1999/08/17 20:59:04 augustss Exp $ */
/*
@@ -131,6 +131,33 @@ char *usbd_error_strs[] = {
};
#endif
+char *
+usbd_errstr(err)
+ usbd_status err;
+{
+ static char buffer[5];
+
+#ifdef USB_DEBUG
+ if ( err < USBD_ERROR_MAX ) {
+ return usbd_error_strs[err];
+ } else {
+#if !defined(__OpenBSD__)
+ snprintf(buffer, sizeof buffer, "%d", err);
+#else
+ sprintf(buffer, "%d", err);
+#endif /* !defined(__OpenBSD__) */
+ return buffer;
+ }
+#else
+#if !defined(__OpenBSD__)
+ snprintf(buffer, sizeof buffer, "%d", err);
+#else
+ sprintf(buffer, "%d", err);
+#endif /* !defined(__OpenBSD__) */
+ return buffer;
+#endif
+}
+
usbd_status
usbd_get_string_desc(dev, sindex, langid, sdesc)
usbd_device_handle dev;
@@ -313,8 +340,8 @@ usbd_reset_port(dev, port, ps)
USETW(req.wIndex, port);
USETW(req.wLength, 0);
r = usbd_do_request(dev, &req, 0);
- DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n",
- port, r, usbd_error_strs[r]));
+ DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
+ port, usbd_errstr(r)));
if (r != USBD_NORMAL_COMPLETION)
return (r);
n = 10;
@@ -574,8 +601,8 @@ usbd_set_config_index(dev, index, msg)
(UGETW(ds.wStatus) & UDS_SELF_POWERED))
selfpowered = 1;
DPRINTF(("usbd_set_config_index: status=0x%04x, "
- "error=%d(%s)\n",
- UGETW(ds.wStatus), r, usbd_error_strs[r]));
+ "error=%s\n",
+ UGETW(ds.wStatus), usbd_errstr(r)));
} else
selfpowered = 1;
}
@@ -609,8 +636,8 @@ usbd_set_config_index(dev, index, msg)
r = usbd_set_config(dev, cdp->bConfigurationValue);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("usbd_set_config_index: setting config=%d failed, "
- "error=%d(%s)\n",
- cdp->bConfigurationValue, r, usbd_error_strs[r]));
+ "error=%s\n",
+ cdp->bConfigurationValue, usbd_errstr(r)));
goto bad;
}
DPRINTF(("usbd_set_config_index: setting new config %d\n",
@@ -669,9 +696,9 @@ usbd_setup_pipe(dev, iface, ep, pipe)
SIMPLEQ_INIT(&p->queue);
r = dev->bus->open_pipe(p);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d"
- "(%s)\n",
- ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
+ DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
+ "%s\n",
+ ep->edesc->bEndpointAddress, usbd_errstr(r)));
free(p, M_USB);
return (r);
}
@@ -764,8 +791,8 @@ usbd_probe_and_attach(parent, dev, port, addr)
if (r != USBD_NORMAL_COMPLETION) {
#ifdef USB_DEBUG
DPRINTF(("%s: port %d, set config at addr %d failed, "
- "error=%d(%s)\n", USBDEVNAME(*parent), port,
- addr, r, usbd_error_strs[r]));
+ "error=%s\n", USBDEVNAME(*parent), port,
+ addr, usbd_errstr(r)));
#else
printf("%s: port %d, set config at addr %d failed\n",
USBDEVNAME(*parent), port, addr);
@@ -926,6 +953,12 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
return (r);
}
+ DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
+ "subclass=%d, protocol=%d, maxpacket=%d, len=%d, ls=%d\n",
+ addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
+ dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength,
+ dev->lowspeed));
+
if (dd->bDescriptorType != UDESC_DEVICE) {
/* Illegal device descriptor */
DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
@@ -934,10 +967,11 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
return (USBD_INVAL);
}
- DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
- "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
- addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
- dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
+ if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
+ DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
+ usbd_remove_device(dev, up);
+ return (USBD_INVAL);
+ }
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
@@ -1086,54 +1120,6 @@ usbd_bus_print_child(device_t bus, device_t dev)
}
#endif
-usbd_status
-usb_insert_transfer(reqh)
- usbd_request_handle reqh;
-{
- usbd_pipe_handle pipe = reqh->pipe;
-
- SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
- if (pipe->running)
- return (USBD_IN_PROGRESS);
- pipe->running = 1;
- return (USBD_NORMAL_COMPLETION);
-}
-
-void
-usb_start_next(pipe)
- usbd_pipe_handle pipe;
-{
- usbd_request_handle reqh;
- usbd_status r;
-
- DPRINTFN(10, ("usb_start_next: pipe=%p\n", pipe));
-
-#ifdef DIAGNOSTIC
- if (!pipe) {
- printf("usb_start_next: pipe == 0\n");
- return;
- }
- if (!pipe->methods || !pipe->methods->start) {
- printf("usb_start_next: no start method\n");
- return;
- }
-#endif
-
- /* Get next request in queue. */
- reqh = SIMPLEQ_FIRST(&pipe->queue);
- DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh));
- if (!reqh)
- pipe->running = 0;
- else {
- r = pipe->methods->start(reqh);
- if (r != USBD_IN_PROGRESS) {
- printf("usb_start_next: error=%d\n", r);
- pipe->running = 0;
- /* XXX do what? */
- }
- }
-}
-
void
usbd_fill_deviceinfo(dev, di)
usbd_device_handle dev;
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 48708c75cd6..319c555f52a 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi.c,v 1.3 1999/08/19 08:18:39 fgsch Exp $ */
-/* $NetBSD: usbdi.c,v 1.30 1999/08/17 20:59:04 augustss Exp $ */
+/* $OpenBSD: usbdi.c,v 1.4 1999/08/27 09:00:30 fgsch Exp $ */
+/* $NetBSD: usbdi.c,v 1.32 1999/08/23 22:55:14 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -71,11 +71,9 @@ extern int usbdebug;
#endif
static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
-static void usbd_transfer_cb __P((usbd_request_handle reqh));
-static void usbd_sync_transfer_cb __P((usbd_request_handle reqh));
-static usbd_status usbd_do_transfer __P((usbd_request_handle reqh));
void usbd_do_request_async_cb
__P((usbd_request_handle, usbd_private_handle, usbd_status));
+void usbd_start_next __P((usbd_pipe_handle pipe));
static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
@@ -229,27 +227,46 @@ usbd_close_pipe(pipe)
return (USBD_NORMAL_COMPLETION);
}
-usbd_status
+usbd_status
usbd_transfer(reqh)
usbd_request_handle reqh;
{
- reqh->xfercb = usbd_transfer_cb;
- return (usbd_do_transfer(reqh));
-}
-
-static usbd_status
-usbd_do_transfer(reqh)
- usbd_request_handle reqh;
-{
usbd_pipe_handle pipe = reqh->pipe;
+ usbd_status r;
+ int s;
- DPRINTFN(5,("usbd_do_transfer: reqh=%p\n", reqh));
+ DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
+ reqh, reqh->flags, pipe, pipe->running));
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
#endif
reqh->done = 0;
- return (pipe->methods->transfer(reqh));
+
+ r = pipe->methods->transfer(reqh);
+ if (!(reqh->flags & USBD_SYNCHRONOUS))
+ return r;
+
+ /* Sync transfer, wait for completion. */
+ if (r != USBD_IN_PROGRESS)
+ return (r);
+ s = splusb();
+ if (!reqh->done) {
+ if (reqh->pipe->device->bus->use_polling)
+ panic("usbd_transfer: not done\n");
+ tsleep(reqh, PRIBIO, "usbsyn", 0);
+ }
+ splx(s);
+ return (reqh->status);
+}
+
+/* Like usbd_transfer(), but waits for completion. */
+usbd_status
+usbd_sync_transfer(reqh)
+ usbd_request_handle reqh;
+{
+ reqh->flags |= USBD_SYNCHRONOUS;
+ return (usbd_transfer(reqh));
}
usbd_request_handle
@@ -300,7 +317,6 @@ usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
reqh->timeout = timeout;
reqh->status = USBD_NOT_STARTED;
reqh->callback = callback;
- reqh->retries = 1;
reqh->isreq = 0;
return (USBD_NORMAL_COMPLETION);
}
@@ -330,12 +346,11 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
reqh->status = USBD_NOT_STARTED;
reqh->callback = callback;
reqh->request = *req;
- reqh->retries = 1;
reqh->isreq = 1;
return (USBD_NORMAL_COMPLETION);
}
-usbd_status
+void
usbd_get_request_status(reqh, priv, buffer, count, status)
usbd_request_handle reqh;
usbd_private_handle *priv;
@@ -343,11 +358,14 @@ usbd_get_request_status(reqh, priv, buffer, count, status)
u_int32_t *count;
usbd_status *status;
{
- *priv = reqh->priv;
- *buffer = reqh->buffer;
- *count = reqh->actlen;
- *status = reqh->status;
- return (USBD_NORMAL_COMPLETION);
+ if (priv)
+ *priv = reqh->priv;
+ if (buffer)
+ *buffer = reqh->buffer;
+ if (count)
+ *count = reqh->actlen;
+ if (status)
+ *status = reqh->status;
}
usb_config_descriptor_t *
@@ -601,23 +619,37 @@ usbd_init()
}
}
-static void
-usbd_transfer_cb(reqh)
+void
+usb_transfer_complete(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
+ int polling;
+
+ DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n",
+ pipe, reqh, reqh->actlen));
- DPRINTFN(10, ("usbd_transfer_cb: reqh=%p\n", reqh));
- /* Count completed transfers. */
#ifdef DIAGNOSTIC
- if (!pipe)
+ if (!pipe) {
printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
- else
+ return;
+ }
#endif
+ polling = reqh->pipe->device->bus->use_polling;
+ /* XXXX */
+ if (polling)
+ pipe->running = 0;
+
+ if (reqh->pipe->methods->done)
+ reqh->pipe->methods->done(reqh);
+
+ /* Remove request from queue. */
+ SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
+
+ /* Count completed transfers. */
++pipe->device->bus->stats.requests
[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
- /* XXX check retry count */
reqh->done = 1;
if (reqh->status == USBD_NORMAL_COMPLETION &&
reqh->actlen < reqh->length &&
@@ -626,40 +658,66 @@ usbd_transfer_cb(reqh)
reqh->actlen, reqh->length));
reqh->status = USBD_SHORT_XFER;
}
+
if (reqh->callback)
reqh->callback(reqh, reqh->priv, reqh->status);
-}
-static void
-usbd_sync_transfer_cb(reqh)
- usbd_request_handle reqh;
-{
- DPRINTFN(10, ("usbd_sync_transfer_cb: reqh=%p\n", reqh));
- usbd_transfer_cb(reqh);
- if (!reqh->pipe->device->bus->use_polling)
+ if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
wakeup(reqh);
+
+ if (!pipe->repeat &&
+ reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT)
+ usbd_start_next(pipe);
}
-/* Like usbd_transfer(), but waits for completion. */
usbd_status
-usbd_sync_transfer(reqh)
+usb_insert_transfer(reqh)
usbd_request_handle reqh;
{
+ usbd_pipe_handle pipe = reqh->pipe;
+
+ DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe,
+ pipe->running));
+ SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
+ if (pipe->running)
+ return (USBD_IN_PROGRESS);
+ pipe->running = 1;
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+usbd_start_next(pipe)
+ usbd_pipe_handle pipe;
+{
+ usbd_request_handle reqh;
usbd_status r;
- int s;
- reqh->xfercb = usbd_sync_transfer_cb;
- r = usbd_do_transfer(reqh);
- if (r != USBD_IN_PROGRESS)
- return (r);
- s = splusb();
- if (!reqh->done) {
- if (reqh->pipe->device->bus->use_polling)
- panic("usbd_sync_transfer: not done\n");
- tsleep(reqh, PRIBIO, "usbsyn", 0);
+ DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
+
+#ifdef DIAGNOSTIC
+ if (!pipe) {
+ printf("usbd_start_next: pipe == 0\n");
+ return;
+ }
+ if (!pipe->methods || !pipe->methods->start) {
+ printf("usbd_start_next: no start method\n");
+ return;
+ }
+#endif
+
+ /* Get next request in queue. */
+ reqh = SIMPLEQ_FIRST(&pipe->queue);
+ DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
+ if (!reqh)
+ pipe->running = 0;
+ else {
+ r = pipe->methods->start(reqh);
+ if (r != USBD_IN_PROGRESS) {
+ printf("usbd_start_next: error=%d\n", r);
+ pipe->running = 0;
+ /* XXX do what? */
+ }
}
- splx(s);
- return (reqh->status);
}
usbd_status
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 335c019eab0..b169b4fccfa 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi.h,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */
+/* $OpenBSD: usbdi.h,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usbdi.h,v 1.20 1999/06/30 06:44:23 augustss Exp $ */
/*
@@ -46,7 +46,7 @@ typedef struct usbd_request *usbd_request_handle;
typedef void *usbd_private_handle;
typedef enum {
- USBD_NORMAL_COMPLETION = 0,
+ USBD_NORMAL_COMPLETION = 0, /* must be 0 */
USBD_IN_PROGRESS,
/* errors */
USBD_PENDING_REQUESTS,
@@ -68,6 +68,8 @@ typedef enum {
USBD_INTERRUPTED,
USBD_XXX,
+
+ USBD_ERROR_MAX, /* must be last */
} usbd_status;
typedef int usbd_lock_token;
@@ -81,7 +83,8 @@ typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle,
/* Request flags */
#define USBD_XFER_OUT 0x01
#define USBD_XFER_IN 0x02
-#define USBD_SHORT_XFER_OK 0x04
+#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
+#define USBD_SYNCHRONOUS 0x08 /* wait for completion */
#define USBD_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -103,7 +106,7 @@ usbd_status usbd_setup_default_request
usbd_private_handle priv, u_int32_t timeout,
usb_device_request_t *req, void *buffer,
u_int32_t length, u_int16_t flags, usbd_callback));
-usbd_status usbd_get_request_status
+void usbd_get_request_status
__P((usbd_request_handle reqh, usbd_private_handle *priv,
void **buffer, u_int32_t *count, usbd_status *status));
usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor
@@ -161,6 +164,8 @@ usb_endpoint_descriptor_t *usbd_find_edesc
void usbd_dopoll __P((usbd_interface_handle));
void usbd_set_polling __P((usbd_interface_handle iface, int on));
+char *usbd_errstr __P((usbd_status err));
+
/* NetBSD attachment information */
/* Attach data */
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 8ed127df125..688c1c48f89 100644
--- a/sys/dev/usb/usbdi_util.c
+++ b/sys/dev/usb/usbdi_util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi_util.c,v 1.2 1999/08/16 22:08:49 fgsch Exp $ */
+/* $OpenBSD: usbdi_util.c,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usbdi_util.c,v 1.16 1999/08/07 23:14:17 augustss Exp $ */
/*
@@ -501,21 +501,20 @@ usbd_bulk_transfer_cb(reqh, priv, status)
}
usbd_status
-usbd_bulk_transfer(reqh, pipe, flags, buf, size, lbl)
+usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
usbd_request_handle reqh;
usbd_pipe_handle pipe;
u_int16_t flags;
+ u_int32_t timeout;
void *buf;
u_int32_t *size;
char *lbl;
{
- usbd_private_handle priv;
- void *buffer;
usbd_status r;
int s, error;
r = usbd_setup_request(reqh, pipe, 0, buf, *size,
- flags, USBD_NO_TIMEOUT, usbd_bulk_transfer_cb);
+ flags, timeout, usbd_bulk_transfer_cb);
if (r != USBD_NORMAL_COMPLETION)
return (r);
DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
@@ -532,7 +531,7 @@ usbd_bulk_transfer(reqh, pipe, flags, buf, size, lbl)
usbd_abort_pipe(pipe);
return (USBD_INTERRUPTED);
}
- usbd_get_request_status(reqh, &priv, &buffer, size, &r);
+ usbd_get_request_status(reqh, 0, 0, size, &r);
DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("usbd_bulk_transfer: error=%d\n", r));
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index 9146a9365d3..f77b789d522 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdi_util.h,v 1.1 1999/08/13 05:28:05 fgsch Exp $ */
+/* $OpenBSD: usbdi_util.h,v 1.2 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usbdi_util.h,v 1.14 1999/08/07 23:14:17 augustss Exp $ */
/*
@@ -91,7 +91,7 @@ usbd_status usbd_set_config_index
usbd_status usbd_bulk_transfer
__P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags,
- void *buf, u_int32_t *size, char *lbl));
+ u_int32_t timeout, void *buf, u_int32_t *size, char *lbl));
void usb_detach_wait __P((bdevice *));
void usb_detach_wakeup __P((bdevice *));
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index 2ccaa846f54..a40975d1420 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdivar.h,v 1.2 1999/08/19 08:18:39 fgsch Exp $ */
+/* $OpenBSD: usbdivar.h,v 1.3 1999/08/27 09:00:30 fgsch Exp $ */
/* $NetBSD: usbdivar.h,v 1.24 1999/08/17 20:59:04 augustss Exp $ */
/*
@@ -46,14 +46,13 @@ struct usbd_endpoint {
int refcnt;
};
-typedef void (*usbd_xfercb)__P((usbd_request_handle req));
-
struct usbd_methods {
usbd_status (*transfer)__P((usbd_request_handle reqh));
usbd_status (*start)__P((usbd_request_handle reqh));
void (*abort)__P((usbd_request_handle reqh));
void (*close)__P((usbd_pipe_handle pipe));
void (*cleartoggle)__P((usbd_pipe_handle pipe));
+ void (*done)__P((usbd_request_handle reqh));
usbd_status (*isobuf)__P((usbd_pipe_handle pipe,
u_int32_t bufsize,u_int32_t nbuf));
};
@@ -152,12 +151,10 @@ struct usbd_request {
u_int32_t timeout;
usbd_status status;
usbd_callback callback;
- usbd_xfercb xfercb;
- u_int32_t retries;
char done;
usb_device_request_t request;
- u_int8_t isreq;
+ char isreq;
SIMPLEQ_ENTRY(usbd_request) next;
@@ -187,12 +184,13 @@ usbd_status usbd_new_device __P((bdevice *parent,
void usbd_remove_device __P((usbd_device_handle,
struct usbd_port *));
int usbd_printBCD __P((char *cp, int bcd));
-usbd_status usb_insert_transfer __P((usbd_request_handle reqh));
-void usb_start_next __P((usbd_pipe_handle pipe));
usbd_status usbd_fill_iface_data __P((usbd_device_handle dev,
int i, int a));
void usb_free_device __P((usbd_device_handle));
+usbd_status usb_insert_transfer __P((usbd_request_handle reqh));
+void usb_transfer_complete __P((usbd_request_handle reqh));
+
/* Routines from usb.c */
int usb_bus_count __P((void));
void usb_needs_explore __P((usbd_bus_handle));