summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/hid.c34
-rw-r--r--sys/dev/usb/ohci.c1296
-rw-r--r--sys/dev/usb/ohcireg.h41
-rw-r--r--sys/dev/usb/ohcivar.h30
-rw-r--r--sys/dev/usb/uaudio.c314
-rw-r--r--sys/dev/usb/uaudioreg.h65
-rw-r--r--sys/dev/usb/ugen.c257
-rw-r--r--sys/dev/usb/uhci.c1071
-rw-r--r--sys/dev/usb/uhcireg.h5
-rw-r--r--sys/dev/usb/uhcivar.h40
-rw-r--r--sys/dev/usb/uhid.c144
-rw-r--r--sys/dev/usb/uhub.c197
-rw-r--r--sys/dev/usb/usb.c251
-rw-r--r--sys/dev/usb/usb.h156
-rw-r--r--sys/dev/usb/usb_mem.c33
-rw-r--r--sys/dev/usb/usb_mem.h6
-rw-r--r--sys/dev/usb/usb_port.h60
-rw-r--r--sys/dev/usb/usb_quirks.c17
-rw-r--r--sys/dev/usb/usb_quirks.h6
-rw-r--r--sys/dev/usb/usb_subr.c345
-rw-r--r--sys/dev/usb/usbdi.c693
-rw-r--r--sys/dev/usb/usbdi.h75
-rw-r--r--sys/dev/usb/usbdi_util.c155
-rw-r--r--sys/dev/usb/usbdi_util.h6
-rw-r--r--sys/dev/usb/usbdivar.h81
25 files changed, 3325 insertions, 2053 deletions
diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c
index d2ef61d3f70..58db47c6ba5 100644
--- a/sys/dev/usb/hid.c
+++ b/sys/dev/usb/hid.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hid.c,v 1.3 1999/11/07 21:30:18 fgsch Exp $ */
-/* $NetBSD: hid.c,v 1.7 1999/01/08 11:58:25 augustss Exp $ */
+/* $OpenBSD: hid.c,v 1.4 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: hid.c,v 1.12 2000/03/17 18:16:18 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -40,11 +40,10 @@
#include <sys/param.h>
#include <sys/systm.h>
+#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/kernel.h>
-#include <sys/malloc.h>
-#if defined(__FreeBSD__)
-#include <sys/bus.h>
#endif
+#include <sys/malloc.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
@@ -112,7 +111,7 @@ void
hid_end_parse(s)
struct hid_data *s;
{
- while (s->cur.next) {
+ while (s->cur.next != NULL) {
struct hid_item *hi = s->cur.next->next;
free(s->cur.next, M_TEMP);
s->cur.next = hi;
@@ -126,7 +125,8 @@ hid_get_item(s, h)
struct hid_item *h;
{
struct hid_item *c = &s->cur;
- int bTag, bType, bSize;
+ unsigned int bTag, bType, bSize;
+ struct hid_location oldloc;
u_char *data;
int32_t dval;
u_char *p;
@@ -134,7 +134,7 @@ hid_get_item(s, h)
int i;
top:
- if (s->multimax) {
+ if (s->multimax != 0) {
if (s->multi < s->multimax) {
c->usage = s->usages[min(s->multi, s->nu-1)];
s->multi++;
@@ -300,7 +300,9 @@ hid_get_item(s, h)
break;
case 11: /* Pop */
hi = c->next;
+ oldloc = c->loc;
s->cur = *hi;
+ c->loc = oldloc;
free(hi, M_TEMP);
break;
default:
@@ -381,11 +383,11 @@ hid_report_size(buf, len, k, idp)
id = 0;
for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); )
- if (h.report_ID)
+ if (h.report_ID != 0)
id = h.report_ID;
hid_end_parse(d);
size = h.loc.pos;
- if (id) {
+ if (id != 0) {
size += 8;
*idp = id; /* XXX wrong */
} else
@@ -407,9 +409,9 @@ hid_locate(desc, size, u, k, loc, flags)
for (d = hid_start_parse(desc, size, 1<<k); hid_get_item(d, &h); ) {
if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) {
- if (loc)
+ if (loc != NULL)
*loc = h.loc;
- if (flags)
+ if (flags != NULL)
*flags = h.flags;
hid_end_parse(d);
return (1);
@@ -457,15 +459,15 @@ hid_is_collection(desc, size, usage)
{
struct hid_data *hd;
struct hid_item hi;
- int r;
+ int err;
hd = hid_start_parse(desc, size, hid_input);
- if (!hd)
+ if (hd == NULL)
return (0);
- r = hid_get_item(hd, &hi) &&
+ err = hid_get_item(hd, &hi) &&
hi.kind == hid_collection &&
hi.usage == usage;
hid_end_parse(hd);
- return (r);
+ return (err);
}
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index fcabdb8c26b..d57b51f1d45 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohci.c,v 1.7 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: ohci.c,v 1.48 1999/09/15 21:14:03 augustss Exp $ */
+/* $OpenBSD: ohci.c,v 1.8 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: ohci.c,v 1.78 2000/03/20 00:37:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -47,19 +47,22 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/kernel.h>
#include <sys/device.h>
+#include <sys/select.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus_pio.h>
#include <machine/bus_memio.h>
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+#include <machine/cpu.h>
+#endif
#endif
#include <sys/proc.h>
#include <sys/queue.h>
-#include <sys/select.h>
#include <machine/bus.h>
#include <machine/endian.h>
@@ -75,6 +78,7 @@
#if defined(__FreeBSD__)
#include <machine/clock.h>
+
#define delay(d) DELAY(d)
#endif
@@ -111,64 +115,77 @@ void ohci_free_sed __P((ohci_softc_t *, ohci_soft_ed_t *));
ohci_soft_td_t *ohci_alloc_std __P((ohci_softc_t *));
void ohci_free_std __P((ohci_softc_t *, ohci_soft_td_t *));
+ohci_soft_itd_t *ohci_alloc_sitd __P((ohci_softc_t *));
+void ohci_free_sitd __P((ohci_softc_t *, ohci_soft_itd_t *));
+
+#if 0
void ohci_free_std_chain __P((ohci_softc_t *,
ohci_soft_td_t *, ohci_soft_td_t *));
+#endif
usbd_status ohci_alloc_std_chain __P((struct ohci_pipe *, ohci_softc_t *,
- int, int, int, usb_dma_t *,
+ int, int, usbd_xfer_handle,
ohci_soft_td_t *,
ohci_soft_td_t **));
+void ohci_shutdown __P((void *v));
void ohci_power __P((int, void *));
usbd_status ohci_open __P((usbd_pipe_handle));
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_softintr __P((struct usbd_bus *));
+void ohci_waitintr __P((ohci_softc_t *, usbd_xfer_handle));
+void ohci_rhsc __P((ohci_softc_t *, usbd_xfer_handle));
-usbd_status ohci_device_request __P((usbd_request_handle reqh));
+usbd_status ohci_device_request __P((usbd_xfer_handle xfer));
void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *));
void ohci_rem_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *));
void ohci_hash_add_td __P((ohci_softc_t *, ohci_soft_td_t *));
void ohci_hash_rem_td __P((ohci_softc_t *, ohci_soft_td_t *));
ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, ohci_physaddr_t));
+usbd_status ohci_setup_isoc __P((usbd_pipe_handle pipe));
+void ohci_device_isoc_enter __P((usbd_xfer_handle));
+
usbd_status ohci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t));
void ohci_freem __P((struct usbd_bus *, usb_dma_t *));
-usbd_status ohci_root_ctrl_transfer __P((usbd_request_handle));
-usbd_status ohci_root_ctrl_start __P((usbd_request_handle));
-void ohci_root_ctrl_abort __P((usbd_request_handle));
+usbd_xfer_handle ohci_allocx __P((struct usbd_bus *));
+void ohci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
+usbd_status ohci_root_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status ohci_root_ctrl_start __P((usbd_xfer_handle));
+void ohci_root_ctrl_abort __P((usbd_xfer_handle));
void ohci_root_ctrl_close __P((usbd_pipe_handle));
+void ohci_root_ctrl_done __P((usbd_xfer_handle));
-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));
+usbd_status ohci_root_intr_transfer __P((usbd_xfer_handle));
+usbd_status ohci_root_intr_start __P((usbd_xfer_handle));
+void ohci_root_intr_abort __P((usbd_xfer_handle));
void ohci_root_intr_close __P((usbd_pipe_handle));
-void ohci_root_intr_done __P((usbd_request_handle));
+void ohci_root_intr_done __P((usbd_xfer_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));
+usbd_status ohci_device_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status ohci_device_ctrl_start __P((usbd_xfer_handle));
+void ohci_device_ctrl_abort __P((usbd_xfer_handle));
void ohci_device_ctrl_close __P((usbd_pipe_handle));
-void ohci_device_ctrl_done __P((usbd_request_handle));
+void ohci_device_ctrl_done __P((usbd_xfer_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));
+usbd_status ohci_device_bulk_transfer __P((usbd_xfer_handle));
+usbd_status ohci_device_bulk_start __P((usbd_xfer_handle));
+void ohci_device_bulk_abort __P((usbd_xfer_handle));
void ohci_device_bulk_close __P((usbd_pipe_handle));
-void ohci_device_bulk_done __P((usbd_request_handle));
+void ohci_device_bulk_done __P((usbd_xfer_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));
+usbd_status ohci_device_intr_transfer __P((usbd_xfer_handle));
+usbd_status ohci_device_intr_start __P((usbd_xfer_handle));
+void ohci_device_intr_abort __P((usbd_xfer_handle));
void ohci_device_intr_close __P((usbd_pipe_handle));
-void ohci_device_intr_done __P((usbd_request_handle));
+void ohci_device_intr_done __P((usbd_xfer_handle));
-usbd_status ohci_device_isoc_transfer __P((usbd_request_handle));
-usbd_status ohci_device_isoc_start __P((usbd_request_handle));
-void ohci_device_isoc_abort __P((usbd_request_handle));
+usbd_status ohci_device_isoc_transfer __P((usbd_xfer_handle));
+usbd_status ohci_device_isoc_start __P((usbd_xfer_handle));
+void ohci_device_isoc_abort __P((usbd_xfer_handle));
void ohci_device_isoc_close __P((usbd_pipe_handle));
-void ohci_device_isoc_done __P((usbd_request_handle));
+void ohci_device_isoc_done __P((usbd_xfer_handle));
usbd_status ohci_device_setintr __P((ohci_softc_t *sc,
struct ohci_pipe *pipe, int ival));
@@ -180,15 +197,14 @@ 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_req __P((usbd_request_handle reqh,
+void ohci_abort_xfer __P((usbd_xfer_handle xfer,
usbd_status status));
-void ohci_abort_req_end __P((void *));
+void ohci_abort_xfer_end __P((void *));
void ohci_device_clear_toggle __P((usbd_pipe_handle pipe));
void ohci_noop __P((usbd_pipe_handle pipe));
#ifdef OHCI_DEBUG
-ohci_softc_t *thesc;
void ohci_dumpregs __P((ohci_softc_t *));
void ohci_dump_tds __P((ohci_soft_td_t *));
void ohci_dump_td __P((ohci_soft_td_t *));
@@ -209,7 +225,10 @@ static u_int8_t revbits[OHCI_NO_INTRS] =
struct ohci_pipe {
struct usbd_pipe pipe;
ohci_soft_ed_t *sed;
- ohci_soft_td_t *tail;
+ union {
+ ohci_soft_td_t *td;
+ ohci_soft_itd_t *itd;
+ } tail;
/* Info needed for different pipe kinds. */
union {
/* Control pipe */
@@ -231,6 +250,7 @@ struct ohci_pipe {
/* Iso pipe */
struct iso {
int xxxxx;
+ int next, inuse;
} iso;
} u;
};
@@ -239,9 +259,12 @@ struct ohci_pipe {
struct usbd_bus_methods ohci_bus_methods = {
ohci_open,
+ ohci_softintr,
ohci_poll,
ohci_allocm,
ohci_freem,
+ ohci_allocx,
+ ohci_freex,
};
struct usbd_pipe_methods ohci_root_ctrl_methods = {
@@ -250,7 +273,7 @@ struct usbd_pipe_methods ohci_root_ctrl_methods = {
ohci_root_ctrl_abort,
ohci_root_ctrl_close,
ohci_noop,
- 0,
+ ohci_root_ctrl_done,
};
struct usbd_pipe_methods ohci_root_intr_methods = {
@@ -289,7 +312,6 @@ struct usbd_pipe_methods ohci_device_bulk_methods = {
ohci_device_bulk_done,
};
-#if 0
struct usbd_pipe_methods ohci_device_isoc_methods = {
ohci_device_isoc_transfer,
ohci_device_isoc_start,
@@ -298,8 +320,8 @@ struct usbd_pipe_methods ohci_device_isoc_methods = {
ohci_noop,
ohci_device_isoc_done,
};
-#endif
+#if defined(__NetBSD__) || defined(__OpenBSD__)
int
ohci_activate(self, act)
device_ptr_t self;
@@ -335,25 +357,28 @@ ohci_detach(sc, flags)
return (rv);
powerhook_disestablish(sc->sc_powerhook);
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+
/* free data structures XXX */
return (rv);
}
+#endif
ohci_soft_ed_t *
ohci_alloc_sed(sc)
ohci_softc_t *sc;
{
ohci_soft_ed_t *sed;
- usbd_status r;
+ usbd_status err;
int i, offs;
usb_dma_t dma;
- if (!sc->sc_freeeds) {
+ if (sc->sc_freeeds == NULL) {
DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
- r = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
+ err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
OHCI_ED_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (0);
for(i = 0; i < OHCI_SED_CHUNK; i++) {
offs = i * OHCI_SED_SIZE;
@@ -384,16 +409,18 @@ ohci_alloc_std(sc)
ohci_softc_t *sc;
{
ohci_soft_td_t *std;
- usbd_status r;
+ usbd_status err;
int i, offs;
usb_dma_t dma;
+ int s;
- if (!sc->sc_freetds) {
+ if (sc->sc_freetds == NULL) {
DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
- r = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+ err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
OHCI_TD_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (0);
+ s = splusb();
for(i = 0; i < OHCI_STD_CHUNK; i++) {
offs = i * OHCI_STD_SIZE;
std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
@@ -401,11 +428,18 @@ ohci_alloc_std(sc)
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
}
+ splx(s);
}
+
+ s = splusb();
std = sc->sc_freetds;
sc->sc_freetds = std->nexttd;
memset(&std->td, 0, sizeof(ohci_td_t));
std->nexttd = 0;
+
+ ohci_hash_add_td(sc, std);
+ splx(s);
+
return (std);
}
@@ -414,33 +448,46 @@ ohci_free_std(sc, std)
ohci_softc_t *sc;
ohci_soft_td_t *std;
{
+ int s;
+
+ s = splusb();
+ ohci_hash_rem_td(sc, std);
+
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
+ splx(s);
}
usbd_status
-ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
- struct ohci_pipe *upipe;
+ohci_alloc_std_chain(opipe, sc, alen, rd, xfer, sp, ep)
+ struct ohci_pipe *opipe;
ohci_softc_t *sc;
- int len, rd, shortok;
- usb_dma_t *dma;
+ int alen, rd;
+ usbd_xfer_handle xfer;
ohci_soft_td_t *sp, **ep;
{
ohci_soft_td_t *next, *cur;
ohci_physaddr_t dataphys, dataphysend;
- u_int32_t intr;
- int curlen;
+ u_int32_t tdflags;
+ int len, curlen;
+ usb_dma_t *dma = &xfer->dmabuf;
+ u_int16_t flags = xfer->flags;
- DPRINTFN(len >= 4096,("ohci_alloc_std_chain: start len=%d\n", len));
+ DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
+
+ len = alen;
cur = sp;
dataphys = DMAADDR(dma);
dataphysend = OHCI_PAGE(dataphys + len - 1);
+ tdflags = LE(
+ (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
+ (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
+ OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR);
+
for (;;) {
next = ohci_alloc_std(sc);
- if (next == 0) {
- /* XXX free chain */
- return (USBD_NOMEM);
- }
+ if (next == NULL)
+ goto nomem;
/* The OHCI hardware can handle at most one page crossing. */
if (OHCI_PAGE(dataphys) == dataphysend ||
@@ -451,6 +498,12 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
/* must use multiple TDs, fill as much as possible. */
curlen = 2 * OHCI_PAGE_SIZE -
(dataphys & (OHCI_PAGE_SIZE-1));
+ /* the length must be a multiple of the max size */
+ curlen -= curlen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
+#ifdef DIAGNOSTIC
+ if (curlen == 0)
+ panic("ohci_alloc_std: curlen == 0\n");
+#endif
}
DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
"dataphysend=0x%08x len=%d curlen=%d\n",
@@ -458,17 +511,14 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
len, curlen));
len -= curlen;
- intr = len == 0 ? OHCI_TD_SET_DI(1) : OHCI_TD_NOINTR;
- cur->td.td_flags = LE(
- (rd ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- intr | OHCI_TD_TOGGLE_CARRY |
- (shortok ? OHCI_TD_R : 0));
+ cur->td.td_flags = tdflags;
cur->td.td_cbp = LE(dataphys);
cur->nexttd = next;
cur->td.td_nexttd = LE(next->physaddr);
cur->td.td_be = LE(dataphys + curlen - 1);
cur->len = curlen;
cur->flags = OHCI_ADD_LEN;
+ cur->xfer = xfer;
DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
dataphys, dataphys + curlen - 1));
if (len == 0)
@@ -477,12 +527,35 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
dataphys += curlen;
cur = next;
}
- cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
- *ep = next;
+ if ((flags & USBD_FORCE_SHORT_XFER) &&
+ alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
+ /* Force a 0 length transfer at the end. */
+
+ cur = next;
+ next = ohci_alloc_std(sc);
+ if (next == NULL)
+ goto nomem;
+
+ cur->td.td_flags = tdflags;
+ cur->td.td_cbp = 0; /* indicate 0 length packet */
+ cur->nexttd = next;
+ cur->td.td_nexttd = LE(next->physaddr);
+ cur->td.td_be = ~0;
+ cur->len = 0;
+ cur->flags = 0;
+ cur->xfer = xfer;
+ DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+ }
+ *ep = cur;
return (USBD_NORMAL_COMPLETION);
+
+nomem:
+ /* XXX free chain */
+ return (USBD_NOMEM);
}
+#if 0
void
ohci_free_std_chain(sc, std, stdend)
ohci_softc_t *sc;
@@ -496,84 +569,131 @@ ohci_free_std_chain(sc, std, stdend)
ohci_free_std(sc, std);
}
}
+#endif
+
+ohci_soft_itd_t *
+ohci_alloc_sitd(sc)
+ ohci_softc_t *sc;
+{
+ ohci_soft_itd_t *sitd;
+ usbd_status err;
+ int i, offs;
+ usb_dma_t dma;
+
+ if (sc->sc_freeitds == NULL) {
+ DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
+ err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+ OHCI_TD_ALIGN, &dma);
+ if (err)
+ return (0);
+ for (i = 0; i < OHCI_STD_CHUNK; i++) {
+ offs = i * OHCI_STD_SIZE;
+ sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma)+offs);
+ sitd->physaddr = DMAADDR(&dma) + offs;
+ sitd->nextitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd;
+ }
+ }
+ sitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd->nextitd;
+ memset(&sitd->itd, 0, sizeof(ohci_itd_t));
+ sitd->nextitd = 0;
+ return (sitd);
+}
+
+void
+ohci_free_sitd(sc, sitd)
+ ohci_softc_t *sc;
+ ohci_soft_itd_t *sitd;
+{
+ sitd->nextitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd;
+}
usbd_status
ohci_init(sc)
ohci_softc_t *sc;
{
ohci_soft_ed_t *sed, *psed;
- usbd_status r;
- int rev;
+ usbd_status err;
int i;
- u_int32_t s, ctl, ival, hcr, fm, per;
+ u_int32_t s, ctl, ival, hcr, fm, per, rev, desca;
DPRINTF(("ohci_init: start\n"));
- rev = OREAD4(sc, OHCI_REVISION);
#if defined(__OpenBSD__)
- printf(" version %d.%d%s",
+ printf(",");
#else
- printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev),
+ printf("%s:", USBDEVNAME(sc->sc_bus.bdev));
#endif
- OHCI_REV_HI(rev), OHCI_REV_LO(rev),
+ rev = OREAD4(sc, OHCI_REVISION);
+ printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
-#if defined(__OpenBSD__)
- printf(": unsupported\n");
-#else
printf("%s: unsupported OHCI revision\n",
USBDEVNAME(sc->sc_bus.bdev));
-#endif
+ sc->sc_bus.usbrev = USBREV_UNKNOWN;
return (USBD_INVAL);
-#if defined(__OpenBSD__)
- } else {
- printf("\n");
-#endif
}
+ sc->sc_bus.usbrev = USBREV_1_0;
for (i = 0; i < OHCI_HASH_SIZE; i++)
LIST_INIT(&sc->sc_hash_tds[i]);
+ SIMPLEQ_INIT(&sc->sc_free_xfers);
+
+ /* XXX determine alignment by R/W */
/* Allocate the HCCA area. */
- r = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE,
+ err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE,
OHCI_HCCA_ALIGN, &sc->sc_hccadma);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ if (err)
+ return (err);
sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma);
memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
sc->sc_eintrs = OHCI_NORMAL_INTRS;
+ /* Allocate dummy ED that starts the control list. */
sc->sc_ctrl_head = ohci_alloc_sed(sc);
- if (!sc->sc_ctrl_head) {
- r = USBD_NOMEM;
+ if (sc->sc_ctrl_head == NULL) {
+ err = USBD_NOMEM;
goto bad1;
}
sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+ /* Allocate dummy ED that starts the bulk list. */
sc->sc_bulk_head = ohci_alloc_sed(sc);
- if (!sc->sc_bulk_head) {
- r = USBD_NOMEM;
+ if (sc->sc_bulk_head == NULL) {
+ err = USBD_NOMEM;
goto bad2;
}
sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+ /* Allocate dummy ED that starts the isochronous list. */
+ sc->sc_isoc_head = ohci_alloc_sed(sc);
+ if (sc->sc_isoc_head == NULL) {
+ err = USBD_NOMEM;
+ goto bad3;
+ }
+ sc->sc_isoc_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++) {
sed = ohci_alloc_sed(sc);
- if (!sed) {
+ if (sed == NULL) {
while (--i >= 0)
ohci_free_sed(sc, sc->sc_eds[i]);
- r = USBD_NOMEM;
- goto bad3;
+ err = USBD_NOMEM;
+ goto bad4;
}
/* All ED fields are set to 0. */
sc->sc_eds[i] = sed;
sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
- if (i != 0) {
+ if (i != 0)
psed = sc->sc_eds[(i-1) / 2];
- sed->next = psed;
- sed->ed.ed_nexted = LE(psed->physaddr);
- }
+ else
+ psed = sc->sc_isoc_head;
+ sed->next = psed;
+ sed->ed.ed_nexted = LE(psed->physaddr);
}
/*
* Fill HCCA interrupt table. The bit reversal is to get
@@ -583,6 +703,17 @@ ohci_init(sc)
sc->sc_hcca->hcca_interrupt_table[revbits[i]] =
LE(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr);
+#ifdef OHCI_DEBUG
+ if (ohcidebug > 15) {
+ for (i = 0; i < OHCI_NO_EDS; i++) {
+ printf("ed#%d ", i);
+ ohci_dump_ed(sc->sc_eds[i]);
+ }
+ printf("iso ");
+ ohci_dump_ed(sc->sc_isoc_head);
+ }
+#endif
+
/* Determine in what context we are running. */
ctl = OREAD4(sc, OHCI_CONTROL);
if (ctl & OHCI_IR) {
@@ -591,7 +722,7 @@ ohci_init(sc)
s = OREAD4(sc, OHCI_COMMAND_STATUS);
OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
- delay(1000);
+ usb_delay_ms(&sc->sc_bus, 1);
ctl = OREAD4(sc, OHCI_CONTROL);
}
if ((ctl & OHCI_IR) == 0) {
@@ -605,13 +736,13 @@ ohci_init(sc)
DPRINTF(("ohci_init: BIOS active\n"));
if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) {
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL);
- delay(USB_RESUME_DELAY * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
}
} else {
DPRINTF(("ohci_init: cold started\n"));
reset:
/* Controller was cold started. */
- delay(USB_BUS_RESET_DELAY * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
}
/*
@@ -620,7 +751,7 @@ ohci_init(sc)
*/
DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
- delay(USB_BUS_RESET_DELAY * 1000);
+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
/* We now own the host controller and the bus has been reset. */
ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
@@ -635,23 +766,24 @@ ohci_init(sc)
}
if (hcr) {
printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
- r = USBD_IOERROR;
- goto bad3;
+ err = USBD_IOERROR;
+ goto bad5;
}
#ifdef OHCI_DEBUG
- thesc = sc;
if (ohcidebug > 15)
ohci_dumpregs(sc);
#endif
- /* The controller is now in suspend state, we have 2ms to finish. */
+ /* The controller is now in SUSPEND state, we have 2ms to finish. */
/* Set up HC registers. */
OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma));
OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
+ /* disable all interrupts and then switch on all desired interrupts */
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
+ /* switch on desired functional features */
ctl = OREAD4(sc, OHCI_CONTROL);
ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE |
@@ -670,7 +802,12 @@ ohci_init(sc)
per = OHCI_PERIODIC(ival); /* 90% periodic */
OWRITE4(sc, OHCI_PERIODIC_START, per);
- OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
+ /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
+ desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
+ OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
+ OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
+ usb_delay_ms(&sc->sc_bus, 5);
+ OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
@@ -684,16 +821,22 @@ ohci_init(sc)
sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
sc->sc_powerhook = powerhook_establish(ohci_power, sc);
+ sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
return (USBD_NORMAL_COMPLETION);
+ bad5:
+ for (i = 0; i < OHCI_NO_EDS; i++)
+ ohci_free_sed(sc, sc->sc_eds[i]);
+ bad4:
+ ohci_free_sed(sc, sc->sc_isoc_head);
bad3:
ohci_free_sed(sc, sc->sc_ctrl_head);
bad2:
ohci_free_sed(sc, sc->sc_bulk_head);
bad1:
usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
- return (r);
+ return (err);
}
usbd_status
@@ -721,7 +864,49 @@ ohci_freem(bus, dma)
usb_freemem(&sc->sc_bus, dma);
}
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+usbd_xfer_handle
+ohci_allocx(bus)
+ struct usbd_bus *bus;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+ usbd_xfer_handle xfer;
+
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer != NULL)
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ else
+ xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ if (xfer != NULL)
+ memset(xfer, 0, sizeof *xfer);
+ return (xfer);
+}
+
+void ohci_freex(bus, xfer)
+ struct usbd_bus *bus;
+ usbd_xfer_handle xfer;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+
+ SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+void
+ohci_shutdown(v)
+ void *v;
+{
+ ohci_softc_t *sc = v;
+
+ DPRINTF(("ohci_shutdown: stopping the HC\n"));
+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+}
+
+/*
+ * Handle suspend/resume.
+ *
+ * We need to switch to polling mode here, because this routine is
+ * called from an interrupt context. This is all right since we
+ * are almost suspended anyway.
+ */
void
ohci_power(why, v)
int why;
@@ -735,12 +920,8 @@ ohci_power(why, v)
ohci_dumpregs(sc);
#endif
}
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
#ifdef OHCI_DEBUG
-void ohcidump(void);
-void ohcidump(void) { ohci_dumpregs(thesc); }
-
void
ohci_dumpregs(sc)
ohci_softc_t *sc;
@@ -782,11 +963,29 @@ ohci_dumpregs(sc)
}
#endif
+int ohci_intr1 __P((ohci_softc_t *));
+
int
ohci_intr(p)
void *p;
{
ohci_softc_t *sc = p;
+
+ /* If we get an interrupt while polling, then just ignore it. */
+ if (sc->sc_bus.use_polling) {
+#ifdef DIAGNOSTIC
+ printf("ohci_intr: ignored interrupt while polling\n");
+#endif
+ return (0);
+ }
+
+ return (ohci_intr1(sc));
+}
+
+int
+ohci_intr1(sc)
+ ohci_softc_t *sc;
+{
u_int32_t intrs, eintrs;
ohci_physaddr_t done;
@@ -808,8 +1007,10 @@ ohci_intr(p)
intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS);
} else
intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS);
+
if (!intrs)
return (0);
+
intrs &= ~OHCI_MIE;
OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */
eintrs = intrs & sc->sc_eintrs;
@@ -818,7 +1019,7 @@ ohci_intr(p)
sc->sc_bus.intr_context++;
sc->sc_bus.no_intrs++;
- DPRINTFN(7, ("ohci_intr: sc=%p intrs=%x(%x) eintr=%x\n",
+ DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintr=0x%x\n",
sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
(u_int)eintrs));
@@ -828,7 +1029,21 @@ ohci_intr(p)
intrs &= ~OHCI_SO;
}
if (eintrs & OHCI_WDH) {
- ohci_process_done(sc, done &~ OHCI_DONE_INTRS);
+ done &= ~OHCI_DONE_INTRS;
+ if (sc->sc_done == 0)
+ sc->sc_done = done;
+ else {
+ /* Tack on at end of the sc_dne. */
+ ohci_physaddr_t ldone;
+ ohci_soft_td_t *std;
+
+ for (ldone = sc->sc_done; ldone != 0;
+ ldone = LE(std->td.td_nexttd))
+ std = ohci_hash_find_td(sc, ldone);
+ std->td.td_nexttd = LE(done);
+ }
+ sc->sc_hcca->hcca_done_head = 0;
+ usb_schedsoftintr(&sc->sc_bus);
intrs &= ~OHCI_WDH;
}
if (eintrs & OHCI_RD) {
@@ -842,7 +1057,7 @@ ohci_intr(p)
/* XXX what else */
}
if (eintrs & OHCI_RHSC) {
- ohci_rhsc(sc, sc->sc_intrreqh);
+ ohci_rhsc(sc, sc->sc_intrxfer);
intrs &= ~OHCI_RHSC;
/*
@@ -890,23 +1105,34 @@ char *ohci_cc_strs[] = {
"DATA_UNDERRUN",
"BUFFER_OVERRUN",
"BUFFER_UNDERRUN",
+ "reserved",
+ "reserved",
+ "NOT ACCESSED",
"NOT_ACCESSED",
};
#endif
void
-ohci_process_done(sc, done)
- ohci_softc_t *sc;
- ohci_physaddr_t done;
+ohci_softintr(bus)
+ struct usbd_bus *bus;
{
+ ohci_softc_t *sc = (ohci_softc_t *)bus;
+ ohci_physaddr_t done;
ohci_soft_td_t *std, *sdone, *stdnext;
- usbd_request_handle reqh;
- int len, cc;
+ usbd_xfer_handle xfer;
+ int len, cc, s;
+
+ sc->sc_bus.intr_context++;
+
+ s = splhardusb();
+ done = sc->sc_done;
+ sc->sc_done = 0;
+ splx(s);
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 = NULL; done != 0; done = LE(std->td.td_nexttd)) {
std = ohci_hash_find_td(sc, done);
std->dnext = sdone;
sdone = std;
@@ -920,29 +1146,30 @@ ohci_process_done(sc, done)
#endif
for (std = sdone; std; std = stdnext) {
- reqh = std->reqh;
+ xfer = std->xfer;
stdnext = std->dnext;
- DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n",
- std, reqh, reqh->hcpriv));
+ DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
+ std, xfer, xfer ? xfer->hcpriv : 0));
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) {
+ usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
+ if (xfer->status == USBD_CANCELLED ||
+ xfer->status == USBD_TIMEOUT) {
DPRINTF(("ohci_process_done: cancel/timeout %p\n",
- reqh));
+ xfer));
/* Handled by abort routine. */
} 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;
+ DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n",
+ len, std->flags));
if (std->flags & OHCI_ADD_LEN)
- reqh->actlen += len;
+ xfer->actlen += len;
if (std->flags & OHCI_CALL_DONE) {
- reqh->status = USBD_NORMAL_COMPLETION;
- usb_transfer_complete(reqh);
+ xfer->status = USBD_NORMAL_COMPLETION;
+ usb_transfer_complete(xfer);
}
- ohci_hash_rem_td(sc, std);
ohci_free_std(sc, std);
} else {
/*
@@ -952,16 +1179,15 @@ ohci_process_done(sc, done)
*/
ohci_soft_td_t *p, *n;
struct ohci_pipe *opipe =
- (struct ohci_pipe *)reqh->pipe;
+ (struct ohci_pipe *)xfer->pipe;
- DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n",
+ DPRINTF(("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))]));
/* remove TDs */
- for (p = std; p->reqh == reqh; p = n) {
+ for (p = std; p->xfer == xfer; p = n) {
n = p->nexttd;
- ohci_hash_rem_td(sc, p);
ohci_free_std(sc, p);
}
@@ -970,87 +1196,87 @@ ohci_process_done(sc, done)
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (cc == OHCI_CC_STALL)
- reqh->status = USBD_STALLED;
+ xfer->status = USBD_STALLED;
else
- reqh->status = USBD_IOERROR;
- usb_transfer_complete(reqh);
+ xfer->status = USBD_IOERROR;
+ usb_transfer_complete(xfer);
}
}
+
+ sc->sc_bus.intr_context--;
}
void
-ohci_device_ctrl_done(reqh)
- usbd_request_handle reqh;
+ohci_device_ctrl_done(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh));
+ DPRINTFN(10,("ohci_ctrl_done: xfer=%p\n", xfer));
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST)) {
+ if (!(xfer->rqflags & URQ_REQUEST)) {
panic("ohci_ctrl_done: not a request\n");
}
#endif
- reqh->hcpriv = 0;
+ xfer->hcpriv = NULL;
}
void
-ohci_device_intr_done(reqh)
- usbd_request_handle reqh;
+ohci_device_intr_done(xfer)
+ usbd_xfer_handle xfer;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed = opipe->sed;
ohci_soft_td_t *data, *tail;
+ DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n",
+ xfer, xfer->actlen));
- DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n",
- reqh, reqh->actlen));
+ xfer->hcpriv = NULL;
- reqh->hcpriv = 0;
-
- if (reqh->pipe->repeat) {
- data = opipe->tail;
+ if (xfer->pipe->repeat) {
+ data = opipe->tail.td;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
- if (!tail) {
- reqh->status = USBD_NOMEM;
+ if (tail == NULL) {
+ xfer->status = USBD_NOMEM;
return;
}
- tail->reqh = 0;
+ tail->xfer = NULL;
data->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)
+ if (xfer->flags & USBD_SHORT_XFER_OK)
data->td.td_flags |= LE(OHCI_TD_R);
- data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
+ data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
data->nexttd = tail;
data->td.td_nexttd = LE(tail->physaddr);
- data->td.td_be = LE(LE(data->td.td_cbp) + reqh->length - 1);
- data->len = reqh->length;
- data->reqh = reqh;
+ data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1);
+ data->len = xfer->length;
+ data->xfer = xfer;
data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
- reqh->hcpriv = data;
- reqh->actlen = 0;
+ xfer->hcpriv = data;
+ xfer->actlen = 0;
- ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
}
}
void
-ohci_device_bulk_done(reqh)
- usbd_request_handle reqh;
+ohci_device_bulk_done(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n",
- reqh, reqh->actlen));
+ DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n",
+ xfer, xfer->actlen));
- reqh->hcpriv = 0;
+ xfer->hcpriv = 0;
}
void
-ohci_rhsc(sc, reqh)
+ohci_rhsc(sc, xfer)
ohci_softc_t *sc;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
{
usbd_pipe_handle pipe;
struct ohci_pipe *opipe;
@@ -1059,36 +1285,43 @@ ohci_rhsc(sc, reqh)
int hstatus;
hstatus = OREAD4(sc, OHCI_RH_STATUS);
- DPRINTF(("ohci_rhsc: sc=%p reqh=%p hstatus=0x%08x\n",
- sc, reqh, hstatus));
+ DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n",
+ sc, xfer, hstatus));
- if (reqh == 0) {
+ if (xfer == 0) {
/* Just ignore the change. */
return;
}
- pipe = reqh->pipe;
+ pipe = xfer->pipe;
opipe = (struct ohci_pipe *)pipe;
- p = KERNADDR(&reqh->dmabuf);
- m = min(sc->sc_noport, reqh->length * 8 - 1);
- memset(p, 0, reqh->length);
+ p = KERNADDR(&xfer->dmabuf);
+ m = min(sc->sc_noport, xfer->length * 8 - 1);
+ memset(p, 0, xfer->length);
for (i = 1; i <= m; i++) {
if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16)
p[i/8] |= 1 << (i%8);
}
DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
- reqh->actlen = reqh->length;
- reqh->status = USBD_NORMAL_COMPLETION;
+ xfer->actlen = xfer->length;
+ xfer->status = USBD_NORMAL_COMPLETION;
+
+ usb_transfer_complete(xfer);
+}
- usb_transfer_complete(reqh);
+void
+ohci_root_intr_done(xfer)
+ usbd_xfer_handle xfer;
+{
+ xfer->hcpriv = NULL;
}
void
-ohci_root_intr_done(reqh)
- usbd_request_handle reqh;
+ohci_root_ctrl_done(xfer)
+ usbd_xfer_handle xfer;
{
- reqh->hcpriv = 0;
+ xfer->hcpriv = NULL;
}
/*
@@ -1097,15 +1330,15 @@ ohci_root_intr_done(reqh)
* too long.
*/
void
-ohci_waitintr(sc, reqh)
+ohci_waitintr(sc, xfer)
ohci_softc_t *sc;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
{
- int timo = reqh->timeout;
+ int timo = xfer->timeout;
int usecs;
u_int32_t intrs;
- reqh->status = USBD_IN_PROGRESS;
+ xfer->status = USBD_IN_PROGRESS;
for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
usb_delay_ms(&sc->sc_bus, 1);
intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
@@ -1115,16 +1348,16 @@ ohci_waitintr(sc, reqh)
ohci_dumpregs(sc);
#endif
if (intrs) {
- ohci_intr(sc);
- if (reqh->status != USBD_IN_PROGRESS)
+ ohci_intr1(sc);
+ if (xfer->status != USBD_IN_PROGRESS)
return;
}
}
/* Timeout */
DPRINTF(("ohci_waitintr: timeout\n"));
- reqh->status = USBD_TIMEOUT;
- usb_transfer_complete(reqh);
+ xfer->status = USBD_TIMEOUT;
+ usb_transfer_complete(xfer);
/* XXX should free TD */
}
@@ -1135,23 +1368,23 @@ ohci_poll(bus)
ohci_softc_t *sc = (ohci_softc_t *)bus;
if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
- ohci_intr(sc);
+ ohci_intr1(sc);
}
usbd_status
-ohci_device_request(reqh)
- usbd_request_handle reqh;
+ohci_device_request(xfer)
+ usbd_xfer_handle xfer;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
- usb_device_request_t *req = &reqh->request;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+ usb_device_request_t *req = &xfer->request;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
int addr = dev->address;
- ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail;
+ ohci_soft_td_t *setup, *stat, *next, *tail;
ohci_soft_ed_t *sed;
int isread;
int len;
- usbd_status r;
+ usbd_status err;
int s;
isread = req->bmRequestType & UT_READ;
@@ -1163,54 +1396,44 @@ ohci_device_request(reqh)
UGETW(req->wIndex), len, addr,
opipe->pipe.endpoint->edesc->bEndpointAddress));
- setup = opipe->tail;
+ setup = opipe->tail.td;
stat = ohci_alloc_std(sc);
- if (!stat) {
- r = USBD_NOMEM;
+ if (stat == NULL) {
+ err = USBD_NOMEM;
goto bad1;
}
tail = ohci_alloc_std(sc);
- if (!tail) {
- r = USBD_NOMEM;
+ if (tail == NULL) {
+ err = USBD_NOMEM;
goto bad2;
}
- tail->reqh = 0;
+ tail->xfer = NULL;
sed = opipe->sed;
opipe->u.ctl.length = len;
/* 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. */
+ /* XXXX Should not touch ED here! */
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)));
+ next = stat;
+
/* Set up data transaction */
if (len != 0) {
- data = ohci_alloc_std(sc);
- if (!data) {
- r = USBD_NOMEM;
+ ohci_soft_td_t *std = stat;
+
+ err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
+ std, &stat);
+ stat = stat->nexttd; /* point at free TD */
+ if (err)
goto bad3;
- }
- data->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));
- data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
- data->nexttd = stat;
- data->td.td_nexttd = LE(stat->physaddr);
- data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
- data->len = len;
- data->reqh = reqh;
- data->flags = OHCI_ADD_LEN;
-
- next = data;
- stat->flags = OHCI_CALL_DONE;
- } else {
- next = stat;
- /* XXX ADD_LEN? */
- stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ /* Start toggle at 1 and then use the carried toggle. */
+ std->td.td_flags &= LE(~OHCI_TD_TOGGLE_MASK);
+ std->td.td_flags |= LE(OHCI_TD_TOGGLE_1);
}
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
@@ -1221,20 +1444,21 @@ ohci_device_request(reqh)
setup->nexttd = next;
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->len = 0;
+ setup->xfer = xfer;
setup->flags = 0;
- reqh->hcpriv = setup;
+ xfer->hcpriv = setup;
stat->td.td_flags = LE(
- (isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
+ (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->nexttd = tail;
stat->td.td_nexttd = LE(tail->physaddr);
stat->td.td_be = 0;
+ stat->flags = OHCI_CALL_DONE;
stat->len = 0;
- stat->reqh = reqh;
+ stat->xfer = xfer;
#ifdef OHCI_DEBUG
if (ohcidebug > 5) {
@@ -1246,22 +1470,18 @@ ohci_device_request(reqh)
/* Insert ED in schedule */
s = splusb();
- ohci_hash_add_td(sc, setup);
- if (len != 0)
- ohci_hash_add_td(sc, data);
- ohci_hash_add_td(sc, stat);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
- if (reqh->timeout && !sc->sc_bus.use_polling) {
- usb_timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+ if (xfer->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(ohci_timeout, xfer,
+ MS_TO_TICKS(xfer->timeout), xfer->timo_handle);
}
splx(s);
-#ifdef OHCI_DEBUG
- if (ohcidebug > 5) {
- delay(5000);
+#if 0
+ if (ohcidebug > 10) {
+ delay(10000);
DPRINTF(("ohci_device_request: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
@@ -1276,7 +1496,7 @@ ohci_device_request(reqh)
bad2:
ohci_free_std(sc, stat);
bad1:
- return (r);
+ return (err);
}
/*
@@ -1307,9 +1527,9 @@ ohci_rem_ed(sed, head)
SPLUSBCHECK;
/* XXX */
- for (p = head; p && p->next != sed; p = p->next)
+ for (p = head; p != NULL && p->next != sed; p = p->next)
;
- if (!p)
+ if (p == NULL)
panic("ohci_rem_ed: ED not found\n");
p->next = sed->next;
p->ed.ed_nexted = sed->ed.ed_nexted;
@@ -1359,7 +1579,7 @@ ohci_hash_find_td(sc, a)
ohci_soft_td_t *std;
for (std = LIST_FIRST(&sc->sc_hash_tds[h]);
- std != 0;
+ std != NULL;
std = LIST_NEXT(std, hnext))
if (std->physaddr == a)
return (std);
@@ -1370,15 +1590,15 @@ void
ohci_timeout(addr)
void *addr;
{
- usbd_request_handle reqh = addr;
+ usbd_xfer_handle xfer = addr;
int s;
- DPRINTF(("ohci_timeout: reqh=%p\n", reqh));
+ DPRINTF(("ohci_timeout: xfer=%p\n", xfer));
s = splusb();
- reqh->device->bus->intr_context++;
- ohci_abort_req(reqh, USBD_TIMEOUT);
- reqh->device->bus->intr_context--;
+ xfer->device->bus->intr_context++;
+ ohci_abort_xfer(xfer, USBD_TIMEOUT);
+ xfer->device->bus->intr_context--;
splx(s);
}
@@ -1411,8 +1631,8 @@ void
ohci_dump_ed(sed)
ohci_soft_ed_t *sed;
{
- DPRINTF(("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
- "headp=%b nexted=0x%08lx\n",
+ DPRINTF(("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
+ "headsflags=%b 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)),
@@ -1422,6 +1642,7 @@ ohci_dump_ed(sed)
(u_long)LE(sed->ed.ed_tailp),
(u_long)LE(sed->ed.ed_headp),
"\20\1HALT\2CARRY",
+ (u_long)LE(sed->ed.ed_headp),
(u_long)LE(sed->ed.ed_nexted)));
}
#endif
@@ -1435,10 +1656,15 @@ ohci_open(pipe)
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
u_int8_t addr = dev->address;
+ u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
ohci_soft_ed_t *sed;
ohci_soft_td_t *std;
- usbd_status r;
+ ohci_soft_itd_t *sitd;
+ ohci_physaddr_t tdphys;
+ u_int32_t fmt;
+ usbd_status err;
int s;
+ int ival;
DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, addr, ed->bEndpointAddress, sc->sc_addr));
@@ -1455,30 +1681,43 @@ ohci_open(pipe)
}
} else {
sed = ohci_alloc_sed(sc);
- if (sed == 0)
+ if (sed == NULL)
goto bad0;
- std = ohci_alloc_std(sc);
- if (std == 0)
- goto bad1;
opipe->sed = sed;
- opipe->tail = std;
+ if (xfertype == UE_ISOCHRONOUS) {
+ sitd = ohci_alloc_sitd(sc);
+ if (sitd == NULL) {
+ ohci_free_sitd(sc, sitd);
+ goto bad1;
+ }
+ opipe->tail.itd = sitd;
+ tdphys = LE(sitd->physaddr);
+ fmt = OHCI_ED_FORMAT_ISO;
+ } else {
+ std = ohci_alloc_std(sc);
+ if (std == NULL) {
+ ohci_free_std(sc, std);
+ goto bad1;
+ }
+ opipe->tail.td = std;
+ tdphys = LE(std->physaddr);
+ fmt = OHCI_ED_FORMAT_GEN;
+ }
sed->ed.ed_flags = LE(
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_EN(ed->bEndpointAddress) |
OHCI_ED_DIR_TD |
- (dev->lowspeed ? OHCI_ED_SPEED : 0) |
- ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ?
- OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) |
+ (dev->lowspeed ? OHCI_ED_SPEED : 0) | fmt |
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 = tdphys;
- switch (ed->bmAttributes & UE_XFERTYPE) {
+ switch (xfertype) {
case UE_CONTROL:
pipe->methods = &ohci_device_ctrl_methods;
- r = usb_allocmem(&sc->sc_bus,
+ err = usb_allocmem(&sc->sc_bus,
sizeof(usb_device_request_t),
0, &opipe->u.ctl.reqdma);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
goto bad;
s = splusb();
ohci_add_ed(sed, sc->sc_ctrl_head);
@@ -1486,10 +1725,13 @@ ohci_open(pipe)
break;
case UE_INTERRUPT:
pipe->methods = &ohci_device_intr_methods;
- return (ohci_device_setintr(sc, opipe, ed->bInterval));
+ ival = pipe->interval;
+ if (ival == USBD_DEFAULT_INTERVAL)
+ ival = ed->bInterval;
+ return (ohci_device_setintr(sc, opipe, ival));
case UE_ISOCHRONOUS:
- printf("ohci_open: open iso unimplemented\n");
- return (USBD_INVAL);
+ pipe->methods = &ohci_device_isoc_methods;
+ return (ohci_setup_isoc(pipe));
case UE_BULK:
pipe->methods = &ohci_device_bulk_methods;
s = splusb();
@@ -1526,12 +1768,12 @@ 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))) {
+ if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) !=
+ (sed->ed.ed_headp & LE(OHCI_HEADMASK))) {
ohci_physaddr_t td = sed->ed.ed_headp;
ohci_soft_td_t *std;
for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]);
- std != 0;
+ std != NULL;
std = LIST_NEXT(std, hnext))
if (std->physaddr == td)
break;
@@ -1540,14 +1782,13 @@ ohci_close_pipe(pipe, head)
(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_HEADMASK)) !=
+ (sed->ed.ed_headp & LE(OHCI_HEADMASK)))
printf("ohci_close_pipe: pipe still not empty\n");
}
#endif
ohci_rem_ed(sed, head);
splx(s);
- ohci_free_std(sc, opipe->tail);
ohci_free_sed(sc, opipe->sed);
}
@@ -1562,38 +1803,47 @@ ohci_close_pipe(pipe, head)
* interrupt processing to process it.
*/
void
-ohci_abort_req(reqh, status)
- usbd_request_handle reqh;
+ohci_abort_xfer(xfer, status)
+ usbd_xfer_handle xfer;
usbd_status status;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_soft_ed_t *sed;
- DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe));
+ DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p\n", xfer, opipe));
- reqh->status = status;
+ xfer->status = status;
- usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
+ usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
sed = opipe->sed;
- DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed));
+ DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
- if (reqh->device->bus->intr_context) {
+#if 1
+ if (xfer->device->bus->intr_context) {
/* We have no process context, so we can't use tsleep(). */
- timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+ timeout(ohci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
} else {
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+ KASSERT(intr_nesting_level == 0,
+ ("ohci_abort_req in interrupt context"));
+#endif
usb_delay_ms(opipe->pipe.device->bus, 1);
- ohci_abort_req_end(reqh);
+ ohci_abort_xfer_end(xfer);
}
+#else
+ delay(1000);
+ ohci_abort_xfer_end(xfer);
+#endif
}
void
-ohci_abort_req_end(v)
+ohci_abort_xfer_end(v)
void *v;
{
- usbd_request_handle reqh = v;
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ usbd_xfer_handle xfer = v;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed;
ohci_soft_td_t *p, *n;
@@ -1601,26 +1851,25 @@ ohci_abort_req_end(v)
s = splusb();
- p = reqh->hcpriv;
+ p = xfer->hcpriv;
#ifdef DIAGNOSTIC
- if (!p) {
- printf("ohci_abort_req: hcpriv==0\n");
+ if (p == NULL) {
+ printf("ohci_abort_xfer: hcpriv==0\n");
return;
}
#endif
- for (; p->reqh == reqh; p = n) {
+ for (; p->xfer == xfer; p = n) {
n = p->nexttd;
- ohci_hash_rem_td(sc, p);
ohci_free_std(sc, p);
}
sed = opipe->sed;
- DPRINTFN(2,("ohci_abort_req: set hd=%x, tl=%x\n",
+ DPRINTFN(2,("ohci_abort_xfer: 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);
+ usb_transfer_complete(xfer);
splx(s);
}
@@ -1632,8 +1881,8 @@ usb_device_descriptor_t ohci_devd = {
USB_DEVICE_DESCRIPTOR_SIZE,
UDESC_DEVICE, /* type */
{0x00, 0x01}, /* USB version */
- UCLASS_HUB, /* class */
- USUBCLASS_HUB, /* subclass */
+ UDCLASS_HUB, /* class */
+ UDSUBCLASS_HUB, /* subclass */
0, /* protocol */
64, /* max packet */
{0},{0},{0x00,0x01}, /* device id */
@@ -1660,8 +1909,8 @@ usb_interface_descriptor_t ohci_ifcd = {
0,
0,
1,
- UCLASS_HUB,
- USUBCLASS_HUB,
+ UICLASS_HUB,
+ UISUBCLASS_HUB,
0,
0
};
@@ -1709,40 +1958,40 @@ ohci_str(p, l, s)
* Simulate a hardware hub by handling all the necessary requests.
*/
usbd_status
-ohci_root_ctrl_transfer(reqh)
- usbd_request_handle reqh;
+ohci_root_ctrl_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
/* Pipe isn't running, start first */
- return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-ohci_root_ctrl_start(reqh)
- usbd_request_handle reqh;
+ohci_root_ctrl_start(xfer)
+ usbd_xfer_handle xfer;
{
- ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
+ ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
usb_device_request_t *req;
void *buf = NULL;
int port, i;
int s, len, value, index, l, totlen = 0;
usb_port_status_t ps;
usb_hub_descriptor_t hubd;
- usbd_status r;
+ usbd_status err;
u_int32_t v;
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST))
+ if (!(xfer->rqflags & URQ_REQUEST))
/* XXX panic */
return (USBD_INVAL);
#endif
- req = &reqh->request;
+ req = &xfer->request;
DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n",
req->bmRequestType, req->bRequest));
@@ -1752,7 +2001,7 @@ ohci_root_ctrl_start(reqh)
index = UGETW(req->wIndex);
if (len != 0)
- buf = KERNADDR(&reqh->dmabuf);
+ buf = KERNADDR(&xfer->dmabuf);
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
@@ -1775,7 +2024,7 @@ ohci_root_ctrl_start(reqh)
switch(value >> 8) {
case UDESC_DEVICE:
if ((value & 0xff) != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
@@ -1784,7 +2033,7 @@ ohci_root_ctrl_start(reqh)
break;
case UDESC_CONFIG:
if ((value & 0xff) != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
@@ -1815,7 +2064,7 @@ ohci_root_ctrl_start(reqh)
}
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
break;
@@ -1840,14 +2089,14 @@ ohci_root_ctrl_start(reqh)
break;
case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
if (value >= USB_MAX_DEVICES) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
sc->sc_addr = value;
break;
case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
if (value != 0 && value != 1) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
sc->sc_conf = value;
@@ -1857,7 +2106,7 @@ ohci_root_ctrl_start(reqh)
case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
break;
@@ -1871,7 +2120,7 @@ ohci_root_ctrl_start(reqh)
"port=%d feature=%d\n",
index, value));
if (index < 1 || index > sc->sc_noport) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
port = OHCI_RH_PORT_STATUS(index);
@@ -1901,7 +2150,7 @@ ohci_root_ctrl_start(reqh)
OWRITE4(sc, port, UPS_C_PORT_RESET << 16);
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
switch(value) {
@@ -1920,7 +2169,7 @@ ohci_root_ctrl_start(reqh)
break;
case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
if (value != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
@@ -1942,7 +2191,7 @@ ohci_root_ctrl_start(reqh)
break;
case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
if (len != 4) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
memset(buf, 0, len); /* ? XXX */
@@ -1952,11 +2201,11 @@ ohci_root_ctrl_start(reqh)
DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n",
index));
if (index < 1 || index > sc->sc_noport) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
if (len != 4) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
@@ -1969,13 +2218,13 @@ ohci_root_ctrl_start(reqh)
totlen = l;
break;
case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
break;
case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
if (index < 1 || index > sc->sc_noport) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
port = OHCI_RH_PORT_STATUS(index);
@@ -2004,28 +2253,28 @@ ohci_root_ctrl_start(reqh)
OWRITE4(sc, port, UPS_PORT_POWER);
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
- reqh->actlen = totlen;
- r = USBD_NORMAL_COMPLETION;
+ xfer->actlen = totlen;
+ err = USBD_NORMAL_COMPLETION;
ret:
- reqh->status = r;
+ xfer->status = err;
s = splusb();
- usb_transfer_complete(reqh);
+ usb_transfer_complete(xfer);
splx(s);
return (USBD_IN_PROGRESS);
}
/* Abort a root control request. */
void
-ohci_root_ctrl_abort(reqh)
- usbd_request_handle reqh;
+ohci_root_ctrl_abort(xfer)
+ usbd_xfer_handle xfer;
{
/* Nothing to do, all transfers are synchronous. */
}
@@ -2040,43 +2289,47 @@ ohci_root_ctrl_close(pipe)
}
usbd_status
-ohci_root_intr_transfer(reqh)
- usbd_request_handle reqh;
+ohci_root_intr_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
/* Pipe isn't running, start first */
- return (ohci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-ohci_root_intr_start(reqh)
- usbd_request_handle reqh;
+ohci_root_intr_start(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
+ usbd_pipe_handle pipe = xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
- sc->sc_intrreqh = reqh;
+ sc->sc_intrxfer = xfer;
return (USBD_IN_PROGRESS);
}
/* Abort a root interrupt request. */
void
-ohci_root_intr_abort(reqh)
- usbd_request_handle reqh;
+ohci_root_intr_abort(xfer)
+ usbd_xfer_handle xfer;
{
- if (reqh->pipe->intrreqh == reqh) {
+ int s;
+
+ if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("ohci_root_intr_abort: remove\n"));
- reqh->pipe->intrreqh = 0;
+ xfer->pipe->intrxfer = NULL;
}
- reqh->status = USBD_CANCELLED;
- usb_transfer_complete(reqh);
+ xfer->status = USBD_CANCELLED;
+ s = splusb();
+ usb_transfer_complete(xfer);
+ splx(s);
}
/* Close the root pipe. */
@@ -2088,57 +2341,57 @@ ohci_root_intr_close(pipe)
DPRINTF(("ohci_root_intr_close\n"));
- sc->sc_intrreqh = 0;
+ sc->sc_intrxfer = NULL;
}
/************************/
usbd_status
-ohci_device_ctrl_transfer(reqh)
- usbd_request_handle reqh;
+ohci_device_ctrl_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
/* Pipe isn't running, start first */
- return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-ohci_device_ctrl_start(reqh)
- usbd_request_handle reqh;
+ohci_device_ctrl_start(xfer)
+ usbd_xfer_handle xfer;
{
- ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
- usbd_status r;
+ ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
+ usbd_status err;
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST)) {
+ if (!(xfer->rqflags & URQ_REQUEST)) {
/* XXX panic */
printf("ohci_device_ctrl_transfer: not a request\n");
return (USBD_INVAL);
}
#endif
- r = ohci_device_request(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = ohci_device_request(xfer);
+ if (err)
+ return (err);
if (sc->sc_bus.use_polling)
- ohci_waitintr(sc, reqh);
+ ohci_waitintr(sc, xfer);
return (USBD_IN_PROGRESS);
}
/* Abort a device control request. */
void
-ohci_device_ctrl_abort(reqh)
- usbd_request_handle reqh;
+ohci_device_ctrl_abort(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh));
- ohci_abort_req(reqh, USBD_CANCELLED);
+ DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
+ ohci_abort_xfer(xfer, USBD_CANCELLED);
}
/* Close a device control pipe. */
@@ -2146,10 +2399,12 @@ void
ohci_device_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
ohci_close_pipe(pipe, sc->sc_ctrl_head);
+ ohci_free_std(sc, opipe->tail.td);
}
/************************/
@@ -2160,7 +2415,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_headp &= LE(~OHCI_TOGGLECARRY);
}
void
@@ -2170,48 +2425,48 @@ ohci_noop(pipe)
}
usbd_status
-ohci_device_bulk_transfer(reqh)
- usbd_request_handle reqh;
+ohci_device_bulk_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
/* Pipe isn't running, start first */
- return (ohci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-ohci_device_bulk_start(reqh)
- usbd_request_handle reqh;
+ohci_device_bulk_start(xfer)
+ usbd_xfer_handle xfer;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
int addr = dev->address;
ohci_soft_td_t *data, *tail, *tdp;
ohci_soft_ed_t *sed;
int s, len, isread, endpt;
- usbd_status r;
+ usbd_status err;
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_REQUEST) {
+ if (xfer->rqflags & URQ_REQUEST) {
/* XXX panic */
printf("ohci_device_bulk_start: a request\n");
return (USBD_INVAL);
}
#endif
- len = reqh->length;
- endpt = reqh->pipe->endpoint->edesc->bEndpointAddress;
+ len = xfer->length;
+ endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
isread = UE_GET_DIR(endpt) == UE_DIR_IN;
sed = opipe->sed;
- DPRINTFN(4,("ohci_device_bulk_start: reqh=%p len=%d isread=%d "
- "flags=%d endpt=%d\n", reqh, len, isread, reqh->flags,
+ DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d "
+ "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags,
endpt));
opipe->u.bulk.isread = isread;
@@ -2223,15 +2478,18 @@ ohci_device_bulk_start(reqh)
OHCI_ED_SET_FA(addr));
/* Allocate a chain of new TDs (including a new tail). */
- data = opipe->tail;
- r = ohci_alloc_std_chain(opipe, sc, len, isread,
- reqh->flags & USBD_SHORT_XFER_OK,
- &reqh->dmabuf, data, &tail);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
-
- tail->reqh = 0;
- reqh->hcpriv = data;
+ data = opipe->tail.td;
+ err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, data, &tail);
+ /* We want interrupt at the end of the transfer. */
+ tail->td.td_flags &= LE(~OHCI_TD_INTR_MASK);
+ tail->td.td_flags |= LE(OHCI_TD_SET_DI(1));
+ tail->flags |= OHCI_CALL_DONE;
+ tail = tail->nexttd; /* point at sentinel */
+ if (err)
+ return (err);
+
+ tail->xfer = NULL;
+ xfer->hcpriv = data;
DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
"td_cbp=0x%08x td_be=0x%08x\n",
@@ -2239,7 +2497,7 @@ ohci_device_bulk_start(reqh)
(int)LE(data->td.td_cbp), (int)LE(data->td.td_be)));
#ifdef OHCI_DEBUG
- if (ohcidebug > 4) {
+ if (ohcidebug > 5) {
ohci_dump_ed(sed);
ohci_dump_tds(data);
}
@@ -2248,22 +2506,21 @@ ohci_device_bulk_start(reqh)
/* Insert ED in schedule */
s = splusb();
for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
- tdp->reqh = reqh;
- ohci_hash_add_td(sc, tdp);
+ tdp->xfer = xfer;
}
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
- if (reqh->timeout && !sc->sc_bus.use_polling) {
- usb_timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+ if (xfer->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(ohci_timeout, xfer,
+ MS_TO_TICKS(xfer->timeout), xfer->timo_handle);
}
#if 0
/* This goes wrong if we are too slow. */
- if (ohcidebug > 5) {
- delay(5000);
+ if (ohcidebug > 10) {
+ delay(10000);
DPRINTF(("ohci_device_intr_transfer: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
@@ -2277,11 +2534,11 @@ ohci_device_bulk_start(reqh)
}
void
-ohci_device_bulk_abort(reqh)
- usbd_request_handle reqh;
+ohci_device_bulk_abort(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh));
- ohci_abort_req(reqh, USBD_CANCELLED);
+ DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
+ ohci_abort_xfer(xfer, USBD_CANCELLED);
}
/*
@@ -2291,34 +2548,36 @@ void
ohci_device_bulk_close(pipe)
usbd_pipe_handle pipe;
{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
ohci_close_pipe(pipe, sc->sc_bulk_head);
+ ohci_free_std(sc, opipe->tail.td);
}
/************************/
usbd_status
-ohci_device_intr_transfer(reqh)
- usbd_request_handle reqh;
+ohci_device_intr_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
/* Pipe isn't running, start first */
- return (ohci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-ohci_device_intr_start(reqh)
- usbd_request_handle reqh;
+ohci_device_intr_start(xfer)
+ usbd_xfer_handle xfer;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
ohci_soft_ed_t *sed = opipe->sed;
@@ -2326,36 +2585,36 @@ ohci_device_intr_start(reqh)
int len;
int s;
- DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p len=%d "
+ DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d "
"flags=%d priv=%p\n",
- reqh, reqh->length, reqh->flags, reqh->priv));
+ xfer, xfer->length, xfer->flags, xfer->priv));
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_REQUEST)
+ if (xfer->rqflags & URQ_REQUEST)
panic("ohci_device_intr_transfer: a request\n");
#endif
- len = reqh->length;
+ len = xfer->length;
- data = opipe->tail;
+ data = opipe->tail.td;
tail = ohci_alloc_std(sc);
- if (!tail)
+ if (tail == NULL)
return (USBD_NOMEM);
- tail->reqh = 0;
+ tail->xfer = NULL;
data->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)
+ if (xfer->flags & USBD_SHORT_XFER_OK)
data->td.td_flags |= LE(OHCI_TD_R);
- data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
+ data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
data->nexttd = tail;
data->td.td_nexttd = LE(tail->physaddr);
data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
data->len = len;
- data->reqh = reqh;
+ data->xfer = xfer;
data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
- reqh->hcpriv = data;
+ xfer->hcpriv = data;
#ifdef OHCI_DEBUG
if (ohcidebug > 5) {
@@ -2367,9 +2626,8 @@ ohci_device_intr_start(reqh)
/* Insert ED in schedule */
s = splusb();
- ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
#if 0
@@ -2379,7 +2637,7 @@ ohci_device_intr_start(reqh)
* TD is gone.
*/
if (ohcidebug > 5) {
- delay(5000);
+ usb_delay_ms(&sc->sc_bus, 5);
DPRINTF(("ohci_device_intr_transfer: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
@@ -2393,14 +2651,14 @@ ohci_device_intr_start(reqh)
/* Abort a device control request. */
void
-ohci_device_intr_abort(reqh)
- usbd_request_handle reqh;
+ohci_device_intr_abort(xfer)
+ usbd_xfer_handle xfer;
{
- if (reqh->pipe->intrreqh == reqh) {
+ if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("ohci_device_intr_abort: remove\n"));
- reqh->pipe->intrreqh = 0;
+ xfer->pipe->intrxfer = NULL;
}
- ohci_abort_req(reqh, USBD_CANCELLED);
+ ohci_abort_xfer(xfer, USBD_CANCELLED);
}
/* Close a device interrupt pipe. */
@@ -2420,14 +2678,16 @@ ohci_device_intr_close(pipe)
pipe, nslots, pos));
s = splusb();
sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
- if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) !=
- (sed->ed.ed_headp & LE(OHCI_TAILMASK)))
+ if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) !=
+ (sed->ed.ed_headp & LE(OHCI_HEADMASK)))
usb_delay_ms(&sc->sc_bus, 2);
for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
;
- if (!p)
+#ifdef DIAGNOSTIC
+ if (p == NULL)
panic("ohci_device_intr_close: ED not found\n");
+#endif
p->next = sed->next;
p->ed.ed_nexted = sed->ed.ed_nexted;
splx(s);
@@ -2435,7 +2695,7 @@ ohci_device_intr_close(pipe)
for (j = 0; j < nslots; j++)
--sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
- ohci_free_std(sc, opipe->tail);
+ ohci_free_std(sc, opipe->tail.td);
ohci_free_sed(sc, opipe->sed);
}
@@ -2504,3 +2764,149 @@ ohci_device_setintr(sc, opipe, ival)
return (USBD_NORMAL_COMPLETION);
}
+/***********************/
+
+usbd_status
+ohci_device_isoc_transfer(xfer)
+ usbd_xfer_handle xfer;
+{
+ usbd_status err;
+
+ DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
+
+ /* Put it on our queue, */
+ err = usb_insert_transfer(xfer);
+
+ /* bail out on error, */
+ if (err && err != USBD_IN_PROGRESS)
+ return (err);
+
+ /* XXX should check inuse here */
+
+ /* insert into schedule */
+ ohci_device_isoc_enter(xfer);
+
+ /* and put on interrupt list if the pipe wasn't running */
+ if (!err)
+ ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+
+ return (err);
+}
+
+void
+ohci_device_isoc_enter(xfer)
+ usbd_xfer_handle xfer;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+ usbd_device_handle dev = opipe->pipe.device;
+ ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+ ohci_soft_ed_t *sed = opipe->sed;
+ struct iso *iso = &opipe->u.iso;
+ ohci_soft_itd_t *sitd, *nsitd;
+ ohci_physaddr_t buf, offs;
+ int i, ncur, nframes;
+ int ncross;
+ int s;
+
+ s = splusb();
+ sitd = opipe->tail.itd;
+ buf = DMAADDR(&xfer->dmabuf);
+ sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK);
+ nframes = xfer->nframes;
+ offs = buf & OHCI_ITD_OFFSET_MASK;
+ ncross = 0;
+ for (i = ncur = 0; i < nframes; i ++, ncur++) {
+ if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */
+ ncross > 1) { /* too many page crossings */
+ nsitd = ohci_alloc_sitd(sc);
+ if (nsitd == NULL) {
+ /* XXX what now? */
+ return;
+ }
+ sitd->nextitd = nsitd;
+ sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+ sitd->itd.itd_flags = LE(
+ OHCI_ITD_NOCC |
+ OHCI_ITD_SET_SF(iso->next) |
+ OHCI_ITD_NOINTR |
+ OHCI_ITD_SET_FC(OHCI_ITD_NOFFSET));
+ sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+ nsitd->itd.itd_bp0 = LE((buf + offs) & OHCI_ITD_PAGE_MASK);
+ sitd = nsitd;
+ iso->next = iso->next + ncur;
+ ncur = 0;
+ ncross = 0;
+ }
+ /* XXX byte order */
+ sitd->itd.itd_offset[i] =
+ offs | (ncross == 1 ? OHCI_ITD_PAGE_SELECT : 0);
+ offs += xfer->frlengths[i];
+ /* XXX update ncross */
+ }
+ nsitd = ohci_alloc_sitd(sc);
+ if (nsitd == NULL) {
+ /* XXX what now? */
+ return;
+ }
+ sitd->nextitd = nsitd;
+ sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+ sitd->itd.itd_flags = LE(
+ OHCI_ITD_NOCC |
+ OHCI_ITD_SET_SF(iso->next) |
+ OHCI_ITD_SET_DI(0) |
+ OHCI_ITD_SET_FC(ncur));
+ sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+ iso->next = iso->next + ncur;
+
+ opipe->tail.itd = nsitd;
+ sed->ed.ed_tailp = LE(nsitd->physaddr);
+ /* XXX update ED */
+ splx(s);
+}
+
+usbd_status
+ohci_device_isoc_start(xfer)
+ usbd_xfer_handle xfer;
+{
+ printf("ohci_device_isoc_start: not implemented\n");
+ return (USBD_INVAL);
+}
+
+void
+ohci_device_isoc_abort(xfer)
+ usbd_xfer_handle xfer;
+{
+}
+
+void
+ohci_device_isoc_done(xfer)
+ usbd_xfer_handle xfer;
+{
+ printf("ohci_device_isoc_done: not implemented\n");
+}
+
+usbd_status
+ohci_setup_isoc(pipe)
+ usbd_pipe_handle pipe;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+ struct iso *iso = &opipe->u.iso;
+
+ iso->next = -1;
+ iso->inuse = 0;
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+ohci_device_isoc_close(pipe)
+ usbd_pipe_handle pipe;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
+
+ DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
+ ohci_close_pipe(pipe, sc->sc_isoc_head);
+ ohci_free_sitd(sc, opipe->tail.itd);
+}
+
diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h
index 67b010a0e5a..c9700f6be29 100644
--- a/sys/dev/usb/ohcireg.h
+++ b/sys/dev/usb/ohcireg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohcireg.h,v 1.3 1999/09/27 18:03:55 fgsch Exp $ */
-/* $NetBSD: ohcireg.h,v 1.9 1999/09/15 21:14:03 augustss Exp $ */
+/* $OpenBSD: ohcireg.h,v 1.4 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: ohcireg.h,v 1.15 2000/03/19 22:24:58 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -109,6 +109,9 @@
#define OHCI_GET_NDP(s) ((s) & 0xff)
#define OHCI_PSM 0x0100 /* Power Switching Mode */
#define OHCI_NPS 0x0200 /* No Power Switching */
+#define OHCI_DT 0x0400 /* Device Type */
+#define OHCI_OCPM 0x0800 /* Overcurrent Protection Mode */
+#define OHCI_NOCP 0x1000 /* No Overcurrent Protection */
#define OHCI_GET_POTPGT(s) ((s) >> 24)
#define OHCI_RH_DESCRIPTOR_B 0x4c
#define OHCI_RH_STATUS 0x50
@@ -162,10 +165,10 @@ typedef struct {
#define OHCI_ED_SET_MAXP(s) ((s) << 16)
#define OHCI_ED_MAXPMASK (0x7ff << 16)
ohci_physaddr_t ed_tailp;
-#define OHCI_HALTED 0x00000002
-#define OHCI_TOGGLECARRY 0x00000001
-#define OHCI_TAILMASK 0xfffffffc
ohci_physaddr_t ed_headp;
+#define OHCI_HALTED 0x00000001
+#define OHCI_TOGGLECARRY 0x00000002
+#define OHCI_HEADMASK 0xfffffffc
ohci_physaddr_t ed_nexted;
} ohci_ed_t;
/* #define OHCI_ED_SIZE 16 */
@@ -181,9 +184,11 @@ typedef struct {
#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */
#define OHCI_TD_SET_DI(x) ((x) << 21)
#define OHCI_TD_NOINTR 0x00e00000
+#define OHCI_TD_INTR_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000
+#define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */
#define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */
#define OHCI_TD_NOCC 0xf0000000
@@ -194,6 +199,32 @@ typedef struct {
/* #define OHCI_TD_SIZE 16 */
#define OHCI_TD_ALIGN 16
+#define OHCI_ITD_NOFFSET 8
+typedef struct {
+ u_int32_t itd_flags;
+#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff)
+#define OHCI_ITD_SET_SF(x) ((x) & 0xffff)
+#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay interrupt */
+#define OHCI_ITD_SET_DI(x) ((x) << 21)
+#define OHCI_ITD_NOINTR 0x00e00000
+#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */
+#define OHCI_ITD_SET_FC(x) (((x)-1) << 24)
+#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */
+#define OHCI_ITD_NOCC 0xf0000000
+ ohci_physaddr_t itd_bp0; /* Buffer Page 0 */
+#define OHCI_ITD_OFFSET_MASK 0x00000fff
+#define OHCI_ITD_PAGE_MASK (~OHCI_ITD_OFFSET_MASK)
+ ohci_physaddr_t itd_nextitd; /* Next ITD */
+ ohci_physaddr_t itd_be; /* Buffer End */
+ u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */
+#define itd_pswn itd_offset /* Packet Status Word */
+#define OHCI_ITD_PAGE_SELECT 0x00001000
+#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */
+#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */
+} ohci_itd_t;
+/* #define OHCI_ITD_SIZE 32 */
+#define OHCI_ITD_ALIGN 32
+
#define OHCI_CC_NO_ERROR 0
#define OHCI_CC_CRC 1
#define OHCI_CC_BIT_STUFFING 2
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index e33423dfb98..a0ad463063c 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohcivar.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: ohcivar.h,v 1.11 1999/09/15 21:14:03 augustss Exp $ */
+/* $OpenBSD: ohcivar.h,v 1.7 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: ohcivar.h,v 1.20 2000/02/22 11:30:55 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -52,7 +52,7 @@ typedef struct ohci_soft_td {
struct ohci_soft_td *dnext; /* next in done list */
ohci_physaddr_t physaddr;
LIST_ENTRY(ohci_soft_td) hnext;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
u_int16_t len;
u_int16_t flags;
#define OHCI_CALL_DONE 0x0001
@@ -61,6 +61,14 @@ typedef struct ohci_soft_td {
#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
#define OHCI_STD_CHUNK 128
+typedef struct ohci_soft_itd {
+ ohci_itd_t itd;
+ struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */
+ ohci_physaddr_t physaddr;
+} ohci_soft_itd_t;
+#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN)
+#define OHCI_SITD_CHUNK 64
+
#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)
#define OHCI_HASH_SIZE 128
@@ -76,6 +84,7 @@ typedef struct ohci_softc {
u_int sc_bws[OHCI_NO_INTRS];
u_int32_t sc_eintrs;
+ ohci_soft_ed_t *sc_isoc_head;
ohci_soft_ed_t *sc_ctrl_head;
ohci_soft_ed_t *sc_bulk_head;
@@ -87,19 +96,30 @@ typedef struct ohci_softc {
ohci_soft_ed_t *sc_freeeds;
ohci_soft_td_t *sc_freetds;
+ ohci_soft_itd_t *sc_freeitds;
+
+ SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
- usbd_request_handle sc_intrreqh;
+ usbd_xfer_handle sc_intrxfer;
+
+ ohci_physaddr_t sc_done;
char sc_vendor[16];
int sc_id_vendor;
- void *sc_powerhook;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+#endif
+
device_ptr_t sc_child;
} ohci_softc_t;
usbd_status ohci_init __P((ohci_softc_t *));
int ohci_intr __P((void *));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
int ohci_detach __P((ohci_softc_t *, int));
int ohci_activate __P((device_ptr_t, enum devact));
+#endif
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
diff --git a/sys/dev/usb/uaudio.c b/sys/dev/usb/uaudio.c
index 2c186819ca1..558f721b9d7 100644
--- a/sys/dev/usb/uaudio.c
+++ b/sys/dev/usb/uaudio.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uaudio.c,v 1.1 1999/11/11 15:54:59 ho Exp $ */
-/* $NetBSD: uaudio.c,v 1.5 1999/10/25 10:16:49 augustss Exp $ */
+/* $OpenBSD: uaudio.c,v 1.2 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: uaudio.c,v 1.20 2000/03/24 13:02:00 augustss Exp $ */
/*
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -132,11 +132,13 @@ struct chan {
int curchanbuf;
struct chanbuf {
struct chan *chan;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
u_char *buffer;
u_int16_t sizes[UAUDIO_NFRAMES];
u_int16_t size;
} chanbufs[UAUDIO_NCHANBUFS];
+
+ struct uaudio_softc *sc; /* our softc */
};
struct uaudio_softc {
@@ -154,6 +156,8 @@ struct uaudio_softc {
int sc_nullalt;
+ int sc_audio_rev;
+
struct as_info *sc_alts;
int sc_nalts;
int sc_props;
@@ -204,6 +208,9 @@ void uaudio_add_selector __P((struct uaudio_softc *sc, usb_descriptor_t *v,
usb_descriptor_t **dps));
void uaudio_add_feature __P((struct uaudio_softc *sc, usb_descriptor_t *v,
usb_descriptor_t **dps));
+void uaudio_add_processing_updown __P((struct uaudio_softc *sc,
+ usb_descriptor_t *v,
+ usb_descriptor_t **dps));
void uaudio_add_processing __P((struct uaudio_softc *sc, usb_descriptor_t *v,
usb_descriptor_t **dps));
void uaudio_add_extension __P((struct uaudio_softc *sc, usb_descriptor_t *v,
@@ -232,11 +239,11 @@ void uaudio_chan_free_buffers __P((struct uaudio_softc *, struct chan *));
void uaudio_chan_set_param __P((struct chan *ch, struct audio_params *param,
u_char *start, u_char *end, int blksize));
void uaudio_chan_ptransfer __P((struct chan *ch));
-void uaudio_chan_pintr __P((usbd_request_handle reqh,
+void uaudio_chan_pintr __P((usbd_xfer_handle xfer,
usbd_private_handle priv, usbd_status status));
void uaudio_chan_rtransfer __P((struct chan *ch));
-void uaudio_chan_rintr __P((usbd_request_handle reqh,
+void uaudio_chan_rintr __P((usbd_xfer_handle xfer,
usbd_private_handle priv, usbd_status status));
@@ -304,14 +311,15 @@ USB_MATCH(uaudio)
USB_MATCH_START(uaudio, uaa);
usb_interface_descriptor_t *id;
- if (!uaa->iface)
+ if (uaa->iface == NULL)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
/* Trigger on the control interface. */
- if (!id ||
- id->bInterfaceClass != UCLASS_AUDIO ||
- id->bInterfaceSubClass != USUBCLASS_AUDIOCONTROL)
+ if (id == NULL ||
+ id->bInterfaceClass != UICLASS_AUDIO ||
+ id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
+ (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
return (UMATCH_NONE);
return (UMATCH_IFACECLASS_IFACESUBCLASS);
@@ -323,7 +331,7 @@ USB_ATTACH(uaudio)
usb_interface_descriptor_t *id;
usb_config_descriptor_t *cdesc;
char devinfo[1024];
- usbd_status r;
+ usbd_status err;
int i;
usbd_devinfo(uaa->device, 0, devinfo);
@@ -332,36 +340,50 @@ USB_ATTACH(uaudio)
sc->sc_udev = uaa->device;
cdesc = usbd_get_config_descriptor(sc->sc_udev);
- if (!cdesc)
+ if (cdesc == NULL) {
+ printf("%s: failed to get configuration descriptor\n",
+ USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
+ }
- r = uaudio_identify(sc, cdesc);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = uaudio_identify(sc, cdesc);
+ if (err) {
printf("%s: audio descriptors make no sense, error=%d\n",
- USBDEVNAME(sc->sc_dev), r);
+ USBDEVNAME(sc->sc_dev), err);
USB_ATTACH_ERROR_RETURN;
}
sc->sc_ac_ifaceh = uaa->iface;
/* Pick up the AS interface. */
for (i = 0; i < uaa->nifaces; i++) {
- if (uaa->ifaces[i]) {
+ if (uaa->ifaces[i] != NULL) {
id = usbd_get_interface_descriptor(uaa->ifaces[i]);
- if (id->bInterfaceNumber == sc->sc_as_iface) {
+ if (id != NULL &&
+ id->bInterfaceNumber == sc->sc_as_iface) {
sc->sc_as_ifaceh = uaa->ifaces[i];
- uaa->ifaces[i] = 0;
+ uaa->ifaces[i] = NULL;
+ break;
}
}
}
- if (!sc->sc_as_ifaceh) {
+ if (sc->sc_as_ifaceh == NULL) {
printf("%s: missing AS interface(s)\n",USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
+ printf("%s: streaming interface %d, audio rev %d.%02x\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_as_iface,
+ sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
+
+ sc->sc_chan.sc = sc;
+
DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
/* sc->sc_audiodev = */ audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
USB_ATTACH_SUCCESS_RETURN;
}
@@ -395,9 +417,15 @@ uaudio_detach(self, flags)
struct uaudio_softc *sc = (struct uaudio_softc *)self;
int rv = 0;
- if (sc->sc_audiodev)
+ /* Wait for outstanding requests to complete. */
+ usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
+
+ if (sc->sc_audiodev != NULL)
rv = config_detach(sc->sc_audiodev, flags);
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
return (rv);
}
@@ -484,7 +512,7 @@ uaudio_find_iface(buf, size, offsp, subtype)
d = (void *)(buf + *offsp);
*offsp += d->bLength;
if (d->bDescriptorType == UDESC_INTERFACE &&
- d->bInterfaceClass == UCLASS_AUDIO &&
+ d->bInterfaceClass == UICLASS_AUDIO &&
d->bInterfaceSubClass == subtype)
return (d);
}
@@ -496,7 +524,7 @@ uaudio_mixer_add_ctl(sc, mc)
struct uaudio_softc *sc;
struct mixerctl *mc;
{
- if (sc->sc_nctls == 0)
+ if (sc->sc_nctls == NULL)
sc->sc_ctls = malloc(sizeof *mc, M_USBDEV, M_NOWAIT);
else
#ifdef __OpenBSD__
@@ -514,7 +542,7 @@ uaudio_mixer_add_ctl(sc, mc)
(sc->sc_nctls+1) * sizeof *mc,
M_USBDEV, M_NOWAIT);
#endif
- if (sc->sc_ctls == 0) {
+ if (sc->sc_ctls == NULL) {
printf("uaudio_mixer_add_ctl: no memory\n");
return;
}
@@ -623,7 +651,7 @@ uaudio_get_cluster(id, dps)
bad:
printf("uaudio_get_cluster: bad data\n");
memset(&r, 0, sizeof r);
- return r;
+ return (r);
}
@@ -644,7 +672,6 @@ uaudio_add_input(sc, v, dps)
d->bNrChannels, UGETW(d->wChannelConfig),
d->iChannelNames, d->iTerminal));
#endif
- printf("uaudio_add_input: not implemented\n");
}
void
@@ -837,7 +864,7 @@ uaudio_add_feature(sc, v, dps)
mix.ctlunit = AudioNtreble;
break;
case GRAPHIC_EQUALIZER_CONTROL:
- continue; /* don't add anything */
+ continue; /* XXX don't add anything */
break;
case AGC_CONTROL:
mix.type = MIX_ON_OFF;
@@ -873,19 +900,88 @@ uaudio_add_feature(sc, v, dps)
}
void
+uaudio_add_processing_updown(sc, v, dps)
+ struct uaudio_softc *sc;
+ usb_descriptor_t *v;
+ usb_descriptor_t **dps;
+{
+ struct usb_audio_processing_unit *d =
+ (struct usb_audio_processing_unit *)v;
+ struct usb_audio_processing_unit_1 *d1 =
+ (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
+ struct usb_audio_processing_unit_updown *ud =
+ (struct usb_audio_processing_unit_updown *)
+ &d1->bmControls[d1->bControlSize];
+ struct mixerctl mix;
+ int i;
+
+ DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
+ d->bUnitId, ud->bNrModes));
+
+ if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
+ DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
+ return;
+ }
+
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
+ mix.class = -1;
+ mix.type = MIX_ON_OFF; /* XXX */
+ mix.ctlunit = "";
+ sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
+
+ for (i = 0; i < ud->bNrModes; i++) {
+ DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
+ i, UGETW(ud->waModes[i])));
+ /* XXX */
+ }
+ uaudio_mixer_add_ctl(sc, &mix);
+}
+
+void
uaudio_add_processing(sc, v, dps)
struct uaudio_softc *sc;
usb_descriptor_t *v;
usb_descriptor_t **dps;
{
-#ifdef UAUDIO_DEBUG
struct usb_audio_processing_unit *d =
- (struct usb_audio_processing_unit *)v;
+ (struct usb_audio_processing_unit *)v;
+ struct usb_audio_processing_unit_1 *d1 =
+ (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
+ int ptype = UGETW(d->wProcessType);
+ struct mixerctl mix;
- DPRINTFN(2,("uaudio_add_processing: bUnitId=%d bNrInPins=%d\n",
- d->bUnitId, d->bNrInPins));
- printf("uaudio_add_processing: NOT IMPLEMENTED\n");
+ DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
+ "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
+
+ if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.nchan = 1;
+ mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
+ mix.class = -1;
+ mix.type = MIX_ON_OFF;
+ mix.ctlunit = "";
+ sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
+ uaudio_mixer_add_ctl(sc, &mix);
+ }
+
+ switch (ptype) {
+ case UPDOWNMIX_PROCESS:
+ uaudio_add_processing_updown(sc, v, dps);
+ break;
+ case DOLBY_PROLOGIC_PROCESS:
+ case P3D_STEREO_EXTENDER_PROCESS:
+ case REVERBATION_PROCESS:
+ case CHORUS_PROCESS:
+ case DYN_RANGE_COMP_PROCESS:
+ default:
+#ifdef UAUDIO_DEBUG
+ printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
+ d->bUnitId, ptype);
#endif
+ break;
+ }
}
void
@@ -903,7 +999,7 @@ uaudio_add_extension(sc, v, dps)
DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
d->bUnitId, d->bNrInPins));
- if (d1->bmControls[0] & (1 << UA_EXT_ENABLE)) {
+ if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
mix.nchan = 1;
mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
@@ -920,11 +1016,11 @@ uaudio_identify(sc, cdesc)
struct uaudio_softc *sc;
usb_config_descriptor_t *cdesc;
{
- usbd_status r;
+ usbd_status err;
- r = uaudio_identify_ac(sc, cdesc);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = uaudio_identify_ac(sc, cdesc);
+ if (err)
+ return (err);
return (uaudio_identify_as(sc, cdesc));
}
@@ -933,7 +1029,7 @@ uaudio_add_alt(sc, ai)
struct uaudio_softc *sc;
struct as_info *ai;
{
- if (sc->sc_nalts == 0)
+ if (sc->sc_nalts == NULL)
sc->sc_alts = malloc(sizeof *ai, M_USBDEV, M_NOWAIT);
else
#ifdef __OpenBSD__
@@ -1084,7 +1180,7 @@ uaudio_identify_as(sc, cdesc)
usb_config_descriptor_t *cdesc;
{
usb_interface_descriptor_t *id;
- usbd_status r;
+ usbd_status err;
char *buf;
int size, offs;
@@ -1093,8 +1189,8 @@ uaudio_identify_as(sc, cdesc)
/* Locate the AudioStreaming interface descriptor. */
offs = 0;
- id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOSTREAM);
- if (!id)
+ id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
+ if (id == NULL)
return (USBD_INVAL);
sc->sc_as_iface = id->bInterfaceNumber;
DPRINTF(("uaudio_identify_as: AS interface is %d\n", sc->sc_as_iface));
@@ -1110,7 +1206,7 @@ uaudio_identify_as(sc, cdesc)
sc->sc_nullalt = id->bAlternateSetting;
break;
case 1:
- r = uaudio_process_as(sc, buf, &offs, size, id);
+ err = uaudio_process_as(sc, buf, &offs, size, id);
break;
default:
#ifdef AUDIO_DEBUG
@@ -1120,7 +1216,7 @@ uaudio_identify_as(sc, cdesc)
#endif
break;
}
- id = uaudio_find_iface(buf, size, &offs,USUBCLASS_AUDIOSTREAM);
+ id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
if (!id)
break;
}
@@ -1151,8 +1247,8 @@ uaudio_identify_ac(sc, cdesc)
/* Locate the AudioControl interface descriptor. */
offs = 0;
- id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOCONTROL);
- if (!id)
+ id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
+ if (id == NULL)
return (USBD_INVAL);
if (offs + sizeof *acdp > size)
return (USBD_INVAL);
@@ -1173,8 +1269,9 @@ uaudio_identify_ac(sc, cdesc)
UGETW(acdp->bcdADC) != UAUDIO_VERSION)
return (USBD_INVAL);
+ sc->sc_audio_rev = UGETW(acdp->bcdADC);
DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n",
- UGETW(acdp->bcdADC), aclen));
+ sc->sc_audio_rev, aclen));
sc->sc_nullalt = -1;
@@ -1204,7 +1301,7 @@ uaudio_identify_ac(sc, cdesc)
for (i = 0; i < ndps; i++) {
dp = dps[i];
- if (dp == 0)
+ if (dp == NULL)
continue;
DPRINTF(("uaudio_identify: subtype=%d\n",
dp->bDescriptorSubtype));
@@ -1362,7 +1459,7 @@ uaudio_halt_out_dma(addr)
struct uaudio_softc *sc = addr;
DPRINTF(("uaudio_halt_out_dma: enter\n"));
- if (sc->sc_chan.pipe) {
+ if (sc->sc_chan.pipe != NULL) {
uaudio_chan_close(sc, &sc->sc_chan);
sc->sc_chan.pipe = 0;
uaudio_chan_free_buffers(sc, &sc->sc_chan);
@@ -1377,7 +1474,7 @@ uaudio_halt_in_dma(addr)
struct uaudio_softc *sc = addr;
DPRINTF(("uaudio_halt_in_dma: enter\n"));
- if (sc->sc_chan.pipe) {
+ if (sc->sc_chan.pipe != NULL) {
uaudio_chan_close(sc, &sc->sc_chan);
sc->sc_chan.pipe = 0;
uaudio_chan_free_buffers(sc, &sc->sc_chan);
@@ -1437,9 +1534,6 @@ uaudio_get_props(addr)
{
struct uaudio_softc *sc = addr;
- if (sc->sc_dying)
- return (EIO);
-
return (sc->sc_props);
}
@@ -1450,7 +1544,7 @@ uaudio_get(sc, which, type, wValue, wIndex, len)
{
usb_device_request_t req;
u_int8_t data[4];
- usbd_status r;
+ usbd_status err;
int val;
if (wValue == -1)
@@ -1464,9 +1558,9 @@ uaudio_get(sc, which, type, wValue, wIndex, len)
DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
"wIndex=0x%04x len=%d\n",
type, which, wValue, wIndex, len));
- r = usbd_do_request(sc->sc_udev, &req, &data);
- if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("uaudio_get: r=%d\n", r));
+ err = usbd_do_request(sc->sc_udev, &req, &data);
+ if (err) {
+ DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
return (-1);
}
switch (len) {
@@ -1491,7 +1585,7 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val)
{
usb_device_request_t req;
u_int8_t data[4];
- usbd_status r;
+ usbd_status err;
if (wValue == -1)
return;
@@ -1515,9 +1609,9 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val)
DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
"wIndex=0x%04x len=%d, val=%d\n",
type, which, wValue, wIndex, len, val & 0xffff));
- r = usbd_do_request(sc->sc_udev, &req, &data);
+ err = usbd_do_request(sc->sc_udev, &req, &data);
#ifdef UAUDIO_DEBUG
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
DPRINTF(("uaudio_set: r=%d\n", r));
#endif
}
@@ -1687,7 +1781,7 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param)
{
struct uaudio_softc *sc = addr;
struct chan *ch = &sc->sc_chan;
- usbd_status r;
+ usbd_status err;
int i, s;
if (sc->sc_dying)
@@ -1701,12 +1795,12 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param)
"fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
ch->fraction));
- r = uaudio_chan_alloc_buffers(sc, ch);
- if (r != USBD_NORMAL_COMPLETION)
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
return (EIO);
- r = uaudio_chan_open(sc, ch);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
uaudio_chan_free_buffers(sc, ch);
return (EIO);
}
@@ -1733,7 +1827,7 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param)
{
struct uaudio_softc *sc = addr;
struct chan *ch = &sc->sc_chan;
- usbd_status r;
+ usbd_status err;
int i, s;
if (sc->sc_dying)
@@ -1747,12 +1841,12 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param)
"fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
ch->fraction));
- r = uaudio_chan_alloc_buffers(sc, ch);
- if (r != USBD_NORMAL_COMPLETION)
+ err = uaudio_chan_alloc_buffers(sc, ch);
+ if (err)
return (EIO);
- r = uaudio_chan_open(sc, ch);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = uaudio_chan_open(sc, ch);
+ if (err) {
uaudio_chan_free_buffers(sc, ch);
return (EIO);
}
@@ -1776,29 +1870,29 @@ uaudio_chan_open(sc, ch)
{
struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
int endpt = as->edesc->bEndpointAddress;
- usbd_status r;
+ usbd_status err;
DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
endpt, ch->sample_rate, as->alt));
/* Set alternate interface corresponding to the mode. */
- r = usbd_set_interface(sc->sc_as_ifaceh, as->alt);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_set_interface(sc->sc_as_ifaceh, as->alt);
+ if (err)
+ return (err);
/* Some devices do not support this request, so ignore errors. */
#ifdef UAUDIO_DEBUG
- r = uaudio_set_speed(sc, endpt, ch->sample_rate);
- if (r != USBD_NORMAL_COMPLETION)
+ err = uaudio_set_speed(sc, endpt, ch->sample_rate);
+ if (err)
DPRINTF(("uaudio_chan_open: set_speed failed r=%s\n",
- usbd_errstr(r)));
+ usbd_errstr(err)));
#else
(void)uaudio_set_speed(sc, endpt, ch->sample_rate);
#endif
DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
- r = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe);
- return (r);
+ err = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe);
+ return (err);
}
void
@@ -1820,17 +1914,17 @@ uaudio_chan_alloc_buffers(sc, ch)
struct uaudio_softc *sc;
struct chan *ch;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
void *buf;
int i, size;
size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
- reqh = usbd_alloc_request(sc->sc_udev);
- if (reqh == 0)
+ xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (xfer == 0)
goto bad;
- ch->chanbufs[i].reqh = reqh;
- buf = usbd_alloc_buffer(reqh, size);
+ ch->chanbufs[i].xfer = xfer;
+ buf = usbd_alloc_buffer(xfer, size);
if (buf == 0) {
i++;
goto bad;
@@ -1844,7 +1938,7 @@ uaudio_chan_alloc_buffers(sc, ch)
bad:
while (--i >= 0)
/* implicit buffer free */
- usbd_free_request(ch->chanbufs[i].reqh);
+ usbd_free_xfer(ch->chanbufs[i].xfer);
return (USBD_NOMEM);
}
@@ -1856,7 +1950,7 @@ uaudio_chan_free_buffers(sc, ch)
int i;
for (i = 0; i < UAUDIO_NCHANBUFS; i++)
- usbd_free_request(ch->chanbufs[i].reqh);
+ usbd_free_xfer(ch->chanbufs[i].xfer);
}
/* Called at splusb() */
@@ -1867,6 +1961,9 @@ uaudio_chan_ptransfer(ch)
struct chanbuf *cb;
int i, n, size, residue, total;
+ if (ch->sc->sc_dying)
+ return;
+
/* Pick the next channel buffer. */
cb = &ch->chanbufs[ch->curchanbuf];
if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
@@ -1913,18 +2010,18 @@ uaudio_chan_ptransfer(ch)
}
#endif
- DPRINTFN(5,("uaudio_chan_transfer: ptransfer reqh=%p\n", cb->reqh));
+ DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
/* Fill the request */
- usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes,
+ usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
UAUDIO_NFRAMES, USBD_NO_COPY,
uaudio_chan_pintr);
- (void)usbd_transfer(cb->reqh);
+ (void)usbd_transfer(cb->xfer);
}
void
-uaudio_chan_pintr(reqh, priv, status)
- usbd_request_handle reqh;
+uaudio_chan_pintr(xfer, priv, status)
+ usbd_xfer_handle xfer;
usbd_private_handle priv;
usbd_status status;
{
@@ -1937,7 +2034,7 @@ uaudio_chan_pintr(reqh, priv, status)
if (status == USBD_CANCELLED)
return;
- usbd_get_request_status(reqh, 0, 0, &count, 0);
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
count, ch->transferred));
#ifdef DIAGNOSTIC
@@ -1970,6 +2067,9 @@ uaudio_chan_rtransfer(ch)
struct chanbuf *cb;
int i, size, residue, total;
+ if (ch->sc->sc_dying)
+ return;
+
/* Pick the next channel buffer. */
cb = &ch->chanbufs[ch->curchanbuf];
if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
@@ -2001,18 +2101,18 @@ uaudio_chan_rtransfer(ch)
}
#endif
- DPRINTFN(5,("uaudio_chan_rtransfer: transfer reqh=%p\n", cb->reqh));
+ DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
/* Fill the request */
- usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes,
+ usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
UAUDIO_NFRAMES, USBD_NO_COPY,
uaudio_chan_rintr);
- (void)usbd_transfer(cb->reqh);
+ (void)usbd_transfer(cb->xfer);
}
void
-uaudio_chan_rintr(reqh, priv, status)
- usbd_request_handle reqh;
+uaudio_chan_rintr(xfer, priv, status)
+ usbd_xfer_handle xfer;
usbd_private_handle priv;
usbd_status status;
{
@@ -2025,7 +2125,7 @@ uaudio_chan_rintr(reqh, priv, status)
if (status == USBD_CANCELLED)
return;
- usbd_get_request_status(reqh, 0, 0, &count, 0);
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
count, ch->transferred));
#ifdef DIAGNOSTIC
@@ -2098,6 +2198,7 @@ uaudio_set_params(addr, setmode, usemode, p, r)
{
struct uaudio_softc *sc = addr;
int flags = sc->sc_altflags;
+ int pfactor, rfactor;
int enc, i, j;
void (*pswcode) __P((void *, u_char *buf, int cnt));
void (*rswcode) __P((void *, u_char *buf, int cnt));
@@ -2105,10 +2206,11 @@ uaudio_set_params(addr, setmode, usemode, p, r)
if (sc->sc_dying)
return (EIO);
- if (sc->sc_chan.pipe)
+ if (sc->sc_chan.pipe != NULL)
return (EBUSY);
pswcode = rswcode = 0;
+ pfactor = rfactor = 1;
enc = p->encoding;
switch (p->encoding) {
case AUDIO_ENCODING_SLINEAR_BE:
@@ -2155,6 +2257,13 @@ uaudio_set_params(addr, setmode, usemode, p, r)
pswcode = mulaw_to_slinear8;
rswcode = slinear8_to_mulaw;
enc = AUDIO_ENCODING_SLINEAR_LE;
+#if 0
+ } else if (flags & HAS_16) {
+ pswcode = mulaw_to_slinear16_le;
+ pfactor = 2;
+ /* XXX recording not handled */
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+#endif
} else
return (EINVAL);
}
@@ -2169,6 +2278,13 @@ uaudio_set_params(addr, setmode, usemode, p, r)
pswcode = alaw_to_slinear8;
rswcode = slinear8_to_alaw;
enc = AUDIO_ENCODING_SLINEAR_LE;
+#if 0
+ } else if (flags & HAS_16) {
+ pswcode = alaw_to_slinear16_le;
+ pfactor = 2;
+ /* XXX recording not handled */
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+#endif
} else
return (EINVAL);
}
@@ -2188,11 +2304,15 @@ uaudio_set_params(addr, setmode, usemode, p, r)
p->precision ==a1d->bBitResolution &&
enc == sc->sc_alts[i].encoding) {
if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+ DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
+ UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
if (UA_SAMP_LO(a1d) < p->sample_rate &&
p->sample_rate < UA_SAMP_HI(a1d))
goto found;
} else {
for (j = 0; j < a1d->bSamFreqType; j++) {
+ DPRINTFN(2,("uaudio_set_params: disc #"
+ "%d: %d\n", j, UA_GETSAMP(a1d, j)));
/* XXX allow for some slack */
if (UA_GETSAMP(a1d, j) ==
p->sample_rate)
@@ -2206,6 +2326,8 @@ uaudio_set_params(addr, setmode, usemode, p, r)
found:
p->sw_code = pswcode;
r->sw_code = rswcode;
+ p->factor = pfactor;
+ r->factor = rfactor;
sc->sc_curaltidx = i;
DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
diff --git a/sys/dev/usb/uaudioreg.h b/sys/dev/usb/uaudioreg.h
index 113752e6214..15da30f2193 100644
--- a/sys/dev/usb/uaudioreg.h
+++ b/sys/dev/usb/uaudioreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: uaudioreg.h,v 1.1 1999/11/11 15:54:59 ho Exp $ */
-/* $NetBSD: uaudioreg.h,v 1.2 1999/10/13 20:13:29 augustss Exp $ */
+/* $OpenBSD: uaudioreg.h,v 1.2 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: uaudioreg.h,v 1.4 2000/01/16 09:32:56 augustss Exp $ */
/*
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -156,14 +156,14 @@ struct usb_audio_mixer_unit {
uByte bDescriptorSubtype;
uByte bUnitId;
uByte bNrInPins;
- uByte baSourceId[255]; /* length is really bNrInPins */
+ uByte baSourceId[255]; /* [bNrInPins] */
/* struct usb_audio_mixer_unit_1 */
};
struct usb_audio_mixer_unit_1 {
uByte bNrChannels;
uWord wChannelConfig;
uByte iChannelNames;
- uByte bmControls[255];
+ uByte bmControls[255]; /* [bNrChannels] */
/*uByte iMixer;*/
};
@@ -174,7 +174,7 @@ struct usb_audio_selector_unit {
uByte bDescriptorSubtype;
uByte bUnitId;
uByte bNrInPins;
- uByte baSourceId[255];
+ uByte baSourceId[255]; /* [bNrInPins] */
/* uByte iSelector; */
};
@@ -198,7 +198,7 @@ struct usb_audio_processing_unit {
uByte bUnitId;
uWord wProcessType;
uByte bNrInPins;
- uByte baSourceId[255];
+ uByte baSourceId[255]; /* [bNrInPins] */
/* struct usb_audio_processing_unit_1 */
};
struct usb_audio_processing_unit_1{
@@ -206,8 +206,14 @@ struct usb_audio_processing_unit_1{
uWord wChannelConfig;
uByte iChannelNames;
uByte bControlSize;
- uByte bmControls[255];
- /*uByte iProcessing;*/
+ uByte bmControls[255]; /* [bControlSize] */
+#define UA_PROC_ENABLE_MASK 1
+};
+
+struct usb_audio_processing_unit_updown {
+ uByte iProcessing;
+ uByte bNrModes;
+ uWord waModes[255]; /* [bNrModes] */
};
/* UDESCSUB_AC_EXTENSION */
@@ -218,7 +224,7 @@ struct usb_audio_extension_unit {
uByte bUnitId;
uWord wExtensionCode;
uByte bNrInPins;
- uByte baSourceId[255];
+ uByte baSourceId[255]; /* [bNrInPins] */
/* struct usb_audio_extension_unit_1 */
};
struct usb_audio_extension_unit_1 {
@@ -226,8 +232,9 @@ struct usb_audio_extension_unit_1 {
uWord wChannelConfig;
uByte iChannelNames;
uByte bControlSize;
- uByte bmControls[255];
-#define UA_EXT_ENABLE 0
+ uByte bmControls[255]; /* [bControlSize] */
+#define UA_EXT_ENABLE_MASK 1
+#define UA_EXT_ENABLE 1
/*uByte iExtension;*/
};
@@ -276,3 +283,39 @@ struct usb_audio_extension_unit_1 {
#define FORMAT_TYPE_I 1
#define FORMAT_TYPE_II 2
#define FORMAT_TYPE_III 3
+
+#define UA_PROC_MASK(n) (1 << ((n)-1))
+#define PROCESS_UNDEFINED 0
+#define XX_ENABLE_CONTROL 1
+
+#define UPDOWNMIX_PROCESS 1
+#define UD_ENABLE_CONTROL 1
+#define UD_MODE_SELECT_CONTROL 2
+
+#define DOLBY_PROLOGIC_PROCESS 2
+#define DP_ENABLE_CONTROL 1
+#define DP_MODE_SELECT_CONTROL 2
+
+#define P3D_STEREO_EXTENDER_PROCESS 3
+#define P3D_ENABLE_CONTROL 1
+#define P3D_SPACIOUSNESS_CONTROL 2
+
+#define REVERBATION_PROCESS 4
+#define RV_ENABLE_CONTROL 1
+#define RV_LEVEL_CONTROL 2
+#define RV_TIME_CONTROL 3
+#define RV_FEEDBACK_CONTROL 4
+
+#define CHORUS_PROCESS 5
+#define CH_ENABLE_CONTROL 1
+#define CH_LEVEL_CONTROL 2
+#define CH_RATE_CONTROL 3
+#define CH_DEPTH_CONTROL 4
+
+#define DYN_RANGE_COMP_PROCESS 6
+#define DR_ENABLE_CONTROL 1
+#define DR_COMPRESSION_RATE_CONTROL 2
+#define DR_MAXAMPL_CONTROL 3
+#define DR_THRESHOLD_CONTROL 4
+#define DR_ATTACK_TIME_CONTROL 5
+#define DR_RELEASE_TIME_CONTROL 6
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index f49ca1d7bfc..a8f62e257e9 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ugen.c,v 1.7 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $ */
+/* $OpenBSD: ugen.c,v 1.8 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: ugen.c,v 1.36 2000/03/06 20:59:17 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -124,24 +124,19 @@ static struct cdevsw ugen_cdevsw = {
/* read */ ugenread,
/* write */ ugenwrite,
/* ioctl */ ugenioctl,
- /* stop */ nostop,
- /* reset */ noreset,
- /* devtotty */ nodevtotty,
/* poll */ ugenpoll,
/* mmap */ nommap,
/* strategy */ nostrategy,
/* name */ "ugen",
- /* parms */ noparms,
/* maj */ UGEN_CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ 0,
- /* maxio */ 0,
/* bmaj */ -1
};
#endif
-void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr,
+void ugenintr __P((usbd_xfer_handle xfer, usbd_private_handle addr,
usbd_status status));
int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int));
@@ -173,23 +168,49 @@ USB_MATCH(ugen)
USB_ATTACH(ugen)
{
USB_ATTACH_START(ugen, sc, uaa);
+ usbd_device_handle udev;
char devinfo[1024];
- usbd_status r;
+ usbd_status err;
int conf;
usbd_devinfo(uaa->device, 0, devinfo);
USB_ATTACH_SETUP;
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
- sc->sc_udev = uaa->device;
- conf = 1; /* XXX should not hard code 1 */
- r = ugen_set_config(sc, conf);
- if (r != USBD_NORMAL_COMPLETION) {
+ sc->sc_udev = udev = uaa->device;
+
+ /* First set configuration index 0, the default one for ugen. */
+ err = usbd_set_config_index(udev, 0, 0);
+ if (err) {
+ printf("%s: setting configuration index 0 failed\n",
+ USBDEVNAME(sc->sc_dev));
+ sc->sc_dying = 1;
+ USB_ATTACH_ERROR_RETURN;
+ }
+ conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
+
+ /* Set up all the local state for this configuration. */
+ err = ugen_set_config(sc, conf);
+ if (err) {
printf("%s: setting configuration %d failed\n",
USBDEVNAME(sc->sc_dev), conf);
sc->sc_dying = 1;
USB_ATTACH_ERROR_RETURN;
}
+
+#ifdef __FreeBSD__
+ {
+ struct int global_init_done = 0;
+ if (!global_init_done) {
+ cdevsw_add(&ugen_cdevsw);
+ global_init_done = 1;
+ }
+ }
+#endif
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
USB_ATTACH_SUCCESS_RETURN;
}
@@ -204,30 +225,30 @@ ugen_set_config(sc, configno)
struct ugen_endpoint *sce;
u_int8_t niface, nendpt;
int ifaceno, endptno, endpt;
- usbd_status r;
+ usbd_status err;
int dir;
DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
USBDEVNAME(sc->sc_dev), configno, sc));
+ /* Avoid setting the current value. */
if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
- /* Avoid setting the current value. */
- r = usbd_set_config_no(dev, configno, 0);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_set_config_no(dev, configno, 0);
+ if (err)
+ return (err);
}
- r = usbd_interface_count(dev, &niface);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_interface_count(dev, &niface);
+ if (err)
+ return (err);
memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
for (ifaceno = 0; ifaceno < niface; ifaceno++) {
DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
- r = usbd_device2interface_handle(dev, ifaceno, &iface);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- r = usbd_endpoint_count(iface, &nendpt);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_device2interface_handle(dev, ifaceno, &iface);
+ if (err)
+ return (err);
+ err = usbd_endpoint_count(iface, &nendpt);
+ if (err)
+ return (err);
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
@@ -258,13 +279,14 @@ ugenopen(dev, flag, mode, p)
usb_endpoint_descriptor_t *edesc;
struct ugen_endpoint *sce;
int dir, isize;
- usbd_status r;
+ usbd_status err;
USB_GET_SC_OPEN(ugen, unit, sc);
+
DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
flag, mode, unit, endpt));
- if (sc->sc_dying)
+ if (sc == NULL || sc->sc_dying)
return (ENXIO);
if (sc->sc_is_open[endpt])
@@ -274,6 +296,7 @@ ugenopen(dev, flag, mode, p)
sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
return (0);
}
+
/* Make sure there are pipes for all directions. */
for (dir = OUT; dir <= IN; dir++) {
if (flag & (dir == OUT ? FWRITE : FREAD)) {
@@ -304,11 +327,12 @@ ugenopen(dev, flag, mode, p)
endpt, isize));
if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
return (ENOMEM);
- r = usbd_open_pipe_intr(sce->iface,
+ err = usbd_open_pipe_intr(sce->iface,
edesc->bEndpointAddress,
USBD_SHORT_XFER_OK, &sce->pipeh, sce,
- sce->ibuf, isize, ugenintr);
- if (r != USBD_NORMAL_COMPLETION) {
+ sce->ibuf, isize, ugenintr,
+ USBD_DEFAULT_INTERVAL);
+ if (err) {
free(sce->ibuf, M_USBDEV);
clfree(&sce->q);
return (EIO);
@@ -316,10 +340,10 @@ ugenopen(dev, flag, mode, p)
DPRINTFN(5, ("ugenopen: interrupt open done\n"));
break;
case UE_BULK:
- r = usbd_open_pipe(sce->iface,
+ err = usbd_open_pipe(sce->iface,
edesc->bEndpointAddress, 0,
&sce->pipeh);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (EIO);
break;
case UE_CONTROL:
@@ -344,6 +368,7 @@ ugenclose(dev, flag, mode, p)
int dir;
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
flag, mode, UGENUNIT(dev), endpt));
@@ -364,7 +389,7 @@ ugenclose(dev, flag, mode, p)
if (!(flag & (dir == OUT ? FWRITE : FREAD)))
continue;
sce = &sc->sc_endpoints[endpt][dir];
- if (!sce || !sce->pipeh)
+ if (sce == NULL || sce->pipeh == NULL)
continue;
DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
endpt, dir, sce));
@@ -375,7 +400,7 @@ ugenclose(dev, flag, mode, p)
if (sce->ibuf) {
free(sce->ibuf, M_USBDEV);
- sce->ibuf = 0;
+ sce->ibuf = NULL;
clfree(&sce->q);
}
}
@@ -394,8 +419,8 @@ ugen_do_read(sc, endpt, uio, flag)
struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
u_int32_t n, tn;
char buf[UGEN_BBSIZE];
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
int s;
int error = 0;
u_char buffer[UGEN_CHUNK];
@@ -460,21 +485,21 @@ ugen_do_read(sc, endpt, uio, flag)
}
break;
case UE_BULK:
- reqh = usbd_alloc_request(sc->sc_udev);
- if (reqh == 0)
+ xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (xfer == 0)
return (ENOMEM);
while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
tn = n;
- r = usbd_bulk_transfer(
- reqh, sce->pipeh,
+ err = usbd_bulk_transfer(
+ xfer, sce->pipeh,
sce->state & UGEN_SHORT_OK ?
USBD_SHORT_XFER_OK : 0,
sce->timeout, buf, &tn, "ugenrb");
- if (r != USBD_NORMAL_COMPLETION) {
- if (r == USBD_INTERRUPTED)
+ if (err) {
+ if (err == USBD_INTERRUPTED)
error = EINTR;
- else if (r == USBD_TIMEOUT)
+ else if (err == USBD_TIMEOUT)
error = ETIMEDOUT;
else
error = EIO;
@@ -485,7 +510,7 @@ ugen_do_read(sc, endpt, uio, flag)
if (error || tn < n)
break;
}
- usbd_free_request(reqh);
+ usbd_free_xfer(xfer);
break;
default:
return (ENXIO);
@@ -504,6 +529,7 @@ ugenread(dev, uio, flag)
int error;
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
sc->sc_refcnt++;
error = ugen_do_read(sc, endpt, uio, flag);
if (--sc->sc_refcnt < 0)
@@ -522,12 +548,10 @@ ugen_do_write(sc, endpt, uio, flag)
u_int32_t n;
int error = 0;
char buf[UGEN_BBSIZE];
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
-#if defined(__NetBSD__) || defined(__OpenBSD__)
DPRINTFN(5, ("ugenwrite: %d:%d\n", sc->sc_dev.dv_unit, endpt));
-#endif
if (sc->sc_dying)
return (EIO);
@@ -548,25 +572,27 @@ ugen_do_write(sc, endpt, uio, flag)
switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
case UE_BULK:
- reqh = usbd_alloc_request(sc->sc_udev);
- if (reqh == 0)
+ xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (xfer == 0)
return (EIO);
while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
error = uiomove(buf, n, uio);
if (error)
break;
DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
- r = usbd_bulk_transfer(reqh, sce->pipeh, 0,
+ err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
sce->timeout, buf, &n,"ugenwb");
- if (r != USBD_NORMAL_COMPLETION) {
- if (r == USBD_INTERRUPTED)
+ if (err) {
+ if (err == USBD_INTERRUPTED)
error = EINTR;
+ else if (err == USBD_TIMEOUT)
+ error = ETIMEDOUT;
else
error = EIO;
break;
}
}
- usbd_free_request(reqh);
+ usbd_free_xfer(xfer);
break;
default:
return (ENXIO);
@@ -585,6 +611,7 @@ ugenwrite(dev, uio, flag)
int error;
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
sc->sc_refcnt++;
error = ugen_do_write(sc, endpt, uio, flag);
if (--sc->sc_refcnt < 0)
@@ -660,12 +687,15 @@ USB_DETACH(ugen)
/* XXX not implemented yet */
#endif
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
return (0);
}
void
-ugenintr(reqh, addr, status)
- usbd_request_handle reqh;
+ugenintr(xfer, addr, status)
+ usbd_xfer_handle xfer;
usbd_private_handle addr;
usbd_status status;
{
@@ -683,11 +713,11 @@ ugenintr(reqh, addr, status)
return;
}
- usbd_get_request_status(reqh, 0, 0, &count, 0);
+ usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
ibuf = sce->ibuf;
- DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n",
- reqh, status, count));
+ DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
+ xfer, status, count));
DPRINTFN(5, (" data = %02x %02x %02x\n",
ibuf[0], ibuf[1], ibuf[2]));
@@ -708,25 +738,25 @@ ugen_set_interface(sc, ifaceidx, altno)
{
usbd_interface_handle iface;
usb_endpoint_descriptor_t *ed;
- usbd_status r;
+ usbd_status err;
struct ugen_endpoint *sce;
u_int8_t niface, nendpt, endptno, endpt;
int dir;
DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
- r = usbd_interface_count(sc->sc_udev, &niface);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_interface_count(sc->sc_udev, &niface);
+ if (err)
+ return (err);
if (ifaceidx < 0 || ifaceidx >= niface)
return (USBD_INVAL);
- r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- r = usbd_endpoint_count(iface, &nendpt);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+ if (err)
+ return (err);
+ err = usbd_endpoint_count(iface, &nendpt);
+ if (err)
+ return (err);
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
@@ -738,13 +768,13 @@ ugen_set_interface(sc, ifaceidx, altno)
}
/* change setting */
- r = usbd_set_interface(iface, altno);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_set_interface(iface, altno);
+ if (err)
+ return (err);
- r = usbd_endpoint_count(iface, &nendpt);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_endpoint_count(iface, &nendpt);
+ if (err)
+ return (err);
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
@@ -766,7 +796,7 @@ ugen_get_cdesc(sc, index, lenp)
{
usb_config_descriptor_t *cdesc, *tdesc, cdescr;
int len;
- usbd_status r;
+ usbd_status err;
if (index == USB_CURRENT_CONFIG_INDEX) {
tdesc = usbd_get_config_descriptor(sc->sc_udev);
@@ -777,16 +807,16 @@ ugen_get_cdesc(sc, index, lenp)
memcpy(cdesc, tdesc, len);
DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
} else {
- r = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
+ if (err)
return (0);
len = UGETW(cdescr.wTotalLength);
DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
if (lenp)
*lenp = len;
cdesc = malloc(len, M_TEMP, M_WAITOK);
- r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
+ if (err) {
free(cdesc, M_TEMP);
return (0);
}
@@ -800,11 +830,11 @@ ugen_get_alt_index(sc, ifaceidx)
int ifaceidx;
{
usbd_interface_handle iface;
- usbd_status r;
+ usbd_status err;
- r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
- if (r != USBD_NORMAL_COMPLETION)
- return (-1);
+ err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+ if (err)
+ return (-1);
return (usbd_get_interface_altindex(iface));
}
@@ -818,7 +848,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
struct proc *p;
{
struct ugen_endpoint *sce;
- usbd_status r;
+ usbd_status err;
usbd_interface_handle iface;
struct usb_config_desc *cd;
usb_config_descriptor_t *cdesc;
@@ -876,32 +906,32 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
return (EINVAL);
switch (cmd) {
-#ifdef USB_DEBUG
+#ifdef UGEN_DEBUG
case USB_SETDEBUG:
ugendebug = *(int *)addr;
break;
#endif
case USB_GET_CONFIG:
- r = usbd_get_config(sc->sc_udev, &conf);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_get_config(sc->sc_udev, &conf);
+ if (err)
return (EIO);
*(int *)addr = conf;
break;
case USB_SET_CONFIG:
if (!(flag & FWRITE))
return (EPERM);
- r = ugen_set_config(sc, *(int *)addr);
- if (r != USBD_NORMAL_COMPLETION)
+ err = ugen_set_config(sc, *(int *)addr);
+ if (err)
return (EIO);
break;
case USB_GET_ALTINTERFACE:
ai = (struct usb_alt_interface *)addr;
- r = usbd_device2interface_handle(sc->sc_udev,
+ err = usbd_device2interface_handle(sc->sc_udev,
ai->interface_index, &iface);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (EINVAL);
idesc = usbd_get_interface_descriptor(iface);
- if (!idesc)
+ if (idesc == NULL)
return (EIO);
ai->alt_no = idesc->bAlternateSetting;
break;
@@ -909,21 +939,21 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
if (!(flag & FWRITE))
return (EPERM);
ai = (struct usb_alt_interface *)addr;
- r = usbd_device2interface_handle(sc->sc_udev,
+ err = usbd_device2interface_handle(sc->sc_udev,
ai->interface_index, &iface);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (EINVAL);
- r = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
- if (r != USBD_NORMAL_COMPLETION)
+ err = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
+ if (err)
return (EINVAL);
break;
case USB_GET_NO_ALT:
ai = (struct usb_alt_interface *)addr;
cdesc = ugen_get_cdesc(sc, ai->config_index, 0);
- if (!cdesc)
+ if (cdesc == NULL)
return (EINVAL);
idesc = usbd_find_idesc(cdesc, ai->interface_index, 0);
- if (!idesc) {
+ if (idesc == NULL) {
free(cdesc, M_TEMP);
return (EINVAL);
}
@@ -937,7 +967,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
case USB_GET_CONFIG_DESC:
cd = (struct usb_config_desc *)addr;
cdesc = ugen_get_cdesc(sc, cd->config_index, 0);
- if (!cdesc)
+ if (cdesc == NULL)
return (EINVAL);
cd->desc = *cdesc;
free(cdesc, M_TEMP);
@@ -945,7 +975,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
case USB_GET_INTERFACE_DESC:
id = (struct usb_interface_desc *)addr;
cdesc = ugen_get_cdesc(sc, id->config_index, 0);
- if (!cdesc)
+ if (cdesc == NULL)
return (EINVAL);
if (id->config_index == USB_CURRENT_CONFIG_INDEX &&
id->alt_index == USB_CURRENT_ALT_INDEX)
@@ -953,7 +983,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
else
alt = id->alt_index;
idesc = usbd_find_idesc(cdesc, id->interface_index, alt);
- if (!idesc) {
+ if (idesc == NULL) {
free(cdesc, M_TEMP);
return (EINVAL);
}
@@ -963,7 +993,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
case USB_GET_ENDPOINT_DESC:
ed = (struct usb_endpoint_desc *)addr;
cdesc = ugen_get_cdesc(sc, ed->config_index, 0);
- if (!cdesc)
+ if (cdesc == NULL)
return (EINVAL);
if (ed->config_index == USB_CURRENT_CONFIG_INDEX &&
ed->alt_index == USB_CURRENT_ALT_INDEX)
@@ -972,7 +1002,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
alt = ed->alt_index;
edesc = usbd_find_edesc(cdesc, ed->interface_index,
alt, ed->endpoint_index);
- if (!edesc) {
+ if (edesc == NULL) {
free(cdesc, M_TEMP);
return (EINVAL);
}
@@ -1005,9 +1035,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
}
case USB_GET_STRING_DESC:
si = (struct usb_string_desc *)addr;
- r = usbd_get_string_desc(sc->sc_udev, si->string_index,
+ err = usbd_get_string_desc(sc->sc_udev, si->string_index,
si->language_id, &si->desc);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (EINVAL);
break;
case USB_DO_REQUEST:
@@ -1017,7 +1047,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
struct iovec iov;
struct uio uio;
void *ptr = 0;
- usbd_status r;
+ usbd_status err;
int error = 0;
if (!(flag & FWRITE))
@@ -1052,9 +1082,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
goto ret;
}
}
- r = usbd_do_request_flags(sc->sc_udev, &ur->request,
+ err = usbd_do_request_flags(sc->sc_udev, &ur->request,
ptr, ur->flags, &ur->actlen);
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
error = EIO;
goto ret;
}
@@ -1093,6 +1123,7 @@ ugenioctl(dev, cmd, addr, flag, p)
int error;
USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
sc->sc_refcnt++;
error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
if (--sc->sc_refcnt < 0)
@@ -1121,7 +1152,7 @@ ugenpoll(dev, events, p)
return (EINVAL);
#ifdef DIAGNOSTIC
if (!sce->edesc) {
- printf("ugenwrite: no edesc\n");
+ printf("ugenpoll: no edesc\n");
return (EIO);
}
if (!sce->pipeh) {
@@ -1156,5 +1187,5 @@ ugenpoll(dev, events, p)
}
#if defined(__FreeBSD__)
-DEV_DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, ugen_cdevsw, usbd_driver_load, 0);
+DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index a92739a62c5..14c9c56b562 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhci.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: uhci.c,v 1.62 1999/10/23 00:21:01 augustss Exp $ */
+/* $OpenBSD: uhci.c,v 1.7 2000/03/26 08:39:45 aaron Exp $ */
+/* $NetBSD: uhci.c,v 1.87 2000/02/29 21:37:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,10 +42,10 @@
* USB Universal Host Controller driver.
* Handles e.g. PIIX3 and PIIX4.
*
- * Data sheets: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
- * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
* UHCI spec: http://www.intel.com/design/usb/uhci11d.pdf
* USB spec: http://www.usb.org/developers/data/usb11.pdf
+ * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
+ * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
*/
#include <sys/param.h>
@@ -54,17 +54,18 @@
#include <sys/malloc.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/device.h>
+#include <sys/select.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
+#include <machine/bus_pio.h>
+#if defined(DIAGNOSTIC) && defined(__i386)
+#include <machine/cpu.h>
+#endif
#endif
#include <sys/proc.h>
#include <sys/queue.h>
-#include <sys/select.h>
-#if defined(__FreeBSD__)
-#include <machine/bus_pio.h>
-#endif
#include <machine/bus.h>
#include <machine/endian.h>
@@ -91,10 +92,10 @@ struct cfdriver uhci_cd = {
};
#endif
-#ifdef USB_DEBUG
+#ifdef UHCI_DEBUG
#define DPRINTF(x) if (uhcidebug) printf x
#define DPRINTFN(n,x) if (uhcidebug>(n)) printf x
-extern int uhcidebug;
+int uhcidebug = 0;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -149,6 +150,7 @@ struct uhci_pipe {
LIST_HEAD(, uhci_intr_info) uhci_ii_free;
void uhci_busreset __P((uhci_softc_t *));
+void uhci_shutdown __P((void *v));
void uhci_power __P((int, void *));
usbd_status uhci_run __P((uhci_softc_t *, int run));
uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *));
@@ -166,15 +168,15 @@ void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *));
void uhci_free_std_chain __P((uhci_softc_t *,
uhci_soft_td_t *, uhci_soft_td_t *));
usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *,
- int, int, int, usb_dma_t *,
+ int, int, u_int16_t, usb_dma_t *,
uhci_soft_td_t **,
uhci_soft_td_t **));
void uhci_timo __P((void *));
-void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle));
+void uhci_waitintr __P((uhci_softc_t *, usbd_xfer_handle));
void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *));
void uhci_idone __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_abort_xfer __P((usbd_xfer_handle, usbd_status status));
+void uhci_abort_xfer_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 *));
@@ -184,53 +186,59 @@ void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
void uhci_remove_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *));
void uhci_remove_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
int uhci_str __P((usb_string_descriptor_t *, int, char *));
+
usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe));
-void uhci_device_isoc_enter __P((usbd_request_handle));
+void uhci_device_isoc_enter __P((usbd_xfer_handle));
-void uhci_wakeup_cb __P((usbd_request_handle reqh));
+void uhci_wakeup_cb __P((usbd_xfer_handle xfer));
usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t));
void uhci_freem __P((struct usbd_bus *, usb_dma_t *));
-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));
+usbd_xfer_handle uhci_allocx __P((struct usbd_bus *));
+void uhci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
+usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle));
+void uhci_device_ctrl_abort __P((usbd_xfer_handle));
void uhci_device_ctrl_close __P((usbd_pipe_handle));
-void uhci_device_ctrl_done __P((usbd_request_handle));
+void uhci_device_ctrl_done __P((usbd_xfer_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));
+usbd_status uhci_device_intr_transfer __P((usbd_xfer_handle));
+usbd_status uhci_device_intr_start __P((usbd_xfer_handle));
+void uhci_device_intr_abort __P((usbd_xfer_handle));
void uhci_device_intr_close __P((usbd_pipe_handle));
-void uhci_device_intr_done __P((usbd_request_handle));
+void uhci_device_intr_done __P((usbd_xfer_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));
+usbd_status uhci_device_bulk_transfer __P((usbd_xfer_handle));
+usbd_status uhci_device_bulk_start __P((usbd_xfer_handle));
+void uhci_device_bulk_abort __P((usbd_xfer_handle));
void uhci_device_bulk_close __P((usbd_pipe_handle));
-void uhci_device_bulk_done __P((usbd_request_handle));
+void uhci_device_bulk_done __P((usbd_xfer_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));
+usbd_status uhci_device_isoc_transfer __P((usbd_xfer_handle));
+usbd_status uhci_device_isoc_start __P((usbd_xfer_handle));
+void uhci_device_isoc_abort __P((usbd_xfer_handle));
void uhci_device_isoc_close __P((usbd_pipe_handle));
-void uhci_device_isoc_done __P((usbd_request_handle));
+void uhci_device_isoc_done __P((usbd_xfer_handle));
-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));
+usbd_status uhci_root_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status uhci_root_ctrl_start __P((usbd_xfer_handle));
+void uhci_root_ctrl_abort __P((usbd_xfer_handle));
void uhci_root_ctrl_close __P((usbd_pipe_handle));
+void uhci_root_ctrl_done __P((usbd_xfer_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));
+usbd_status uhci_root_intr_transfer __P((usbd_xfer_handle));
+usbd_status uhci_root_intr_start __P((usbd_xfer_handle));
+void uhci_root_intr_abort __P((usbd_xfer_handle));
void uhci_root_intr_close __P((usbd_pipe_handle));
-void uhci_root_intr_done __P((usbd_request_handle));
+void uhci_root_intr_done __P((usbd_xfer_handle));
usbd_status uhci_open __P((usbd_pipe_handle));
void uhci_poll __P((struct usbd_bus *));
+void uhci_softintr __P((struct usbd_bus *));
-usbd_status uhci_device_request __P((usbd_request_handle reqh));
+usbd_status uhci_device_request __P((usbd_xfer_handle xfer));
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 *));
@@ -242,12 +250,14 @@ void uhci_noop __P((usbd_pipe_handle pipe));
#ifdef UHCI_DEBUG
static void uhci_dumpregs __P((uhci_softc_t *));
-void uhci_dump_tds __P((uhci_soft_td_t *));
+void uhci_dump_qhs __P((uhci_soft_qh_t *));
void uhci_dump_qh __P((uhci_soft_qh_t *));
void uhci_dump __P((void));
+void uhci_dump_tds __P((uhci_soft_td_t *));
void uhci_dump_td __P((uhci_soft_td_t *));
#endif
+#define UWRITE1(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
#define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
#define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
#define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r))
@@ -265,9 +275,12 @@ void uhci_dump_td __P((uhci_soft_td_t *));
struct usbd_bus_methods uhci_bus_methods = {
uhci_open,
+ uhci_softintr,
uhci_poll,
uhci_allocm,
uhci_freem,
+ uhci_allocx,
+ uhci_freex,
};
struct usbd_pipe_methods uhci_root_ctrl_methods = {
@@ -276,7 +289,7 @@ struct usbd_pipe_methods uhci_root_ctrl_methods = {
uhci_root_ctrl_abort,
uhci_root_ctrl_close,
uhci_noop,
- 0,
+ uhci_root_ctrl_done,
};
struct usbd_pipe_methods uhci_root_intr_methods = {
@@ -337,14 +350,14 @@ usbd_status
uhci_init(sc)
uhci_softc_t *sc;
{
- usbd_status r;
+ usbd_status err;
int i, j;
uhci_soft_qh_t *csqh, *bsqh, *sqh;
uhci_soft_td_t *std;
DPRINTFN(1,("uhci_init: start\n"));
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
if (uhcidebug > 2)
uhci_dumpregs(sc);
#endif
@@ -355,18 +368,18 @@ uhci_init(sc)
uhci_busreset(sc);
/* Allocate and initialize real frame array. */
- r = usb_allocmem(&sc->sc_bus,
+ err = usb_allocmem(&sc->sc_bus,
UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ if (err)
+ return (err);
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*/
/* Allocate the dummy QH where bulk traffic will be queued. */
bsqh = uhci_alloc_sqh(sc);
- if (!bsqh)
+ if (bsqh == NULL)
return (USBD_NOMEM);
bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */
bsqh->qh.qh_elink = LE(UHCI_PTR_T);
@@ -374,7 +387,7 @@ uhci_init(sc)
/* Allocate the dummy QH where control traffic will be queued. */
csqh = uhci_alloc_sqh(sc);
- if (!csqh)
+ if (csqh == NULL)
return (USBD_NOMEM);
csqh->hlink = bsqh;
csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q);
@@ -389,7 +402,7 @@ uhci_init(sc)
for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
std = uhci_alloc_std(sc);
sqh = uhci_alloc_sqh(sc);
- if (!std || !sqh)
+ if (std == NULL || sqh == NULL)
return (USBD_NOMEM);
std->link.sqh = sqh;
std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q);
@@ -412,6 +425,8 @@ uhci_init(sc)
LIST_INIT(&sc->sc_intrhead);
+ SIMPLEQ_INIT(&sc->sc_free_xfers);
+
/* Set up the bus struct. */
sc->sc_bus.methods = &uhci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
@@ -419,13 +434,18 @@ uhci_init(sc)
sc->sc_suspend = PWR_RESUME;
sc->sc_powerhook = powerhook_establish(uhci_power, sc);
+ sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc);
+
DPRINTFN(1,("uhci_init: enabling\n"));
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */
+ UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */
+
return (uhci_run(sc, 1)); /* and here we go... */
}
+#if defined(__NetBSD__) || defined(__OpenBSD__)
int
uhci_activate(self, act)
device_ptr_t self;
@@ -452,6 +472,7 @@ uhci_detach(sc, flags)
struct uhci_softc *sc;
int flags;
{
+ usbd_xfer_handle xfer;
int rv = 0;
if (sc->sc_child != NULL)
@@ -461,10 +482,22 @@ uhci_detach(sc, flags)
return (rv);
powerhook_disestablish(sc->sc_powerhook);
- /* free data structures XXX */
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+
+ /* Free all xfers associated with this HC. */
+ for (;;) {
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer == NULL)
+ break;
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ free(xfer, M_USB);
+ }
+
+ /* XXX free other data structures XXX */
return (rv);
}
+#endif
usbd_status
uhci_allocm(bus, dma, size)
@@ -472,11 +505,8 @@ uhci_allocm(bus, dma, size)
usb_dma_t *dma;
u_int32_t size;
{
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- struct uhci_softc *sc = (struct uhci_softc *)bus;
-#endif
-
- return (usb_allocmem(&sc->sc_bus, size, 0, dma));
+ return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0,
+ dma));
}
void
@@ -484,14 +514,49 @@ uhci_freem(bus, dma)
struct usbd_bus *bus;
usb_dma_t *dma;
{
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+ usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma);
+}
+
+usbd_xfer_handle
+uhci_allocx(bus)
+ struct usbd_bus *bus;
+{
struct uhci_softc *sc = (struct uhci_softc *)bus;
-#endif
+ usbd_xfer_handle xfer;
- usb_freemem(&sc->sc_bus, dma);
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer != NULL)
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ else
+ xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ if (xfer != NULL)
+ memset(xfer, 0, sizeof *xfer);
+ return (xfer);
+}
+
+void
+uhci_freex(bus, xfer)
+ struct usbd_bus *bus;
+ usbd_xfer_handle xfer;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)bus;
+
+ SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+/*
+ * Shut down the controller when the system is going down.
+ */
+void
+uhci_shutdown(v)
+ void *v;
+{
+ uhci_softc_t *sc = v;
+
+ DPRINTF(("uhci_shutdown: stopping the HC\n"));
+ uhci_run(sc, 0); /* stop the controller */
}
-#if defined(__NetBSD__) || defined(__OpenBSD__)
/*
* Handle suspend/resume.
*
@@ -515,26 +580,26 @@ uhci_power(why, v)
sc, why, sc->sc_suspend, cmd));
if (why != PWR_RESUME) {
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
if (uhcidebug > 2)
uhci_dumpregs(sc);
#endif
- if (sc->sc_has_timo)
+ if (sc->sc_has_timo != NULL)
usb_untimeout(uhci_timo, sc->sc_has_timo,
sc->sc_has_timo->timo_handle);
sc->sc_bus.use_polling++;
uhci_run(sc, 0); /* stop the controller */
+
+ /* save some state if BIOS doesn't */
+ sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM);
+ sc->sc_saved_sof = UREAD1(sc, UHCI_SOF);
+
UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
sc->sc_suspend = why;
sc->sc_bus.use_polling--;
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
} else {
- /*
- * XXX We should really do much more here in case the
- * controller registers have been lost and BIOS has
- * not restored them.
- */
#ifdef DIAGNOSTIC
if (sc->sc_suspend == PWR_RESUME)
printf("uhci_power: weird, resume without suspend.\n");
@@ -543,6 +608,12 @@ uhci_power(why, v)
sc->sc_suspend = why;
if (cmd & UHCI_CMD_RS)
uhci_run(sc, 0); /* in case BIOS has started it */
+
+ /* restore saved state */
+ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma));
+ UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
+ UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
+
UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
@@ -551,17 +622,16 @@ uhci_power(why, v)
uhci_run(sc, 1); /* and start traffic again */
usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
sc->sc_bus.use_polling--;
- if (sc->sc_has_timo)
+ if (sc->sc_has_timo != NULL)
usb_timeout(uhci_timo, sc->sc_has_timo,
sc->sc_ival, sc->sc_has_timo->timo_handle);
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
if (uhcidebug > 2)
uhci_dumpregs(sc);
#endif
}
splx(s);
}
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
#ifdef UHCI_DEBUG
static void
@@ -609,14 +679,13 @@ uhci_dump_td(p)
}
void
-uhci_dump_qh(p)
- uhci_soft_qh_t *p;
+uhci_dump_qh(sqh)
+ uhci_soft_qh_t *sqh;
{
- DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", p,
- (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink)));
+ DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh,
+ (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink)));
}
-
#if 0
void
uhci_dump()
@@ -631,13 +700,53 @@ uhci_dump()
#endif
void
+uhci_dump_qhs(sqh)
+ uhci_soft_qh_t *sqh;
+{
+ uhci_dump_qh(sqh);
+
+ /* uhci_dump_sqh displays all the QHs and TDs from the given QH onwards
+ * Traverses sideways first, then down.
+ *
+ * QH1
+ * QH2
+ * No QH
+ * TD2.1
+ * TD2.2
+ * TD1.1
+ * etc.
+ *
+ * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1.
+ */
+
+ if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T))
+ uhci_dump_qhs(sqh->hlink);
+ else
+ DPRINTF(("No QH\n"));
+
+ if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T))
+ uhci_dump_tds(sqh->elink);
+ else
+ DPRINTF(("No TD\n"));
+}
+
+void
uhci_dump_tds(std)
uhci_soft_td_t *std;
{
- uhci_soft_td_t *p;
+ uhci_soft_td_t *td;
+
+ for(td = std; td != NULL; td = td->link.std) {
+ uhci_dump_td(td);
- for(p = std; p; p = p->link.std)
- uhci_dump_td(p);
+ /* Check whether the link pointer in this TD marks
+ * the link pointer as end of queue. This avoids
+ * printing the free list in case the queue/TD has
+ * already been moved there (seatbelt).
+ */
+ if (td->td.td_link & UHCI_PTR_T || td->td.td_link == 0)
+ break;
+ }
}
#endif
@@ -649,17 +758,17 @@ void
uhci_timo(addr)
void *addr;
{
- usbd_request_handle reqh = addr;
- usbd_pipe_handle pipe = reqh->pipe;
+ usbd_xfer_handle xfer = addr;
+ usbd_pipe_handle pipe = xfer->pipe;
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
int s;
u_char *p;
- DPRINTFN(15, ("uhci_timo\n"));
+ DPRINTFN(20, ("uhci_timo\n"));
- usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
+ usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
- p = KERNADDR(&reqh->dmabuf);
+ p = KERNADDR(&xfer->dmabuf);
p[0] = 0;
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<1;
@@ -669,19 +778,25 @@ uhci_timo(addr)
/* No change, try again in a while */
return;
- reqh->actlen = 1;
- reqh->status = USBD_NORMAL_COMPLETION;
+ xfer->actlen = 1;
+ xfer->status = USBD_NORMAL_COMPLETION;
s = splusb();
- reqh->hcpriv = 0;
- reqh->device->bus->intr_context++;
- usb_transfer_complete(reqh);
- reqh->device->bus->intr_context--;
+ xfer->hcpriv = 0;
+ xfer->device->bus->intr_context++;
+ usb_transfer_complete(xfer);
+ xfer->device->bus->intr_context--;
splx(s);
}
void
-uhci_root_intr_done(reqh)
- usbd_request_handle reqh;
+uhci_root_intr_done(xfer)
+ usbd_xfer_handle xfer;
+{
+}
+
+void
+uhci_root_ctrl_done(xfer)
+ usbd_xfer_handle xfer;
{
}
@@ -691,7 +806,8 @@ uhci_lock_frames(sc)
uhci_softc_t *sc;
{
int s = splusb();
- while (sc->sc_vflock) {
+
+ while (sc->sc_vflock & UHCI_HAS_LOCK) {
sc->sc_vflock |= UHCI_WANT_LOCK;
tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0);
}
@@ -704,6 +820,7 @@ uhci_unlock_frames(sc)
uhci_softc_t *sc;
{
int s = splusb();
+
sc->sc_vflock &= ~UHCI_HAS_LOCK;
if (sc->sc_vflock & UHCI_WANT_LOCK)
wakeup(&sc->sc_vflock);
@@ -838,9 +955,8 @@ uhci_intr(arg)
uhci_softc_t *sc = arg;
int status;
int ack;
- uhci_intr_info_t *ii;
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
if (uhcidebug > 15) {
DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev)));
uhci_dumpregs(sc);
@@ -867,17 +983,18 @@ uhci_intr(arg)
}
if (status & UHCI_STS_HSE) {
ack |= UHCI_STS_HSE;
- printf("%s: host controller process error\n",
- USBDEVNAME(sc->sc_bus.bdev));
+ printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
}
if (status & UHCI_STS_HCPE) {
ack |= UHCI_STS_HCPE;
- printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
+ printf("%s: host controller process error\n",
+ USBDEVNAME(sc->sc_bus.bdev));
}
if (status & UHCI_STS_HCH) {
/* no acknowledge needed */
printf("%s: host controller halted\n",
USBDEVNAME(sc->sc_bus.bdev));
+ sc->sc_dying = 1;
}
if (ack) /* acknowledge the ints */
@@ -885,8 +1002,24 @@ uhci_intr(arg)
else /* nothing to acknowledge */
return (0);
- sc->sc_bus.intr_context++;
sc->sc_bus.no_intrs++;
+ usb_schedsoftintr(&sc->sc_bus);
+
+ DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev)));
+
+ return (1);
+}
+
+void
+uhci_softintr(bus)
+ struct usbd_bus *bus;
+{
+ uhci_softc_t *sc = (uhci_softc_t *)bus;
+ uhci_intr_info_t *ii;
+
+ DPRINTFN(10,("%s: uhci_softintr\n", USBDEVNAME(sc->sc_bus.bdev)));
+
+ sc->sc_bus.intr_context++;
/*
* Interrupts on UHCI really suck. When the host controller
@@ -902,11 +1035,7 @@ uhci_intr(arg)
for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list))
uhci_check_intr(sc, ii);
- DPRINTFN(10, ("uhci_intr: exit\n"));
-
sc->sc_bus.intr_context--;
-
- return (1);
}
/* Check for an interrupt. */
@@ -920,16 +1049,16 @@ uhci_check_intr(sc, ii)
DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii));
#ifdef DIAGNOSTIC
- if (!ii) {
+ if (ii == NULL) {
printf("uhci_check_intr: no ii? %p\n", ii);
return;
}
#endif
- if (!ii->stdstart)
+ if (ii->stdstart == NULL)
return;
lstd = ii->stdend;
#ifdef DIAGNOSTIC
- if (!lstd) {
+ if (lstd == NULL) {
printf("uhci_check_intr: std==0\n");
return;
}
@@ -943,9 +1072,16 @@ uhci_check_intr(sc, ii)
DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
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)
+ /* If there's an active TD the xfer isn't done. */
+ if (status & UHCI_TD_ACTIVE)
+ break;
+ /* Any kind of error makes the xfer done. */
+ if (status & UHCI_TD_STALLED)
+ goto done;
+ /* We want short packets, and it is short: it's done */
+ if ((status & UHCI_TD_SPD) &&
+ UHCI_TD_GET_ACTLEN(status) <
+ UHCI_TD_GET_MAXLEN(LE(std->td.td_token)))
goto done;
}
DPRINTFN(15, ("uhci_check_intr: ii=%p std=%p still active\n",
@@ -953,6 +1089,7 @@ uhci_check_intr(sc, ii)
return;
}
done:
+ DPRINTFN(15, ("uhci_check_intr: ii=%p done\n", ii));
usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
uhci_idone(ii);
}
@@ -962,10 +1099,10 @@ void
uhci_idone(ii)
uhci_intr_info_t *ii;
{
- usbd_request_handle reqh = ii->reqh;
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ usbd_xfer_handle xfer = ii->xfer;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_soft_td_t *std;
- u_int32_t status;
+ u_int32_t status = 0, nstatus;
int actlen;
#ifdef DIAGNOSTIC
@@ -981,22 +1118,22 @@ uhci_idone(ii)
}
#endif
- if (reqh->status == USBD_CANCELLED ||
- reqh->status == USBD_TIMEOUT) {
- DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh));
+ if (xfer->status == USBD_CANCELLED ||
+ xfer->status == USBD_TIMEOUT) {
+ DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer));
return;
}
- if (reqh->nframes) {
+ if (xfer->nframes != 0) {
/* Isoc transfer, do things differently. */
uhci_soft_td_t **stds = upipe->u.iso.stds;
int i, n, nframes;
DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii));
- nframes = reqh->nframes;
+ nframes = xfer->nframes;
actlen = 0;
- n = reqh->hcprivint;
+ n = xfer->hcprivint;
for (i = 0; i < nframes; i++) {
std = stds[n];
#ifdef UHCI_DEBUG
@@ -1011,15 +1148,16 @@ uhci_idone(ii)
actlen += UHCI_TD_GET_ACTLEN(status);
}
upipe->u.iso.inuse -= nframes;
- reqh->actlen = actlen;
- reqh->status = USBD_NORMAL_COMPLETION;
- reqh->hcpriv = ii;
- usb_transfer_complete(reqh);
+ xfer->actlen = actlen;
+ xfer->status = USBD_NORMAL_COMPLETION;
+ xfer->hcpriv = ii;
+ usb_transfer_complete(xfer);
return;
}
#ifdef UHCI_DEBUG
- DPRINTFN(10, ("uhci_idone: ii=%p ready\n", ii));
+ DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n",
+ ii, xfer, upipe));
if (uhcidebug > 10)
uhci_dump_tds(ii->stdstart);
#endif
@@ -1027,40 +1165,41 @@ 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->link.std) {
- status = LE(std->td.td_status);
- if (status & UHCI_TD_ACTIVE)
+ for (std = ii->stdstart; std != NULL; std = std->link.std) {
+ nstatus = LE(std->td.td_status);
+ if (nstatus & UHCI_TD_ACTIVE)
break;
- if (UHCI_TD_GET_PID(LE(std->td.td_token)) !=
- UHCI_TD_PID_SETUP)
+
+ status = nstatus;
+ 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)
+ if (std != NULL)
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",
actlen, status));
- reqh->actlen = actlen;
+ xfer->actlen = actlen;
if (status != 0) {
- DPRINTFN(-1+((status&UHCI_TD_STALLED)!=0),
+ DPRINTFN((status == UHCI_TD_STALLED)*10,
("uhci_idone: error, addr=%d, endpt=0x%02x, "
"status 0x%b\n",
- reqh->pipe->device->address,
- reqh->pipe->endpoint->edesc->bEndpointAddress,
+ xfer->pipe->device->address,
+ xfer->pipe->endpoint->edesc->bEndpointAddress,
(int)status,
"\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
"STALLED\30ACTIVE"));
if (status == UHCI_TD_STALLED)
- reqh->status = USBD_STALLED;
+ xfer->status = USBD_STALLED;
else
- reqh->status = USBD_IOERROR; /* more info XXX */
+ xfer->status = USBD_IOERROR; /* more info XXX */
} else {
- reqh->status = USBD_NORMAL_COMPLETION;
+ xfer->status = USBD_NORMAL_COMPLETION;
}
- reqh->hcpriv = ii;
- usb_transfer_complete(reqh);
+ xfer->hcpriv = ii;
+ usb_transfer_complete(xfer);
}
/*
@@ -1074,9 +1213,14 @@ uhci_timeout(addr)
DPRINTF(("uhci_timeout: ii=%p\n", ii));
- ii->reqh->device->bus->intr_context++;
- uhci_abort_req(ii->reqh, USBD_TIMEOUT);
- ii->reqh->device->bus->intr_context--;
+#ifdef UHCI_DEBUG
+ if (uhcidebug > 10)
+ uhci_dump_tds(ii->stdstart);
+#endif
+
+ ii->xfer->device->bus->intr_context++;
+ uhci_abort_xfer(ii->xfer, USBD_TIMEOUT);
+ ii->xfer->device->bus->intr_context--;
}
/*
@@ -1086,22 +1230,22 @@ uhci_timeout(addr)
* Only used during boot when interrupts are not enabled yet.
*/
void
-uhci_waitintr(sc, reqh)
+uhci_waitintr(sc, xfer)
uhci_softc_t *sc;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
{
- int timo = reqh->timeout;
+ int timo = xfer->timeout;
uhci_intr_info_t *ii;
DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo));
- reqh->status = USBD_IN_PROGRESS;
+ xfer->status = USBD_IN_PROGRESS;
for (; timo >= 0; timo--) {
usb_delay_ms(&sc->sc_bus, 1);
DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS)));
if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) {
uhci_intr(sc);
- if (reqh->status != USBD_IN_PROGRESS)
+ if (xfer->status != USBD_IN_PROGRESS)
return;
}
}
@@ -1109,11 +1253,11 @@ uhci_waitintr(sc, reqh)
/* Timeout */
DPRINTF(("uhci_waitintr: timeout\n"));
for (ii = LIST_FIRST(&sc->sc_intrhead);
- ii && ii->reqh != reqh;
+ ii != NULL && ii->xfer != xfer;
ii = LIST_NEXT(ii, list))
;
#ifdef DIAGNOSTIC
- if (!ii)
+ if (ii == NULL)
panic("uhci_waitintr: lost intr_info\n");
#endif
uhci_idone(ii);
@@ -1154,11 +1298,17 @@ uhci_run(sc, run)
int run;
{
int s, n, running;
+ u_int16_t cmd;
run = run != 0;
s = splusb();
DPRINTF(("uhci_run: setting run=%d\n", run));
- UHCICMD(sc, run ? UHCI_CMD_RS : 0);
+ cmd = UREAD2(sc, UHCI_CMD);
+ if (run)
+ cmd |= UHCI_CMD_RS;
+ else
+ cmd &= ~UHCI_CMD_RS;
+ UHCICMD(sc, cmd);
for(n = 0; n < 10; n++) {
running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
/* return when we've entered the state we want */
@@ -1191,15 +1341,15 @@ uhci_alloc_std(sc)
uhci_softc_t *sc;
{
uhci_soft_td_t *std;
- usbd_status r;
+ usbd_status err;
int i, offs;
usb_dma_t dma;
- if (!sc->sc_freetds) {
+ if (sc->sc_freetds == NULL) {
DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
- r = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
+ err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
UHCI_TD_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (0);
for(i = 0; i < UHCI_STD_CHUNK; i++) {
offs = i * UHCI_STD_SIZE;
@@ -1222,7 +1372,7 @@ uhci_free_std(sc, std)
{
#ifdef DIAGNOSTIC
#define TD_IS_FREE 0x12345678
- if (LE(std->td.td_token) == TD_IS_FREE) {
+ if (std->td.td_token == LE(TD_IS_FREE)) {
printf("uhci_free_std: freeing free TD %p\n", std);
return;
}
@@ -1237,15 +1387,15 @@ uhci_alloc_sqh(sc)
uhci_softc_t *sc;
{
uhci_soft_qh_t *sqh;
- usbd_status r;
+ usbd_status err;
int i, offs;
usb_dma_t dma;
- if (!sc->sc_freeqhs) {
+ if (sc->sc_freeqhs == NULL) {
DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
- r = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
+ err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
UHCI_QH_ALIGN, &dma);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return 0;
for(i = 0; i < UHCI_SQH_CHUNK; i++) {
offs = i * UHCI_SQH_SIZE;
@@ -1301,10 +1451,11 @@ uhci_free_std_chain(sc, std, stdend)
}
usbd_status
-uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
+uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep)
struct uhci_pipe *upipe;
uhci_softc_t *sc;
- int len, rd, shortok;
+ int len, rd;
+ u_int16_t flags;
usb_dma_t *dma;
uhci_soft_td_t **sp, **ep;
{
@@ -1316,20 +1467,22 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
- "shortok=%d\n", addr, UE_GET_ADDR(endpt), len,
- upipe->pipe.device->lowspeed, shortok));
- if (len == 0) {
- *sp = *ep = 0;
- DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
- return (USBD_NORMAL_COMPLETION);
- }
+ "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len,
+ upipe->pipe.device->lowspeed, flags));
maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize);
if (maxp == 0) {
printf("uhci_alloc_std_chain: maxp=0\n");
return (USBD_INVAL);
}
ntd = (len + maxp - 1) / maxp;
+ if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
+ ntd++;
DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
+ if (ntd == 0) {
+ *sp = *ep = 0;
+ DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
+ return (USBD_NORMAL_COMPLETION);
+ }
tog = upipe->nexttoggle;
if (ntd % 2 == 0)
tog ^= 1;
@@ -1340,23 +1493,27 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
if (upipe->pipe.device->lowspeed)
status |= UHCI_TD_LS;
- if (shortok)
+ if (flags & USBD_SHORT_XFER_OK)
status |= UHCI_TD_SPD;
for (i = ntd; i >= 0; i--) {
p = uhci_alloc_std(sc);
- if (!p) {
+ if (p == NULL) {
uhci_free_std_chain(sc, lastp, 0);
return (USBD_NOMEM);
}
p->link.std = lastp;
- p->td.td_link = LE(lastlink);
+ if (lastlink == UHCI_PTR_T)
+ p->td.td_link = LE(lastlink);
+ else
+ p->td.td_link = LE(lastlink|UHCI_PTR_VF);
lastp = p;
lastlink = p->physaddr;
p->td.td_status = LE(status);
if (i == ntd) {
/* last TD */
l = len % maxp;
- if (l == 0) l = maxp;
+ if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER))
+ l = maxp;
*ep = p;
} else
l = maxp;
@@ -1387,55 +1544,59 @@ uhci_noop(pipe)
}
usbd_status
-uhci_device_bulk_transfer(reqh)
- usbd_request_handle reqh;
+uhci_device_bulk_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
- /* Pipe isn't running, start first */
- return (uhci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ /* Pipe isn't running (otherwise err would be USBD_INPROG),
+ * start first
+ */
+ return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-uhci_device_bulk_start(reqh)
- usbd_request_handle reqh;
+uhci_device_bulk_start(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
uhci_intr_info_t *ii = upipe->iinfo;
uhci_soft_td_t *data, *dataend;
uhci_soft_qh_t *sqh;
- usbd_status r;
+ usbd_status err;
int len, isread, endpt;
int s;
- DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n",
- reqh, reqh->length, reqh->flags));
+ DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n",
+ xfer, xfer->length, xfer->flags));
+
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_REQUEST)
+ if (xfer->rqflags & URQ_REQUEST)
panic("uhci_device_bulk_transfer: a request\n");
#endif
- len = reqh->length;
- endpt = reqh->pipe->endpoint->edesc->bEndpointAddress;
+ len = xfer->length;
+ endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
isread = UE_GET_DIR(endpt) == UE_DIR_IN;
sqh = upipe->u.bulk.sqh;
upipe->u.bulk.isread = isread;
upipe->u.bulk.length = len;
- r = uhci_alloc_std_chain(upipe, sc, len, isread,
- reqh->flags & USBD_SHORT_XFER_OK,
- &reqh->dmabuf, &data, &dataend);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
+ if (err)
+ return (err);
dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef UHCI_DEBUG
@@ -1446,13 +1607,16 @@ uhci_device_bulk_start(reqh)
#endif
/* Set up interrupt info. */
- ii->reqh = reqh;
+ ii->xfer = xfer;
ii->stdstart = data;
ii->stdend = dataend;
#if defined(__FreeBSD__)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -1464,8 +1628,8 @@ uhci_device_bulk_start(reqh)
uhci_add_bulk(sc, sqh);
LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
- if (reqh->timeout && !sc->sc_bus.use_polling) {
- usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout),
+ if (xfer->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout),
ii->timeout_handle);
}
splx(s);
@@ -1478,31 +1642,33 @@ uhci_device_bulk_start(reqh)
#endif
if (sc->sc_bus.use_polling)
- uhci_waitintr(sc, reqh);
+ uhci_waitintr(sc, xfer);
return (USBD_IN_PROGRESS);
}
/* Abort a device bulk request. */
void
-uhci_device_bulk_abort(reqh)
- usbd_request_handle reqh;
+uhci_device_bulk_abort(xfer)
+ usbd_xfer_handle xfer;
{
DPRINTF(("uhci_device_bulk_abort:\n"));
- uhci_abort_req(reqh, USBD_CANCELLED);
+ uhci_abort_xfer(xfer, USBD_CANCELLED);
}
void
-uhci_abort_req(reqh, status)
- usbd_request_handle reqh;
+uhci_abort_xfer(xfer, status)
+ usbd_xfer_handle xfer;
usbd_status status;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_intr_info_t *ii = upipe->iinfo;
uhci_soft_td_t *std;
+ DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status));
+
/* Make interrupt routine ignore it, */
- reqh->status = status;
+ xfer->status = status;
/* don't timeout, */
usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
@@ -1511,28 +1677,37 @@ uhci_abort_req(reqh, status)
for (std = ii->stdstart; std != 0; std = std->link.std)
std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
- reqh->hcpriv = ii;
+ xfer->hcpriv = ii;
- /* make sure hardware has completed, */
- if (reqh->device->bus->intr_context) {
+#if 1
+ /* Make sure hardware has completed, */
+ if (xfer->device->bus->intr_context) {
/* We have no process context, so we can't use tsleep(). */
- timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+ timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
} else {
- usb_delay_ms(reqh->pipe->device->bus, 1);
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+ KASSERT(intr_nesting_level == 0,
+ ("ohci_abort_req in interrupt context"));
+#endif
+ usb_delay_ms(xfer->pipe->device->bus, 1);
/* and call final part of interrupt handler. */
- uhci_abort_req_end(reqh);
+ uhci_abort_xfer_end(xfer);
}
+#else
+ delay(1000);
+ uhci_abort_xfer_end(xfer);
+#endif
}
void
-uhci_abort_req_end(v)
+uhci_abort_xfer_end(v)
void *v;
{
- usbd_request_handle reqh = v;
+ usbd_xfer_handle xfer = v;
int s;
s = splusb();
- usb_transfer_complete(reqh);
+ usb_transfer_complete(xfer);
splx(s);
}
@@ -1547,86 +1722,95 @@ uhci_device_bulk_close(pipe)
uhci_free_sqh(sc, upipe->u.bulk.sqh);
uhci_free_intr_info(upipe->iinfo);
- /* XXX free other resources */
+ /* XXX free other resources? */
}
usbd_status
-uhci_device_ctrl_transfer(reqh)
- usbd_request_handle reqh;
+uhci_device_ctrl_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
- /* Pipe isn't running, start first */
- return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ /* Pipe isn't running (otherwise err would be USBD_INPROG),
+ * start first
+ */
+ return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-uhci_device_ctrl_start(reqh)
- usbd_request_handle reqh;
+uhci_device_ctrl_start(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
- usbd_status r;
+ uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
+ usbd_status err;
+
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST))
+ if (!(xfer->rqflags & URQ_REQUEST))
panic("uhci_device_ctrl_transfer: not a request\n");
#endif
- r = uhci_device_request(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = uhci_device_request(xfer);
+ if (err)
+ return (err);
if (sc->sc_bus.use_polling)
- uhci_waitintr(sc, reqh);
+ uhci_waitintr(sc, xfer);
return (USBD_IN_PROGRESS);
}
usbd_status
-uhci_device_intr_transfer(reqh)
- usbd_request_handle reqh;
+uhci_device_intr_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
- /* Pipe isn't running, start first */
- return (uhci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ /* Pipe isn't running (otherwise err would be USBD_INPROG),
+ * start first
+ */
+ return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-uhci_device_intr_start(reqh)
- usbd_request_handle reqh;
+uhci_device_intr_start(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
uhci_intr_info_t *ii = upipe->iinfo;
uhci_soft_td_t *data, *dataend;
uhci_soft_qh_t *sqh;
- usbd_status r;
+ usbd_status err;
int i, s;
- DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n",
- reqh, reqh->length, reqh->flags));
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
+
+ DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n",
+ xfer, xfer->length, xfer->flags));
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_REQUEST)
+ if (xfer->rqflags & URQ_REQUEST)
panic("uhci_device_intr_transfer: a request\n");
#endif
- r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
- reqh->flags & USBD_SHORT_XFER_OK,
- &reqh->dmabuf, &data, &dataend);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
+ if (err)
+ return (err);
dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef UHCI_DEBUG
@@ -1639,13 +1823,16 @@ uhci_device_intr_start(reqh)
s = splusb();
/* Set up interrupt info. */
- ii->reqh = reqh;
+ ii->xfer = xfer;
ii->stdstart = data;
ii->stdend = dataend;
#if defined(__FreeBSD__)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_intr_transfer: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -1671,11 +1858,11 @@ uhci_device_intr_start(reqh)
/* Abort a device control request. */
void
-uhci_device_ctrl_abort(reqh)
- usbd_request_handle reqh;
+uhci_device_ctrl_abort(xfer)
+ usbd_xfer_handle xfer;
{
DPRINTF(("uhci_device_ctrl_abort:\n"));
- uhci_abort_req(reqh, USBD_CANCELLED);
+ uhci_abort_xfer(xfer, USBD_CANCELLED);
}
/* Close a device control pipe. */
@@ -1691,15 +1878,15 @@ uhci_device_ctrl_close(pipe)
/* Abort a device interrupt request. */
void
-uhci_device_intr_abort(reqh)
- usbd_request_handle reqh;
+uhci_device_intr_abort(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTFN(1,("uhci_device_intr_abort: reqh=%p\n", reqh));
- if (reqh->pipe->intrreqh == reqh) {
+ DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer));
+ if (xfer->pipe->intrxfer == xfer) {
DPRINTFN(1,("uhci_device_intr_abort: remove\n"));
- reqh->pipe->intrreqh = 0;
+ xfer->pipe->intrxfer = 0;
}
- uhci_abort_req(reqh, USBD_CANCELLED);
+ uhci_abort_xfer(xfer, USBD_CANCELLED);
}
/* Close a device interrupt pipe. */
@@ -1740,11 +1927,11 @@ uhci_device_intr_close(pipe)
}
usbd_status
-uhci_device_request(reqh)
- usbd_request_handle reqh;
+uhci_device_request(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
- usb_device_request_t *req = &reqh->request;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+ usb_device_request_t *req = &xfer->request;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
int addr = dev->address;
@@ -1754,7 +1941,7 @@ uhci_device_request(reqh)
uhci_soft_qh_t *sqh;
int len;
u_int32_t ls;
- usbd_status r;
+ usbd_status err;
int isread;
int s;
@@ -1775,14 +1962,13 @@ uhci_device_request(reqh)
/* Set up data transaction */
if (len != 0) {
upipe->nexttoggle = 1;
- r = uhci_alloc_std_chain(upipe, sc, len, isread,
- reqh->flags & USBD_SHORT_XFER_OK,
- &reqh->dmabuf, &data, &dataend);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
+ if (err)
+ return (err);
next = data;
dataend->link.std = stat;
- dataend->td.td_link = LE(stat->physaddr);
+ dataend->td.td_link = LE(stat->physaddr | UHCI_PTR_VF);
} else {
next = stat;
}
@@ -1791,7 +1977,7 @@ uhci_device_request(reqh)
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
setup->link.std = next;
- setup->td.td_link = LE(next->physaddr);
+ setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
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));
@@ -1806,20 +1992,23 @@ uhci_device_request(reqh)
stat->td.td_buffer = LE(0);
#ifdef UHCI_DEBUG
- if (uhcidebug > 20) {
+ if (uhcidebug > 10) {
DPRINTF(("uhci_device_request: before transfer\n"));
uhci_dump_tds(setup);
}
#endif
/* Set up interrupt info. */
- ii->reqh = reqh;
+ ii->xfer = xfer;
ii->stdstart = setup;
ii->stdend = stat;
#if defined(__FreeBSD__)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_request: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -1844,21 +2033,22 @@ uhci_device_request(reqh)
link = LE(std->td.td_link);
uhci_dump_td(std);
}
- for (sxqh = xqh = (uhci_soft_qh_t *)std;
- xqh;
+ sxqh = (uhci_soft_qh_t *)std;
+ uhci_dump_qh(sxqh);
+ for (xqh = sxqh;
+ xqh != NULL;
xqh = (maxqh++ == 5 || xqh->hlink==sxqh ||
xqh->hlink==xqh ? NULL : xqh->hlink)) {
uhci_dump_qh(xqh);
- uhci_dump_qh(sxqh);
}
DPRINTF(("Enqueued QH:\n"));
uhci_dump_qh(sqh);
uhci_dump_tds(sqh->elink);
}
#endif
- if (reqh->timeout && !sc->sc_bus.use_polling) {
+ if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_timeout(uhci_timeout, ii,
- MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
+ MS_TO_TICKS(xfer->timeout), ii->timeout_handle);
}
splx(s);
@@ -1866,37 +2056,37 @@ uhci_device_request(reqh)
}
usbd_status
-uhci_device_isoc_transfer(reqh)
- usbd_request_handle reqh;
+uhci_device_isoc_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
- DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh));
+ DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer));
/* Put it on our queue, */
- r = usb_insert_transfer(reqh);
+ err = usb_insert_transfer(xfer);
/* bail out on error, */
- if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS)
- return (r);
+ if (err && err != USBD_IN_PROGRESS)
+ return (err);
/* XXX should check inuse here */
/* insert into schedule, */
- uhci_device_isoc_enter(reqh);
+ uhci_device_isoc_enter(xfer);
/* and put on interrupt list if the pipe wasn't running */
- if (r == USBD_NORMAL_COMPLETION)
- uhci_device_isoc_start(SIMPLEQ_FIRST(&reqh->pipe->queue));
+ if (!err)
+ uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
- return (r);
+ return (err);
}
void
-uhci_device_isoc_enter(reqh)
- usbd_request_handle reqh;
+uhci_device_isoc_enter(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
struct iso *iso = &upipe->u.iso;
@@ -1904,12 +2094,16 @@ uhci_device_isoc_enter(reqh)
u_int32_t buf, len, status;
int s, i, next, nframes;
- DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p "
+ DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
"nframes=%d\n",
- iso->inuse, iso->next, reqh, reqh->nframes));
+ iso->inuse, iso->next, xfer, xfer->nframes));
+
+ if (sc->sc_dying)
+ return;
- if (reqh->status == USBD_IN_PROGRESS) {
+ if (xfer->status == USBD_IN_PROGRESS) {
/* This request has already been entered into the frame list */
+ /* XXX */
}
#ifdef DIAGNOSTIC
@@ -1924,20 +2118,20 @@ uhci_device_isoc_enter(reqh)
DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next));
}
- reqh->status = USBD_IN_PROGRESS;
- reqh->hcprivint = next;
+ xfer->status = USBD_IN_PROGRESS;
+ xfer->hcprivint = next;
- buf = DMAADDR(&reqh->dmabuf);
+ buf = DMAADDR(&xfer->dmabuf);
status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
UHCI_TD_ACTIVE |
UHCI_TD_IOS));
- nframes = reqh->nframes;
+ nframes = xfer->nframes;
s = splusb();
for (i = 0; i < nframes; i++) {
std = iso->stds[next];
if (++next >= UHCI_VFRAMELIST_COUNT)
next = 0;
- len = reqh->frlengths[i];
+ len = xfer->frlengths[i];
std->td.td_buffer = LE(buf);
if (i == nframes - 1)
status |= LE(UHCI_TD_IOC);
@@ -1953,28 +2147,31 @@ uhci_device_isoc_enter(reqh)
buf += len;
}
iso->next = next;
- iso->inuse += reqh->nframes;
+ iso->inuse += xfer->nframes;
splx(s);
}
usbd_status
-uhci_device_isoc_start(reqh)
- usbd_request_handle reqh;
+uhci_device_isoc_start(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus;
uhci_intr_info_t *ii = upipe->iinfo;
uhci_soft_td_t *end;
int s, i;
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
+
#ifdef DIAGNOSTIC
- if (reqh->status != USBD_IN_PROGRESS)
- printf("uhci_device_isoc_start: not in progress %p\n", reqh);
+ if (xfer->status != USBD_IN_PROGRESS)
+ printf("uhci_device_isoc_start: not in progress %p\n", xfer);
#endif
/* Find the last TD */
- i = reqh->hcprivint + reqh->nframes;
+ i = xfer->hcprivint + xfer->nframes;
if (i >= UHCI_VFRAMELIST_COUNT)
i -= UHCI_VFRAMELIST_COUNT;
end = upipe->u.iso.stds[i];
@@ -1982,13 +2179,16 @@ uhci_device_isoc_start(reqh)
s = splusb();
/* Set up interrupt info. */
- ii->reqh = reqh;
+ ii->xfer = xfer;
ii->stdstart = end;
ii->stdend = end;
#if defined(__FreeBSD__)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_isoc_start: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
@@ -1999,21 +2199,21 @@ uhci_device_isoc_start(reqh)
}
void
-uhci_device_isoc_abort(reqh)
- usbd_request_handle reqh;
+uhci_device_isoc_abort(xfer)
+ usbd_xfer_handle xfer;
{
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_intr_info_t *ii = upipe->iinfo;
uhci_soft_td_t **stds = upipe->u.iso.stds;
uhci_soft_td_t *std;
int i, n, nframes;
/* Make interrupt routine ignore it, */
- reqh->status = USBD_CANCELLED;
+ xfer->status = USBD_CANCELLED;
/* make hardware ignore it, */
- nframes = reqh->nframes;
- n = reqh->hcprivint;
+ nframes = xfer->nframes;
+ n = xfer->hcprivint;
for (i = 0; i < nframes; i++) {
std = stds[n];
std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
@@ -2021,16 +2221,16 @@ uhci_device_isoc_abort(reqh)
n = 0;
}
- reqh->hcpriv = ii;
+ xfer->hcpriv = ii;
/* make sure hardware has completed, */
- if (reqh->device->bus->intr_context) {
+ if (xfer->device->bus->intr_context) {
/* We have no process context, so we can't use tsleep(). */
- timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+ timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
} else {
- usb_delay_ms(reqh->pipe->device->bus, 1);
+ usb_delay_ms(xfer->pipe->device->bus, 1);
/* and call final part of interrupt handler. */
- uhci_abort_req_end(reqh);
+ uhci_abort_xfer_end(xfer);
}
}
@@ -2061,10 +2261,10 @@ uhci_device_isoc_close(pipe)
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
std = iso->stds[i];
for (vstd = sc->sc_vframes[i].htd;
- vstd && vstd->link.std != std;
+ vstd != NULL && vstd->link.std != std;
vstd = vstd->link.std)
;
- if (!vstd) {
+ if (vstd == NULL) {
/*panic*/
printf("uhci_device_isoc_close: %p not found\n", std);
uhci_unlock_frames(sc);
@@ -2136,12 +2336,12 @@ uhci_setup_isoc(pipe)
}
void
-uhci_device_isoc_done(reqh)
- usbd_request_handle reqh;
+uhci_device_isoc_done(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_intr_info_t *ii = reqh->hcpriv;
+ uhci_intr_info_t *ii = xfer->hcpriv;
- DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen));
+ DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen));
/* Turn off the interrupt since it is active even if the TD is not. */
ii->stdend->td.td_status &= LE(~UHCI_TD_IOC);
@@ -2150,16 +2350,16 @@ uhci_device_isoc_done(reqh)
}
void
-uhci_device_intr_done(reqh)
- usbd_request_handle reqh;
+uhci_device_intr_done(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_intr_info_t *ii = reqh->hcpriv;
+ uhci_intr_info_t *ii = xfer->hcpriv;
uhci_softc_t *sc = ii->sc;
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
uhci_soft_qh_t *sqh;
int i, npoll;
- DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen));
+ DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen));
npoll = upipe->u.intr.npoll;
for(i = 0; i < npoll; i++) {
@@ -2170,13 +2370,12 @@ uhci_device_intr_done(reqh)
uhci_free_std_chain(sc, ii->stdstart, 0);
/* XXX Wasteful. */
- if (reqh->pipe->repeat) {
+ if (xfer->pipe->repeat) {
uhci_soft_td_t *data, *dataend;
/* This alloc cannot fail since we freed the chain above. */
- uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
- reqh->flags & USBD_SHORT_XFER_OK,
- &reqh->dmabuf, &data, &dataend);
+ uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef UHCI_DEBUG
@@ -2193,6 +2392,9 @@ uhci_device_intr_done(reqh)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_intr_done: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
for (i = 0; i < npoll; i++) {
@@ -2207,15 +2409,15 @@ uhci_device_intr_done(reqh)
/* Deallocate request data structures */
void
-uhci_device_ctrl_done(reqh)
- usbd_request_handle reqh;
+uhci_device_ctrl_done(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_intr_info_t *ii = reqh->hcpriv;
+ uhci_intr_info_t *ii = xfer->hcpriv;
uhci_softc_t *sc = ii->sc;
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST))
+ if (!(xfer->rqflags & URQ_REQUEST))
panic("uhci_ctrl_done: not a request\n");
#endif
@@ -2226,17 +2428,17 @@ uhci_device_ctrl_done(reqh)
if (upipe->u.ctl.length != 0)
uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
- DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen));
+ DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen));
}
/* Deallocate request data structures */
void
-uhci_device_bulk_done(reqh)
- usbd_request_handle reqh;
+uhci_device_bulk_done(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_intr_info_t *ii = reqh->hcpriv;
+ uhci_intr_info_t *ii = xfer->hcpriv;
uhci_softc_t *sc = ii->sc;
- struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
LIST_REMOVE(ii, list); /* remove from active list */
@@ -2244,7 +2446,7 @@ uhci_device_bulk_done(reqh)
uhci_free_std_chain(sc, ii->stdstart, 0);
- DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen));
+ DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen));
}
/* Add interrupt QH, called with vflock. */
@@ -2368,7 +2570,8 @@ uhci_open(pipe)
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
- usbd_status r;
+ usbd_status err;
+ int ival;
DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, pipe->device->address,
@@ -2392,23 +2595,23 @@ uhci_open(pipe)
case UE_CONTROL:
pipe->methods = &uhci_device_ctrl_methods;
upipe->u.ctl.sqh = uhci_alloc_sqh(sc);
- if (upipe->u.ctl.sqh == 0)
+ if (upipe->u.ctl.sqh == NULL)
goto bad;
upipe->u.ctl.setup = uhci_alloc_std(sc);
- if (upipe->u.ctl.setup == 0) {
+ if (upipe->u.ctl.setup == NULL) {
uhci_free_sqh(sc, upipe->u.ctl.sqh);
goto bad;
}
upipe->u.ctl.stat = uhci_alloc_std(sc);
- if (upipe->u.ctl.stat == 0) {
+ if (upipe->u.ctl.stat == NULL) {
uhci_free_sqh(sc, upipe->u.ctl.sqh);
uhci_free_std(sc, upipe->u.ctl.setup);
goto bad;
}
- r = usb_allocmem(&sc->sc_bus,
+ err = usb_allocmem(&sc->sc_bus,
sizeof(usb_device_request_t),
0, &upipe->u.ctl.reqdma);
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
uhci_free_sqh(sc, upipe->u.ctl.sqh);
uhci_free_std(sc, upipe->u.ctl.setup);
uhci_free_std(sc, upipe->u.ctl.stat);
@@ -2417,14 +2620,17 @@ uhci_open(pipe)
break;
case UE_INTERRUPT:
pipe->methods = &uhci_device_intr_methods;
- return (uhci_device_setintr(sc, upipe, ed->bInterval));
+ ival = pipe->interval;
+ if (ival == USBD_DEFAULT_INTERVAL)
+ ival = ed->bInterval;
+ return (uhci_device_setintr(sc, upipe, ival));
case UE_ISOCHRONOUS:
pipe->methods = &uhci_device_isoc_methods;
return (uhci_setup_isoc(pipe));
case UE_BULK:
pipe->methods = &uhci_device_bulk_methods;
upipe->u.bulk.sqh = uhci_alloc_sqh(sc);
- if (upipe->u.bulk.sqh == 0)
+ if (upipe->u.bulk.sqh == NULL)
goto bad;
break;
}
@@ -2443,8 +2649,8 @@ usb_device_descriptor_t uhci_devd = {
USB_DEVICE_DESCRIPTOR_SIZE,
UDESC_DEVICE, /* type */
{0x00, 0x01}, /* USB version */
- UCLASS_HUB, /* class */
- USUBCLASS_HUB, /* subclass */
+ UDCLASS_HUB, /* class */
+ UDSUBCLASS_HUB, /* subclass */
0, /* protocol */
64, /* max packet */
{0},{0},{0x00,0x01}, /* device id */
@@ -2471,8 +2677,8 @@ usb_interface_descriptor_t uhci_ifcd = {
0,
0,
1,
- UCLASS_HUB,
- USUBCLASS_HUB,
+ UICLASS_HUB,
+ UISUBCLASS_HUB,
0,
0
};
@@ -2520,37 +2726,42 @@ uhci_str(p, l, s)
* Simulate a hardware hub by handling all the necessary requests.
*/
usbd_status
-uhci_root_ctrl_transfer(reqh)
- usbd_request_handle reqh;
+uhci_root_ctrl_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
- /* Pipe isn't running, start first */
- return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ /* Pipe isn't running (otherwise err would be USBD_INPROG),
+ * start first
+ */
+ return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
usbd_status
-uhci_root_ctrl_start(reqh)
- usbd_request_handle reqh;
+uhci_root_ctrl_start(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
+ uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
usb_device_request_t *req;
void *buf = NULL;
int port, x;
int s, len, value, index, status, change, l, totlen = 0;
usb_port_status_t ps;
- usbd_status r;
+ usbd_status err;
+
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & URQ_REQUEST))
+ if (!(xfer->rqflags & URQ_REQUEST))
panic("uhci_root_ctrl_transfer: not a request\n");
#endif
- req = &reqh->request;
+ req = &xfer->request;
DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n",
req->bmRequestType, req->bRequest));
@@ -2560,7 +2771,7 @@ uhci_root_ctrl_start(reqh)
index = UGETW(req->wIndex);
if (len != 0)
- buf = KERNADDR(&reqh->dmabuf);
+ buf = KERNADDR(&xfer->dmabuf);
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
@@ -2583,7 +2794,7 @@ uhci_root_ctrl_start(reqh)
switch(value >> 8) {
case UDESC_DEVICE:
if ((value & 0xff) != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
@@ -2592,7 +2803,7 @@ uhci_root_ctrl_start(reqh)
break;
case UDESC_CONFIG:
if ((value & 0xff) != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
@@ -2623,7 +2834,7 @@ uhci_root_ctrl_start(reqh)
}
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
break;
@@ -2648,14 +2859,14 @@ uhci_root_ctrl_start(reqh)
break;
case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
if (value >= USB_MAX_DEVICES) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
sc->sc_addr = value;
break;
case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
if (value != 0 && value != 1) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
sc->sc_conf = value;
@@ -2665,7 +2876,7 @@ uhci_root_ctrl_start(reqh)
case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
break;
@@ -2683,7 +2894,7 @@ uhci_root_ctrl_start(reqh)
else if (index == 2)
port = UHCI_PORTSC2;
else {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
switch(value) {
@@ -2713,7 +2924,7 @@ uhci_root_ctrl_start(reqh)
break;
case UHF_C_PORT_RESET:
sc->sc_isreset = 0;
- r = USBD_NORMAL_COMPLETION;
+ err = USBD_NORMAL_COMPLETION;
goto ret;
case UHF_PORT_CONNECTION:
case UHF_PORT_OVER_CURRENT:
@@ -2721,7 +2932,7 @@ uhci_root_ctrl_start(reqh)
case UHF_PORT_LOW_SPEED:
case UHF_C_PORT_SUSPEND:
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
break;
@@ -2731,7 +2942,7 @@ uhci_root_ctrl_start(reqh)
else if (index == 2)
port = UHCI_PORTSC2;
else {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
if (len > 0) {
@@ -2743,7 +2954,7 @@ uhci_root_ctrl_start(reqh)
break;
case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
if (value != 0) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
l = min(len, USB_HUB_DESCRIPTOR_SIZE);
@@ -2752,7 +2963,7 @@ uhci_root_ctrl_start(reqh)
break;
case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
if (len != 4) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
memset(buf, 0, len);
@@ -2764,11 +2975,11 @@ uhci_root_ctrl_start(reqh)
else if (index == 2)
port = UHCI_PORTSC2;
else {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
if (len != 4) {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
x = UREAD2(sc, port);
@@ -2799,7 +3010,7 @@ uhci_root_ctrl_start(reqh)
totlen = l;
break;
case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
break;
@@ -2809,7 +3020,7 @@ uhci_root_ctrl_start(reqh)
else if (index == 2)
port = UHCI_PORTSC2;
else {
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
switch(value) {
@@ -2844,31 +3055,31 @@ uhci_root_ctrl_start(reqh)
case UHF_C_PORT_SUSPEND:
case UHF_C_PORT_RESET:
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
break;
default:
- r = USBD_IOERROR;
+ err = USBD_IOERROR;
goto ret;
}
- reqh->actlen = totlen;
- r = USBD_NORMAL_COMPLETION;
+ xfer->actlen = totlen;
+ err = USBD_NORMAL_COMPLETION;
ret:
- reqh->status = r;
- reqh->hcpriv = 0;
+ xfer->status = err;
+ xfer->hcpriv = 0;
s = splusb();
- usb_transfer_complete(reqh);
+ usb_transfer_complete(xfer);
splx(s);
return (USBD_IN_PROGRESS);
}
/* Abort a root control request. */
void
-uhci_root_ctrl_abort(reqh)
- usbd_request_handle reqh;
+uhci_root_ctrl_abort(xfer)
+ usbd_xfer_handle xfer;
{
- /* Nothing to do, all transfers are syncronous. */
+ /* Nothing to do, all transfers are synchronous. */
}
/* Close the root pipe. */
@@ -2876,59 +3087,61 @@ void
uhci_root_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
- uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
-
- sc->sc_has_timo = 0;
DPRINTF(("uhci_root_ctrl_close\n"));
}
/* Abort a root interrupt request. */
void
-uhci_root_intr_abort(reqh)
- usbd_request_handle reqh;
+uhci_root_intr_abort(xfer)
+ usbd_xfer_handle xfer;
{
- uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
+ uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
- usb_untimeout(uhci_timo, reqh, reqh->timo_handle);
- sc->sc_has_timo = 0;
+ usb_untimeout(uhci_timo, xfer, xfer->timo_handle);
+ sc->sc_has_timo = NULL;
- if (reqh->pipe->intrreqh == reqh) {
+ if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("uhci_root_intr_abort: remove\n"));
- reqh->pipe->intrreqh = 0;
+ xfer->pipe->intrxfer = 0;
}
- reqh->status = USBD_CANCELLED;
- usb_transfer_complete(reqh);
+ xfer->status = USBD_CANCELLED;
+ usb_transfer_complete(xfer);
}
usbd_status
-uhci_root_intr_transfer(reqh)
- usbd_request_handle reqh;
+uhci_root_intr_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_status r;
+ usbd_status err;
/* Insert last in queue. */
- r = usb_insert_transfer(reqh);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usb_insert_transfer(xfer);
+ if (err)
+ return (err);
- /* Pipe isn't running, start first */
- return (uhci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+ /* Pipe isn't running (otherwise err would be USBD_INPROG),
+ * start first
+ */
+ return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
}
/* Start a transfer on the root interrupt pipe */
usbd_status
-uhci_root_intr_start(reqh)
- usbd_request_handle reqh;
+uhci_root_intr_start(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
+ usbd_pipe_handle pipe = xfer->pipe;
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
- DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n",
- reqh, reqh->length, reqh->flags));
+ DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n",
+ xfer, xfer->length, xfer->flags));
+
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
- sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval);
- usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
- sc->sc_has_timo = reqh;
+ sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
+ usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
+ sc->sc_has_timo = xfer;
return (USBD_IN_PROGRESS);
}
@@ -2939,8 +3152,8 @@ uhci_root_intr_close(pipe)
{
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
- usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
- sc->sc_has_timo = 0;
+ usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle);
+ sc->sc_has_timo = NULL;
DPRINTF(("uhci_root_intr_close\n"));
}
diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h
index a49c9c31c3c..2213fdea4b3 100644
--- a/sys/dev/usb/uhcireg.h
+++ b/sys/dev/usb/uhcireg.h
@@ -1,5 +1,5 @@
-/* $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 $ */
+/* $OpenBSD: uhcireg.h,v 1.3 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: uhcireg.h,v 1.9 1999/11/20 00:57:09 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -47,6 +47,7 @@
#define PCI_USBREV_MASK 0xff
#define PCI_USBREV_PRE_1_0 0x00
#define PCI_USBREV_1_0 0x10
+#define PCI_USBREV_1_1 0x11
#define PCI_LEGSUP 0xc0 /* Legacy Support register */
#define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index 26c6177672f..3f526106f4d 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhcivar.h,v 1.5 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: uhcivar.h,v 1.16 1999/10/13 08:10:56 augustss Exp $ */
+/* $OpenBSD: uhcivar.h,v 1.6 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: uhcivar.h,v 1.23 2000/02/22 16:03:44 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@ typedef union {
*/
typedef struct uhci_intr_info {
struct uhci_softc *sc;
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
uhci_soft_td_t *stdstart;
uhci_soft_td_t *stdend;
LIST_ENTRY(uhci_intr_info) list;
@@ -92,7 +92,7 @@ struct uhci_soft_td {
};
/*
* 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
+ * we can pack a number of soft TD together and have the real TD well
* aligned.
* NOTE: Minimum size is 32 bytes.
*/
@@ -116,7 +116,7 @@ struct uhci_soft_qh {
#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
/*
- * Information about an entry in the virtial frame list.
+ * Information about an entry in the virtual frame list.
*/
struct uhci_vframe {
uhci_soft_td_t *htd; /* pointer to dummy TD */
@@ -140,35 +140,43 @@ typedef struct uhci_softc {
uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */
uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */
- uhci_soft_td_t *sc_freetds;
- uhci_soft_qh_t *sc_freeqhs;
+ uhci_soft_td_t *sc_freetds; /* TD free list */
+ uhci_soft_qh_t *sc_freeqhs; /* QH free list */
+
+ SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
u_int8_t sc_addr; /* device address */
u_int8_t sc_conf; /* device configuration */
- char sc_isreset;
+ u_int8_t sc_saved_sof;
+ u_int16_t sc_saved_frnum;
+ char sc_isreset;
char sc_suspend;
- usbd_request_handle sc_has_timo;
+ char sc_dying;
LIST_HEAD(, uhci_intr_info) sc_intrhead;
/* Info for the root hub interrupt channel. */
- int sc_ival;
+ int sc_ival; /* time between root hub intrs */
+ usbd_xfer_handle sc_has_timo; /* root hub interrupt transfer */
- char sc_vflock;
+ char sc_vflock; /* for lock virtual frame list */
#define UHCI_HAS_LOCK 1
#define UHCI_WANT_LOCK 2
- char sc_vendor[16];
- int sc_id_vendor;
+ char sc_vendor[16]; /* vendor string for root hub */
+ int sc_id_vendor; /* vendor ID for root hub */
- void *sc_powerhook;
- device_ptr_t sc_child;
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+
+ device_ptr_t sc_child; /* /dev/usb device */
} uhci_softc_t;
usbd_status uhci_init __P((uhci_softc_t *));
int uhci_intr __P((void *));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
int uhci_detach __P((uhci_softc_t *, int));
int uhci_activate __P((device_ptr_t, enum devact));
-
+#endif
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index d0bd5efa5ed..0443d21994a 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhid.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: uhid.c,v 1.26 1999/10/13 08:10:56 augustss Exp $ */
+/* $OpenBSD: uhid.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: uhid.c,v 1.35 2000/03/19 22:23:28 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -83,6 +83,7 @@ int uhiddebug = 0;
struct uhid_softc {
USBBASEDEVICE sc_dev; /* base device */
+ usbd_device_handle sc_udev;
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -94,8 +95,8 @@ struct uhid_softc {
u_int8_t sc_oid;
u_int8_t sc_fid;
- char *sc_ibuf;
- char *sc_obuf;
+ u_char *sc_ibuf;
+ u_char *sc_obuf;
void *sc_repdesc;
int sc_repdesc_size;
@@ -146,7 +147,7 @@ static struct cdevsw uhid_cdevsw = {
};
#endif
-void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
+void uhid_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int));
int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int));
@@ -159,10 +160,10 @@ USB_MATCH(uhid)
USB_MATCH_START(uhid, uaa);
usb_interface_descriptor_t *id;
- if (!uaa->iface)
+ if (uaa->iface == NULL)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (!id || id->bInterfaceClass != UCLASS_HID)
+ if (id == NULL || id->bInterfaceClass != UICLASS_HID)
return (UMATCH_NONE);
return (UMATCH_IFACECLASS_GENERIC);
}
@@ -175,9 +176,10 @@ USB_ATTACH(uhid)
usb_endpoint_descriptor_t *ed;
int size;
void *desc;
- usbd_status r;
+ usbd_status err;
char devinfo[1024];
-
+
+ sc->sc_udev = uaa->device;
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
@@ -186,7 +188,7 @@ USB_ATTACH(uhid)
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
ed = usbd_interface2endpoint_descriptor(iface, 0);
- if (!ed) {
+ if (ed == NULL) {
printf("%s: could not read endpoint descriptor\n",
USBDEVNAME(sc->sc_dev));
sc->sc_dying = 1;
@@ -212,12 +214,10 @@ USB_ATTACH(uhid)
sc->sc_ep_addr = ed->bEndpointAddress;
desc = 0;
- r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);
+ if (err) {
printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
sc->sc_dying = 1;
- if (desc)
- free(desc, M_USBDEV);
USB_ATTACH_ERROR_RETURN;
}
@@ -230,6 +230,20 @@ USB_ATTACH(uhid)
sc->sc_repdesc = desc;
sc->sc_repdesc_size = size;
+#ifdef __FreeBSD__
+ {
+ static int global_init_done = 0;
+
+ if (!global_init_done) {
+ cdevsw_add(&uhid_cdevsw);
+ global_init_done = 1;
+ }
+ }
+#endif
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
USB_ATTACH_SUCCESS_RETURN;
}
@@ -267,7 +281,7 @@ USB_DETACH(uhid)
#endif
sc->sc_dying = 1;
- if (sc->sc_intrpipe)
+ if (sc->sc_intrpipe != NULL)
usbd_abort_pipe(sc->sc_intrpipe);
if (sc->sc_state & UHID_OPEN) {
@@ -296,20 +310,32 @@ USB_DETACH(uhid)
free(sc->sc_repdesc, M_USBDEV);
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
return (0);
}
void
-uhid_intr(reqh, addr, status)
- usbd_request_handle reqh;
+uhid_intr(xfer, addr, status)
+ usbd_xfer_handle xfer;
usbd_private_handle addr;
usbd_status status;
{
struct uhid_softc *sc = addr;
- DPRINTFN(5, ("uhid_intr: status=%d\n", status));
- DPRINTFN(5, ("uhid_intr: data = %02x %02x %02x\n",
- sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2]));
+#ifdef UHID_DEBUG
+ if (uhiddebug > 5) {
+ u_int32_t cc, i;
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
+ DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));
+ DPRINTF(("uhid_intr: data="));
+ for (i = 0; i < cc; i++)
+ DPRINTF((" %02x", sc->sc_ibuf[i]));
+ DPRINTF(("\n"));
+ }
+#endif
if (status == USBD_CANCELLED)
return;
@@ -338,7 +364,7 @@ uhidopen(dev, flag, mode, p)
struct proc *p;
{
struct uhid_softc *sc;
- usbd_status r;
+ usbd_status err;
USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
@@ -360,13 +386,12 @@ uhidopen(dev, flag, mode, p)
sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
/* Set up interrupt pipe. */
- r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
- USBD_SHORT_XFER_OK,
- &sc->sc_intrpipe, sc, sc->sc_ibuf,
- sc->sc_isize, uhid_intr);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
+ USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
+ sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
+ if (err) {
DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
- "error=%d\n",r));
+ "error=%d\n",err));
free(sc->sc_ibuf, M_USBDEV);
free(sc->sc_obuf, M_USBDEV);
sc->sc_state &= ~UHID_OPEN;
@@ -416,15 +441,15 @@ uhid_do_read(sc, uio, flag)
int error = 0;
size_t length;
u_char buffer[UHID_CHUNK];
- usbd_status r;
+ usbd_status err;
DPRINTFN(1, ("uhidread\n"));
if (sc->sc_state & UHID_IMMED) {
DPRINTFN(1, ("uhidread immed\n"));
- r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
+ err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
sc->sc_iid, buffer, sc->sc_isize);
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
return (EIO);
return (uiomove(buffer, sc->sc_isize, uio));
}
@@ -461,7 +486,7 @@ uhid_do_read(sc, uio, flag)
/* Remove a small chunk from the input queue. */
(void) q_to_b(&sc->sc_q, buffer, length);
- DPRINTFN(5, ("uhidread: got %d chars\n", length));
+ DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
/* Copy the data to the user process. */
if ((error = uiomove(buffer, length, uio)) != 0)
@@ -497,7 +522,7 @@ uhid_do_write(sc, uio, flag)
{
int error;
int size;
- usbd_status r;
+ usbd_status err;
DPRINTFN(1, ("uhidwrite\n"));
@@ -511,15 +536,13 @@ uhid_do_write(sc, uio, flag)
error = uiomove(sc->sc_obuf, size, uio);
if (!error) {
if (sc->sc_oid)
- r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
- sc->sc_obuf[0],
- sc->sc_obuf+1, size-1);
+ err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
+ sc->sc_obuf[0], sc->sc_obuf+1, size-1);
else
- r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
- 0, sc->sc_obuf, size);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
+ 0, sc->sc_obuf, size);
+ if (err)
error = EIO;
- }
}
return (error);
@@ -554,7 +577,7 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
struct usb_ctl_report_desc *rd;
struct usb_ctl_report *re;
int size, id;
- usbd_status r;
+ usbd_status err;
DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
@@ -575,11 +598,10 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
case USB_SET_IMMED:
if (*(int *)addr) {
- /* XXX should read into ibuf, but does it matter */
- r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
- sc->sc_iid, sc->sc_ibuf,
- sc->sc_isize);
- if (r != USBD_NORMAL_COMPLETION)
+ /* XXX should read into ibuf, but does it matter? */
+ err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
+ sc->sc_iid, sc->sc_ibuf, sc->sc_isize);
+ if (err)
return (EOPNOTSUPP);
sc->sc_state |= UHID_IMMED;
@@ -605,9 +627,32 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
default:
return (EINVAL);
}
- r = usbd_get_report(sc->sc_iface, re->report, id,
- re->data, size);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_get_report(sc->sc_iface, re->report, id, re->data,
+ size);
+ if (err)
+ return (EIO);
+ break;
+ case USB_SET_REPORT:
+ re = (struct usb_ctl_report *)addr;
+ switch (re->report) {
+ case UHID_INPUT_REPORT:
+ size = sc->sc_isize;
+ id = sc->sc_iid;
+ break;
+ case UHID_OUTPUT_REPORT:
+ size = sc->sc_osize;
+ id = sc->sc_oid;
+ break;
+ case UHID_FEATURE_REPORT:
+ size = sc->sc_fsize;
+ id = sc->sc_fid;
+ break;
+ default:
+ return (EINVAL);
+ }
+ err = usbd_set_report(sc->sc_iface, re->report, id, re->data,
+ size);
+ if (err)
return (EIO);
break;
@@ -667,6 +712,5 @@ uhidpoll(dev, events, p)
}
#if defined(__FreeBSD__)
-DEV_DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass,
- uhid_cdevsw, usbd_driver_load, 0);
+DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 517d48a29e3..4ba332ef49e 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhub.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: uhub.c,v 1.32 1999/10/13 08:10:56 augustss Exp $ */
+/* $OpenBSD: uhub.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: uhub.c,v 1.40 2000/02/29 21:37:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -48,12 +48,12 @@
#include <sys/malloc.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/device.h>
+#include <sys/proc.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
#include "bus_if.h"
#endif
-#include <sys/proc.h>
#include <machine/bus.h>
@@ -63,9 +63,9 @@
#include <dev/usb/usbdivar.h>
#ifdef UHUB_DEBUG
-#define DPRINTF(x) if (usbdebug) logprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
-extern int usbdebug;
+#define DPRINTF(x) if (uhubdebug) logprintf x
+#define DPRINTFN(n,x) if (uhubdebug>(n)) logprintf x
+int uhubdebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -81,15 +81,12 @@ struct uhub_softc {
usbd_status uhub_init_port __P((struct usbd_port *));
usbd_status uhub_explore __P((usbd_device_handle hub));
-void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
+void uhub_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
#if defined(__FreeBSD__)
static bus_child_detached_t uhub_child_detached;
#endif
-USB_DECLARE_DRIVER_INIT(uhub,
- DEVMETHOD(bus_child_detached, uhub_child_detached));
-
/*
* We need two attachment points:
* hub to usb and hub to hub
@@ -97,12 +94,17 @@ USB_DECLARE_DRIVER_INIT(uhub,
*/
#if defined(__NetBSD__) || defined(__OpenBSD__)
+USB_DECLARE_DRIVER(uhub);
+
/* Create the driver instance for the hub connected to hub case */
struct cfattach uhub_uhub_ca = {
sizeof(struct uhub_softc), uhub_match, uhub_attach,
uhub_detach, uhub_activate
};
#elif defined(__FreeBSD__)
+USB_DECLARE_DRIVER_INIT(uhub.
+ DEVMETHOD(bus_child_detached, uhub_child_detached));
+
/* Create the driver instance for the hub connected to usb case. */
devclass_t uhubroot_devclass;
@@ -131,7 +133,7 @@ USB_MATCH(uhub)
* The subclass for hubs seems to be 0 for some and 1 for others,
* so we just ignore the subclass.
*/
- if (uaa->iface == 0 && dd->bDeviceClass == UCLASS_HUB)
+ if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB)
return (UMATCH_DEVCLASS_DEVSUBCLASS);
return (UMATCH_NONE);
}
@@ -141,7 +143,7 @@ USB_ATTACH(uhub)
USB_ATTACH_START(uhub, sc, uaa);
usbd_device_handle dev = uaa->device;
char devinfo[1024];
- usbd_status r;
+ usbd_status err;
struct usbd_hub *hub;
usb_device_request_t req;
usb_hub_descriptor_t hubdesc;
@@ -155,10 +157,10 @@ USB_ATTACH(uhub)
USB_ATTACH_SETUP;
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
- r = usbd_set_config_index(dev, 0, 1);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_set_config_index(dev, 0, 1);
+ if (err) {
DPRINTF(("%s: configuration failed, error=%s\n",
- USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
USB_ATTACH_ERROR_RETURN;
}
@@ -175,15 +177,15 @@ USB_ATTACH(uhub)
USETW(req.wIndex, 0);
USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));
- r = usbd_do_request(dev, &req, &hubdesc);
+ err = usbd_do_request(dev, &req, &hubdesc);
nports = hubdesc.bNbrPorts;
- if (r == USBD_NORMAL_COMPLETION && nports > 7) {
+ if (!err && nports > 7) {
USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
- r = usbd_do_request(dev, &req, &hubdesc);
+ err = usbd_do_request(dev, &req, &hubdesc);
}
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
DPRINTF(("%s: getting hub descriptor failed, error=%s\n",
- USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
USB_ATTACH_ERROR_RETURN;
}
@@ -196,7 +198,7 @@ USB_ATTACH(uhub)
hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
M_USBDEV, M_NOWAIT);
- if (hub == 0)
+ if (hub == NULL)
USB_ATTACH_ERROR_RETURN;
dev->hub = hub;
dev->hub->hubsoftc = sc;
@@ -209,7 +211,7 @@ USB_ATTACH(uhub)
dev->powersrc->parent ?
dev->powersrc->parent->self_powered : 0));
- if (!dev->self_powered && dev->powersrc->parent &&
+ if (!dev->self_powered && dev->powersrc->parent != NULL &&
!dev->powersrc->parent->self_powered) {
printf("%s: bus powered hub connected to bus powered hub, "
"ignored\n", USBDEVNAME(sc->sc_dev));
@@ -217,13 +219,13 @@ USB_ATTACH(uhub)
}
/* Set up interrupt pipe. */
- r = usbd_device2interface_handle(dev, 0, &iface);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_device2interface_handle(dev, 0, &iface);
+ if (err) {
printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev));
goto bad;
}
ed = usbd_interface2endpoint_descriptor(iface, 0);
- if (ed == 0) {
+ if (ed == NULL) {
printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev));
goto bad;
}
@@ -232,11 +234,10 @@ USB_ATTACH(uhub)
goto bad;
}
- r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK,
- &sc->sc_ipipe, sc, sc->sc_status,
- sizeof(sc->sc_status),
- uhub_intr);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_open_pipe_intr(iface, ed->bEndpointAddress,
+ USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status,
+ sizeof(sc->sc_status), uhub_intr, USBD_DEFAULT_INTERVAL);
+ if (err) {
printf("%s: cannot open interrupt pipe\n",
USBDEVNAME(sc->sc_dev));
goto bad;
@@ -245,15 +246,17 @@ USB_ATTACH(uhub)
/* Wait with power off for a while. */
usbd_delay_ms(dev, USB_POWER_DOWN_TIME);
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev));
+
for (p = 0; p < nports; p++) {
struct usbd_port *up = &hub->ports[p];
up->device = 0;
up->parent = dev;
up->portno = p+1;
- r = uhub_init_port(up);
- if (r != USBD_NORMAL_COMPLETION)
+ err = uhub_init_port(up);
+ if (err)
printf("%s: init of port %d failed\n",
- USBDEVNAME(sc->sc_dev), up->portno);
+ USBDEVNAME(sc->sc_dev), up->portno);
}
sc->sc_running = 1;
@@ -271,12 +274,12 @@ uhub_init_port(up)
{
int port = up->portno;
usbd_device_handle dev = up->parent;
- usbd_status r;
+ usbd_status err;
u_int16_t pstatus;
- r = usbd_get_port_status(dev, port, &up->status);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_get_port_status(dev, port, &up->status);
+ if (err)
+ return (err);
pstatus = UGETW(up->status.wPortStatus);
DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x "
"change=0x%04x\n",
@@ -287,15 +290,10 @@ uhub_init_port(up)
/* First let the device go through a good power cycle, */
usbd_delay_ms(dev, USB_PORT_POWER_DOWN_TIME);
-#if 0
-usbd_clear_hub_feature(dev, UHF_C_HUB_OVER_CURRENT);
-usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT);
-#endif
-
/* then turn the power on. */
- r = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
+ if (err)
+ return (err);
DPRINTF(("usb_init_port: turn on port %d power status=0x%04x "
"change=0x%04x\n",
port, UGETW(up->status.wPortStatus),
@@ -304,9 +302,9 @@ usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT);
usbd_delay_ms(dev, dev->hub->hubdesc.bPwrOn2PwrGood *
UHD_PWRON_FACTOR);
/* Get the port status again. */
- r = usbd_get_port_status(dev, port, &up->status);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_get_port_status(dev, port, &up->status);
+ if (err)
+ return (err);
DPRINTF(("usb_init_port: after power on status=0x%04x "
"change=0x%04x\n",
UGETW(up->status.wPortStatus),
@@ -339,7 +337,7 @@ uhub_explore(dev)
usb_hub_descriptor_t *hd = &dev->hub->hubdesc;
struct uhub_softc *sc = dev->hub->hubsoftc;
struct usbd_port *up;
- usbd_status r;
+ usbd_status err;
int port;
int change, status;
@@ -354,17 +352,16 @@ uhub_explore(dev)
for(port = 1; port <= hd->bNbrPorts; port++) {
up = &dev->hub->ports[port-1];
- r = usbd_get_port_status(dev, port, &up->status);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_get_port_status(dev, port, &up->status);
+ if (err) {
DPRINTF(("uhub_explore: get port status failed, "
- "error=%s\n",
- usbd_errstr(r)));
+ "error=%s\n", usbd_errstr(err)));
continue;
}
status = UGETW(up->status.wPortStatus);
change = UGETW(up->status.wPortChange);
- DPRINTFN(5, ("uhub_explore: port %d status 0x%04x 0x%04x\n",
- port, status, change));
+ DPRINTFN(3,("uhub_explore: port %d status 0x%04x 0x%04x\n",
+ port, status, change));
if (change & UPS_C_PORT_ENABLED) {
usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
if (status & UPS_PORT_ENABLED) {
@@ -385,6 +382,8 @@ uhub_explore(dev)
}
}
if (!(change & UPS_C_CONNECT_STATUS)) {
+ DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_"
+ "STATUS\n", port));
/* No status change, just do recursive explore. */
if (up->device && up->device->hub)
up->device->hub->explore(up->device);
@@ -402,16 +401,19 @@ uhub_explore(dev)
* the disconnect.
*/
disco:
- if (up->device) {
+ if (up->device != NULL) {
/* Disconnected */
- DPRINTF(("uhub_explore: device %d disappeared "
+ DPRINTF(("uhub_explore: device addr=%d disappeared "
"on port %d\n", up->device->address, port));
usb_disconnect_port(up, USBDEV(sc->sc_dev));
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
- if (!(status & UPS_CURRENT_CONNECT_STATUS))
+ if (!(status & UPS_CURRENT_CONNECT_STATUS)) {
+ DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT"
+ "_STATUS\n", port));
continue;
+ }
/* Connected */
up->restartcnt = 0;
@@ -420,18 +422,20 @@ uhub_explore(dev)
usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
/* Reset port, which implies enabling it. */
- if (usbd_reset_port(dev, port, &up->status) !=
- USBD_NORMAL_COMPLETION)
+ if (usbd_reset_port(dev, port, &up->status)) {
+ DPRINTF(("uhub_explore: port=%d reset failed\n",
+ port));
continue;
+ }
/* Get device info and set its address. */
- r = usbd_new_device(USBDEV(sc->sc_dev), dev->bus,
+ err = usbd_new_device(USBDEV(sc->sc_dev), dev->bus,
dev->depth + 1, status & UPS_LOW_SPEED,
port, up);
/* XXX retry a few times? */
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
DPRINTFN(-1,("uhub_explore: usb_new_device failed, "
- "error=%s\n", usbd_errstr(r)));
+ "error=%s\n", usbd_errstr(err)));
/* Avoid addressing problems by disabling. */
/* usbd_reset_port(dev, port, &up->status); */
@@ -460,8 +464,9 @@ uhub_activate(self, act)
enum devact act;
{
struct uhub_softc *sc = (struct uhub_softc *)self;
- usbd_device_handle devhub = sc->sc_hub;
- int nports, p, i;
+ struct usbd_hub *hub = sc->sc_hub->hub;
+ usbd_device_handle dev;
+ int nports, port, i;
switch (act) {
case DVACT_ACTIVATE:
@@ -469,10 +474,12 @@ uhub_activate(self, act)
break;
case DVACT_DEACTIVATE:
- nports = devhub->hub->hubdesc.bNbrPorts;
- for(p = 0; p < nports; p++) {
- usbd_device_handle dev = devhub->hub->ports[p].device;
- if (dev) {
+ if (hub == NULL) /* malfunctioning hub */
+ break;
+ nports = hub->hubdesc.bNbrPorts;
+ for(port = 0; port < nports; port++) {
+ dev = hub->ports[port].device;
+ if (dev != NULL) {
for (i = 0; dev->subdevs[i]; i++)
config_deactivate(dev->subdevs[i]);
}
@@ -490,7 +497,7 @@ uhub_activate(self, act)
USB_DETACH(uhub)
{
USB_DETACH_START(uhub, sc);
- usbd_device_handle dev = sc->sc_hub;
+ struct usbd_hub *hub = sc->sc_hub->hub;
struct usbd_port *rup;
int port, nports;
@@ -500,25 +507,61 @@ USB_DETACH(uhub)
DPRINTF(("uhub_detach: sc=%port\n", sc));
#endif
- if (!dev->hub) /* Must be partially working */
+ if (hub == NULL) /* Must be partially working */
return (0);
usbd_abort_pipe(sc->sc_ipipe);
usbd_close_pipe(sc->sc_ipipe);
- nports = dev->hub->hubdesc.bNbrPorts;
+ nports = hub->hubdesc.bNbrPorts;
for(port = 0; port < nports; port++) {
- rup = &dev->hub->ports[port];
+ rup = &hub->ports[port];
if (rup->device)
usb_disconnect_port(rup, self);
}
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub,
+ USBDEV(sc->sc_dev));
- free(dev->hub, M_USBDEV);
- dev->hub = 0;
+ free(hub, M_USBDEV);
+ sc->sc_hub->hub = NULL;
return (0);
}
+#if defined(__FreeBSD__)
+/* Called when a device has been detached from it */
+static void
+uhub_child_detached(self, child)
+ device_t self;
+ device_t child;
+{
+ struct uhub_softc *sc = device_get_softc(self);
+ usbd_device_handle devhub = sc->sc_hub;
+ usbd_device_handle dev;
+ int nports;
+ int port;
+ int i;
+
+ if (!devhub->hub)
+ /* should never happen; children are only created after init */
+ panic("hub not fully initialised, but child deleted?");
+
+ nports = devhub->hub->hubdesc.bNbrPorts;
+ for (port = 0; port < nports; port++) {
+ dev = devhub->hub->ports[port].device;
+ if (dev && dev->subdevs) {
+ for (i = 0; dev->subdevs[i]; i++) {
+ if (dev->subdevs[i] == child) {
+ dev->subdevs[i] = NULL;
+ return;
+ }
+ }
+ }
+ }
+}
+#endif
+
/*
* Hub interrupt.
* This an indication that some port has changed status.
@@ -526,8 +569,8 @@ USB_DETACH(uhub)
* to be explored again.
*/
void
-uhub_intr(reqh, addr, status)
- usbd_request_handle reqh;
+uhub_intr(xfer, addr, status)
+ usbd_xfer_handle xfer;
usbd_private_handle addr;
usbd_status status;
{
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index e23f43d46c0..22a3b3777cd 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb.c,v 1.7 1999/11/11 15:57:40 ho Exp $ */
-/* $NetBSD: usb.c,v 1.28 1999/10/13 08:10:57 augustss Exp $ */
+/* $OpenBSD: usb.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb.c,v 1.41 2000/03/16 00:46:38 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,15 +51,15 @@
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/device.h>
#include <sys/kthread.h>
+#include <sys/proc.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/ioccom.h>
+#include <sys/filio.h>
#include <sys/uio.h>
#endif
#include <sys/conf.h>
#include <sys/poll.h>
-#include <sys/proc.h>
#include <sys/select.h>
#include <sys/vnode.h>
#include <sys/signalvar.h>
@@ -87,8 +87,17 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
#define DPRINTF(x) if (usbdebug) logprintf x
#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
int usbdebug = 0;
-int uhcidebug;
-int ohcidebug;
+#ifdef UHCI_DEBUG
+int uhcidebug;
+#endif
+#ifdef OHCI_DEBUG
+int ohcidebug;
+#endif
+/*
+ * 0 - do usual exploration
+ * 1 - do not use timeout exploration
+ * >1 - do no exploration
+ */
int usb_noexplore = 0;
#else
#define DPRINTF(x)
@@ -100,8 +109,12 @@ struct usb_softc {
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
+#if defined (__FreeBSD__)
+ /* This part should be deleted when kthreads is available */
struct selinfo sc_consel; /* waiting for connect change */
+#else
struct proc *sc_event_thread;
+#endif
char sc_dying;
};
@@ -111,6 +124,7 @@ cdev_decl(usb);
#elif defined(__FreeBSD__)
d_open_t usbopen;
d_close_t usbclose;
+d_read_t usbread;
d_ioctl_t usbioctl;
int usbpoll __P((dev_t, int, struct proc *));
@@ -136,7 +150,7 @@ usbd_status usb_discover __P((struct usb_softc *));
void usb_create_event_thread __P((void *));
void usb_event_thread __P((void *));
-#define USB_MAX_EVENTS 50
+#define USB_MAX_EVENTS 100
struct usb_event_q {
struct usb_event ue;
SIMPLEQ_ENTRY(usb_event_q) next;
@@ -146,11 +160,16 @@ int usb_nevents = 0;
struct selinfo usb_selevent;
struct proc *usb_async_proc; /* process who wants USB SIGIO */
int usb_dev_open = 0;
+void usb_add_event __P((int, struct usb_event *));
int usb_get_next_event __P((struct usb_event *));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
/* Flag to see if we are in the cold boot process. */
extern int cold;
+#endif
+
+static const char *usbrev_str[] = USBREV_STR;
USB_DECLARE_DRIVER(usb);
@@ -169,25 +188,42 @@ USB_ATTACH(usb)
void *aux = device_get_ivars(self);
#endif
usbd_device_handle dev;
- usbd_status r;
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- printf("\n");
-#elif defined(__FreeBSD__)
+ usbd_status err;
+ int usbrev;
+ struct usb_event ue;
+
+#if defined(__FreeBSD__)
+ printf("%s", USBDEVNAME(sc->sc_dev));
sc->sc_dev = self;
#endif
DPRINTF(("usbd_attach\n"));
+
usbd_init();
sc->sc_bus = aux;
sc->sc_bus->usbctl = sc;
sc->sc_port.power = USB_MAX_POWER;
- r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
- &sc->sc_port);
- if (r == USBD_NORMAL_COMPLETION) {
+ usbrev = sc->sc_bus->usbrev;
+ printf(": USB revision %s", usbrev_str[usbrev]);
+ if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) {
+ printf(", not supported\n");
+ USB_ATTACH_ERROR_RETURN;
+ }
+ printf("\n");
+
+ /* Make sure not to use tsleep() if we are cold booting. */
+ if (cold)
+ sc->sc_bus->use_polling++;
+
+ ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
+ usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
+
+ err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
+ &sc->sc_port);
+ if (!err) {
dev = sc->sc_port.device;
- if (!dev->hub) {
+ if (dev->hub == NULL) {
sc->sc_dying = 1;
printf("%s: root device is not a hub\n",
USBDEVNAME(sc->sc_dev));
@@ -200,23 +236,18 @@ USB_ATTACH(usb)
* until the USB event thread is running, which means that
* the keyboard will not work until after cold boot.
*/
- if (cold) {
- sc->sc_bus->use_polling++;
+ if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)
dev->hub->explore(sc->sc_bus->root_hub);
- sc->sc_bus->use_polling--;
- }
#endif
} else {
printf("%s: root hub problem, error=%d\n",
- USBDEVNAME(sc->sc_dev), r);
+ USBDEVNAME(sc->sc_dev), err);
sc->sc_dying = 1;
}
+ if (cold)
+ sc->sc_bus->use_polling--;
-#if defined(__NetBSD__)
- kthread_create(usb_create_event_thread, sc);
-#elif defined(__OpenBSD__)
kthread_create_deferred(usb_create_event_thread, sc);
-#endif
#if defined(__FreeBSD__)
make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR,
@@ -253,13 +284,20 @@ usb_event_thread(arg)
DPRINTF(("usb_event_thread: start\n"));
+ /* Make sure first discover does something. */
+ sc->sc_bus->needs_explore = 1;
+
while (!sc->sc_dying) {
#ifdef USB_DEBUG
- if (!usb_noexplore)
+ if (usb_noexplore < 2)
#endif
usb_discover(sc);
- (void)tsleep(&sc->sc_bus->needs_explore,
- PWAIT, "usbevt", hz*60);
+ (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
+#ifdef USB_DEBUG
+ usb_noexplore ? 0 :
+#endif
+ hz*60
+ );
DPRINTFN(2,("usb_event_thread: woke up\n"));
}
sc->sc_event_thread = 0;
@@ -397,13 +435,20 @@ usbioctl(devt, cmd, data, flag, p)
switch (cmd) {
#if defined(__FreeBSD__)
+ /* This part should be deleted when kthreads is available */
case USB_DISCOVER:
usb_discover(sc);
break;
#endif
#ifdef USB_DEBUG
case USB_SETDEBUG:
- usbdebug = uhcidebug = ohcidebug = *(int *)data;
+ usbdebug = ((*(int *)data) & 0x000000ff);
+#ifdef UHCI_DEBUG
+ uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8;
+#endif
+#ifdef OHCI_DEBUG
+ ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16;
+#endif
break;
#endif
case USB_REQUEST:
@@ -414,7 +459,7 @@ usbioctl(devt, cmd, data, flag, p)
struct uio uio;
void *ptr = 0;
int addr = ur->addr;
- usbd_status r;
+ usbd_status err;
int error = 0;
DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
@@ -442,10 +487,9 @@ usbioctl(devt, cmd, data, flag, p)
goto ret;
}
}
- r = usbd_do_request_flags(sc->sc_bus->devices[addr],
- &ur->request, ptr,
- ur->flags, &ur->actlen);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_do_request_flags(sc->sc_bus->devices[addr],
+ &ur->request, ptr, ur->flags, &ur->actlen);
+ if (err) {
error = EIO;
goto ret;
}
@@ -466,14 +510,14 @@ usbioctl(devt, cmd, data, flag, p)
{
struct usb_device_info *di = (void *)data;
int addr = di->addr;
- usbd_device_handle devh;
+ usbd_device_handle dev;
if (addr < 1 || addr >= USB_MAX_DEVICES)
return (EINVAL);
- devh = sc->sc_bus->devices[addr];
- if (devh == 0)
+ dev = sc->sc_bus->devices[addr];
+ if (dev == NULL)
return (ENXIO);
- usbd_fill_deviceinfo(devh, di);
+ usbd_fill_deviceinfo(dev, di);
break;
}
@@ -495,25 +539,41 @@ usbpoll(dev, events, p)
{
int revents, mask, s;
- if (minor(dev) != USB_DEV_MINOR)
- return (ENXIO);
+ if (minor(dev) != USB_DEV_MINOR) {
+ revents = 0;
+ mask = POLLIN | POLLRDNORM;
- revents = 0;
- s = splusb();
- mask = POLLIN | POLLRDNORM;
- if (events & mask)
- if (usb_nevents > 0)
+ s = splusb();
+ if (events & mask && usb_nevents > 0)
revents |= events & mask;
-
- DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents));
- if (revents == 0) {
- if (events & mask) {
- DPRINTFN(2, ("usbpoll: selrecord\n"));
+ if (revents == 0 && events & mask)
selrecord(p, &usb_selevent);
- }
+ splx(s);
+
+ return(revents);
+ } else {
+#if defined(__FreeBSD__)
+ /* This part should be deleted when kthreads is available */
+ struct usb_softc *sc;
+ int unit = minor(dev);
+
+ USB_GET_SC(usb, unit, sc);
+
+ revents = 0;
+ mask = POLLOUT | POLLRDNORM;
+
+ s = splusb();
+ if (events & mask && sc->sc_bus->needs_explore)
+ revents |= events & mask;
+ if (revents == 0 && events & mask)
+ selrecord(p, &sc->sc_consel);
+ splx(s);
+
+ return (revents);
+#else
+ return (ENXIO);
+#endif
}
- splx(s);
- return (revents);
}
/* Explore device tree from the root. */
@@ -521,15 +581,31 @@ usbd_status
usb_discover(sc)
struct usb_softc *sc;
{
+#if defined(__FreeBSD__)
+ /* The splxxx parts should be deleted when kthreads is available */
+ int s;
+#endif
/*
* We need mutual exclusion while traversing the device tree,
* but this is guaranteed since this function is only called
* from the event thread for the controller.
*/
- do {
+#if defined(__FreeBSD__)
+ s = splusb();
+#endif
+ while (sc->sc_bus->needs_explore && !sc->sc_dying) {
sc->sc_bus->needs_explore = 0;
+#if defined(__FreeBSD__)
+ splx(s);
+#endif
sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
- } while (sc->sc_bus->needs_explore && !sc->sc_dying);
+#if defined(__FreeBSD__)
+ s = splusb();
+#endif
+ }
+#if defined(__FreeBSD__)
+ splx(s);
+#endif
return (USBD_NORMAL_COMPLETION);
}
@@ -538,6 +614,10 @@ usb_needs_explore(bus)
usbd_bus_handle bus;
{
bus->needs_explore = 1;
+#if defined(__FreeBSD__)
+ /* This part should be deleted when kthreads is available */
+ selwakeup(&bus->usbctl->sc_consel);
+#endif
wakeup(&bus->needs_explore);
}
@@ -559,40 +639,66 @@ usb_get_next_event(ue)
}
void
-usbd_add_event(type, devh)
+usbd_add_dev_event(type, udev)
+ int type;
+ usbd_device_handle udev;
+{
+ struct usb_event ue;
+
+ usbd_fill_deviceinfo(udev, &ue.u.ue_device);
+ usb_add_event(type, &ue);
+}
+
+void
+usbd_add_drv_event(type, udev, dev)
int type;
- usbd_device_handle devh;
+ usbd_device_handle udev;
+ device_ptr_t dev;
+{
+ struct usb_event ue;
+
+ ue.u.ue_driver.ue_cookie = udev->cookie;
+ strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev),
+ sizeof ue.u.ue_driver.ue_devname);
+ usb_add_event(type, &ue);
+}
+
+void
+usb_add_event(type, uep)
+ int type;
+ struct usb_event *uep;
{
struct usb_event_q *ueq;
struct usb_event ue;
struct timeval thetime;
int s;
+ microtime(&thetime);
+ /* Don't want to wait here inside splusb() */
+ ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
+ ueq->ue = *uep;
+ ueq->ue.ue_type = type;
+ TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
+
s = splusb();
if (++usb_nevents >= USB_MAX_EVENTS) {
/* Too many queued events, drop an old one. */
DPRINTFN(-1,("usb: event dropped\n"));
(void)usb_get_next_event(&ue);
}
- /* Don't want to wait here inside splusb() */
- ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT);
- if (ueq == 0) {
- printf("usb: no memory, event dropped\n");
- splx(s);
- return;
- }
- ueq->ue.ue_type = type;
- ueq->ue.ue_cookie = devh->cookie;
- usbd_fill_deviceinfo(devh, &ueq->ue.ue_device);
- microtime(&thetime);
- TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
wakeup(&usb_events);
selwakeup(&usb_selevent);
- if (usb_async_proc)
+ if (usb_async_proc != NULL)
psignal(usb_async_proc, SIGIO);
splx(s);
}
+void
+usb_schedsoftintr(bus)
+ struct usbd_bus *bus;
+{
+ bus->methods->soft_intr(bus);
+}
#if defined(__NetBSD__) || defined(__OpenBSD__)
int
@@ -626,6 +732,7 @@ usb_detach(self, flags)
int flags;
{
struct usb_softc *sc = (struct usb_softc *)self;
+ struct usb_event ue;
DPRINTF(("usb_detach: start\n"));
@@ -645,6 +752,10 @@ usb_detach(self, flags)
}
usbd_finish();
+
+ ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
+ usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
+
return (0);
}
#elif defined(__FreeBSD__)
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 1e5ebeadb21..1878d444cd8 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb.h,v 1.38 1999/10/20 21:02:39 augustss Exp $ */
+/* $OpenBSD: usb.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb.h,v 1.42 2000/03/19 22:23:28 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -335,54 +335,78 @@ typedef struct {
#define UPS_C_PORT_RESET 0x0010
} usb_port_status_t;
-#define UCLASS_UNSPEC 0
-#define UCLASS_AUDIO 1
-#define USUBCLASS_AUDIOCONTROL 1
-#define USUBCLASS_AUDIOSTREAM 2
-#define USUBCLASS_MIDISTREAM 3
-#define UCLASS_CDC 2 /* communication */
-#define USUBCLASS_DIRECT_LINE_CONTROL_MODEL 1
-#define USUBCLASS_ABSTRACT_CONTROL_MODEL 2
-#define USUBCLASS_TELEPHONE_CONTROL_MODEL 3
-#define USUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
-#define USUBCLASS_CAPI_CONTROLMODEL 5
-#define USUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
-#define USUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
-#define UPROTO_CDC_AT 1
-#define UCLASS_HID 3
-#define USUBCLASS_BOOT 1
-#define UCLASS_PRINTER 7
-#define USUBCLASS_PRINTER 1
-#define UPROTO_PRINTER_UNI 1
-#define UPROTO_PRINTER_BI 2
-#define UCLASS_MASS 8
-#define USUBCLASS_RBC 1
-#define USUBCLASS_SFF8020I 2
-#define USUBCLASS_QIC157 3
-#define USUBCLASS_UFI 4
-#define USUBCLASS_SFF8070I 5
-#define USUBCLASS_SCSI 6
-#define UPROTO_MASS_CBI_I 0
-#define UPROTO_MASS_CBI 1
-#define UPROTO_MASS_BULK 2
-#define UPROTO_MASS_BULK_P 80
-#define UCLASS_HUB 9
-#define USUBCLASS_HUB 0
-#define UCLASS_DATA 10
-#define USUBCLASS_DATA 0
-#define UPROTO_DATA_ISDNBRI 0x30 /* Physical iface */
-#define UPROTO_DATA_HDLC 0x31 /* HDLC */
-#define UPROTO_DATA_TRANSPARENT 0x32 /* Transparent */
-#define UPROTO_DATA_Q921M 0x50 /* Management for Q921 */
-#define UPROTO_DATA_Q921 0x51 /* Data for Q921 */
-#define UPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */
-#define UPROTO_DATA_V42BIS 0x90 /* Data compression */
-#define UPROTO_DATA_Q931 0x91 /* Euro-ISDN */
-#define UPROTO_DATA_V120 0x92 /* V.24 rate adaption */
-#define UPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */
-#define UPROTO_DATA_HOST_BASED 0xfd /* Host based driver */
-#define UPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/
-#define UPROTO_DATA_VENDOR 0xff /* Vendor specific */
+/* Device class codes */
+#define UDCLASS_AUDIO 0x00
+#define UDCLASS_COMM 0x02
+#define UDCLASS_HID 0x00
+#define UDCLASS_HUB 0x09
+#define UDSUBCLASS_HUB 0
+#define UDCLASS_MASS 0x00
+
+/* Interface class codes */
+#define UICLASS_UNSPEC 0x00
+
+#define UICLASS_AUDIO 0x01
+#define UISUBCLASS_AUDIOCONTROL 1
+#define UISUBCLASS_AUDIOSTREAM 2
+#define UISUBCLASS_MIDISTREAM 3
+
+#define UICLASS_CDC 0x02 /* communication */
+#define UI_SUBCLASS_DIRECT_LINE_CONTROL_MODEL 1
+#define UI_SUBCLASS_ABSTRACT_CONTROL_MODEL 2
+#define UI_SUBCLASS_TELEPHONE_CONTROL_MODEL 3
+#define UI_SUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
+#define UI_SUBCLASS_CAPI_CONTROL_MODEL 5
+#define UI_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
+#define UI_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
+#define UIPROTO_CDC_AT 1
+
+#define UICLASS_HID 0x03
+#define UI_SUBCLASS_BOOT 1
+#define UIPROTO_BOOT_KEYBOARD 1
+
+#define UICLASS_PHYSICAL 0x05
+
+#define UICLASS_PRINTER 0x07
+#define UISUBCLASS_PRINTER 1
+#define UIPROTO_PRINTER_UNI 1
+#define UIPROTO_PRINTER_BI 2
+
+#define UICLASS_MASS 0x08
+#define UISUBCLASS_RBC 1
+#define UISUBCLASS_SFF8020I 2
+#define UISUBCLASS_QIC157 3
+#define UISUBCLASS_UFI 4
+#define UISUBCLASS_SFF8070I 5
+#define UISUBCLASS_SCSI 6
+#define UIPROTO_MASS_CBI_I 0
+#define UIPROTO_MASS_CBI 1
+#define UIPROTO_MASS_BULK 2
+#define UIPROTO_MASS_BULK_P 80
+
+#define UICLASS_HUB 0x09
+#define UISUBCLASS_HUB 0
+
+#define UICLASS_CDC_DATA 0x0a
+#define UISUBCLASS_DATA 0
+#define UIPROTO_DATA_ISDNBRI 0x30
+#define UIPROTO_DATA_HDLC 0x31
+#define UIPROTO_DATA_TRANSPARENT 0x32
+#define UIPROTO_DATA_Q921M 0x50
+#define UIPROTO_DATA_Q921 0x51
+#define UIPROTO_DATA_Q921TM 0x52
+#define UIPROTO_DATA_V42BIS 0x90
+#define UIPROTO_DATA_Q931 0x91
+#define UIPROTO_DATA_V120 0x92
+#define UIPROTO_DATA_CAPI 0x93
+#define UIPROTO_DATA_HOST_BASED 0xfd
+#define UIPROTO_DATA_PUF 0xfe
+#define UIPROTO_DATA_VENDOR 0xff
+
+#define UICLASS_FIRM_UPD 0x0c
+
+#define UICLASS_APPL_SPEC 0xfe
+#define UICLASS_VENDOR 0xff
#define USB_HUB_MAX_DEPTH 5
@@ -476,18 +500,28 @@ struct usb_ctl_report_desc {
u_char data[1024]; /* filled data size will vary */
};
+typedef struct { u_int32_t cookie; } usb_event_cookie_t;
+
+#define USB_MAX_DEVNAMES 4
+#define USB_MAX_DEVNAMELEN 16
struct usb_device_info {
+ u_int8_t bus;
u_int8_t addr; /* device address */
+ usb_event_cookie_t cookie;
char product[USB_MAX_STRING_LEN];
char vendor[USB_MAX_STRING_LEN];
char release[8];
u_int16_t productNo;
u_int16_t vendorNo;
+ u_int16_t releaseNo;
u_int8_t class;
+ u_int8_t subclass;
+ u_int8_t protocol;
u_int8_t config;
u_int8_t lowspeed;
int power; /* power consumption in mA, 0 if selfpowered */
int nports;
+ char devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
u_int8_t ports[16];/* hub only: addresses of devices on ports */
#define USB_PORT_ENABLED 0xff
#define USB_PORT_SUSPENDED 0xfe
@@ -504,15 +538,26 @@ struct usb_device_stats {
u_long requests[4]; /* indexed by transfer type UE_* */
};
-typedef struct { u_int32_t cookie; } usb_event_cookie_t;
/* Events that can be read from /dev/usb */
struct usb_event {
int ue_type;
-#define USB_EVENT_ATTACH 1
-#define USB_EVENT_DETACH 2
- struct usb_device_info ue_device;
+#define USB_EVENT_CTRLR_ATTACH 1
+#define USB_EVENT_CTRLR_DETACH 2
+#define USB_EVENT_DEVICE_ATTACH 3
+#define USB_EVENT_DEVICE_DETACH 4
+#define USB_EVENT_DRIVER_ATTACH 5
+#define USB_EVENT_DRIVER_DETACH 6
struct timespec ue_time;
- usb_event_cookie_t ue_cookie;
+ union {
+ struct {
+ int ue_bus;
+ } ue_ctrlr;
+ struct usb_device_info ue_device;
+ struct {
+ usb_event_cookie_t ue_cookie;
+ char ue_devname[USB_MAX_DEVNAMELEN];
+ } ue_driver;
+ } u;
};
/* USB controller */
@@ -526,6 +571,7 @@ struct usb_event {
#define USB_GET_REPORT_DESC _IOR ('U', 21, struct usb_ctl_report_desc)
#define USB_SET_IMMED _IOW ('U', 22, int)
#define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report)
+#define USB_SET_REPORT _IOW ('U', 24, struct usb_ctl_report)
/* Generic USB device */
#define USB_GET_CONFIG _IOR ('U', 100, int)
diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c
index 06be4c7befe..df3bdf152ed 100644
--- a/sys/dev/usb/usb_mem.c
+++ b/sys/dev/usb/usb_mem.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_mem.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb_mem.c,v 1.15 1999/10/12 11:24:22 augustss Exp $ */
+/* $OpenBSD: usb_mem.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_mem.c,v 1.17 1999/12/18 22:47:11 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -103,7 +103,8 @@ usb_block_allocmem(tag, size, align, dmap)
usb_dma_block_t *p;
int s;
- DPRINTFN(5, ("usb_block_allocmem: size=%d align=%d\n", size, align));
+ DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n",
+ (u_long)size, (u_long)align));
#ifdef DIAGNOSTIC
if (!curproc) {
@@ -119,8 +120,8 @@ usb_block_allocmem(tag, size, align, dmap)
LIST_REMOVE(p, next);
splx(s);
*dmap = p;
- DPRINTFN(6,("usb_block_allocmem: free list size=%d\n",
- p->size));
+ DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n",
+ (u_long)p->size));
return (USBD_NORMAL_COMPLETION);
}
}
@@ -135,7 +136,7 @@ usb_block_allocmem(tag, size, align, dmap)
DPRINTFN(6, ("usb_block_allocmem: no free\n"));
p = malloc(sizeof *p, M_USB, M_NOWAIT);
- if (p == 0)
+ if (p == NULL)
return (USBD_NOMEM);
*dmap = p;
@@ -162,7 +163,7 @@ usb_block_allocmem(tag, size, align, dmap)
BUS_DMA_NOWAIT);
if (error)
goto destroy;
- return 0;
+ return (USBD_NORMAL_COMPLETION);
destroy:
bus_dmamap_destroy(tag, p->map);
@@ -203,7 +204,7 @@ usb_block_freemem(p)
{
int s;
- DPRINTFN(6, ("usb_block_freemem: size=%d\n", p->size));
+ DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size));
s = splusb();
LIST_INSERT_HEAD(&usb_blk_freelist, p, next);
splx(s);
@@ -217,7 +218,7 @@ usb_allocmem(bus, size, align, p)
usb_dma_t *p;
{
bus_dma_tag_t tag = bus->dmatag;
- usbd_status r;
+ usbd_status err;
struct usb_frag_dma *f;
usb_dma_block_t *b;
int i;
@@ -227,12 +228,12 @@ usb_allocmem(bus, size, align, p)
if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) {
DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size));
size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1);
- r = usb_block_allocmem(tag, size, align, &p->block);
- if (r == USBD_NORMAL_COMPLETION) {
+ err = usb_block_allocmem(tag, size, align, &p->block);
+ if (!err) {
p->block->fullblock = 1;
p->offs = 0;
}
- return (r);
+ return (err);
}
s = splusb();
@@ -240,12 +241,12 @@ usb_allocmem(bus, size, align, p)
for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next))
if (f->block->tag == tag)
break;
- if (!f) {
+ if (f == NULL) {
DPRINTFN(1, ("usb_allocmem: adding fragments\n"));
- r = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b);
+ if (err) {
splx(s);
- return (r);
+ return (err);
}
b->fullblock = 0;
for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) {
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index 0dca4f7d792..0e48fd4082d 100644
--- a/sys/dev/usb/usb_mem.h
+++ b/sys/dev/usb/usb_mem.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_mem.h,v 1.4 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb_mem.h,v 1.10 1999/10/13 18:52:54 augustss Exp $ */
+/* $OpenBSD: usb_mem.h,v 1.5 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_mem.h,v 1.12 2000/03/12 23:10:29 nathanw Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,7 +51,7 @@ typedef struct usb_dma_block {
LIST_ENTRY(usb_dma_block) next;
} usb_dma_block_t;
-#define DMAADDR(dma) ((dma)->block->segs[0].ds_addr + (dma)->offs)
+#define DMAADDR(dma) ((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs)
#define KERNADDR(dma) ((void *)((dma)->block->kaddr + (dma)->offs))
usbd_status usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *));
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index e5f69af8938..83a8f6b8024 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_port.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb_port.h,v 1.14 1999/10/14 01:18:39 augustss Exp $ */
+/* $OpenBSD: usb_port.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_port.h,v 1.21 2000/02/02 07:34:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -57,14 +57,21 @@
#define UHCI_DEBUG 1
#define UHUB_DEBUG 1
#define ULPT_DEBUG 1
+#define UCOM_DEBUG 1
+#define UMODEM_DEBUG 1
#define UAUDIO_DEBUG 1
+#define AUE_DEBUG 1
+#define CUE_DEBUG 1
+#define KUE_DEBUG 1
#endif
typedef struct device *device_ptr_t;
#define USBBASEDEVICE struct device
#define USBDEV(bdev) (&(bdev))
#define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
#define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
+#define USBGETSOFTC(d) ((void *)(d))
#define DECLARE_USB_DMA_T \
struct usb_dma_block; \
@@ -78,7 +85,7 @@ typedef struct device *device_ptr_t;
#define logprintf printf
-#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2) \
+#define USB_DECLARE_DRIVER_(dname) \
int __CONCAT(dname,_match) __P((struct device *, struct cfdata *, void *)); \
void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
int __CONCAT(dname,_detach) __P((struct device *, int)); \
@@ -156,8 +163,15 @@ __CONCAT(dname,_detach)(self, flags) \
#define UHCI_DEBUG 1
#define UHUB_DEBUG 1
#define ULPT_DEBUG 1
+#define UCOM_DEBUG 1
+#define UMODEM_DEBUG 1
+#define UAUDIO_DEBUG 1
+#define AUE_DEBUG 1
+#define CUE_DEBUG 1
+#define KUE_DEBUG 1
#endif
+typedef struct device *device_ptr_t;
#define memcpy(d, s, l) bcopy((s),(d),(l))
#define memset(d, v, l) bzero((d),(l))
#define bswap32(x) swap32(x)
@@ -166,11 +180,12 @@ __CONCAT(dname,_detach)(self, flags) \
#define uhidpoll uhidselect
#define ugenpoll ugenselect
-typedef struct device *device_ptr_t;
#define USBBASEDEVICE struct device
#define USBDEV(bdev) (&(bdev))
#define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
#define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
+#define USBGETSOFTC(d) ((void *)(d))
#define DECLARE_USB_DMA_T \
struct usb_dma_block; \
@@ -182,8 +197,8 @@ typedef struct device *device_ptr_t;
#define usb_timeout(f, d, t, h) timeout((f), (d), (t))
#define usb_untimeout(f, d, h) untimeout((f), (d))
-#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2) \
-int __CONCAT(dname,_match) __P((struct device *, void *, void *)); \
+#define USB_DECLARE_DRIVER(dname) \
+int __CONCAT(dname,_match) __P((struct device *, void *, void *)); \
void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
int __CONCAT(dname,_detach) __P((struct device *, int)); \
int __CONCAT(dname,_activate) __P((struct device *, enum devact)); \
@@ -260,10 +275,13 @@ __CONCAT(dname,_detach)(self, flags) \
#define USBVERBOSE
+#define device_ptr_t device_t
#define USBBASEDEVICE device_t
#define USBDEV(bdev) (bdev)
#define USBDEVNAME(bdev) device_get_nameunit(bdev)
+#define USBDEVUNIT(bdev) device_get_unit(bdev)
#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
+#define USBGETSOFTC(bdev) (device_get_softc(bdev))
#define DECLARE_USB_DMA_T typedef void * usb_dma_t
@@ -271,23 +289,22 @@ __CONCAT(dname,_detach)(self, flags) \
*/
#define memcpy(d, s, l) bcopy((s),(d),(l))
#define memset(d, v, l) bzero((d),(l))
-#define bswap32(x) swap32(x) /* XXX not available in FreeBSD */
-#define kthread_create1
-#define kthread_create
+#define bswap32(x) swap32(x)
+#define kthread_create1(function, sc, priv, string, name)
+#define kthread_create(create_function, sc)
+#define kthread_exit(err)
#define usb_timeout(f, d, t, h) ((h) = timeout((f), (d), (t)))
#define usb_untimeout(f, d, h) untimeout((f), (d), (h))
-#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (x)), 0)
+#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0)
#define clfree(p) clist_free_cblocks((p))
-#define powerhook_establish(fn, sc) 0
+#define powerhook_establish(fn, sc) (fn)
#define powerhook_disestablish(hdl)
#define PWR_RESUME 0
-#define config_detach(d, _1) device_delete_child(device_get_parent((d)), (d))
-
-#define USB_DECLARE_DRIVER_NAME_INIT(name, dname, init) \
+#define USB_DECLARE_DRIVER_INIT(dname, init) \
static device_probe_t __CONCAT(dname,_match); \
static device_attach_t __CONCAT(dname,_attach); \
static device_detach_t __CONCAT(dname,_detach); \
@@ -303,10 +320,12 @@ static device_method_t __CONCAT(dname,_methods)[] = { \
}; \
\
static driver_t __CONCAT(dname,_driver) = { \
- name, \
+ #dname, \
__CONCAT(dname,_methods), \
sizeof(struct __CONCAT(dname,_softc)) \
}
+#define METHODS_NONE {0,0}
+#define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE)
#define USB_MATCH(dname) \
static int \
@@ -373,14 +392,3 @@ __CONCAT(dname,_detach)(device_t self)
#define logprintf printf
#endif /* __FreeBSD__ */
-
-#define NONE {0,0}
-
-#define USB_DECLARE_DRIVER_NAME(name, dname) \
- USB_DECLARE_DRIVER_NAME_INIT(#name, dname, NONE )
-#define USB_DECLARE_DRIVER_INIT(dname, init) \
- USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, init)
-#define USB_DECLARE_DRIVER(dname) \
- USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, NONE )
-
-#undef NONE
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index aa273cd8c27..d607943fc90 100644
--- a/sys/dev/usb/usb_quirks.c
+++ b/sys/dev/usb/usb_quirks.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_quirks.c,v 1.2 1999/09/27 18:03:56 fgsch Exp $ */
-/* $NetBSD: usb_quirks.c,v 1.14 1999/09/15 13:57:09 augustss Exp $ */
+/* $OpenBSD: usb_quirks.c,v 1.3 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_quirks.c,v 1.22 2000/03/16 21:51:24 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -40,9 +40,6 @@
#include <sys/param.h>
#include <sys/systm.h>
-#if defined(__FreeBSD__)
-#include <sys/bus.h>
-#endif
#include <dev/usb/usb.h>
@@ -58,15 +55,17 @@ struct usbd_quirk_entry {
u_int16_t idProduct;
u_int16_t bcdDevice;
struct usbd_quirks quirks;
-} quirks[] = {
+} usb_quirks[] = {
{ USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, 0x100, { UQ_NO_SET_PROTO}},
{ USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4,
0x094, { UQ_SWAP_UNICODE}},
{ USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }},
- { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS }},
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT, 0x002, { UQ_NO_STRINGS }},
{ USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }},
{ USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48, 0x110, { UQ_MS_REVZ }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }},
+ { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, {UQ_SPUR_BUT_UP}},
{ 0, 0, 0, { 0 } }
};
@@ -78,7 +77,7 @@ usbd_find_quirk(d)
{
struct usbd_quirk_entry *t;
- for (t = quirks; t->idVendor != 0; t++) {
+ for (t = usb_quirks; t->idVendor != 0; t++) {
if (t->idVendor == UGETW(d->idVendor) &&
t->idProduct == UGETW(d->idProduct) &&
t->bcdDevice == UGETW(d->bcdDevice))
diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h
index f74a645641b..816791f8302 100644
--- a/sys/dev/usb/usb_quirks.h
+++ b/sys/dev/usb/usb_quirks.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_quirks.h,v 1.2 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb_quirks.h,v 1.8 1999/10/11 09:16:39 augustss Exp $ */
+/* $OpenBSD: usb_quirks.h,v 1.3 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_quirks.h,v 1.10 1999/11/18 23:32:31 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -46,6 +46,8 @@ struct usbd_quirks {
#define UQ_NO_STRINGS 0x08 /* string descriptors are broken. */
#define UQ_BAD_ADC 0x10 /* bad audio spec version number. */
#define UQ_BUS_POWERED 0x20 /* device is bus powered, despite claim */
+#define UQ_BAD_AUDIO 0x40 /* device claims audio class, but isn't */
+#define UQ_SPUR_BUT_UP 0x80 /* spurious mouse button up events */
};
extern struct usbd_quirks usbd_no_quirk;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index f8dc1eaacb5..1a4cd5af419 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb_subr.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $ */
-/* $NetBSD: usb_subr.c,v 1.52 1999/10/13 08:10:58 augustss Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usb_subr.c,v 1.67 2000/03/13 23:52:37 soren Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -44,12 +44,12 @@
#include <sys/malloc.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/device.h>
+#include <sys/select.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
#endif
#include <sys/proc.h>
-#include <sys/select.h>
#include <machine/bus.h>
@@ -158,16 +158,16 @@ usbd_get_string_desc(dev, sindex, langid, sdesc)
usb_string_descriptor_t *sdesc;
{
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
req.bmRequestType = UT_READ_DEVICE;
req.bRequest = UR_GET_DESCRIPTOR;
USETW2(req.wValue, UDESC_STRING, sindex);
USETW(req.wIndex, langid);
USETW(req.wLength, 1); /* only size byte first */
- r = usbd_do_request(dev, &req, sdesc);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_do_request(dev, &req, sdesc);
+ if (err)
+ return (err);
USETW(req.wLength, sdesc->bLength); /* the whole string */
return (usbd_do_request(dev, &req, sdesc));
}
@@ -183,7 +183,7 @@ usbd_get_string(dev, si, buf)
char *s;
int i, n;
u_int16_t c;
- usbd_status r;
+ usbd_status err;
if (si == 0)
return (0);
@@ -191,16 +191,16 @@ usbd_get_string(dev, si, buf)
return (0);
if (dev->langid == USBD_NOLANG) {
/* Set up default language */
- r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
- if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) {
+ err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
+ if (err || us.bLength < 4) {
dev->langid = 0; /* Well, just pick English then */
} else {
/* Pick the first language as the default. */
dev->langid = UGETW(us.bString[0]);
}
}
- r = usbd_get_string_desc(dev, si, dev->langid, &us);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_get_string_desc(dev, si, dev->langid, &us);
+ if (err)
return (0);
s = buf;
n = us.bLength / 2 - 1;
@@ -215,7 +215,7 @@ usbd_get_string(dev, si, buf)
*s++ = '?';
}
*s++ = 0;
- return buf;
+ return (buf);
}
void
@@ -229,7 +229,7 @@ usbd_devinfo_vp(dev, v, p)
struct usb_knowndev *kdp;
#endif
- if (!dev) {
+ if (dev == NULL) {
v[0] = p[0] = '\0';
return;
}
@@ -237,7 +237,7 @@ usbd_devinfo_vp(dev, v, p)
vendor = usbd_get_string(dev, udd->iManufacturer, v);
product = usbd_get_string(dev, udd->iProduct, p);
#ifdef USBVERBOSE
- if (!vendor) {
+ if (vendor == NULL || product == NULL) {
for(kdp = usb_knowndevs;
kdp->vendorname != NULL;
kdp++) {
@@ -246,20 +246,20 @@ usbd_devinfo_vp(dev, v, p)
(kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
break;
}
- if (kdp->vendorname == NULL)
- vendor = product = NULL;
- else {
- vendor = kdp->vendorname;
+ if (kdp->vendorname != NULL) {
+ if (!vendor)
+ vendor = kdp->vendorname;
+ if (!product)
product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
- kdp->productname : NULL;
+ kdp->productname : NULL;
}
}
#endif
- if (vendor)
+ if (vendor != NULL)
strcpy(v, vendor);
else
sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
- if (product)
+ if (product != NULL)
strcpy(p, product);
else
sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
@@ -305,8 +305,10 @@ usb_delay_ms(bus, ms)
usbd_bus_handle bus;
u_int ms;
{
+ extern int cold;
+
/* Wait at least two clock ticks so we know the time has passed. */
- if (bus->use_polling)
+ if (bus->use_polling || cold)
delay((ms+1) * 1000);
else
tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
@@ -328,7 +330,7 @@ usbd_reset_port(dev, port, ps)
usb_port_status_t *ps;
{
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
int n;
req.bmRequestType = UT_WRITE_CLASS_OTHER;
@@ -336,34 +338,35 @@ usbd_reset_port(dev, port, ps)
USETW(req.wValue, UHF_PORT_RESET);
USETW(req.wIndex, port);
USETW(req.wLength, 0);
- r = usbd_do_request(dev, &req, 0);
+ err = usbd_do_request(dev, &req, 0);
DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
- port, usbd_errstr(r)));
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ port, usbd_errstr(err)));
+ if (err)
+ return (err);
n = 10;
do {
/* Wait for device to recover from reset. */
usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
- r = usbd_get_port_status(dev, port, ps);
- if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("usbd_reset_port: get status failed %d\n",r));
- return (r);
+ err = usbd_get_port_status(dev, port, ps);
+ if (err) {
+ DPRINTF(("usbd_reset_port: get status failed %d\n",
+ err));
+ return (err);
}
} while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
if (n == 0) {
printf("usbd_reset_port: timeout\n");
return (USBD_IOERROR);
}
- r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
+ err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
#ifdef USB_DEBUG
- if (r != USBD_NORMAL_COMPLETION)
+ if (err)
DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
#endif
/* Wait for the device to recover from reset. */
usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
- return (r);
+ return (err);
}
usb_interface_descriptor_t *
@@ -397,7 +400,7 @@ usbd_find_idesc(cd, ifaceidx, altidx)
return (d);
}
}
- return (0);
+ return (NULL);
}
usb_endpoint_descriptor_t *
@@ -414,10 +417,10 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
int curidx;
d = usbd_find_idesc(cd, ifaceidx, altidx);
- if (!d)
- return (0);
+ if (d == NULL)
+ return (NULL);
if (endptidx >= d->bNumEndpoints) /* quick exit */
- return (0);
+ return (NULL);
curidx = -1;
for (p = (char *)d + d->bLength; p < end; ) {
@@ -426,14 +429,14 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
break;
p += e->bLength;
if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
- return (0);
+ return (NULL);
if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
curidx++;
if (curidx == endptidx)
return (e);
}
}
- return (0);
+ return (NULL);
}
usbd_status
@@ -455,15 +458,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
ifc->index = ifaceidx;
ifc->altindex = altidx;
nendpt = ifc->idesc->bNumEndpoints;
- DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
+ DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
if (nendpt != 0) {
ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
M_USB, M_NOWAIT);
- if (ifc->endpoints == 0)
+ if (ifc->endpoints == NULL)
return (USBD_NOMEM);
} else
- ifc->endpoints = 0;
- ifc->priv = 0;
+ ifc->endpoints = NULL;
+ ifc->priv = NULL;
p = (char *)ifc->idesc + ifc->idesc->bLength;
end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
#define ed ((usb_endpoint_descriptor_t *)p)
@@ -477,11 +480,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
if (p + ed->bLength <= end && ed->bLength != 0 &&
ed->bDescriptorType == UDESC_ENDPOINT)
goto found;
- if (ed->bDescriptorType == UDESC_INTERFACE ||
- ed->bLength == 0)
+ if (ed->bLength == 0 ||
+ ed->bDescriptorType == UDESC_INTERFACE)
break;
}
/* passed end, or bad desc */
+ DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n",
+ ed->bLength == 0 ? "0 length" :
+ ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
+ "out of data"));
goto bad;
found:
ifc->endpoints[endpt].edesc = ed;
@@ -493,7 +500,8 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
return (USBD_NORMAL_COMPLETION);
bad:
- free(ifc->endpoints, M_USB);
+ if (ifc->endpoints != NULL)
+ free(ifc->endpoints, M_USB);
return (USBD_INVAL);
}
@@ -530,14 +538,14 @@ usbd_set_config_no(dev, no, msg)
{
int index;
usb_config_descriptor_t cd;
- usbd_status r;
+ usbd_status err;
DPRINTFN(5,("usbd_set_config_no: %d\n", no));
/* Figure out what config index to use. */
for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
- r = usbd_get_config_desc(dev, index, &cd);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_get_config_desc(dev, index, &cd);
+ if (err)
+ return (err);
if (cd.bConfigurationValue == no)
return (usbd_set_config_index(dev, index, msg));
}
@@ -552,7 +560,7 @@ usbd_set_config_index(dev, index, msg)
{
usb_status_t ds;
usb_config_descriptor_t cd, *cdp;
- usbd_status r;
+ usbd_status err;
int ifcidx, nifc, len, selfpowered, power;
DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
@@ -566,26 +574,26 @@ usbd_set_config_index(dev, index, msg)
usbd_free_iface_data(dev, ifcidx);
free(dev->ifaces, M_USB);
free(dev->cdesc, M_USB);
- dev->ifaces = 0;
- dev->cdesc = 0;
+ dev->ifaces = NULL;
+ dev->cdesc = NULL;
dev->config = 0;
}
/* Figure out what config number to use. */
- r = usbd_get_config_desc(dev, index, &cd);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_get_config_desc(dev, index, &cd);
+ if (err)
+ return (err);
len = UGETW(cd.wTotalLength);
cdp = malloc(len, M_USB, M_NOWAIT);
- if (cdp == 0)
+ if (cdp == NULL)
return (USBD_NOMEM);
- r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
+ if (err)
goto bad;
if (cdp->bDescriptorType != UDESC_CONFIG) {
DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
cdp->bDescriptorType));
- r = USBD_INVAL;
+ err = USBD_INVAL;
goto bad;
}
selfpowered = 0;
@@ -594,13 +602,12 @@ usbd_set_config_index(dev, index, msg)
/* May be self powered. */
if (cdp->bmAttributes & UC_BUS_POWERED) {
/* Must ask device. */
- r = usbd_get_device_status(dev, &ds);
- if (r == USBD_NORMAL_COMPLETION &&
- (UGETW(ds.wStatus) & UDS_SELF_POWERED))
+ err = usbd_get_device_status(dev, &ds);
+ if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
selfpowered = 1;
DPRINTF(("usbd_set_config_index: status=0x%04x, "
"error=%s\n",
- UGETW(ds.wStatus), usbd_errstr(r)));
+ UGETW(ds.wStatus), usbd_errstr(err)));
} else
selfpowered = 1;
}
@@ -609,7 +616,7 @@ usbd_set_config_index(dev, index, msg)
dev->address, cdp->bmAttributes,
selfpowered, cdp->bMaxPower * 2));
#ifdef USB_DEBUG
- if (!dev->powersrc) {
+ if (dev->powersrc == NULL) {
DPRINTF(("usbd_set_config_index: No power source?\n"));
return (USBD_IOERROR);
}
@@ -623,7 +630,7 @@ usbd_set_config_index(dev, index, msg)
USBDEVNAME(dev->bus->bdev), dev->address,
cdp->bConfigurationValue,
power, dev->powersrc->power);
- r = USBD_NO_POWER;
+ err = USBD_NO_POWER;
goto bad;
}
dev->power = power;
@@ -631,11 +638,11 @@ usbd_set_config_index(dev, index, msg)
DPRINTF(("usbd_set_config_index: set config %d\n",
cdp->bConfigurationValue));
- r = usbd_set_config(dev, cdp->bConfigurationValue);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_set_config(dev, cdp->bConfigurationValue);
+ if (err) {
DPRINTF(("usbd_set_config_index: setting config=%d failed, "
"error=%s\n",
- cdp->bConfigurationValue, usbd_errstr(r)));
+ cdp->bConfigurationValue, usbd_errstr(err)));
goto bad;
}
DPRINTF(("usbd_set_config_index: setting new config %d\n",
@@ -643,16 +650,16 @@ usbd_set_config_index(dev, index, msg)
nifc = cdp->bNumInterface;
dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
M_USB, M_NOWAIT);
- if (dev->ifaces == 0) {
- r = USBD_NOMEM;
+ if (dev->ifaces == NULL) {
+ err = USBD_NOMEM;
goto bad;
}
DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
dev->cdesc = cdp;
dev->config = cdp->bConfigurationValue;
for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
- r = usbd_fill_iface_data(dev, ifcidx, 0);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_fill_iface_data(dev, ifcidx, 0);
+ if (err) {
while (--ifcidx >= 0)
usbd_free_iface_data(dev, ifcidx);
goto bad;
@@ -663,42 +670,44 @@ usbd_set_config_index(dev, index, msg)
bad:
free(cdp, M_USB);
- return (r);
+ return (err);
}
/* XXX add function for alternate settings */
usbd_status
-usbd_setup_pipe(dev, iface, ep, pipe)
+usbd_setup_pipe(dev, iface, ep, ival, pipe)
usbd_device_handle dev;
usbd_interface_handle iface;
struct usbd_endpoint *ep;
+ int ival;
usbd_pipe_handle *pipe;
{
usbd_pipe_handle p;
- usbd_status r;
+ usbd_status err;
DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
dev, iface, ep, pipe));
p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
- if (p == 0)
+ if (p == NULL)
return (USBD_NOMEM);
p->device = dev;
p->iface = iface;
p->endpoint = ep;
ep->refcnt++;
p->refcnt = 1;
- p->intrreqh = 0;
+ p->intrxfer = 0;
p->running = 0;
p->repeat = 0;
+ p->interval = ival;
SIMPLEQ_INIT(&p->queue);
- r = dev->bus->methods->open_pipe(p);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = dev->bus->methods->open_pipe(p);
+ if (err) {
DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
"%s\n",
- ep->edesc->bEndpointAddress, usbd_errstr(r)));
+ ep->edesc->bEndpointAddress, usbd_errstr(err)));
free(p, M_USB);
- return (r);
+ return (err);
}
/* Clear any stall and make sure DATA0 toggle will be used next. */
if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT)
@@ -739,7 +748,8 @@ usbd_probe_and_attach(parent, dev, port, addr)
{
struct usb_attach_arg uaa;
usb_device_descriptor_t *dd = &dev->ddesc;
- int r, found, i, confi, nifaces;
+ int found, i, confi, nifaces;
+ usbd_status err;
device_ptr_t dv;
usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
@@ -770,10 +780,11 @@ usbd_probe_and_attach(parent, dev, port, addr)
uaa.release = UGETW(dd->bcdDevice);
/* First try with device specific drivers. */
+ DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
- if (dv) {
+ if (dv != NULL) {
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0)
+ if (dev->subdevs == NULL)
return (USBD_NOMEM);
dev->subdevs[0] = dv;
dev->subdevs[1] = 0;
@@ -782,16 +793,18 @@ usbd_probe_and_attach(parent, dev, port, addr)
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
+ DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
+ dd->bNumConfigurations));
/* Next try with interface drivers. */
for (confi = 0; confi < dd->bNumConfigurations; confi++) {
DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
confi));
- r = usbd_set_config_index(dev, confi, 1);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_set_config_index(dev, confi, 1);
+ if (err) {
#ifdef USB_DEBUG
DPRINTF(("%s: port %d, set config at addr %d failed, "
"error=%s\n", USBDEVPTRNAME(parent), port,
- addr, usbd_errstr(r)));
+ addr, usbd_errstr(err)));
#else
printf("%s: port %d, set config at addr %d failed\n",
USBDEVPTRNAME(parent), port, addr);
@@ -800,7 +813,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
device_delete_child(parent, bdev);
#endif
- return (r);
+ return (err);
}
nifaces = dev->cdesc->bNumInterface;
uaa.configno = dev->cdesc->bConfigurationValue;
@@ -809,7 +822,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
uaa.ifaces = ifaces;
uaa.nifaces = nifaces;
dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
- if (dev->subdevs == 0) {
+ if (dev->subdevs == NULL) {
#if defined(__FreeBSD__)
device_delete_child(parent, bdev);
#endif
@@ -906,12 +919,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
{
usbd_device_handle dev;
usb_device_descriptor_t *dd;
- usbd_status r;
+ usbd_status err;
int addr;
int i;
DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
bus, depth, lowspeed));
+
addr = usbd_getnewaddr(bus);
if (addr < 0) {
printf("%s: No free USB addresses, new device ignored.\n",
@@ -920,7 +934,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
}
dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
- if (dev == 0)
+ if (dev == NULL)
return (USBD_NOMEM);
memset(dev, 0, sizeof(*dev));
@@ -946,29 +960,29 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
dev->langid = USBD_NOLANG;
dev->cookie.cookie = ++usb_cookie_no;
- /* Establish the the default pipe. */
- r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
- if (r != USBD_NORMAL_COMPLETION) {
+ /* Establish the default pipe. */
+ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+ &dev->default_pipe);
+ if (err) {
usbd_remove_device(dev, up);
- return (r);
+ return (err);
}
up->device = dev;
dd = &dev->ddesc;
/* Try a few times in case the device is slow (i.e. outside specs.) */
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 3; i++) {
/* Get the first 8 bytes of the device descriptor. */
- r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
- if (r == USBD_NORMAL_COMPLETION)
+ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
+ if (!err)
break;
usbd_delay_ms(dev, 200);
}
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
- "failed\n",
- addr));
+ "failed\n", addr));
usbd_remove_device(dev, up);
- return (r);
+ return (err);
}
DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
@@ -994,24 +1008,22 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
/* Get the full device descriptor. */
- r = usbd_get_device_desc(dev, dd);
- if (r != USBD_NORMAL_COMPLETION) {
+ err = usbd_reload_device_desc(dev);
+ if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
"failed\n", addr));
usbd_remove_device(dev, up);
- return (r);
+ return (err);
}
- /* Figure out what's wrong with this device. */
- dev->quirks = usbd_find_quirk(dd);
-
/* Set the address */
- r = usbd_set_address(dev, addr);
- if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
- r = USBD_SET_ADDR_FAILED;
+ err = usbd_set_address(dev, addr);
+ DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
+ if (err) {
+ DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
+ err = USBD_SET_ADDR_FAILED;
usbd_remove_device(dev, up);
- return (r);
+ return (err);
}
/* Allow device time to set new address */
usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
@@ -1026,16 +1038,34 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
addr, dev, parent));
- r = usbd_probe_and_attach(parent, dev, port, addr);
- if (r != USBD_NORMAL_COMPLETION) {
+ usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
+
+ err = usbd_probe_and_attach(parent, dev, port, addr);
+ if (err) {
usbd_remove_device(dev, up);
- return (r);
+ return (err);
}
-
- usbd_add_event(USB_EVENT_ATTACH, dev);
+
return (USBD_NORMAL_COMPLETION);
}
+usbd_status
+usbd_reload_device_desc(dev)
+ usbd_device_handle dev;
+{
+ usbd_status err;
+
+ /* Get the full device descriptor. */
+ err = usbd_get_device_desc(dev, &dev->ddesc);
+ if (err)
+ return (err);
+
+ /* Figure out what's wrong with this device. */
+ dev->quirks = usbd_find_quirk(&dev->ddesc);
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
void
usbd_remove_device(dev, up)
usbd_device_handle dev;
@@ -1043,7 +1073,7 @@ usbd_remove_device(dev, up)
{
DPRINTF(("usbd_remove_device: %p\n", dev));
- if (dev->default_pipe)
+ if (dev->default_pipe != NULL)
usbd_kill_pipe(dev->default_pipe);
up->device = 0;
dev->bus->devices[dev->address] = 0;
@@ -1138,17 +1168,35 @@ usbd_fill_deviceinfo(dev, di)
struct usb_device_info *di;
{
struct usbd_port *p;
- int i, r, s;
+ int i, err, s;
- di->config = dev->config;
+ di->bus = USBDEVUNIT(dev->bus->bdev);
+ di->addr = dev->address;
+ di->cookie = dev->cookie;
usbd_devinfo_vp(dev, di->vendor, di->product);
usbd_printBCD(di->release, UGETW(dev->ddesc.bcdDevice));
di->vendorNo = UGETW(dev->ddesc.idVendor);
di->productNo = UGETW(dev->ddesc.idProduct);
+ di->releaseNo = UGETW(dev->ddesc.bcdDevice);
di->class = dev->ddesc.bDeviceClass;
+ di->subclass = dev->ddesc.bDeviceSubClass;
+ di->protocol = dev->ddesc.bDeviceProtocol;
+ di->config = dev->config;
di->power = dev->self_powered ? 0 : dev->power;
di->lowspeed = dev->lowspeed;
- di->addr = dev->address;
+
+ if (dev->subdevs != NULL) {
+ for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) {
+ strncpy(di->devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
+ USB_MAX_DEVNAMELEN);
+ di->devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
+ }
+ } else {
+ i = 0;
+ }
+ for (/* i is set */; i < USB_MAX_DEVNAMES; i++)
+ di->devnames[i][0] = 0; /* empty */
+
if (dev->hub) {
for (i = 0;
i < sizeof(di->ports) / sizeof(di->ports[0]) &&
@@ -1156,19 +1204,19 @@ usbd_fill_deviceinfo(dev, di)
i++) {
p = &dev->hub->ports[i];
if (p->device)
- r = p->device->address;
+ err = p->device->address;
else {
s = UGETW(p->status.wPortStatus);
if (s & UPS_PORT_ENABLED)
- r = USB_PORT_ENABLED;
+ err = USB_PORT_ENABLED;
else if (s & UPS_SUSPEND)
- r = USB_PORT_SUSPENDED;
+ err = USB_PORT_SUSPENDED;
else if (s & UPS_PORT_POWER)
- r = USB_PORT_POWERED;
+ err = USB_PORT_POWERED;
else
- r = USB_PORT_DISABLED;
+ err = USB_PORT_DISABLED;
}
- di->ports[i] = r;
+ di->ports[i] = err;
}
di->nports = dev->hub->hubdesc.bNbrPorts;
} else
@@ -1181,17 +1229,17 @@ usb_free_device(dev)
{
int ifcidx, nifc;
- if (dev->default_pipe)
+ if (dev->default_pipe != NULL)
usbd_kill_pipe(dev->default_pipe);
- if (dev->ifaces) {
+ if (dev->ifaces != NULL) {
nifc = dev->cdesc->bNumInterface;
for (ifcidx = 0; ifcidx < nifc; ifcidx++)
usbd_free_iface_data(dev, ifcidx);
free(dev->ifaces, M_USB);
}
- if (dev->cdesc)
+ if (dev->cdesc != NULL)
free(dev->cdesc, M_USB);
- if (dev->subdevs)
+ if (dev->subdevs != NULL)
free(dev->subdevs, M_USB);
free(dev, M_USB);
}
@@ -1226,36 +1274,33 @@ usb_disconnect_port(up, parent)
up, dev, up->portno));
#ifdef DIAGNOSTIC
- if (!dev) {
+ if (dev == NULL) {
printf("usb_disconnect_port: no device\n");
return;
}
#endif
- if (!dev->cdesc) {
- /* Partially attached device, just drop it. */
- dev->bus->devices[dev->address] = 0;
- up->device = 0;
- return;
- }
-
- if (dev->subdevs) {
+ if (dev->subdevs != NULL) {
+ DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
for (i = 0; dev->subdevs[i]; i++) {
- if (!dev->subdevs[i]) /* skip empty elements */
- continue;
-
printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
hubname);
if (up->portno != 0)
printf(" port %d", up->portno);
printf(" (addr %d) disconnected\n", dev->address);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
config_detach(dev->subdevs[i], DETACH_FORCE);
+#elif defined(__FreeBSD__)
+ device_delete_child(device_get_parent(dev->subdevs[i]),
+ dev->subdevs[i]);
+#endif
+
}
}
- usbd_add_event(USB_EVENT_DETACH, dev);
- dev->bus->devices[dev->address] = 0;
- up->device = 0;
+ usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
+ dev->bus->devices[dev->address] = NULL;
+ up->device = NULL;
usb_free_device(dev);
}
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index f37596c2392..2765d7b4b07 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi.c,v 1.7 1999/11/07 21:30:20 fgsch Exp $ */
-/* $NetBSD: usbdi.c,v 1.47 1999/10/13 23:46:10 augustss Exp $ */
+/* $OpenBSD: usbdi.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usbdi.c,v 1.65 2000/03/08 15:34:10 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -40,14 +40,17 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/kernel.h>
#include <sys/device.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include "usb_if.h"
+#if defined(DIAGNOSTIC) && defined(__i386__)
+#include <machine/cpu.h>
+#endif
#endif
#include <sys/malloc.h>
#include <sys/proc.h>
@@ -60,6 +63,10 @@
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
+#if defined(__FreeBSD__)
+#include "usb_if.h"
+#endif
+
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) logprintf x
#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
@@ -71,11 +78,10 @@ extern int usbdebug;
static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
void usbd_do_request_async_cb
- __P((usbd_request_handle, usbd_private_handle, usbd_status));
+ __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
void usbd_start_next __P((usbd_pipe_handle pipe));
-
-static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests =
- SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests);
+usbd_status usbd_open_pipe_ival
+ __P((usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int));
static int usbd_nbuses = 0;
@@ -88,29 +94,18 @@ usbd_init()
void
usbd_finish()
{
- usbd_request_handle reqh;
-
- if (--usbd_nbuses == 0) {
- /* Last controller is gone, free all requests. */
- for (;;) {
- reqh = SIMPLEQ_FIRST(&usbd_free_requests);
- if (reqh == NULL)
- break;
- SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
- free(reqh, M_USB);
- }
- }
+ --usbd_nbuses;
}
-static __inline int usbd_reqh_isread __P((usbd_request_handle reqh));
+static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer));
static __inline int
-usbd_reqh_isread(reqh)
- usbd_request_handle reqh;
+usbd_xfer_isread(xfer)
+ usbd_xfer_handle xfer;
{
- if (reqh->rqflags & URQ_REQUEST)
- return (reqh->request.bmRequestType & UT_READ);
+ if (xfer->rqflags & URQ_REQUEST)
+ return (xfer->request.bmRequestType & UT_READ);
else
- return (reqh->pipe->endpoint->edesc->bEndpointAddress &
+ return (xfer->pipe->endpoint->edesc->bEndpointAddress &
UE_DIR_IN);
}
@@ -121,13 +116,13 @@ void
usbd_dump_queue(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
printf("usbd_dump_queue: pipe=%p\n", pipe);
- for (reqh = SIMPLEQ_FIRST(&pipe->queue);
- reqh;
- reqh = SIMPLEQ_NEXT(reqh, next)) {
- printf(" reqh=%p\n", reqh);
+ for (xfer = SIMPLEQ_FIRST(&pipe->queue);
+ xfer;
+ xfer = SIMPLEQ_NEXT(xfer, next)) {
+ printf(" xfer=%p\n", xfer);
}
}
#endif
@@ -139,69 +134,90 @@ usbd_open_pipe(iface, address, flags, pipe)
u_int8_t flags;
usbd_pipe_handle *pipe;
{
+ return (usbd_open_pipe_ival(iface, address, flags, pipe,
+ USBD_DEFAULT_INTERVAL));
+}
+
+usbd_status
+usbd_open_pipe_ival(iface, address, flags, pipe, ival)
+ usbd_interface_handle iface;
+ u_int8_t address;
+ u_int8_t flags;
+ usbd_pipe_handle *pipe;
+ int ival;
+{
usbd_pipe_handle p;
struct usbd_endpoint *ep;
- usbd_status r;
+ usbd_status err;
int i;
+ DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
+ iface, address, flags));
+
for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
ep = &iface->endpoints[i];
+ if (ep->edesc == NULL)
+ return (USBD_IOERROR);
if (ep->edesc->bEndpointAddress == address)
goto found;
}
return (USBD_BAD_ADDRESS);
found:
- if ((flags & USBD_EXCLUSIVE_USE) &&
- ep->refcnt != 0)
+ if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
return (USBD_IN_USE);
- r = usbd_setup_pipe(iface->device, iface, ep, &p);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
+ if (err)
+ return (err);
LIST_INSERT_HEAD(&iface->pipes, p, next);
*pipe = p;
return (USBD_NORMAL_COMPLETION);
}
usbd_status
-usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
+usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, len, cb, ival)
usbd_interface_handle iface;
u_int8_t address;
u_int8_t flags;
usbd_pipe_handle *pipe;
usbd_private_handle priv;
void *buffer;
- u_int32_t length;
+ u_int32_t len;
usbd_callback cb;
+ int ival;
{
- usbd_status r;
- usbd_request_handle reqh;
+ usbd_status err;
+ usbd_xfer_handle xfer;
usbd_pipe_handle ipipe;
- r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- reqh = usbd_alloc_request(iface->device);
- if (reqh == 0) {
- r = USBD_NOMEM;
+ DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
+ address, flags, len));
+
+ err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
+ &ipipe, ival);
+ if (err)
+ return (err);
+ xfer = usbd_alloc_xfer(iface->device);
+ if (xfer == NULL) {
+ err = USBD_NOMEM;
goto bad1;
}
- usbd_setup_request(reqh, ipipe, priv, buffer, length, flags,
+ usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
USBD_NO_TIMEOUT, cb);
- ipipe->intrreqh = reqh;
+ ipipe->intrxfer = xfer;
ipipe->repeat = 1;
- r = usbd_transfer(reqh);
+ err = usbd_transfer(xfer);
*pipe = ipipe;
- if (r != USBD_IN_PROGRESS)
+ if (err != USBD_IN_PROGRESS)
goto bad2;
return (USBD_NORMAL_COMPLETION);
bad2:
- ipipe->intrreqh = 0;
+ ipipe->intrxfer = 0;
ipipe->repeat = 0;
- usbd_free_request(reqh);
+ usbd_free_xfer(xfer);
bad1:
usbd_close_pipe(ipipe);
- return r;
+ return (err);
}
usbd_status
@@ -209,7 +225,7 @@ usbd_close_pipe(pipe)
usbd_pipe_handle pipe;
{
#ifdef DIAGNOSTIC
- if (pipe == 0) {
+ if (pipe == NULL) {
printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
@@ -222,185 +238,197 @@ usbd_close_pipe(pipe)
LIST_REMOVE(pipe, next);
pipe->endpoint->refcnt--;
pipe->methods->close(pipe);
- if (pipe->intrreqh)
- usbd_free_request(pipe->intrreqh);
+ if (pipe->intrxfer != NULL)
+ usbd_free_xfer(pipe->intrxfer);
free(pipe, M_USB);
return (USBD_NORMAL_COMPLETION);
}
usbd_status
-usbd_transfer(reqh)
- usbd_request_handle reqh;
+usbd_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
- usb_dma_t *dmap = &reqh->dmabuf;
- usbd_status r;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usb_dma_t *dmap = &xfer->dmabuf;
+ usbd_status err;
u_int size;
int s;
- DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
- reqh, reqh->flags, pipe, pipe->running));
+ DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
+ xfer, xfer->flags, pipe, pipe->running));
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
#endif
- reqh->done = 0;
+ xfer->done = 0;
- size = reqh->length;
+ size = xfer->length;
/* If there is no buffer, allocate one. */
- if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) {
+ if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
struct usbd_bus *bus = pipe->device->bus;
#ifdef DIAGNOSTIC
- if (reqh->rqflags & URQ_AUTO_DMABUF)
+ if (xfer->rqflags & URQ_AUTO_DMABUF)
printf("usbd_transfer: has old buffer!\n");
#endif
- r = bus->methods->allocm(bus, dmap, size);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- reqh->rqflags |= URQ_AUTO_DMABUF;
+ err = bus->methods->allocm(bus, dmap, size);
+ if (err)
+ return (err);
+ xfer->rqflags |= URQ_AUTO_DMABUF;
}
/* Copy data if going out. */
- if (!(reqh->flags & USBD_NO_COPY) && size != 0 &&
- !usbd_reqh_isread(reqh))
- memcpy(KERNADDR(dmap), reqh->buffer, size);
+ if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
+ !usbd_xfer_isread(xfer))
+ memcpy(KERNADDR(dmap), xfer->buffer, size);
- r = pipe->methods->transfer(reqh);
+ err = pipe->methods->transfer(xfer);
- if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) {
+ if (err != USBD_IN_PROGRESS && err) {
/* The transfer has not been queued, so free buffer. */
- if (reqh->rqflags & URQ_AUTO_DMABUF) {
+ if (xfer->rqflags & URQ_AUTO_DMABUF) {
struct usbd_bus *bus = pipe->device->bus;
- bus->methods->freem(bus, &reqh->dmabuf);
- reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ bus->methods->freem(bus, &xfer->dmabuf);
+ xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
}
- if (!(reqh->flags & USBD_SYNCHRONOUS))
- return (r);
+ if (!(xfer->flags & USBD_SYNCHRONOUS))
+ return (err);
/* Sync transfer, wait for completion. */
- if (r != USBD_IN_PROGRESS)
- return (r);
+ if (err != USBD_IN_PROGRESS)
+ return (err);
s = splusb();
- if (!reqh->done) {
+ if (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done\n");
- tsleep(reqh, PRIBIO, "usbsyn", 0);
+ /* XXX Temporary hack XXX */
+ if (xfer->flags & USBD_NO_TSLEEP) {
+ int i;
+ usbd_bus_handle bus = pipe->device->bus;
+ int to = xfer->timeout * 1000;
+ for (i = 0; i < to; i += 10) {
+ delay(10);
+ bus->methods->do_poll(bus);
+ if (xfer->done)
+ break;
+ }
+ if (!xfer->done) {
+ pipe->methods->abort(xfer);
+ xfer->status = USBD_TIMEOUT;
+ }
+ } else
+ /* XXX End hack XXX */
+ tsleep(xfer, PRIBIO, "usbsyn", 0);
}
splx(s);
- return (reqh->status);
+ return (xfer->status);
}
/* Like usbd_transfer(), but waits for completion. */
usbd_status
-usbd_sync_transfer(reqh)
- usbd_request_handle reqh;
+usbd_sync_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- reqh->flags |= USBD_SYNCHRONOUS;
- return (usbd_transfer(reqh));
+ xfer->flags |= USBD_SYNCHRONOUS;
+ return (usbd_transfer(xfer));
}
void *
-usbd_alloc_buffer(reqh, size)
- usbd_request_handle reqh;
+usbd_alloc_buffer(xfer, size)
+ usbd_xfer_handle xfer;
u_int32_t size;
{
- struct usbd_bus *bus = reqh->device->bus;
- usbd_status r;
+ struct usbd_bus *bus = xfer->device->bus;
+ usbd_status err;
- r = bus->methods->allocm(bus, &reqh->dmabuf, size);
- if (r != USBD_NORMAL_COMPLETION)
+ err = bus->methods->allocm(bus, &xfer->dmabuf, size);
+ if (err)
return (0);
- reqh->rqflags |= URQ_DEV_DMABUF;
- return (KERNADDR(&reqh->dmabuf));
+ xfer->rqflags |= URQ_DEV_DMABUF;
+ return (KERNADDR(&xfer->dmabuf));
}
void
-usbd_free_buffer(reqh)
- usbd_request_handle reqh;
+usbd_free_buffer(xfer)
+ usbd_xfer_handle xfer;
{
#ifdef DIAGNOSTIC
- if (!(reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
+ if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
printf("usbd_free_buffer: no buffer\n");
return;
}
#endif
- reqh->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
- reqh->device->bus->methods->freem(reqh->device->bus, &reqh->dmabuf);
+ xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
+ xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
}
void *
-usbd_get_buffer(reqh)
- usbd_request_handle reqh;
+usbd_get_buffer(xfer)
+ usbd_xfer_handle xfer;
{
- if (!(reqh->rqflags & URQ_DEV_DMABUF))
+ if (!(xfer->rqflags & URQ_DEV_DMABUF))
return (0);
- return (KERNADDR(&reqh->dmabuf));
+ return (KERNADDR(&xfer->dmabuf));
}
-usbd_request_handle
-usbd_alloc_request(dev)
+usbd_xfer_handle
+usbd_alloc_xfer(dev)
usbd_device_handle dev;
{
- usbd_request_handle reqh;
-
- reqh = SIMPLEQ_FIRST(&usbd_free_requests);
- if (reqh)
- SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
- else
- reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
- if (!reqh)
- return (0);
- memset(reqh, 0, sizeof *reqh);
- reqh->device = dev;
- DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh));
- return (reqh);
+ usbd_xfer_handle xfer;
+
+ xfer = dev->bus->methods->allocx(dev->bus);
+ if (!xfer)
+ return (NULL);
+ xfer->device = dev;
+ DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
+ return (xfer);
}
usbd_status
-usbd_free_request(reqh)
- usbd_request_handle reqh;
+usbd_free_xfer(xfer)
+ usbd_xfer_handle xfer;
{
- DPRINTFN(5,("usbd_free_request: %p\n", reqh));
- if (reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
- usbd_free_buffer(reqh);
- SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
+ DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
+ if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
+ usbd_free_buffer(xfer);
+ xfer->device->bus->methods->freex(xfer->device->bus, xfer);
return (USBD_NORMAL_COMPLETION);
}
void
-usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
- usbd_request_handle reqh;
+usbd_setup_xfer(xfer, pipe, priv, buffer, length, flags, timeout, callback)
+ usbd_xfer_handle xfer;
usbd_pipe_handle pipe;
usbd_private_handle priv;
void *buffer;
u_int32_t length;
u_int16_t flags;
u_int32_t timeout;
- void (*callback) __P((usbd_request_handle,
+ void (*callback) __P((usbd_xfer_handle,
usbd_private_handle,
usbd_status));
{
- reqh->pipe = pipe;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = timeout;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->rqflags &= ~URQ_REQUEST;
- reqh->nframes = 0;
+ xfer->pipe = pipe;
+ xfer->priv = priv;
+ xfer->buffer = buffer;
+ xfer->length = length;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = timeout;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->rqflags &= ~URQ_REQUEST;
+ xfer->nframes = 0;
}
void
-usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
+usbd_setup_default_xfer(xfer, dev, priv, timeout, req, buffer,
length, flags, callback)
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
usbd_device_handle dev;
usbd_private_handle priv;
u_int32_t timeout;
@@ -408,27 +436,27 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
void *buffer;
u_int32_t length;
u_int16_t flags;
- void (*callback) __P((usbd_request_handle,
+ void (*callback) __P((usbd_xfer_handle,
usbd_private_handle,
usbd_status));
{
- reqh->pipe = dev->default_pipe;
- reqh->priv = priv;
- reqh->buffer = buffer;
- reqh->length = length;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = timeout;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->request = *req;
- reqh->rqflags |= URQ_REQUEST;
- reqh->nframes = 0;
+ xfer->pipe = dev->default_pipe;
+ xfer->priv = priv;
+ xfer->buffer = buffer;
+ xfer->length = length;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = timeout;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->request = *req;
+ xfer->rqflags |= URQ_REQUEST;
+ xfer->nframes = 0;
}
void
-usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback)
- usbd_request_handle reqh;
+usbd_setup_isoc_xfer(xfer, pipe, priv, frlengths, nframes, flags, callback)
+ usbd_xfer_handle xfer;
usbd_pipe_handle pipe;
usbd_private_handle priv;
u_int16_t *frlengths;
@@ -436,42 +464,48 @@ usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback)
u_int16_t flags;
usbd_callback callback;
{
- reqh->pipe = pipe;
- reqh->priv = priv;
- reqh->buffer = 0;
- reqh->length = 0;
- reqh->actlen = 0;
- reqh->flags = flags;
- reqh->timeout = USBD_NO_TIMEOUT;
- reqh->status = USBD_NOT_STARTED;
- reqh->callback = callback;
- reqh->rqflags &= ~URQ_REQUEST;
- reqh->frlengths = frlengths;
- reqh->nframes = nframes;
+ xfer->pipe = pipe;
+ xfer->priv = priv;
+ xfer->buffer = 0;
+ xfer->length = 0;
+ xfer->actlen = 0;
+ xfer->flags = flags;
+ xfer->timeout = USBD_NO_TIMEOUT;
+ xfer->status = USBD_NOT_STARTED;
+ xfer->callback = callback;
+ xfer->rqflags &= ~URQ_REQUEST;
+ xfer->frlengths = frlengths;
+ xfer->nframes = nframes;
}
void
-usbd_get_request_status(reqh, priv, buffer, count, status)
- usbd_request_handle reqh;
+usbd_get_xfer_status(xfer, priv, buffer, count, status)
+ usbd_xfer_handle xfer;
usbd_private_handle *priv;
void **buffer;
u_int32_t *count;
usbd_status *status;
{
- if (priv)
- *priv = reqh->priv;
- if (buffer)
- *buffer = reqh->buffer;
- if (count)
- *count = reqh->actlen;
- if (status)
- *status = reqh->status;
+ if (priv != NULL)
+ *priv = xfer->priv;
+ if (buffer != NULL)
+ *buffer = xfer->buffer;
+ if (count != NULL)
+ *count = xfer->actlen;
+ if (status != NULL)
+ *status = xfer->status;
}
usb_config_descriptor_t *
usbd_get_config_descriptor(dev)
usbd_device_handle dev;
{
+#ifdef DIAGNOSTIC
+ if (dev == NULL) {
+ printf("usbd_get_config_descriptor: dev == NULL\n");
+ return (NULL);
+ }
+#endif
return (dev->cdesc);
}
@@ -479,6 +513,12 @@ usb_interface_descriptor_t *
usbd_get_interface_descriptor(iface)
usbd_interface_handle iface;
{
+#ifdef DIAGNOSTIC
+ if (iface == NULL) {
+ printf("usbd_get_interface_descriptor: dev == NULL\n");
+ return (NULL);
+ }
+#endif
return (iface->idesc);
}
@@ -503,19 +543,19 @@ usbd_status
usbd_abort_pipe(pipe)
usbd_pipe_handle pipe;
{
- usbd_status r;
+ usbd_status err;
int s;
#ifdef DIAGNOSTIC
- if (pipe == 0) {
+ if (pipe == NULL) {
printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
#endif
s = splusb();
- r = usbd_ar_pipe(pipe);
+ err = usbd_ar_pipe(pipe);
splx(s);
- return (r);
+ return (err);
}
usbd_status
@@ -524,7 +564,7 @@ usbd_clear_endpoint_stall(pipe)
{
usbd_device_handle dev = pipe->device;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
@@ -539,15 +579,15 @@ usbd_clear_endpoint_stall(pipe)
USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
- r = usbd_do_request(dev, &req, 0);
+ err = usbd_do_request(dev, &req, 0);
#if 0
XXX should we do this?
- if (r == USBD_NORMAL_COMPLETION) {
+ if (!err) {
pipe->state = USBD_PIPE_ACTIVE;
/* XXX activate pipe */
}
#endif
- return (r);
+ return (err);
}
usbd_status
@@ -556,7 +596,7 @@ usbd_clear_endpoint_stall_async(pipe)
{
usbd_device_handle dev = pipe->device;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
pipe->methods->cleartoggle(pipe);
@@ -565,8 +605,16 @@ usbd_clear_endpoint_stall_async(pipe)
USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
- r = usbd_do_request_async(dev, &req, 0);
- return (r);
+ err = usbd_do_request_async(dev, &req, 0);
+ return (err);
+}
+
+void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */
+void
+usbd_clear_endpoint_toggle(pipe)
+ usbd_pipe_handle pipe;
+{
+ pipe->methods->cleartoggle(pipe);
}
usbd_status
@@ -583,7 +631,7 @@ usbd_interface_count(dev, count)
usbd_device_handle dev;
u_int8_t *count;
{
- if (!dev->cdesc)
+ if (dev->cdesc == NULL)
return (USBD_NOT_CONFIGURED);
*count = dev->cdesc->bNumInterface;
return (USBD_NORMAL_COMPLETION);
@@ -604,7 +652,7 @@ usbd_device2interface_handle(dev, ifaceno, iface)
u_int8_t ifaceno;
usbd_interface_handle *iface;
{
- if (!dev->cdesc)
+ if (dev->cdesc == NULL)
return (USBD_NOT_CONFIGURED);
if (ifaceno >= dev->cdesc->bNumInterface)
return (USBD_INVAL);
@@ -626,7 +674,7 @@ usbd_set_interface(iface, altidx)
int altidx;
{
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
if (LIST_FIRST(&iface->pipes) != 0)
return (USBD_IN_USE);
@@ -636,16 +684,16 @@ usbd_set_interface(iface, altidx)
iface->endpoints = 0;
iface->idesc = 0;
- r = usbd_fill_iface_data(iface->device, iface->index, altidx);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_fill_iface_data(iface->device, iface->index, altidx);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_INTERFACE;
req.bRequest = UR_SET_INTERFACE;
USETW(req.wValue, iface->idesc->bAlternateSetting);
USETW(req.wIndex, iface->idesc->bInterfaceNumber);
USETW(req.wLength, 0);
- return usbd_do_request(iface->device, &req, 0);
+ return (usbd_do_request(iface->device, &req, 0));
}
int
@@ -687,7 +735,7 @@ usbd_get_interface(iface, aiface)
USETW(req.wValue, 0);
USETW(req.wIndex, iface->idesc->bInterfaceNumber);
USETW(req.wLength, 1);
- return usbd_do_request(iface->device, &req, aiface);
+ return (usbd_do_request(iface->device, &req, aiface));
}
/*** Internal routines ***/
@@ -697,7 +745,7 @@ static usbd_status
usbd_ar_pipe(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
+ usbd_xfer_handle xfer;
SPLUSBCHECK;
@@ -707,11 +755,11 @@ usbd_ar_pipe(pipe)
usbd_dump_queue(pipe);
#endif
pipe->repeat = 0;
- while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
- DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n",
- pipe, reqh, pipe->methods));
+ while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
+ DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
+ pipe, xfer, pipe->methods));
/* Make the HC abort it (and invoke the callback). */
- pipe->methods->abort(reqh);
+ pipe->methods->abort(xfer);
/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
}
return (USBD_NORMAL_COMPLETION);
@@ -719,22 +767,22 @@ usbd_ar_pipe(pipe)
/* Called at splusb() */
void
-usb_transfer_complete(reqh)
- usbd_request_handle reqh;
+usb_transfer_complete(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
- usb_dma_t *dmap = &reqh->dmabuf;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usb_dma_t *dmap = &xfer->dmabuf;
int repeat = pipe->repeat;
int polling;
SPLUSBCHECK;
- DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p status=%d actlen=%d\n",
- pipe, reqh, reqh->status, reqh->actlen));
+ DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d actlen=%d\n",
+ pipe, xfer, xfer->status, xfer->actlen));
#ifdef DIAGNOSTIC
- if (!pipe) {
- printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
+ if (pipe == NULL) {
+ printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
return;
}
#endif
@@ -743,63 +791,71 @@ usb_transfer_complete(reqh)
if (polling)
pipe->running = 0;
- if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 &&
- usbd_reqh_isread(reqh)) {
+ if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
+ usbd_xfer_isread(xfer)) {
#ifdef DIAGNOSTIC
- if (reqh->actlen > reqh->length) {
+ if (xfer->actlen > xfer->length) {
printf("usb_transfer_complete: actlen > len %d > %d\n",
- reqh->actlen, reqh->length);
- reqh->actlen = reqh->length;
+ xfer->actlen, xfer->length);
+ xfer->actlen = xfer->length;
}
#endif
- memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
+ memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
}
/* if we allocated the buffer in usbd_transfer() we free it here. */
- if (reqh->rqflags & URQ_AUTO_DMABUF) {
+ if (xfer->rqflags & URQ_AUTO_DMABUF) {
if (!repeat) {
struct usbd_bus *bus = pipe->device->bus;
bus->methods->freem(bus, dmap);
- reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
}
- if (pipe->methods->done)
- pipe->methods->done(reqh);
-
if (!repeat) {
/* Remove request from queue. */
#ifdef DIAGNOSTIC
- if (reqh != SIMPLEQ_FIRST(&pipe->queue))
+ if (xfer != SIMPLEQ_FIRST(&pipe->queue))
printf("usb_transfer_complete: bad dequeue %p != %p\n",
- reqh, SIMPLEQ_FIRST(&pipe->queue));
+ xfer, SIMPLEQ_FIRST(&pipe->queue));
#endif
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
+ SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
}
+ DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
+ repeat, SIMPLEQ_FIRST(&pipe->queue)));
/* Count completed transfers. */
++pipe->device->bus->stats.requests
[pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
- reqh->done = 1;
- if (reqh->status == USBD_NORMAL_COMPLETION &&
- reqh->actlen < reqh->length &&
- !(reqh->flags & USBD_SHORT_XFER_OK)) {
+ xfer->done = 1;
+ if (xfer->status && xfer->actlen < xfer->length &&
+ !(xfer->flags & USBD_SHORT_XFER_OK)) {
DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
- reqh->actlen, reqh->length));
- reqh->status = USBD_SHORT_XFER;
+ xfer->actlen, xfer->length));
+ xfer->status = USBD_SHORT_XFER;
}
- if (reqh->callback)
- reqh->callback(reqh, reqh->priv, reqh->status);
+ if (xfer->callback)
+ xfer->callback(xfer, xfer->priv, xfer->status);
+
+#ifdef DIAGNOSTIC
+ if (pipe->methods->done != NULL)
+ pipe->methods->done(xfer);
+ else
+ printf("usb_transfer_complete: pipe->methods->done == NULL\n");
+#else
+ pipe->methods->done(xfer);
+#endif
- if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
- wakeup(reqh);
+ if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
+ wakeup(xfer);
if (!repeat) {
/* XXX should we stop the queue on all errors? */
- if (reqh->status == USBD_CANCELLED ||
- reqh->status == USBD_TIMEOUT)
+ if ((xfer->status == USBD_CANCELLED ||
+ xfer->status == USBD_TIMEOUT) &&
+ pipe->iface != NULL) /* not control pipe */
pipe->running = 0;
else
usbd_start_next(pipe);
@@ -807,25 +863,25 @@ usb_transfer_complete(reqh)
}
usbd_status
-usb_insert_transfer(reqh)
- usbd_request_handle reqh;
+usb_insert_transfer(xfer)
+ usbd_xfer_handle xfer;
{
- usbd_pipe_handle pipe = reqh->pipe;
- usbd_status r;
+ usbd_pipe_handle pipe = xfer->pipe;
+ usbd_status err;
int s;
DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
- pipe, pipe->running, reqh->timeout));
+ pipe, pipe->running, xfer->timeout));
s = splusb();
- SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
+ SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
if (pipe->running)
- r = USBD_IN_PROGRESS;
+ err = USBD_IN_PROGRESS;
else {
pipe->running = 1;
- r = USBD_NORMAL_COMPLETION;
+ err = USBD_NORMAL_COMPLETION;
}
splx(s);
- return (r);
+ return (err);
}
/* Called at splusb() */
@@ -833,33 +889,31 @@ void
usbd_start_next(pipe)
usbd_pipe_handle pipe;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
SPLUSBCHECK;
- DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
-
#ifdef DIAGNOSTIC
- if (!pipe) {
- printf("usbd_start_next: pipe == 0\n");
+ if (pipe == NULL) {
+ printf("usbd_start_next: pipe == NULL\n");
return;
}
- if (!pipe->methods || !pipe->methods->start) {
- printf("usbd_start_next: no start method\n");
+ if (pipe->methods == NULL || pipe->methods->start == NULL) {
+ printf("usbd_start_next: pipe=%p no start method\n", pipe);
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)
+ xfer = SIMPLEQ_FIRST(&pipe->queue);
+ DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
+ if (xfer == NULL) {
pipe->running = 0;
- else {
- r = pipe->methods->start(reqh);
- if (r != USBD_IN_PROGRESS) {
- printf("usbd_start_next: error=%d\n", r);
+ } else {
+ err = pipe->methods->start(xfer);
+ if (err != USBD_IN_PROGRESS) {
+ printf("usbd_start_next: error=%d\n", err);
pipe->running = 0;
/* XXX do what? */
}
@@ -883,35 +937,39 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
u_int16_t flags;
int *actlen;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
#ifdef DIAGNOSTIC
+#if defined(__i386__) && defined(__FreeBSD__)
+ KASSERT(intr_nesting_level == 0,
+ ("usbd_do_request: in interrupt context"));
+#endif
if (dev->bus->intr_context) {
printf("usbd_do_request: not in process context\n");
return (USBD_INVAL);
}
#endif
- reqh = usbd_alloc_request(dev);
- if (reqh == 0)
+ xfer = usbd_alloc_xfer(dev);
+ if (xfer == NULL)
return (USBD_NOMEM);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
+ usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
data, UGETW(req->wLength), flags, 0);
- r = usbd_sync_transfer(reqh);
+ err = usbd_sync_transfer(xfer);
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
+ if (xfer->actlen > xfer->length)
DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
"%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- dev->address, reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen));
+ dev->address, xfer->request.bmRequestType,
+ xfer->request.bRequest, UGETW(xfer->request.wValue),
+ UGETW(xfer->request.wIndex),
+ UGETW(xfer->request.wLength),
+ xfer->length, xfer->actlen));
#endif
- if (actlen)
- *actlen = reqh->actlen;
- if (r == USBD_STALLED) {
+ if (actlen != NULL)
+ *actlen = xfer->actlen;
+ if (err == USBD_STALLED) {
/*
* The control endpoint has stalled. Control endpoints
* should not halt, but some may do so anyway so clear
@@ -920,18 +978,18 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
usb_device_request_t treq;
usb_status_t status;
u_int16_t s;
- usbd_status nr;
+ usbd_status nerr;
treq.bmRequestType = UT_READ_ENDPOINT;
treq.bRequest = UR_GET_STATUS;
USETW(treq.wValue, 0);
USETW(treq.wIndex, 0);
USETW(treq.wLength, sizeof(usb_status_t));
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
&treq, &status,sizeof(usb_status_t),
0, 0);
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
+ nerr = usbd_sync_transfer(xfer);
+ if (nerr)
goto bad;
s = UGETW(status.wStatus);
DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
@@ -942,36 +1000,36 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
USETW(treq.wValue, UF_ENDPOINT_HALT);
USETW(treq.wIndex, 0);
USETW(treq.wLength, 0);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
&treq, &status, 0, 0, 0);
- nr = usbd_sync_transfer(reqh);
- if (nr != USBD_NORMAL_COMPLETION)
+ nerr = usbd_sync_transfer(xfer);
+ if (nerr)
goto bad;
}
bad:
- usbd_free_request(reqh);
- return (r);
+ usbd_free_xfer(xfer);
+ return (err);
}
void
-usbd_do_request_async_cb(reqh, priv, status)
- usbd_request_handle reqh;
+usbd_do_request_async_cb(xfer, priv, status)
+ usbd_xfer_handle xfer;
usbd_private_handle priv;
usbd_status status;
{
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
- if (reqh->actlen > reqh->length)
+ if (xfer->actlen > xfer->length)
DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
"%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
- reqh->pipe->device->address,
- reqh->request.bmRequestType,
- reqh->request.bRequest, UGETW(reqh->request.wValue),
- UGETW(reqh->request.wIndex),
- UGETW(reqh->request.wLength),
- reqh->length, reqh->actlen));
+ xfer->pipe->device->address,
+ xfer->request.bmRequestType,
+ xfer->request.bRequest, UGETW(xfer->request.wValue),
+ UGETW(xfer->request.wIndex),
+ UGETW(xfer->request.wLength),
+ xfer->length, xfer->actlen));
#endif
- usbd_free_request(reqh);
+ usbd_free_xfer(xfer);
}
/*
@@ -984,19 +1042,19 @@ usbd_do_request_async(dev, req, data)
usb_device_request_t *req;
void *data;
{
- usbd_request_handle reqh;
- usbd_status r;
+ usbd_xfer_handle xfer;
+ usbd_status err;
- reqh = usbd_alloc_request(dev);
- if (reqh == 0)
+ xfer = usbd_alloc_xfer(dev);
+ if (xfer == NULL)
return (USBD_NOMEM);
- usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
+ usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
UGETW(req->wLength), 0,
usbd_do_request_async_cb);
- r = usbd_transfer(reqh);
- if (r != USBD_IN_PROGRESS) {
- usbd_free_request(reqh);
- return (r);
+ err = usbd_transfer(xfer);
+ if (err != USBD_IN_PROGRESS) {
+ usbd_free_xfer(xfer);
+ return (err);
}
return (USBD_NORMAL_COMPLETION);
}
@@ -1021,14 +1079,14 @@ usbd_dopoll(iface)
}
void
-usbd_set_polling(iface, on)
- usbd_interface_handle iface;
+usbd_set_polling(dev, on)
+ usbd_device_handle dev;
int on;
{
if (on)
- iface->device->bus->use_polling++;
+ dev->bus->use_polling++;
else
- iface->device->bus->use_polling--;
+ dev->bus->use_polling--;
}
@@ -1048,6 +1106,21 @@ usbd_get_endpoint_descriptor(iface, address)
return (0);
}
+/*
+ * usbd_ratecheck() can limit the number of error messages that occurs.
+ * When a device is unplugged it may take up to 0.25s for the hub driver
+ * to notice it. If the driver continuously tries to do I/O operations
+ * this can generate a large number of messages.
+ */
+int
+usbd_ratecheck(last)
+ struct timeval *last;
+{
+ struct timeval errinterval = { 0, 250000 }; /* 0.25s */
+
+ return (ratecheck(last, &errinterval));
+}
+
#if defined(__FreeBSD__)
int
usbd_driver_load(module_t mod, int what, void *arg)
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 7efe8acf65d..29f969c58cc 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $ */
-/* $NetBSD: usbdi.h,v 1.31 1999/10/13 08:10:58 augustss Exp $ */
+/* $OpenBSD: usbdi.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usbdi.h,v 1.31 2000/03/02 12:37:51 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@ typedef struct usbd_bus *usbd_bus_handle;
typedef struct usbd_device *usbd_device_handle;
typedef struct usbd_interface *usbd_interface_handle;
typedef struct usbd_pipe *usbd_pipe_handle;
-typedef struct usbd_request *usbd_request_handle;
+typedef struct usbd_xfer *usbd_xfer_handle;
typedef void *usbd_private_handle;
typedef enum { /* keep in sync with usbd_status_msgs */
@@ -70,18 +70,23 @@ typedef enum { /* keep in sync with usbd_status_msgs */
USBD_ERROR_MAX, /* must be last */
} usbd_status;
-typedef int usbd_lock_token;
-
-typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle,
+typedef void (*usbd_callback) __P((usbd_xfer_handle, usbd_private_handle,
usbd_status));
/* Open flags */
#define USBD_EXCLUSIVE_USE 0x01
+/* Use default (specified by ep. desc.) interval on interrupt pipe */
+#define USBD_DEFAULT_INTERVAL (-1)
+
/* Request flags */
#define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */
#define USBD_SYNCHRONOUS 0x02 /* wait for completion */
/* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */
+#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */
+
+/* XXX Temporary hack XXX */
+#define USBD_NO_TSLEEP 0x80 /* XXX use busy wait */
#define USBD_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -94,25 +99,25 @@ usbd_status usbd_open_pipe
__P((usbd_interface_handle iface, u_int8_t address,
u_int8_t flags, usbd_pipe_handle *pipe));
usbd_status usbd_close_pipe __P((usbd_pipe_handle pipe));
-usbd_status usbd_transfer __P((usbd_request_handle req));
-usbd_request_handle usbd_alloc_request __P((usbd_device_handle));
-usbd_status usbd_free_request __P((usbd_request_handle reqh));
-void usbd_setup_request
- __P((usbd_request_handle reqh, usbd_pipe_handle pipe,
+usbd_status usbd_transfer __P((usbd_xfer_handle req));
+usbd_xfer_handle usbd_alloc_xfer __P((usbd_device_handle));
+usbd_status usbd_free_xfer __P((usbd_xfer_handle xfer));
+void usbd_setup_xfer
+ __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe,
usbd_private_handle priv, void *buffer,
u_int32_t length, u_int16_t flags, u_int32_t timeout,
usbd_callback));
-void usbd_setup_default_request
- __P((usbd_request_handle reqh, usbd_device_handle dev,
+void usbd_setup_default_xfer
+ __P((usbd_xfer_handle xfer, usbd_device_handle dev,
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));
-void usbd_setup_isoc_request
- __P((usbd_request_handle reqh, usbd_pipe_handle pipe,
+void usbd_setup_isoc_xfer
+ __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe,
usbd_private_handle priv, u_int16_t *frlengths,
u_int32_t nframes, u_int16_t flags, usbd_callback));
-void usbd_get_request_status
- __P((usbd_request_handle reqh, usbd_private_handle *priv,
+void usbd_get_xfer_status
+ __P((usbd_xfer_handle xfer, usbd_private_handle *priv,
void **buffer, u_int32_t *count, usbd_status *status));
usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor
__P((usbd_interface_handle iface, u_int8_t address));
@@ -129,15 +134,15 @@ usbd_status usbd_device2interface_handle
__P((usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface));
usbd_device_handle usbd_pipe2device_handle __P((usbd_pipe_handle));
-void *usbd_alloc_buffer __P((usbd_request_handle req, u_int32_t size));
-void usbd_free_buffer __P((usbd_request_handle req));
-void *usbd_get_buffer __P((usbd_request_handle reqh));
-usbd_status usbd_sync_transfer __P((usbd_request_handle req));
+void *usbd_alloc_buffer __P((usbd_xfer_handle req, u_int32_t size));
+void usbd_free_buffer __P((usbd_xfer_handle req));
+void *usbd_get_buffer __P((usbd_xfer_handle xfer));
+usbd_status usbd_sync_transfer __P((usbd_xfer_handle req));
usbd_status usbd_open_pipe_intr
__P((usbd_interface_handle iface, u_int8_t address,
u_int8_t flags, usbd_pipe_handle *pipe,
usbd_private_handle priv, void *buffer,
- u_int32_t length, usbd_callback));
+ u_int32_t length, usbd_callback, int));
usbd_status usbd_do_request
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usbd_status usbd_do_request_async
@@ -166,11 +171,21 @@ usb_endpoint_descriptor_t *usbd_find_edesc
int endptidx));
void usbd_dopoll __P((usbd_interface_handle));
-void usbd_set_polling __P((usbd_interface_handle iface, int on));
+void usbd_set_polling __P((usbd_device_handle iface, int on));
const char *usbd_errstr __P((usbd_status err));
-void usbd_add_event __P((int, usbd_device_handle));
+void usbd_add_dev_event __P((int, usbd_device_handle));
+void usbd_add_drv_event __P((int, usbd_device_handle, device_ptr_t));
+
+void usbd_devinfo __P((usbd_device_handle, int, char *));
+struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
+usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
+ __P((usbd_interface_handle iface, u_int8_t address));
+
+usbd_status usbd_reload_device_desc __P((usbd_device_handle));
+
+int usbd_ratecheck __P((struct timeval *last));
/* NetBSD attachment information */
@@ -231,17 +246,19 @@ struct usb_attach_arg {
#endif
-void usbd_devinfo __P((usbd_device_handle, int, char *));
-struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
-usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
- __P((usbd_interface_handle iface, u_int8_t address));
-
#if defined(__FreeBSD__)
int usbd_driver_load __P((module_t mod, int what, void *arg));
#endif
+/*
+ * XXX
+ * splusb MUST be the lowest level interrupt so that within USB callbacks
+ * the level can be raised the appropriate level.
+ * XXX Should probably use a softsplusb.
+ */
/* XXX */
#define splusb splbio
+#define splhardusb splbio
#define IPL_USB IPL_BIO
/* XXX */
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 52a55f047e5..152e81db2fa 100644
--- a/sys/dev/usb/usbdi_util.c
+++ b/sys/dev/usb/usbdi_util.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi_util.c,v 1.5 1999/11/07 21:30:20 fgsch Exp $ */
-/* $NetBSD: usbdi_util.c,v 1.22 1999/10/13 08:10:59 augustss Exp $ */
+/* $OpenBSD: usbdi_util.c,v 1.6 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usbdi_util.c,v 1.28 2000/02/22 11:25:06 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,9 +42,8 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/device.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/proc.h>
#include <sys/device.h>
#elif defined(__FreeBSD__)
#include <sys/bus.h>
@@ -74,6 +73,9 @@ usbd_get_desc(dev, type, index, len, desc)
{
usb_device_request_t req;
+ DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
+ type, index, len));
+
req.bmRequestType = UT_READ_DEVICE;
req.bRequest = UR_GET_DESCRIPTOR;
USETW2(req.wValue, type, index);
@@ -83,21 +85,22 @@ usbd_get_desc(dev, type, index, len, desc)
}
usbd_status
-usbd_get_config_desc(dev, conf, d)
+usbd_get_config_desc(dev, confidx, d)
usbd_device_handle dev;
- int conf;
+ int confidx;
usb_config_descriptor_t *d;
{
- usbd_status r;
+ usbd_status err;
- DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf));
- r = usbd_get_desc(dev, UDESC_CONFIG, conf,
- USB_CONFIG_DESCRIPTOR_SIZE, d);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx));
+ err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
+ USB_CONFIG_DESCRIPTOR_SIZE, d);
+ if (err)
+ return (err);
if (d->bDescriptorType != UDESC_CONFIG) {
- DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n",
- conf, d->bDescriptorType));
+ DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc ",
+ "len=%d type=%d\n",
+ confidx, d->bLength, d->bDescriptorType));
return (USBD_INVAL);
}
return (USBD_NORMAL_COMPLETION);
@@ -254,17 +257,15 @@ usbd_set_protocol(iface, report)
usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
iface, report, id->bInterfaceNumber));
- if (!id)
+ if (id == NULL)
return (USBD_IOERROR);
- r = usbd_interface2device_handle(iface, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!id)
- return (USBD_INVAL);
+ err = usbd_interface2device_handle(iface, &dev);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UR_SET_PROTOCOL;
USETW(req.wValue, report);
@@ -284,16 +285,14 @@ usbd_set_report(iface, type, id, data, len)
usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
- if (!ifd)
+ if (ifd == NULL)
return (USBD_IOERROR);
- r = usbd_interface2device_handle(iface, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!ifd)
- return (USBD_INVAL);
+ err = usbd_interface2device_handle(iface, &dev);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UR_SET_REPORT;
USETW2(req.wValue, type, id);
@@ -313,16 +312,14 @@ usbd_set_report_async(iface, type, id, data, len)
usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
- if (!ifd)
+ if (ifd == NULL)
return (USBD_IOERROR);
- r = usbd_interface2device_handle(iface, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!ifd)
- return (USBD_INVAL);
+ err = usbd_interface2device_handle(iface, &dev);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UR_SET_REPORT;
USETW2(req.wValue, type, id);
@@ -342,16 +339,14 @@ usbd_get_report(iface, type, id, data, len)
usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
- DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
- if (!id)
+ DPRINTFN(4, ("usbd_get_report: len=%d\n", len));
+ if (ifd == NULL)
return (USBD_IOERROR);
- r = usbd_interface2device_handle(iface, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!ifd)
- return (USBD_INVAL);
+ err = usbd_interface2device_handle(iface, &dev);
+ if (err)
+ return (err);
req.bmRequestType = UT_READ_CLASS_INTERFACE;
req.bRequest = UR_GET_REPORT;
USETW2(req.wValue, type, id);
@@ -369,16 +364,14 @@ usbd_set_idle(iface, duration, id)
usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
usbd_device_handle dev;
usb_device_request_t req;
- usbd_status r;
+ usbd_status err;
DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
- if (!ifd)
+ if (ifd == NULL)
return (USBD_IOERROR);
- r = usbd_interface2device_handle(iface, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!ifd)
- return (USBD_INVAL);
+ err = usbd_interface2device_handle(iface, &dev);
+ if (err)
+ return (err);
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
req.bRequest = UR_SET_IDLE;
USETW2(req.wValue, duration, id);
@@ -414,12 +407,12 @@ usbd_get_hid_descriptor(ifc)
usb_config_descriptor_t *cdesc;
usb_hid_descriptor_t *hd;
char *p, *end;
- usbd_status r;
+ usbd_status err;
- if (!idesc)
+ if (idesc == NULL)
return (0);
- r = usbd_interface2device_handle(ifc, &dev);
- if (r != USBD_NORMAL_COMPLETION)
+ err = usbd_interface2device_handle(ifc, &dev);
+ if (err)
return (0);
cdesc = usbd_get_config_descriptor(dev);
@@ -451,27 +444,27 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem)
usb_interface_descriptor_t *id;
usb_hid_descriptor_t *hid;
usbd_device_handle dev;
- usbd_status r;
+ usbd_status err;
- r = usbd_interface2device_handle(ifc, &dev);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ err = usbd_interface2device_handle(ifc, &dev);
+ if (err)
+ return (err);
id = usbd_get_interface_descriptor(ifc);
- if (!id)
+ if (id == NULL)
return (USBD_INVAL);
hid = usbd_get_hid_descriptor(ifc);
- if (!hid)
+ if (hid == NULL)
return (USBD_IOERROR);
*sizep = UGETW(hid->descrs[0].wDescriptorLength);
*descp = malloc(*sizep, mem, M_NOWAIT);
- if (!*descp)
+ if (*descp == NULL)
return (USBD_NOMEM);
/* XXX should not use 0 Report ID */
- r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0,
+ err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0,
*sizep, *descp);
- if (r != USBD_NORMAL_COMPLETION) {
+ if (err) {
free(*descp, mem);
- return (r);
+ return (err);
}
return (USBD_NORMAL_COMPLETION);
}
@@ -491,20 +484,20 @@ usbd_get_config(dev, conf)
return (usbd_do_request(dev, &req, conf));
}
-static void usbd_bulk_transfer_cb __P((usbd_request_handle reqh,
+static void usbd_bulk_transfer_cb __P((usbd_xfer_handle xfer,
usbd_private_handle priv, usbd_status status));
static void
-usbd_bulk_transfer_cb(reqh, priv, status)
- usbd_request_handle reqh;
+usbd_bulk_transfer_cb(xfer, priv, status)
+ usbd_xfer_handle xfer;
usbd_private_handle priv;
usbd_status status;
{
- wakeup(reqh);
+ wakeup(xfer);
}
usbd_status
-usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
- usbd_request_handle reqh;
+usbd_bulk_transfer(xfer, pipe, flags, timeout, buf, size, lbl)
+ usbd_xfer_handle xfer;
usbd_pipe_handle pipe;
u_int16_t flags;
u_int32_t timeout;
@@ -512,32 +505,32 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
u_int32_t *size;
char *lbl;
{
- usbd_status r;
+ usbd_status err;
int s, error;
- usbd_setup_request(reqh, pipe, 0, buf, *size,
- flags, timeout, usbd_bulk_transfer_cb);
+ usbd_setup_xfer(xfer, pipe, 0, buf, *size,
+ flags, timeout, usbd_bulk_transfer_cb);
DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
s = splusb(); /* don't want callback until tsleep() */
- r = usbd_transfer(reqh);
- if (r != USBD_IN_PROGRESS) {
+ err = usbd_transfer(xfer);
+ if (err != USBD_IN_PROGRESS) {
splx(s);
- return (r);
+ return (err);
}
- error = tsleep((caddr_t)reqh, PZERO | PCATCH, lbl, 0);
+ error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
splx(s);
if (error) {
DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
usbd_abort_pipe(pipe);
return (USBD_INTERRUPTED);
}
- usbd_get_request_status(reqh, 0, 0, size, &r);
+ usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
- if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("usbd_bulk_transfer: error=%d\n", r));
+ if (err != USBD_NORMAL_COMPLETION) {
+ DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
usbd_clear_endpoint_stall(pipe);
}
- return (r);
+ return (err);
}
void
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index e3c055e36d0..098316bac4d 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi_util.h,v 1.3 1999/09/27 18:03:56 fgsch Exp $ */
-/* $NetBSD: usbdi_util.h,v 1.17 1999/09/05 19:32:19 augustss Exp $ */
+/* $OpenBSD: usbdi_util.h,v 1.4 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usbdi_util.h,v 1.19 1999/11/18 23:32:37 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@ usbd_status usbd_set_config_index
__P((usbd_device_handle dev, int index, int msg));
usbd_status usbd_bulk_transfer
- __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags,
+ __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, u_int16_t flags,
u_int32_t timeout, void *buf, u_int32_t *size, char *lbl));
void usb_detach_wait __P((device_ptr_t));
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index 9fd4931567e..ad013bedc34 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdivar.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $ */
-/* $NetBSD: usbdivar.h,v 1.38 1999/10/25 10:51:46 augustss Exp $ */
+/* $OpenBSD: usbdivar.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/* $NetBSD: usbdivar.h,v 1.47 2000/02/22 11:30:56 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
/* From usb_mem.h */
DECLARE_USB_DMA_T;
-struct usbd_request;
+struct usbd_xfer;
struct usbd_pipe;
struct usbd_endpoint {
@@ -51,19 +51,23 @@ struct usbd_endpoint {
struct usbd_bus_methods {
usbd_status (*open_pipe)__P((struct usbd_pipe *pipe));
+ void (*soft_intr)__P((struct usbd_bus *));
void (*do_poll)__P((struct usbd_bus *));
usbd_status (*allocm)__P((struct usbd_bus *, usb_dma_t *,
u_int32_t bufsize));
void (*freem)__P((struct usbd_bus *, usb_dma_t *));
+ struct usbd_xfer * (*allocx)__P((struct usbd_bus *));
+ void (*freex)__P((struct usbd_bus *,
+ struct usbd_xfer *));
};
struct usbd_pipe_methods {
- usbd_status (*transfer)__P((usbd_request_handle reqh));
- usbd_status (*start)__P((usbd_request_handle reqh));
- void (*abort)__P((usbd_request_handle reqh));
+ usbd_status (*transfer)__P((usbd_xfer_handle xfer));
+ usbd_status (*start)__P((usbd_xfer_handle xfer));
+ void (*abort)__P((usbd_xfer_handle xfer));
void (*close)__P((usbd_pipe_handle pipe));
void (*cleartoggle)__P((usbd_pipe_handle pipe));
- void (*done)__P((usbd_request_handle reqh));
+ void (*done)__P((usbd_xfer_handle xfer));
};
struct usbd_port {
@@ -101,31 +105,38 @@ struct usbd_bus {
struct usb_device_stats stats;
int intr_context;
u_int no_intrs;
+ int usbrev; /* USB revision */
+#define USBREV_UNKNOWN 0
+#define USBREV_PRE_1_0 1
+#define USBREV_1_0 2
+#define USBREV_1_1 3
+#define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1" }
+
#if defined(__NetBSD__) || defined(__OpenBSD__)
bus_dma_tag_t dmatag; /* DMA tag */
#endif
};
struct usbd_device {
- struct usbd_bus *bus;
- struct usbd_pipe *default_pipe;
- u_int8_t address;
- u_int8_t depth;
- u_int8_t lowspeed;
- u_int16_t power;
- u_int8_t self_powered;
- int config;
- int langid; /* language to use for strings */
+ struct usbd_bus *bus; /* our controller */
+ struct usbd_pipe *default_pipe; /* pipe 0 */
+ u_int8_t address; /* device address */
+ u_int8_t config; /* current configuration # */
+ u_int8_t depth; /* distance from root hub */
+ u_int8_t lowspeed; /* lowspeed flag */
+ u_int8_t self_powered; /* flag for self powered */
+ u_int16_t power; /* mA the device uses */
+ int16_t langid; /* language for strings */
#define USBD_NOLANG (-1)
- usb_event_cookie_t cookie; /* unique connection id */
- struct usbd_port *powersrc;
- struct usbd_endpoint def_ep; /* for pipe 0 */
- usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */
- struct usbd_interface *ifaces;
- usb_device_descriptor_t ddesc;
- usb_config_descriptor_t *cdesc; /* full config descr */
- struct usbd_quirks *quirks;
- struct usbd_hub *hub; /* only if this is a hub */
+ usb_event_cookie_t cookie; /* unique connection id */
+ struct usbd_port *powersrc; /* upstream hub port, or 0 */
+ struct usbd_endpoint def_ep; /* for pipe 0 */
+ usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */
+ struct usbd_interface *ifaces; /* array of all interfaces */
+ usb_device_descriptor_t ddesc; /* device descriptor */
+ usb_config_descriptor_t *cdesc; /* full config descr */
+ struct usbd_quirks *quirks; /* device quirks, always set */
+ struct usbd_hub *hub; /* only if this is a hub */
device_ptr_t *subdevs; /* sub-devices, 0 terminated */
};
@@ -145,17 +156,18 @@ struct usbd_pipe {
struct usbd_endpoint *endpoint;
int refcnt;
char running;
- SIMPLEQ_HEAD(, usbd_request) queue;
+ SIMPLEQ_HEAD(, usbd_xfer) queue;
LIST_ENTRY(usbd_pipe) next;
- usbd_request_handle intrreqh; /* used for repeating requests */
+ usbd_xfer_handle intrxfer; /* used for repeating requests */
char repeat;
+ int interval;
/* Filled by HC driver. */
struct usbd_pipe_methods *methods;
};
-struct usbd_request {
+struct usbd_xfer {
struct usbd_pipe *pipe;
void *priv;
void *buffer;
@@ -183,10 +195,10 @@ struct usbd_request {
#define URQ_AUTO_DMABUF 0x10
#define URQ_DEV_DMABUF 0x20
- SIMPLEQ_ENTRY(usbd_request) next;
+ SIMPLEQ_ENTRY(usbd_xfer) next;
void *hcpriv; /* private use by the HC driver */
- int hcprivint; /* ditto */
+ int hcprivint;
#if defined(__FreeBSD__)
struct callout_handle timo_handle;
@@ -204,7 +216,7 @@ usbd_status usbd_reset_port __P((usbd_device_handle dev,
int port, usb_port_status_t *ps));
usbd_status usbd_setup_pipe __P((usbd_device_handle dev,
usbd_interface_handle iface,
- struct usbd_endpoint *,
+ struct usbd_endpoint *, int,
usbd_pipe_handle *pipe));
usbd_status usbd_new_device __P((device_ptr_t parent,
usbd_bus_handle bus, int depth,
@@ -217,13 +229,13 @@ 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));
+usbd_status usb_insert_transfer __P((usbd_xfer_handle xfer));
+void usb_transfer_complete __P((usbd_xfer_handle xfer));
void usb_disconnect_port __P((struct usbd_port *up, device_ptr_t));
/* Routines from usb.c */
-int usb_bus_count __P((void));
void usb_needs_explore __P((usbd_bus_handle));
+void usb_schedsoftintr __P((struct usbd_bus *));
#ifdef DIAGNOSTIC
#define SPLUSBCHECK \
@@ -231,6 +243,7 @@ void usb_needs_explore __P((usbd_bus_handle));
extern int cold; \
if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \
_s, _su, __FILE__, __LINE__); \
+ splx(_s); \
} while (0)
#else
#define SPLUSBCHECK