summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-09-27 18:03:57 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-09-27 18:03:57 +0000
commit665e2d3eed98c780ba0039928b2a498dfe74a659 (patch)
treee839e0b559aca6e7b30f3ba4b50eb71b90fd7ed2 /sys/dev
parent3a203f68ae62de8dce87fb1db2777617a91698cd (diff)
Sync with NetBSD.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/TODO41
-rw-r--r--sys/dev/usb/files.usb8
-rw-r--r--sys/dev/usb/ohci.c723
-rw-r--r--sys/dev/usb/ohcireg.h7
-rw-r--r--sys/dev/usb/ohcivar.h14
-rw-r--r--sys/dev/usb/ugen.c42
-rw-r--r--sys/dev/usb/uhci.c865
-rw-r--r--sys/dev/usb/uhcivar.h14
-rw-r--r--sys/dev/usb/uhid.c22
-rw-r--r--sys/dev/usb/uhub.c88
-rw-r--r--sys/dev/usb/usb.c192
-rw-r--r--sys/dev/usb/usb.h19
-rw-r--r--sys/dev/usb/usb_mem.c25
-rw-r--r--sys/dev/usb/usb_mem.h13
-rw-r--r--sys/dev/usb/usb_port.h49
-rw-r--r--sys/dev/usb/usb_quirks.c16
-rw-r--r--sys/dev/usb/usb_subr.c111
-rw-r--r--sys/dev/usb/usbdi.c354
-rw-r--r--sys/dev/usb/usbdi.h34
-rw-r--r--sys/dev/usb/usbdi_util.c22
-rw-r--r--sys/dev/usb/usbdi_util.h8
-rw-r--r--sys/dev/usb/usbdivar.h65
22 files changed, 1617 insertions, 1115 deletions
diff --git a/sys/dev/usb/TODO b/sys/dev/usb/TODO
index 159fd38c204..ad0c72376c5 100644
--- a/sys/dev/usb/TODO
+++ b/sys/dev/usb/TODO
@@ -3,10 +3,6 @@ Some things that need to be done in no particular order:
Add lots of bus_dmamap_sync().
-Implement isochronous transfer mode.
-
-Implement audio driver.
-
Do bandwidth accounting.
Use lock manager locks.
@@ -15,15 +11,42 @@ Use the pool allocator for TDs et al.
Throw out more USBDI gunk.
-Make hub driver note transition between self and bus powered state.
+Make hub driver notice transition between self and bus powered state.
Handle overcurrent conditions.
-Make it possible to preallocate DMA buffers to avoid calling the
-memory allocator from an interrupt context.
+Add an event mechanism to find out about attach and detach.
+
+Make it possible to open any device in a "generic" way, i.e., like ugen.
+
+Rewrite mouse and keyboard driver to handle devices which use the
+report ID. One way would be to attach ums and ukbd to uhid.
+
+Rotate the QHs for bulk transport to get fairer scheduling.
+
+Change HC drivers to queue multiple request for an endpoint
+to get better performance.
+
+Add generic ucom layer for serial adapters.
+
+Add isoc to OHCI driver.
+
+Do memory deallocation when HC driver is deactivated.
-Move memory allocation and copying to HC independent code.
+uaudio problems:
+ mixer names are awful, use some heuristics.
+ implement selector units
+ implement input
+ test with more devices
-Use a TD chain in ohci.c to allow transfers > 8K.
+Stylistic changes:
+ use NULL not 0
+ declare all local definitions static
+ rename s/request/xfer/
+ use usb_ and usbd_ consistently
+ rename s/r/err/
+ use implicit test for no err
+ indent continuation lines according to KNF
+ rearrange the contents and names of some files (Nick)
Document device driver API.
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb
index dd5b235d810..6dbc9f49e02 100644
--- a/sys/dev/usb/files.usb
+++ b/sys/dev/usb/files.usb
@@ -1,4 +1,4 @@
-# $OpenBSD: files.usb,v 1.4 1999/08/31 07:46:28 fgsch Exp $
+# $OpenBSD: files.usb,v 1.5 1999/09/27 18:03:54 fgsch Exp $
# $NetBSD: files.usb,v 1.8 1999/06/30 06:44:22 augustss Exp $
#
# Config file and device description for machine-independent USB code.
@@ -24,9 +24,9 @@ file dev/usb/uhub.c usb
attach uhub at uhub with uhub_uhub
# Audio devices
-#device uaudio: audio, auconv, mulaw
-#attach uaudio at uhub
-#file dev/usb/uaudio.c uaudio
+device uaudio: audio, auconv, mulaw
+attach uaudio at uhub
+file dev/usb/uaudio.c uaudio
# Generic devices
device ugen
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 7892a19c232..64f471eb792 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohci.c,v 1.5 1999/08/27 09:00:28 fgsch Exp $ */
-/* $NetBSD: ohci.c,v 1.33 1999/06/30 06:44:23 augustss Exp $ */
+/* $OpenBSD: ohci.c,v 1.6 1999/09/27 18:03:54 fgsch Exp $ */
+/* $NetBSD: ohci.c,v 1.48 1999/09/15 21:14:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -102,6 +102,13 @@ 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 *));
+void ohci_free_std_chain __P((ohci_softc_t *,
+ ohci_soft_td_t *, ohci_soft_td_t *));
+usbd_status ohci_alloc_std_chain __P((struct ohci_pipe *, ohci_softc_t *,
+ int, int, int, usb_dma_t *,
+ ohci_soft_td_t *,
+ ohci_soft_td_t **));
+
void ohci_power __P((int, void *));
usbd_status ohci_open __P((usbd_pipe_handle));
void ohci_poll __P((struct usbd_bus *));
@@ -116,6 +123,9 @@ 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_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));
@@ -145,6 +155,12 @@ void ohci_device_intr_abort __P((usbd_request_handle));
void ohci_device_intr_close __P((usbd_pipe_handle));
void ohci_device_intr_done __P((usbd_request_handle));
+usbd_status ohci_device_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));
+void ohci_device_isoc_close __P((usbd_pipe_handle));
+void ohci_device_isoc_done __P((usbd_request_handle));
+
usbd_status ohci_device_setintr __P((ohci_softc_t *sc,
struct ohci_pipe *pipe, int ival));
@@ -189,78 +205,133 @@ struct ohci_pipe {
union {
/* Control pipe */
struct {
- usb_dma_t datadma;
usb_dma_t reqdma;
u_int length;
- ohci_soft_td_t *setup, *xfer, *stat;
+ ohci_soft_td_t *setup, *data, *stat;
} ctl;
/* Interrupt pipe */
struct {
- usb_dma_t datadma;
int nslots;
int pos;
} intr;
/* Bulk pipe */
struct {
- usb_dma_t datadma;
u_int length;
int isread;
} bulk;
+ /* Iso pipe */
+ struct iso {
+ int xxxxx;
+ } iso;
} u;
};
#define OHCI_INTR_ENDPT 1
-struct usbd_methods ohci_root_ctrl_methods = {
+struct usbd_bus_methods ohci_bus_methods = {
+ ohci_open,
+ ohci_poll,
+ ohci_allocm,
+ ohci_freem,
+};
+
+struct usbd_pipe_methods ohci_root_ctrl_methods = {
ohci_root_ctrl_transfer,
ohci_root_ctrl_start,
ohci_root_ctrl_abort,
ohci_root_ctrl_close,
ohci_noop,
0,
- 0,
};
-struct usbd_methods ohci_root_intr_methods = {
+struct usbd_pipe_methods ohci_root_intr_methods = {
ohci_root_intr_transfer,
ohci_root_intr_start,
ohci_root_intr_abort,
ohci_root_intr_close,
ohci_noop,
ohci_root_intr_done,
- 0,
};
-struct usbd_methods ohci_device_ctrl_methods = {
+struct usbd_pipe_methods ohci_device_ctrl_methods = {
ohci_device_ctrl_transfer,
ohci_device_ctrl_start,
ohci_device_ctrl_abort,
ohci_device_ctrl_close,
ohci_noop,
ohci_device_ctrl_done,
- 0,
};
-struct usbd_methods ohci_device_intr_methods = {
+struct usbd_pipe_methods ohci_device_intr_methods = {
ohci_device_intr_transfer,
ohci_device_intr_start,
ohci_device_intr_abort,
ohci_device_intr_close,
ohci_device_clear_toggle,
ohci_device_intr_done,
- 0,
};
-struct usbd_methods ohci_device_bulk_methods = {
+struct usbd_pipe_methods ohci_device_bulk_methods = {
ohci_device_bulk_transfer,
ohci_device_bulk_start,
ohci_device_bulk_abort,
ohci_device_bulk_close,
ohci_device_clear_toggle,
ohci_device_bulk_done,
- 0,
};
+#if 0
+struct usbd_pipe_methods ohci_device_isoc_methods = {
+ ohci_device_isoc_transfer,
+ ohci_device_isoc_start,
+ ohci_device_isoc_abort,
+ ohci_device_isoc_close,
+ ohci_noop,
+ ohci_device_isoc_done,
+};
+#endif
+
+int
+ohci_activate(self, act)
+ device_ptr_t self;
+ enum devact act;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)self;
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ if (sc->sc_child != NULL)
+ rv = config_deactivate(sc->sc_child);
+ break;
+ }
+ return (rv);
+}
+
+int
+ohci_detach(self, flags)
+ device_ptr_t self;
+ int flags;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)self;
+ int rv = 0;
+
+ if (sc->sc_child != NULL)
+ rv = config_detach(sc->sc_child, flags);
+
+ if (rv != 0)
+ return (rv);
+
+ powerhook_disestablish(sc->sc_powerhook);
+ /* free data structures XXX */
+
+ return (rv);
+}
+
ohci_soft_ed_t *
ohci_alloc_sed(sc)
ohci_softc_t *sc;
@@ -272,7 +343,7 @@ ohci_alloc_sed(sc)
if (!sc->sc_freeeds) {
DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
- r = usb_allocmem(sc->sc_dmatag, OHCI_SED_SIZE * OHCI_SED_CHUNK,
+ r = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
OHCI_ED_ALIGN, &dma);
if (r != USBD_NORMAL_COMPLETION)
return (0);
@@ -311,7 +382,7 @@ ohci_alloc_std(sc)
if (!sc->sc_freetds) {
DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
- r = usb_allocmem(sc->sc_dmatag, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+ r = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
OHCI_TD_ALIGN, &dma);
if (r != USBD_NORMAL_COMPLETION)
return (0);
@@ -340,6 +411,85 @@ ohci_free_std(sc, std)
}
usbd_status
+ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
+ struct ohci_pipe *upipe;
+ ohci_softc_t *sc;
+ int len, rd, shortok;
+ usb_dma_t *dma;
+ ohci_soft_td_t *sp, **ep;
+{
+ ohci_soft_td_t *next, *cur;
+ ohci_physaddr_t dataphys, dataphysend;
+ u_int32_t intr;
+ int curlen;
+
+ DPRINTFN(len >= 4096,("ohci_alloc_std_chain: start len=%d\n", len));
+ cur = sp;
+ dataphys = DMAADDR(dma);
+ dataphysend = OHCI_PAGE(dataphys + len - 1);
+ for (;;) {
+ next = ohci_alloc_std(sc);
+ if (next == 0) {
+ /* XXX free chain */
+ return (USBD_NOMEM);
+ }
+
+ /* The OHCI hardware can handle at most one page crossing. */
+ if (OHCI_PAGE(dataphys) == dataphysend ||
+ OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend) {
+ /* we can handle it in this TD */
+ curlen = len;
+ } else {
+ /* must use multiple TDs, fill as much as possible. */
+ curlen = 2 * OHCI_PAGE_SIZE -
+ (dataphys & (OHCI_PAGE_SIZE-1));
+ }
+ DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
+ "dataphysend=0x%08x len=%d curlen=%d\n",
+ dataphys, dataphysend,
+ 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_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;
+ DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
+ dataphys, dataphys + curlen - 1));
+ if (len == 0)
+ break;
+ DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
+ dataphys += curlen;
+ cur = next;
+ }
+ cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ *ep = next;
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+ohci_free_std_chain(sc, std, stdend)
+ ohci_softc_t *sc;
+ ohci_soft_td_t *std;
+ ohci_soft_td_t *stdend;
+{
+ ohci_soft_td_t *p;
+
+ for (; std != stdend; std = p) {
+ p = std->nexttd;
+ ohci_free_std(sc, std);
+ }
+}
+
+usbd_status
ohci_init(sc)
ohci_softc_t *sc;
{
@@ -376,7 +526,7 @@ ohci_init(sc)
LIST_INIT(&sc->sc_hash_tds[i]);
/* Allocate the HCCA area. */
- r = usb_allocmem(sc->sc_dmatag, OHCI_HCCA_SIZE,
+ r = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE,
OHCI_HCCA_ALIGN, &sc->sc_hccadma);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -522,11 +672,10 @@ ohci_init(sc)
#endif
/* Set up the bus struct. */
- sc->sc_bus.open_pipe = ohci_open;
+ sc->sc_bus.methods = &ohci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
- sc->sc_bus.do_poll = ohci_poll;
- powerhook_establish(ohci_power, sc);
+ sc->sc_powerhook = powerhook_establish(ohci_power, sc);
return (USBD_NORMAL_COMPLETION);
@@ -535,10 +684,31 @@ ohci_init(sc)
bad2:
ohci_free_sed(sc, sc->sc_bulk_head);
bad1:
- usb_freemem(sc->sc_dmatag, &sc->sc_hccadma);
+ usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
return (r);
}
+usbd_status
+ohci_allocm(bus, dma, size)
+ struct usbd_bus *bus;
+ usb_dma_t *dma;
+ u_int32_t size;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+
+ return (usb_allocmem(&sc->sc_bus, size, 0, dma));
+}
+
+void
+ohci_freem(bus, dma)
+ struct usbd_bus *bus;
+ usb_dma_t *dma;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+
+ usb_freemem(&sc->sc_bus, dma);
+}
+
#if !defined(__OpenBSD__)
void
ohci_power(why, v)
@@ -548,7 +718,7 @@ ohci_power(why, v)
#ifdef USB_DEBUG
ohci_softc_t *sc = v;
- printf("ohci_power: sc=%p, why=%d\n", sc, why);
+ DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why));
/* XXX should suspend/resume */
ohci_dumpregs(sc);
#endif
@@ -563,40 +733,40 @@ void
ohci_dumpregs(sc)
ohci_softc_t *sc;
{
- printf("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
- OREAD4(sc, OHCI_REVISION),
- OREAD4(sc, OHCI_CONTROL),
- OREAD4(sc, OHCI_COMMAND_STATUS));
- printf(" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
- OREAD4(sc, OHCI_INTERRUPT_STATUS),
- OREAD4(sc, OHCI_INTERRUPT_ENABLE),
- OREAD4(sc, OHCI_INTERRUPT_DISABLE));
- printf(" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
- OREAD4(sc, OHCI_HCCA),
- OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
- OREAD4(sc, OHCI_CONTROL_HEAD_ED));
- printf(" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
- OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
- OREAD4(sc, OHCI_BULK_HEAD_ED),
- OREAD4(sc, OHCI_BULK_CURRENT_ED));
- printf(" done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
- OREAD4(sc, OHCI_DONE_HEAD),
- OREAD4(sc, OHCI_FM_INTERVAL),
- OREAD4(sc, OHCI_FM_REMAINING));
- printf(" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
- OREAD4(sc, OHCI_FM_NUMBER),
- OREAD4(sc, OHCI_PERIODIC_START),
- OREAD4(sc, OHCI_LS_THRESHOLD));
- printf(" desca=0x%08x descb=0x%08x stat=0x%08x\n",
- OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
- OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
- OREAD4(sc, OHCI_RH_STATUS));
- printf(" port1=0x%08x port2=0x%08x\n",
- OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
- OREAD4(sc, OHCI_RH_PORT_STATUS(2)));
- printf(" HCCA: frame_number=0x%04x done_head=0x%08x\n",
- LE(sc->sc_hcca->hcca_frame_number),
- LE(sc->sc_hcca->hcca_done_head));
+ DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
+ OREAD4(sc, OHCI_REVISION),
+ OREAD4(sc, OHCI_CONTROL),
+ OREAD4(sc, OHCI_COMMAND_STATUS)));
+ DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
+ OREAD4(sc, OHCI_INTERRUPT_STATUS),
+ OREAD4(sc, OHCI_INTERRUPT_ENABLE),
+ OREAD4(sc, OHCI_INTERRUPT_DISABLE)));
+ DPRINTF((" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
+ OREAD4(sc, OHCI_HCCA),
+ OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
+ OREAD4(sc, OHCI_CONTROL_HEAD_ED)));
+ DPRINTF((" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
+ OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
+ OREAD4(sc, OHCI_BULK_HEAD_ED),
+ OREAD4(sc, OHCI_BULK_CURRENT_ED)));
+ DPRINTF((" done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
+ OREAD4(sc, OHCI_DONE_HEAD),
+ OREAD4(sc, OHCI_FM_INTERVAL),
+ OREAD4(sc, OHCI_FM_REMAINING)));
+ DPRINTF((" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
+ OREAD4(sc, OHCI_FM_NUMBER),
+ OREAD4(sc, OHCI_PERIODIC_START),
+ OREAD4(sc, OHCI_LS_THRESHOLD)));
+ DPRINTF((" desca=0x%08x descb=0x%08x stat=0x%08x\n",
+ OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
+ OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
+ OREAD4(sc, OHCI_RH_STATUS)));
+ DPRINTF((" port1=0x%08x port2=0x%08x\n",
+ OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
+ OREAD4(sc, OHCI_RH_PORT_STATUS(2))));
+ DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n",
+ LE(sc->sc_hcca->hcca_frame_number),
+ LE(sc->sc_hcca->hcca_done_head)));
}
#endif
@@ -634,7 +804,8 @@ ohci_intr(p)
if (!eintrs)
return (0);
- sc->sc_intrs++;
+ sc->sc_bus.intr_context++;
+ sc->sc_bus.no_intrs++;
DPRINTFN(7, ("ohci_intr: sc=%p intrs=%x(%x) eintr=%x\n",
sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
(u_int)eintrs));
@@ -669,6 +840,8 @@ ohci_intr(p)
ohci_rhsc_able(sc, 0);
}
+ sc->sc_bus.intr_context--;
+
/* Block unprocessed interrupts. XXX */
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, intrs);
sc->sc_eintrs &= ~intrs;
@@ -714,7 +887,7 @@ ohci_process_done(sc, done)
ohci_softc_t *sc;
ohci_physaddr_t done;
{
- ohci_soft_td_t *std, *sdone;
+ ohci_soft_td_t *std, *sdone, *stdnext;
usbd_request_handle reqh;
int len, cc;
@@ -729,13 +902,14 @@ ohci_process_done(sc, done)
#ifdef USB_DEBUG
if (ohcidebug > 10) {
- printf("ohci_process_done: TD done:\n");
+ DPRINTF(("ohci_process_done: TD done:\n"));
ohci_dump_tds(sdone);
}
#endif
- for (std = sdone; std; std = std->dnext) {
+ for (std = sdone; std; std = stdnext) {
reqh = std->reqh;
+ stdnext = std->dnext;
DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n",
std, reqh, reqh->hcpriv));
cc = OHCI_TD_GET_CC(LE(std->td.td_flags));
@@ -745,47 +919,50 @@ ohci_process_done(sc, done)
DPRINTF(("ohci_process_done: cancel/timeout %p\n",
reqh));
/* Handled by abort routine. */
- continue;
} else if (cc == OHCI_CC_NO_ERROR) {
len = std->len;
if (std->td.td_cbp != 0)
len -= LE(std->td.td_be) -
LE(std->td.td_cbp) + 1;
- if (std->flags & OHCI_SET_LEN)
- reqh->actlen = len;
+ if (std->flags & OHCI_ADD_LEN)
+ reqh->actlen += len;
if (std->flags & OHCI_CALL_DONE) {
reqh->status = USBD_NORMAL_COMPLETION;
usb_transfer_complete(reqh);
}
+ ohci_hash_rem_td(sc, std);
+ ohci_free_std(sc, std);
} else {
+ /*
+ * Endpoint is halted. First unlink all the TDs
+ * belonging to the failed transfer, and then restart
+ * the endpoint.
+ */
ohci_soft_td_t *p, *n;
struct ohci_pipe *opipe =
(struct ohci_pipe *)reqh->pipe;
+
DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n",
OHCI_TD_GET_CC(LE(std->td.td_flags)),
ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))]));
- /*
- * Endpoint is halted. First unlink all the TDs
- * belonging to the failed transfer, and then restart
- * the endpoint.
- */
- for (p = std->nexttd; p->reqh == reqh; p = n) {
+
+ /* remove TDs */
+ for (p = std; p->reqh == reqh; p = n) {
n = p->nexttd;
ohci_hash_rem_td(sc, p);
ohci_free_std(sc, p);
}
+
/* clear halt */
opipe->sed->ed.ed_headp = LE(p->physaddr);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
-
+
if (cc == OHCI_CC_STALL)
reqh->status = USBD_STALLED;
else
reqh->status = USBD_IOERROR;
usb_transfer_complete(reqh);
}
- ohci_hash_rem_td(sc, std);
- ohci_free_std(sc, std);
}
}
@@ -793,26 +970,14 @@ void
ohci_device_ctrl_done(reqh)
usbd_request_handle reqh;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
- ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
- u_int len = opipe->u.ctl.length;
- usb_dma_t *dma;
-
DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh));
#ifdef DIAGNOSTIC
- if (!reqh->isreq) {
+ if (!(reqh->rqflags & URQ_REQUEST)) {
panic("ohci_ctrl_done: not a request\n");
}
#endif
reqh->hcpriv = 0;
-
- if (len != 0) {
- dma = &opipe->u.ctl.datadma;
- if (reqh->request.bmRequestType & UT_READ)
- memcpy(reqh->buffer, KERNADDR(dma), len);
- usb_freemem(sc->sc_dmatag, dma);
- }
}
void
@@ -821,9 +986,8 @@ ohci_device_intr_done(reqh)
{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
- usb_dma_t *dma;
ohci_soft_ed_t *sed = opipe->sed;
- ohci_soft_td_t *xfer, *tail;
+ ohci_soft_td_t *data, *tail;
DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n",
@@ -831,11 +995,8 @@ ohci_device_intr_done(reqh)
reqh->hcpriv = 0;
- dma = &opipe->u.intr.datadma;
- memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
-
if (reqh->pipe->repeat) {
- xfer = opipe->tail;
+ data = opipe->tail;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
if (!tail) {
reqh->status = USBD_NOMEM;
@@ -843,25 +1004,24 @@ ohci_device_intr_done(reqh)
}
tail->reqh = 0;
- xfer->td.td_flags = LE(
+ 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)
- xfer->td.td_flags |= LE(OHCI_TD_R);
- xfer->td.td_cbp = LE(DMAADDR(dma));
- xfer->nexttd = tail;
- xfer->td.td_nexttd = LE(tail->physaddr);
- xfer->td.td_be = LE(LE(xfer->td.td_cbp) + reqh->length - 1);
- xfer->len = reqh->length;
- xfer->reqh = reqh;
- xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
- reqh->hcpriv = xfer;
-
- ohci_hash_add_td(sc, xfer);
+ data->td.td_flags |= LE(OHCI_TD_R);
+ data->td.td_cbp = LE(DMAADDR(&reqh->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->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ reqh->hcpriv = data;
+ reqh->actlen = 0;
+
+ ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
- } else {
- usb_freemem(sc->sc_dmatag, dma);
}
}
@@ -869,20 +1029,10 @@ void
ohci_device_bulk_done(reqh)
usbd_request_handle reqh;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
- ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
- u_int len = opipe->u.bulk.length;
- usb_dma_t *dma;
-
DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n",
reqh, reqh->actlen));
reqh->hcpriv = 0;
-
- dma = &opipe->u.bulk.datadma;
- if (opipe->u.bulk.isread)
- memcpy(reqh->buffer, KERNADDR(dma), len);
- usb_freemem(sc->sc_dmatag, dma);
}
void
@@ -908,7 +1058,7 @@ ohci_rhsc(sc, reqh)
pipe = reqh->pipe;
opipe = (struct ohci_pipe *)pipe;
- p = KERNADDR(&opipe->u.intr.datadma);
+ p = KERNADDR(&reqh->dmabuf);
m = min(sc->sc_noport, reqh->length * 8 - 1);
memset(p, 0, reqh->length);
for (i = 1; i <= m; i++) {
@@ -926,13 +1076,7 @@ void
ohci_root_intr_done(reqh)
usbd_request_handle reqh;
{
- struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
- ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
-
reqh->hcpriv = 0;
-
- if (!reqh->pipe->repeat)
- usb_freemem(sc->sc_dmatag, &opipe->u.intr.datadma);
}
/*
@@ -991,9 +1135,8 @@ ohci_device_request(reqh)
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, *xfer = 0, *stat, *next, *tail;
+ ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail;
ohci_soft_ed_t *sed;
- usb_dma_t *dmap;
int isread;
int len;
usbd_status r;
@@ -1022,7 +1165,6 @@ ohci_device_request(reqh)
tail->reqh = 0;
sed = opipe->sed;
- dmap = &opipe->u.ctl.datadma;
opipe->u.ctl.length = len;
/* Update device address and length since they may have changed. */
@@ -1034,36 +1176,32 @@ ohci_device_request(reqh)
/* Set up data transaction */
if (len != 0) {
- xfer = ohci_alloc_std(sc);
- if (!xfer) {
+ data = ohci_alloc_std(sc);
+ if (!data) {
r = USBD_NOMEM;
goto bad3;
}
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad4;
- xfer->td.td_flags = LE(
+ 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));
- xfer->td.td_cbp = LE(DMAADDR(dmap));
- xfer->nexttd = stat;
- xfer->td.td_nexttd = LE(stat->physaddr);
- xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1);
- xfer->len = len;
- xfer->reqh = reqh;
- xfer->flags = OHCI_SET_LEN;
-
- next = xfer;
+ 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;
- stat->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
+ /* XXX ADD_LEN? */
+ stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
}
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
- if (!isread && len != 0)
- memcpy(KERNADDR(dmap), reqh->buffer, len);
setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
@@ -1088,7 +1226,7 @@ ohci_device_request(reqh)
#if USB_DEBUG
if (ohcidebug > 5) {
- printf("ohci_device_request:\n");
+ DPRINTF(("ohci_device_request:\n"));
ohci_dump_ed(sed);
ohci_dump_tds(setup);
}
@@ -1098,7 +1236,7 @@ ohci_device_request(reqh)
s = splusb();
ohci_hash_add_td(sc, setup);
if (len != 0)
- ohci_hash_add_td(sc, xfer);
+ ohci_hash_add_td(sc, data);
ohci_hash_add_td(sc, stat);
sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
@@ -1112,8 +1250,8 @@ ohci_device_request(reqh)
#if USB_DEBUG
if (ohcidebug > 5) {
delay(5000);
- printf("ohci_device_request: status=%x\n",
- OREAD4(sc, OHCI_COMMAND_STATUS));
+ DPRINTF(("ohci_device_request: status=%x\n",
+ OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
ohci_dump_tds(setup);
}
@@ -1121,8 +1259,6 @@ ohci_device_request(reqh)
return (USBD_NORMAL_COMPLETION);
- bad4:
- ohci_free_std(sc, xfer);
bad3:
ohci_free_std(sc, tail);
bad2:
@@ -1139,6 +1275,7 @@ ohci_add_ed(sed, head)
ohci_soft_ed_t *sed;
ohci_soft_ed_t *head;
{
+ SPLUSBCHECK;
sed->next = head->next;
sed->ed.ed_nexted = head->ed.ed_nexted;
head->next = sed;
@@ -1155,6 +1292,8 @@ ohci_rem_ed(sed, head)
{
ohci_soft_ed_t *p;
+ SPLUSBCHECK;
+
/* XXX */
for (p = head; p && p->next != sed; p = p->next)
;
@@ -1183,6 +1322,8 @@ ohci_hash_add_td(sc, std)
{
int h = HASH(std->physaddr);
+ SPLUSBCHECK;
+
LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext);
}
@@ -1192,6 +1333,8 @@ ohci_hash_rem_td(sc, std)
ohci_softc_t *sc;
ohci_soft_td_t *std;
{
+ SPLUSBCHECK;
+
LIST_REMOVE(std, hnext);
}
@@ -1216,9 +1359,15 @@ ohci_timeout(addr)
void *addr;
{
usbd_request_handle reqh = addr;
+ int s;
DPRINTF(("ohci_timeout: reqh=%p\n", reqh));
+
+ s = splusb();
+ reqh->device->bus->intr_context++;
ohci_abort_req(reqh, USBD_TIMEOUT);
+ reqh->device->bus->intr_context--;
+ splx(s);
}
#ifdef USB_DEBUG
@@ -1234,33 +1383,33 @@ void
ohci_dump_td(std)
ohci_soft_td_t *std;
{
- printf("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx "
- "nexttd=0x%08lx be=0x%08lx\n",
- std, (u_long)std->physaddr,
- (int)LE(std->td.td_flags),
- "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
- OHCI_TD_GET_DI(LE(std->td.td_flags)),
- OHCI_TD_GET_EC(LE(std->td.td_flags)),
- OHCI_TD_GET_CC(LE(std->td.td_flags)),
- (u_long)LE(std->td.td_cbp),
- (u_long)LE(std->td.td_nexttd), (u_long)LE(std->td.td_be));
+ DPRINTF(("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx "
+ "nexttd=0x%08lx be=0x%08lx\n",
+ std, (u_long)std->physaddr,
+ (int)LE(std->td.td_flags),
+ "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
+ OHCI_TD_GET_DI(LE(std->td.td_flags)),
+ OHCI_TD_GET_EC(LE(std->td.td_flags)),
+ OHCI_TD_GET_CC(LE(std->td.td_flags)),
+ (u_long)LE(std->td.td_cbp),
+ (u_long)LE(std->td.td_nexttd), (u_long)LE(std->td.td_be)));
}
void
ohci_dump_ed(sed)
ohci_soft_ed_t *sed;
{
- printf("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
- "headp=%b nexted=0x%08lx\n",
- sed, (u_long)sed->physaddr,
- OHCI_ED_GET_FA(LE(sed->ed.ed_flags)),
- OHCI_ED_GET_EN(LE(sed->ed.ed_flags)),
- OHCI_ED_GET_MAXP(LE(sed->ed.ed_flags)),
- (int)LE(sed->ed.ed_flags),
- "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
- (u_long)LE(sed->ed.ed_tailp),
- (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY",
- (u_long)LE(sed->ed.ed_nexted));
+ DPRINTF(("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
+ "headp=%b nexted=0x%08lx\n",
+ sed, (u_long)sed->physaddr,
+ OHCI_ED_GET_FA(LE(sed->ed.ed_flags)),
+ OHCI_ED_GET_EN(LE(sed->ed.ed_flags)),
+ OHCI_ED_GET_MAXP(LE(sed->ed.ed_flags)),
+ (int)LE(sed->ed.ed_flags),
+ "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
+ (u_long)LE(sed->ed.ed_tailp),
+ (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY",
+ (u_long)LE(sed->ed.ed_nexted)));
}
#endif
@@ -1285,7 +1434,7 @@ ohci_open(pipe)
case USB_CONTROL_ENDPOINT:
pipe->methods = &ohci_root_ctrl_methods;
break;
- case UE_IN | OHCI_INTR_ENDPT:
+ case UE_DIR_IN | OHCI_INTR_ENDPT:
pipe->methods = &ohci_root_intr_methods;
break;
default:
@@ -1313,7 +1462,7 @@ ohci_open(pipe)
switch (ed->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
pipe->methods = &ohci_device_ctrl_methods;
- r = usb_allocmem(sc->sc_dmatag,
+ r = usb_allocmem(&sc->sc_bus,
sizeof(usb_device_request_t),
0, &opipe->u.ctl.reqdma);
if (r != USBD_NORMAL_COMPLETION)
@@ -1327,7 +1476,7 @@ ohci_open(pipe)
return (ohci_device_setintr(sc, opipe, ed->bInterval));
case UE_ISOCHRONOUS:
printf("ohci_open: open iso unimplemented\n");
- return (USBD_XXX);
+ return (USBD_INVAL);
case UE_BULK:
pipe->methods = &ohci_device_bulk_methods;
s = splusb();
@@ -1417,11 +1566,12 @@ ohci_abort_req(reqh, status)
DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed));
sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
- if (curproc) {
+ if (reqh->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);
+ } else {
usb_delay_ms(opipe->pipe.device->bus, 1);
ohci_abort_req_end(reqh);
- } else {
- timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
}
}
@@ -1506,7 +1656,7 @@ usb_interface_descriptor_t ohci_ifcd = {
usb_endpoint_descriptor_t ohci_endpd = {
USB_ENDPOINT_DESCRIPTOR_SIZE,
UDESC_ENDPOINT,
- UE_IN | OHCI_INTR_ENDPT,
+ UE_DIR_IN | OHCI_INTR_ENDPT,
UE_INTERRUPT,
{8, 0}, /* max packet */
255
@@ -1549,16 +1699,15 @@ usbd_status
ohci_root_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (ohci_root_ctrl_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1569,17 +1718,18 @@ ohci_root_ctrl_start(reqh)
usb_device_request_t *req;
void *buf;
int port, i;
- int len, value, index, l, totlen = 0;
+ int s, len, value, index, l, totlen = 0;
usb_port_status_t ps;
usb_hub_descriptor_t hubd;
usbd_status r;
u_int32_t v;
- if (!reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (!(reqh->rqflags & URQ_REQUEST))
/* XXX panic */
return (USBD_INVAL);
+#endif
req = &reqh->request;
- buf = reqh->buffer;
DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n",
req->bmRequestType, req->bRequest));
@@ -1587,6 +1737,14 @@ ohci_root_ctrl_start(reqh)
len = UGETW(req->wLength);
value = UGETW(req->wValue);
index = UGETW(req->wIndex);
+
+ if (len != 0)
+ buf = KERNADDR(&reqh->dmabuf);
+#ifdef DIAGNOSTIC
+ else
+ buf = 0;
+#endif
+
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
@@ -1849,7 +2007,9 @@ ohci_root_ctrl_start(reqh)
r = USBD_NORMAL_COMPLETION;
ret:
reqh->status = r;
+ s = splusb();
usb_transfer_complete(reqh);
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -1874,16 +2034,15 @@ usbd_status
ohci_root_intr_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (ohci_root_intr_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (ohci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1892,19 +2051,7 @@ ohci_root_intr_start(reqh)
{
usbd_pipe_handle pipe = reqh->pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
- struct ohci_pipe *upipe = (struct ohci_pipe *)pipe;
- usb_dma_t *dmap;
- usbd_status r;
- int len;
-
- len = reqh->length;
- dmap = &upipe->u.intr.datadma;
- if (len == 0)
- return (USBD_INVAL); /* XXX should it be? */
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
sc->sc_intrreqh = reqh;
return (USBD_IN_PROGRESS);
@@ -1936,16 +2083,15 @@ usbd_status
ohci_device_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (ohci_device_ctrl_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1955,11 +2101,13 @@ ohci_device_ctrl_start(reqh)
ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
usbd_status r;
- if (!reqh->isreq) {
+#ifdef DIAGNOSTIC
+ if (!(reqh->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)
@@ -2011,16 +2159,15 @@ usbd_status
ohci_device_bulk_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (ohci_device_bulk_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (ohci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -2031,14 +2178,13 @@ ohci_device_bulk_start(reqh)
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
int addr = dev->address;
- ohci_soft_td_t *xfer, *tail;
+ ohci_soft_td_t *data, *tail, *tdp;
ohci_soft_ed_t *sed;
- usb_dma_t *dmap;
+ int s, len, isread, endpt;
usbd_status r;
- int s, len, isread;
#ifdef DIAGNOSTIC
- if (reqh->isreq) {
+ if (reqh->rqflags & URQ_REQUEST) {
/* XXX panic */
printf("ohci_device_bulk_start: a request\n");
return (USBD_INVAL);
@@ -2046,66 +2192,51 @@ ohci_device_bulk_start(reqh)
#endif
len = reqh->length;
- dmap = &opipe->u.bulk.datadma;
- isread = reqh->pipe->endpoint->edesc->bEndpointAddress & UE_IN;
+ endpt = reqh->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,
- reqh->pipe->endpoint->edesc->bEndpointAddress));
+ endpt));
opipe->u.bulk.isread = isread;
opipe->u.bulk.length = len;
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto ret1;
-
- tail = ohci_alloc_std(sc);
- if (!tail) {
- r = USBD_NOMEM;
- goto ret2;
- }
- tail->reqh = 0;
-
/* Update device address */
sed->ed.ed_flags = LE(
(LE(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |
OHCI_ED_SET_FA(addr));
- /* Set up data transaction */
- xfer = opipe->tail;
- xfer->td.td_flags = LE(
- (isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY |
- (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
- xfer->td.td_cbp = LE(DMAADDR(dmap));
- xfer->nexttd = tail;
- xfer->td.td_nexttd = LE(tail->physaddr);
- xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1);
- xfer->len = len;
- xfer->reqh = reqh;
- xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
- reqh->hcpriv = xfer;
-
- if (!isread)
- memcpy(KERNADDR(dmap), reqh->buffer, len);
+ /* 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;
DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
"td_cbp=0x%08x td_be=0x%08x\n",
- (int)LE(sed->ed.ed_flags), (int)LE(xfer->td.td_flags),
- (int)LE(xfer->td.td_cbp), (int)LE(xfer->td.td_be)));
+ (int)LE(sed->ed.ed_flags), (int)LE(data->td.td_flags),
+ (int)LE(data->td.td_cbp), (int)LE(data->td.td_be)));
#ifdef USB_DEBUG
if (ohcidebug > 4) {
ohci_dump_ed(sed);
- ohci_dump_tds(xfer);
+ ohci_dump_tds(data);
}
#endif
/* Insert ED in schedule */
s = splusb();
- ohci_hash_add_td(sc, xfer);
+ for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
+ tdp->reqh = reqh;
+ ohci_hash_add_td(sc, tdp);
+ }
sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
@@ -2118,21 +2249,16 @@ ohci_device_bulk_start(reqh)
#ifdef USB_DEBUG
if (ohcidebug > 5) {
delay(5000);
- printf("ohci_device_intr_transfer: status=%x\n",
- OREAD4(sc, OHCI_COMMAND_STATUS));
+ DPRINTF(("ohci_device_intr_transfer: status=%x\n",
+ OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
- ohci_dump_tds(xfer);
+ ohci_dump_tds(data);
}
#endif
splx(s);
return (USBD_IN_PROGRESS);
-
- ret2:
- usb_freemem(sc->sc_dmatag, dmap);
- ret1:
- return (r);
}
void
@@ -2162,16 +2288,15 @@ usbd_status
ohci_device_intr_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (ohci_device_intr_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (ohci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -2182,61 +2307,52 @@ ohci_device_intr_start(reqh)
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
ohci_soft_ed_t *sed = opipe->sed;
- ohci_soft_td_t *xfer, *tail;
- usb_dma_t *dmap;
- usbd_status r;
+ ohci_soft_td_t *data, *tail;
int len;
int s;
- DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p buf=%p len=%d "
+ DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p len=%d "
"flags=%d priv=%p\n",
- reqh, reqh->buffer, reqh->length, reqh->flags, reqh->priv));
+ reqh, reqh->length, reqh->flags, reqh->priv));
- if (reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (reqh->rqflags & URQ_REQUEST)
panic("ohci_device_intr_transfer: a request\n");
+#endif
len = reqh->length;
- dmap = &opipe->u.intr.datadma;
- if (len == 0)
- return (USBD_INVAL); /* XXX should it be? */
- xfer = opipe->tail;
+ data = opipe->tail;
tail = ohci_alloc_std(sc);
- if (!tail) {
- r = USBD_NOMEM;
- goto ret1;
- }
+ if (!tail)
+ return (USBD_NOMEM);
tail->reqh = 0;
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto ret2;
-
- xfer->td.td_flags = LE(
+ 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)
- xfer->td.td_flags |= LE(OHCI_TD_R);
- xfer->td.td_cbp = LE(DMAADDR(dmap));
- xfer->nexttd = tail;
- xfer->td.td_nexttd = LE(tail->physaddr);
- xfer->td.td_be = LE(LE(xfer->td.td_cbp) + len - 1);
- xfer->len = len;
- xfer->reqh = reqh;
- xfer->flags = OHCI_CALL_DONE | OHCI_SET_LEN;
- reqh->hcpriv = xfer;
+ data->td.td_flags |= LE(OHCI_TD_R);
+ data->td.td_cbp = LE(DMAADDR(&reqh->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->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ reqh->hcpriv = data;
#if USB_DEBUG
if (ohcidebug > 5) {
- printf("ohci_device_intr_transfer:\n");
+ DPRINTF(("ohci_device_intr_transfer:\n"));
ohci_dump_ed(sed);
- ohci_dump_tds(xfer);
+ ohci_dump_tds(data);
}
#endif
/* Insert ED in schedule */
s = splusb();
- ohci_hash_add_td(sc, xfer);
+ ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
@@ -2244,20 +2360,15 @@ ohci_device_intr_start(reqh)
#ifdef USB_DEBUG
if (ohcidebug > 5) {
delay(5000);
- printf("ohci_device_intr_transfer: status=%x\n",
- OREAD4(sc, OHCI_COMMAND_STATUS));
+ DPRINTF(("ohci_device_intr_transfer: status=%x\n",
+ OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
- ohci_dump_tds(xfer);
+ ohci_dump_tds(data);
}
#endif
splx(s);
return (USBD_IN_PROGRESS);
-
- ret2:
- ohci_free_std(sc, xfer);
- ret1:
- return (r);
}
/* Abort a device control request. */
diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h
index d054fd5a56a..67b010a0e5a 100644
--- a/sys/dev/usb/ohcireg.h
+++ b/sys/dev/usb/ohcireg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohcireg.h,v 1.2 1999/08/27 09:00:28 fgsch Exp $ */
-/* $NetBSD: ohcireg.h,v 1.7 1998/12/10 23:16:47 augustss Exp $ */
+/* $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 $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -140,6 +140,9 @@ struct ohci_hcca {
#define OHCI_HCCA_SIZE 256
#define OHCI_HCCA_ALIGN 256
+#define OHCI_PAGE_SIZE 0x1000
+#define OHCI_PAGE(x) ((x) &~ 0xfff)
+
typedef struct {
u_int32_t ed_flags;
#define OHCI_ED_GET_FA(s) ((s) & 0x7f)
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index ffa75a6b072..330bdd18d7f 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ohcivar.h,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */
-/* $NetBSD: ohcivar.h,v 1.6 1999/08/14 14:49:31 augustss Exp $ */
+/* $OpenBSD: ohcivar.h,v 1.5 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: ohcivar.h,v 1.11 1999/09/15 21:14:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@ typedef struct ohci_soft_td {
u_int16_t len;
u_int16_t flags;
#define OHCI_CALL_DONE 0x0001
-#define OHCI_SET_LEN 0x0002
+#define OHCI_ADD_LEN 0x0002
} ohci_soft_td_t;
#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
#define OHCI_STD_CHUNK 128
@@ -72,7 +72,6 @@ typedef struct ohci_softc {
#if defined(__NetBSD__) || defined(__OpenBSD__)
void *sc_ih; /* interrupt vectoring */
- bus_dma_tag_t sc_dmatag; /* DMA tag */
/* XXX should keep track of all DMA memory */
#endif /* __NetBSD__ || defined(__OpenBSD__) */
@@ -96,14 +95,17 @@ typedef struct ohci_softc {
usbd_request_handle sc_intrreqh;
- int sc_intrs;
-
char sc_vendor[16];
int sc_id_vendor;
+
+ void *sc_powerhook;
+ device_ptr_t sc_child;
} ohci_softc_t;
usbd_status ohci_init __P((ohci_softc_t *));
int ohci_intr __P((void *));
+int ohci_detach __P((device_ptr_t, int));
+int ohci_activate __P((device_ptr_t, enum devact));
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 90d84931172..38b95d8afd5 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ugen.c,v 1.5 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: ugen.c,v 1.19 1999/08/28 10:01:59 augustss Exp $ */
+/* $OpenBSD: ugen.c,v 1.6 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: ugen.c,v 1.23 1999/09/09 12:26:44 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -94,13 +94,13 @@ struct ugen_endpoint {
#define UGEN_BBSIZE 1024
struct ugen_softc {
- bdevice sc_dev; /* base device */
+ USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev;
char sc_is_open[USB_MAX_ENDPOINTS];
struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
-#define OUT 0 /* index order is important, from UE_OUT */
-#define IN 1 /* from UE_IN */
+#define OUT 0
+#define IN 1
int sc_refcnt;
u_char sc_dying;
@@ -205,6 +205,7 @@ ugen_set_config(sc, configno)
u_int8_t niface, nendpt;
int ifaceno, endptno, endpt;
usbd_status r;
+ int dir;
DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
USBDEVNAME(sc->sc_dev), configno, sc));
@@ -230,12 +231,12 @@ ugen_set_config(sc, configno)
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
- sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)]
- [UE_GET_IN(endpt)];
+ dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
"(%d,%d), sce=%p\n",
endptno, endpt, UE_GET_ADDR(endpt),
- UE_GET_IN(endpt), sce));
+ UE_GET_DIR(endpt), sce));
sce->sc = sc;
sce->edesc = ed;
sce->iface = iface;
@@ -407,7 +408,9 @@ ugen_do_read(sc, endpt, uio, flag)
int error = 0;
u_char buffer[UGEN_CHUNK];
+#ifdef __NetBSD__
DPRINTFN(5, ("ugenread: %d:%d\n", sc->sc_dev.dv_unit, endpt));
+#endif
if (sc->sc_dying)
return (EIO);
@@ -461,7 +464,7 @@ ugen_do_read(sc, endpt, uio, flag)
}
break;
case UE_BULK:
- reqh = usbd_alloc_request();
+ reqh = usbd_alloc_request(sc->sc_udev);
if (reqh == 0)
return (ENOMEM);
while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
@@ -507,7 +510,7 @@ ugenread(dev, uio, flag)
sc->sc_refcnt++;
error = ugen_do_read(sc, endpt, uio, flag);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
@@ -542,7 +545,7 @@ ugen_do_write(sc, endpt, uio, flag)
DPRINTF(("ugenwrite\n"));
switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
case UE_BULK:
- reqh = usbd_alloc_request();
+ reqh = usbd_alloc_request(sc->sc_udev);
if (reqh == 0)
return (EIO);
while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
@@ -581,13 +584,13 @@ ugenwrite(dev, uio, flag)
sc->sc_refcnt++;
error = ugen_do_write(sc, endpt, uio, flag);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
int
ugen_activate(self, act)
- bdevice *self;
+ device_ptr_t self;
enum devact act;
{
struct ugen_softc *sc = (struct ugen_softc *)self;
@@ -606,7 +609,7 @@ ugen_activate(self, act)
int
ugen_detach(self, flags)
- bdevice *self;
+ device_ptr_t self;
int flags;
{
struct ugen_softc *sc = (struct ugen_softc *)self;
@@ -633,7 +636,7 @@ ugen_detach(self, flags)
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
wakeup(&sc->sc_endpoints[i][IN]);
/* Wait for processes to go away. */
- usb_detach_wait(&sc->sc_dev);
+ usb_detach_wait(USBDEV(sc->sc_dev));
}
splx(s);
@@ -697,6 +700,7 @@ ugen_set_interface(sc, ifaceidx, altno)
usbd_status r;
struct ugen_endpoint *sce;
u_int8_t niface, nendpt, endptno, endpt;
+ int dir;
DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
@@ -715,7 +719,8 @@ ugen_set_interface(sc, ifaceidx, altno)
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
- sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
+ dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
sce->sc = 0;
sce->edesc = 0;
sce->iface = 0;
@@ -732,7 +737,8 @@ ugen_set_interface(sc, ifaceidx, altno)
for (endptno = 0; endptno < nendpt; endptno++) {
ed = usbd_interface2endpoint_descriptor(iface,endptno);
endpt = ed->bEndpointAddress;
- sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
+ dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
sce->sc = sc;
sce->edesc = ed;
sce->iface = iface;
@@ -1074,7 +1080,7 @@ ugenioctl(dev, cmd, addr, flag, p)
sc->sc_refcnt++;
error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 6f523d43cfd..414f3b94042 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhci.c,v 1.4 1999/08/27 09:00:28 fgsch Exp $ */
-/* $NetBSD: uhci.c,v 1.43 1999/08/22 23:41:00 augustss Exp $ */
+/* $OpenBSD: uhci.c,v 1.5 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: uhci.c,v 1.55 1999/09/15 21:12:29 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -111,29 +111,24 @@ struct uhci_pipe {
struct {
uhci_soft_qh_t *sqh;
usb_dma_t reqdma;
- usb_dma_t datadma;
uhci_soft_td_t *setup, *stat;
u_int length;
} ctl;
/* Interrupt pipe */
struct {
- usb_dma_t datadma;
int npoll;
uhci_soft_qh_t **qhs;
} intr;
/* Bulk pipe */
struct {
uhci_soft_qh_t *sqh;
- usb_dma_t datadma;
u_int length;
int isread;
} bulk;
/* Iso pipe */
struct iso {
- u_int bufsize;
- u_int nbuf;
- usb_dma_t *bufs;
uhci_soft_td_t **stds;
+ int next, inuse;
} iso;
} u;
};
@@ -180,9 +175,14 @@ 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_wakeup_cb __P((usbd_request_handle reqh));
+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));
@@ -206,7 +206,6 @@ usbd_status uhci_device_isoc_start __P((usbd_request_handle));
void uhci_device_isoc_abort __P((usbd_request_handle));
void uhci_device_isoc_close __P((usbd_pipe_handle));
void uhci_device_isoc_done __P((usbd_request_handle));
-usbd_status uhci_device_isoc_setbuf __P((usbd_pipe_handle, u_int, u_int));
usbd_status uhci_root_ctrl_transfer __P((usbd_request_handle));
usbd_status uhci_root_ctrl_start __P((usbd_request_handle));
@@ -255,64 +254,65 @@ void uhci_dump_td __P((uhci_soft_td_t *));
#define UHCI_INTR_ENDPT 1
-struct usbd_methods uhci_root_ctrl_methods = {
+struct usbd_bus_methods uhci_bus_methods = {
+ uhci_open,
+ uhci_poll,
+ uhci_allocm,
+ uhci_freem,
+};
+
+struct usbd_pipe_methods uhci_root_ctrl_methods = {
uhci_root_ctrl_transfer,
uhci_root_ctrl_start,
uhci_root_ctrl_abort,
uhci_root_ctrl_close,
uhci_noop,
0,
- 0,
};
-struct usbd_methods uhci_root_intr_methods = {
+struct usbd_pipe_methods uhci_root_intr_methods = {
uhci_root_intr_transfer,
uhci_root_intr_start,
uhci_root_intr_abort,
uhci_root_intr_close,
uhci_noop,
uhci_root_intr_done,
- 0,
};
-struct usbd_methods uhci_device_ctrl_methods = {
+struct usbd_pipe_methods uhci_device_ctrl_methods = {
uhci_device_ctrl_transfer,
uhci_device_ctrl_start,
uhci_device_ctrl_abort,
uhci_device_ctrl_close,
uhci_noop,
uhci_device_ctrl_done,
- 0,
};
-struct usbd_methods uhci_device_intr_methods = {
+struct usbd_pipe_methods uhci_device_intr_methods = {
uhci_device_intr_transfer,
uhci_device_intr_start,
uhci_device_intr_abort,
uhci_device_intr_close,
uhci_device_clear_toggle,
uhci_device_intr_done,
- 0,
};
-struct usbd_methods uhci_device_bulk_methods = {
+struct usbd_pipe_methods uhci_device_bulk_methods = {
uhci_device_bulk_transfer,
uhci_device_bulk_start,
uhci_device_bulk_abort,
uhci_device_bulk_close,
uhci_device_clear_toggle,
uhci_device_bulk_done,
- 0,
};
-struct usbd_methods uhci_device_isoc_methods = {
+struct usbd_pipe_methods uhci_device_isoc_methods = {
uhci_device_isoc_transfer,
uhci_device_isoc_start,
uhci_device_isoc_abort,
uhci_device_isoc_close,
uhci_noop,
uhci_device_isoc_done,
- uhci_device_isoc_setbuf,
};
void
@@ -346,7 +346,7 @@ uhci_init(sc)
uhci_busreset(sc);
/* Allocate and initialize real frame array. */
- r = usb_allocmem(sc->sc_dmatag,
+ r = usb_allocmem(&sc->sc_bus,
UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
if (r != USBD_NORMAL_COMPLETION)
@@ -404,14 +404,13 @@ uhci_init(sc)
LIST_INIT(&sc->sc_intrhead);
/* Set up the bus struct. */
- sc->sc_bus.open_pipe = uhci_open;
+ sc->sc_bus.methods = &uhci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
- sc->sc_bus.do_poll = uhci_poll;
#if !defined(__OpenBSD__)
sc->sc_suspend = PWR_RESUME;
#endif
- powerhook_establish(uhci_power, sc);
+ sc->sc_powerhook = powerhook_establish(uhci_power, sc);
DPRINTFN(1,("uhci_init: enabling\n"));
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
@@ -420,6 +419,68 @@ uhci_init(sc)
return (uhci_run(sc, 1)); /* and here we go... */
}
+int
+uhci_activate(self, act)
+ device_ptr_t self;
+ enum devact act;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)self;
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ if (sc->sc_child != NULL)
+ rv = config_deactivate(sc->sc_child);
+ break;
+ }
+ return (rv);
+}
+
+int
+uhci_detach(self, flags)
+ device_ptr_t self;
+ int flags;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)self;
+ int rv = 0;
+
+ if (sc->sc_child != NULL)
+ rv = config_detach(sc->sc_child, flags);
+
+ if (rv != 0)
+ return (rv);
+
+ powerhook_disestablish(sc->sc_powerhook);
+ /* free data structures XXX */
+
+ return (rv);
+}
+
+usbd_status
+uhci_allocm(bus, dma, size)
+ struct usbd_bus *bus;
+ usb_dma_t *dma;
+ u_int32_t size;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)bus;
+
+ return (usb_allocmem(&sc->sc_bus, size, 0, dma));
+}
+
+void
+uhci_freem(bus, dma)
+ struct usbd_bus *bus;
+ usb_dma_t *dma;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)bus;
+
+ usb_freemem(&sc->sc_bus, dma);
+}
+
#if !defined(__OpenBSD__)
/*
* Handle suspend/resume.
@@ -451,7 +512,7 @@ uhci_power(why, v)
if (sc->sc_has_timo)
usb_untimeout(uhci_timo, sc->sc_has_timo,
sc->sc_has_timo->timo_handle);
- sc->sc_bus.use_polling = 1;
+ sc->sc_bus.use_polling++;
uhci_run(sc, 0); /* stop the controller */
UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
@@ -473,7 +534,7 @@ uhci_power(why, v)
UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */
uhci_run(sc, 1); /* and start traffic again */
usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
- sc->sc_bus.use_polling = 0;
+ sc->sc_bus.use_polling--;
if (sc->sc_has_timo)
usb_timeout(uhci_timo, sc->sc_has_timo,
sc->sc_ival, sc->sc_has_timo->timo_handle);
@@ -491,55 +552,52 @@ static void
uhci_dumpregs(sc)
uhci_softc_t *sc;
{
- printf("%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
- "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
- USBDEVNAME(sc->sc_bus.bdev),
- UREAD2(sc, UHCI_CMD),
- UREAD2(sc, UHCI_STS),
- UREAD2(sc, UHCI_INTR),
- UREAD2(sc, UHCI_FRNUM),
- UREAD4(sc, UHCI_FLBASEADDR),
- UREAD1(sc, UHCI_SOF),
- UREAD2(sc, UHCI_PORTSC1),
- UREAD2(sc, UHCI_PORTSC2));
+ DPRINTFN(-1,("%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
+ "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
+ USBDEVNAME(sc->sc_bus.bdev),
+ UREAD2(sc, UHCI_CMD),
+ UREAD2(sc, UHCI_STS),
+ UREAD2(sc, UHCI_INTR),
+ UREAD2(sc, UHCI_FRNUM),
+ UREAD4(sc, UHCI_FLBASEADDR),
+ UREAD1(sc, UHCI_SOF),
+ UREAD2(sc, UHCI_PORTSC1),
+ UREAD2(sc, UHCI_PORTSC2)));
}
-int uhci_longtd = 1;
-
void
uhci_dump_td(p)
uhci_soft_td_t *p;
{
- printf("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
- "token=0x%08lx buffer=0x%08lx\n",
- p, (long)p->physaddr,
- (long)LE(p->td.td_link),
- (long)LE(p->td.td_status),
- (long)LE(p->td.td_token),
- (long)LE(p->td.td_buffer));
- if (uhci_longtd)
- printf(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,"
- "D=%d,maxlen=%d\n",
- (int)LE(p->td.td_link),
- "\20\1T\2Q\3VF",
- (int)LE(p->td.td_status),
- "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
- "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
- UHCI_TD_GET_ERRCNT(LE(p->td.td_status)),
- UHCI_TD_GET_ACTLEN(LE(p->td.td_status)),
- UHCI_TD_GET_PID(LE(p->td.td_token)),
- UHCI_TD_GET_DEVADDR(LE(p->td.td_token)),
- UHCI_TD_GET_ENDPT(LE(p->td.td_token)),
- UHCI_TD_GET_DT(LE(p->td.td_token)),
- UHCI_TD_GET_MAXLEN(LE(p->td.td_token)));
+ DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx "
+ "token=0x%08lx buffer=0x%08lx\n",
+ p, (long)p->physaddr,
+ (long)LE(p->td.td_link),
+ (long)LE(p->td.td_status),
+ (long)LE(p->td.td_token),
+ (long)LE(p->td.td_buffer)));
+ DPRINTFN(-1,(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,"
+ "D=%d,maxlen=%d\n",
+ (int)LE(p->td.td_link),
+ "\20\1T\2Q\3VF",
+ (int)LE(p->td.td_status),
+ "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
+ "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
+ UHCI_TD_GET_ERRCNT(LE(p->td.td_status)),
+ UHCI_TD_GET_ACTLEN(LE(p->td.td_status)),
+ UHCI_TD_GET_PID(LE(p->td.td_token)),
+ UHCI_TD_GET_DEVADDR(LE(p->td.td_token)),
+ UHCI_TD_GET_ENDPT(LE(p->td.td_token)),
+ UHCI_TD_GET_DT(LE(p->td.td_token)),
+ UHCI_TD_GET_MAXLEN(LE(p->td.td_token))));
}
void
uhci_dump_qh(p)
uhci_soft_qh_t *p;
{
- printf("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", p,
+ (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink)));
}
@@ -550,7 +608,7 @@ uhci_dump()
uhci_softc_t *sc = uhci;
uhci_dumpregs(sc);
- printf("intrs=%d\n", sc->sc_intrs);
+ printf("intrs=%d\n", sc->sc_bus.no_intrs);
printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link);
uhci_dump_qh(sc->sc_ctl_start->qh.hlink);
}
@@ -578,7 +636,6 @@ uhci_timo(addr)
usbd_request_handle reqh = addr;
usbd_pipe_handle pipe = reqh->pipe;
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
- struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
int s;
u_char *p;
@@ -586,7 +643,7 @@ uhci_timo(addr)
usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
- p = KERNADDR(&upipe->u.intr.datadma);
+ p = KERNADDR(&reqh->dmabuf);
p[0] = 0;
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<1;
@@ -600,7 +657,9 @@ uhci_timo(addr)
reqh->status = USBD_NORMAL_COMPLETION;
s = splusb();
reqh->hcpriv = 0;
+ reqh->device->bus->intr_context++;
usb_transfer_complete(reqh);
+ reqh->device->bus->intr_context--;
splx(s);
}
@@ -608,12 +667,6 @@ void
uhci_root_intr_done(reqh)
usbd_request_handle reqh;
{
- usbd_pipe_handle pipe = reqh->pipe;
- uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
- struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
-
- if (!reqh->pipe->repeat)
- usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma);
}
@@ -676,6 +729,8 @@ uhci_add_ctrl(sc, sqh)
{
uhci_soft_qh_t *eqh;
+ SPLUSBCHECK;
+
DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh));
eqh = sc->sc_ctl_end;
sqh->hlink = eqh->hlink;
@@ -693,6 +748,8 @@ uhci_remove_ctrl(sc, sqh)
{
uhci_soft_qh_t *pqh;
+ SPLUSBCHECK;
+
DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh));
for (pqh = sc->sc_ctl_start; pqh->hlink != sqh; pqh=pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
@@ -717,6 +774,8 @@ uhci_add_bulk(sc, sqh)
{
uhci_soft_qh_t *eqh;
+ SPLUSBCHECK;
+
DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh));
eqh = sc->sc_bulk_end;
sqh->hlink = eqh->hlink;
@@ -734,6 +793,8 @@ uhci_remove_bulk(sc, sqh)
{
uhci_soft_qh_t *pqh;
+ SPLUSBCHECK;
+
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
for (pqh = sc->sc_bulk_start; pqh->hlink != sqh; pqh = pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
@@ -751,53 +812,58 @@ uhci_remove_bulk(sc, sqh)
}
int
-uhci_intr(p)
- void *p;
+uhci_intr(arg)
+ void *arg;
{
- uhci_softc_t *sc = p;
- int status, ret;
+ uhci_softc_t *sc = arg;
+ int status;
+ int ack;
uhci_intr_info_t *ii;
- sc->sc_intrs++;
#if defined(USB_DEBUG)
- if (uhcidebug > 9) {
- printf("uhci_intr %p\n", sc);
+ if (uhcidebug > 15) {
+ DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev)));
uhci_dumpregs(sc);
}
#endif
- status = UREAD2(sc, UHCI_STS);
-#if defined(DIAGNOSTIC) && !defined(__OpenBSD__)
+
+#if defined(DIAGNOSTIC) && defined(__NetBSD__)
if (sc->sc_suspend != PWR_RESUME)
printf("uhci_intr: suspended sts=0x%x\n", status);
#endif
- ret = 0;
- if (status & UHCI_STS_USBINT) {
- UWRITE2(sc, UHCI_STS, UHCI_STS_USBINT); /* acknowledge */
- ret = 1;
- }
- if (status & UHCI_STS_USBEI) {
- UWRITE2(sc, UHCI_STS, UHCI_STS_USBEI); /* acknowledge */
- ret = 1;
- }
+
+ status = UREAD2(sc, UHCI_STS);
+ ack = 0;
+ if (status & UHCI_STS_USBINT)
+ ack |= UHCI_STS_USBINT;
+ if (status & UHCI_STS_USBEI)
+ ack |= UHCI_STS_USBEI;
if (status & UHCI_STS_RD) {
- UWRITE2(sc, UHCI_STS, UHCI_STS_RD); /* acknowledge */
+ ack |= UHCI_STS_RD;
printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
- ret = 1;
}
if (status & UHCI_STS_HSE) {
- UWRITE2(sc, UHCI_STS, UHCI_STS_HSE); /* acknowledge */
- printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
- ret = 1;
+ ack |= UHCI_STS_HSE;
+ printf("%s: host controller process error\n",
+ USBDEVNAME(sc->sc_bus.bdev));
}
if (status & UHCI_STS_HCPE) {
- UWRITE2(sc, UHCI_STS, UHCI_STS_HCPE); /* acknowledge */
- printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
- ret = 1;
+ ack |= UHCI_STS_HCPE;
+ printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
}
- if (status & UHCI_STS_HCH)
- printf("%s: controller halted\n", USBDEVNAME(sc->sc_bus.bdev));
- if (!ret)
- return 0;
+ if (status & UHCI_STS_HCH) {
+ /* no acknowledge needed */
+ printf("%s: host controller halted\n",
+ USBDEVNAME(sc->sc_bus.bdev));
+ }
+
+ if (ack) /* acknowledge the ints */
+ UWRITE2(sc, UHCI_STS, ack);
+ else /* nothing to acknowledge */
+ return (0);
+
+ sc->sc_bus.intr_context++;
+ sc->sc_bus.no_intrs++;
/*
* Interrupts on UHCI really suck. When the host controller
@@ -814,7 +880,10 @@ uhci_intr(p)
uhci_check_intr(sc, ii);
DPRINTFN(10, ("uhci_intr: exit\n"));
- return 1;
+
+ sc->sc_bus.intr_context--;
+
+ return (1);
}
/* Check for an interrupt. */
@@ -849,7 +918,7 @@ uhci_check_intr(sc, ii)
*/
if (LE(lstd->td.td_status) & UHCI_TD_ACTIVE) {
DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
- for (std = ii->stdstart; std != lstd; std = std->link.std){
+ 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)) ==
@@ -865,6 +934,7 @@ uhci_check_intr(sc, ii)
uhci_idone(ii);
}
+/* Called at splusb() */
void
uhci_idone(ii)
uhci_intr_info_t *ii;
@@ -875,18 +945,6 @@ uhci_idone(ii)
u_int32_t status;
int actlen;
-#ifdef USB_DEBUG
- DPRINTFN(10, ("uhci_idone: ii=%p ready\n", ii));
- if (uhcidebug > 10)
- uhci_dump_tds(ii->stdstart);
-#endif
-
- if (reqh->status == USBD_CANCELLED ||
- reqh->status == USBD_TIMEOUT) {
- DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh));
- return;
- }
-
#ifdef DIAGNOSTIC
{
int s = splhigh();
@@ -900,6 +958,49 @@ uhci_idone(ii)
}
#endif
+ if (reqh->status == USBD_CANCELLED ||
+ reqh->status == USBD_TIMEOUT) {
+ DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh));
+ return;
+ }
+
+ if (reqh->nframes) {
+ /* 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;
+ actlen = 0;
+ n = reqh->hcprivint;
+ for (i = 0; i < nframes; i++) {
+ std = stds[n];
+#ifdef USB_DEBUG
+ if (uhcidebug > 5) {
+ DPRINTFN(-1,("uhci_idone: isoc TD %d\n", i));
+ uhci_dump_td(std);
+ }
+#endif
+ if (++n >= UHCI_VFRAMELIST_COUNT)
+ n = 0;
+ status = LE(std->td.td_status);
+ 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);
+ return;
+ }
+
+#ifdef USB_DEBUG
+ DPRINTFN(10, ("uhci_idone: ii=%p ready\n", ii));
+ if (uhcidebug > 10)
+ uhci_dump_tds(ii->stdstart);
+#endif
+
/* The transfer is done, compute actual length and status. */
/* XXX Is this correct for control xfers? */
actlen = 0;
@@ -949,7 +1050,10 @@ uhci_timeout(addr)
uhci_intr_info_t *ii = 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--;
}
/*
@@ -1070,7 +1174,7 @@ uhci_alloc_std(sc)
if (!sc->sc_freetds) {
DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
- r = usb_allocmem(sc->sc_dmatag, UHCI_STD_SIZE * UHCI_STD_CHUNK,
+ r = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
UHCI_TD_ALIGN, &dma);
if (r != USBD_NORMAL_COMPLETION)
return (0);
@@ -1116,7 +1220,7 @@ uhci_alloc_sqh(sc)
if (!sc->sc_freeqhs) {
DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
- r = usb_allocmem(sc->sc_dmatag, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
+ r = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
UHCI_QH_ALIGN, &dma);
if (r != USBD_NORMAL_COMPLETION)
return 0;
@@ -1263,16 +1367,15 @@ usbd_status
uhci_device_bulk_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (uhci_device_bulk_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (uhci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1283,58 +1386,52 @@ uhci_device_bulk_start(reqh)
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 *xfer, *xferend;
+ uhci_soft_td_t *data, *dataend;
uhci_soft_qh_t *sqh;
- usb_dma_t *dmap;
usbd_status r;
- int len, isread;
+ int len, isread, endpt;
int s;
- DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p buf=%p len=%d "
- "flags=%d\n",
- reqh, reqh->buffer, reqh->length, reqh->flags));
+ DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n",
+ reqh, reqh->length, reqh->flags));
- if (reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (reqh->rqflags & URQ_REQUEST)
panic("uhci_device_bulk_transfer: a request\n");
+#endif
len = reqh->length;
- dmap = &upipe->u.bulk.datadma;
- isread = reqh->pipe->endpoint->edesc->bEndpointAddress & UE_IN;
+ endpt = reqh->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 = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto ret1;
r = uhci_alloc_std_chain(upipe, sc, len, isread,
reqh->flags & USBD_SHORT_XFER_OK,
- dmap, &xfer, &xferend);
+ &reqh->dmabuf, &data, &dataend);
if (r != USBD_NORMAL_COMPLETION)
- goto ret2;
- xferend->td.td_status |= LE(UHCI_TD_IOC);
-
- if (!isread && len != 0)
- memcpy(KERNADDR(dmap), reqh->buffer, len);
+ return (r);
+ dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef USB_DEBUG
if (uhcidebug > 8) {
- printf("uhci_device_bulk_transfer: xfer(1)\n");
- uhci_dump_tds(xfer);
+ DPRINTF(("uhci_device_bulk_transfer: data(1)\n"));
+ uhci_dump_tds(data);
}
#endif
/* Set up interrupt info. */
ii->reqh = reqh;
- ii->stdstart = xfer;
- ii->stdend = xferend;
+ ii->stdstart = data;
+ ii->stdend = dataend;
#ifdef DIAGNOSTIC
ii->isdone = 0;
#endif
- sqh->elink = xfer;
- sqh->qh.qh_elink = LE(xfer->physaddr);
+ sqh->elink = data;
+ sqh->qh.qh_elink = LE(data->physaddr);
sqh->intr_info = ii;
s = splusb();
@@ -1342,15 +1439,15 @@ uhci_device_bulk_start(reqh)
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), ii->timeout_handle);
+ usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout),
+ ii->timeout_handle);
}
splx(s);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
- printf("uhci_device_bulk_transfer: xfer(2)\n");
- uhci_dump_tds(xfer);
+ DPRINTF(("uhci_device_bulk_transfer: data(2)\n"));
+ uhci_dump_tds(data);
}
#endif
@@ -1358,12 +1455,6 @@ uhci_device_bulk_start(reqh)
uhci_waitintr(sc, reqh);
return (USBD_IN_PROGRESS);
-
- ret2:
- if (len != 0)
- usb_freemem(sc->sc_dmatag, dmap);
- ret1:
- return (r);
}
/* Abort a device bulk request. */
@@ -1392,18 +1483,18 @@ uhci_abort_req(reqh, status)
/* make hardware ignore it, */
for (std = ii->stdstart; std != 0; std = std->link.std)
- std->td.td_status &= LE(~UHCI_TD_ACTIVE);
+ std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
reqh->hcpriv = ii;
/* make sure hardware has completed, */
- if (curproc) {
+ if (reqh->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);
+ } else {
usb_delay_ms(reqh->pipe->device->bus, 1);
/* and call final part of interrupt handler. */
uhci_abort_req_end(reqh);
- } else {
- /* We have no process context, so we can't use tsleep(). */
- timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
}
}
@@ -1437,16 +1528,15 @@ usbd_status
uhci_device_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (uhci_device_ctrl_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1456,8 +1546,10 @@ uhci_device_ctrl_start(reqh)
uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
usbd_status r;
- if (!reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (!(reqh->rqflags & URQ_REQUEST))
panic("uhci_device_ctrl_transfer: not a request\n");
+#endif
r = uhci_device_request(reqh);
if (r != USBD_NORMAL_COMPLETION)
@@ -1472,16 +1564,15 @@ usbd_status
uhci_device_intr_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (uhci_device_intr_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (uhci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -1492,39 +1583,30 @@ uhci_device_intr_start(reqh)
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 *xfer, *xferend;
+ uhci_soft_td_t *data, *dataend;
uhci_soft_qh_t *sqh;
- usb_dma_t *dmap;
usbd_status r;
- int len, i;
- int s;
+ int i, s;
- DPRINTFN(3, ("uhci_device_intr_transfer: reqh=%p buf=%p len=%d "
- "flags=%d\n",
- reqh, reqh->buffer, reqh->length, reqh->flags));
+ DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n",
+ reqh, reqh->length, reqh->flags));
- if (reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (reqh->rqflags & URQ_REQUEST)
panic("uhci_device_intr_transfer: a request\n");
+#endif
- len = reqh->length;
- dmap = &upipe->u.intr.datadma;
- if (len == 0)
- return (USBD_INVAL); /* XXX should it be? */
-
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto ret1;
- r = uhci_alloc_std_chain(upipe, sc, len, 1,
+ r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
reqh->flags & USBD_SHORT_XFER_OK,
- dmap, &xfer, &xferend);
+ &reqh->dmabuf, &data, &dataend);
if (r != USBD_NORMAL_COMPLETION)
- goto ret2;
- xferend->td.td_status |= LE(UHCI_TD_IOC);
+ return (r);
+ dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
- printf("uhci_device_intr_transfer: xfer(1)\n");
- uhci_dump_tds(xfer);
+ DPRINTF(("uhci_device_intr_transfer: data(1)\n"));
+ uhci_dump_tds(data);
uhci_dump_qh(upipe->u.intr.qhs[0]);
}
#endif
@@ -1532,8 +1614,8 @@ uhci_device_intr_start(reqh)
s = splusb();
/* Set up interrupt info. */
ii->reqh = reqh;
- ii->stdstart = xfer;
- ii->stdend = xferend;
+ ii->stdstart = data;
+ ii->stdend = dataend;
#ifdef DIAGNOSTIC
ii->isdone = 0;
#endif
@@ -1542,26 +1624,20 @@ uhci_device_intr_start(reqh)
upipe->u.intr.qhs[0]));
for (i = 0; i < upipe->u.intr.npoll; i++) {
sqh = upipe->u.intr.qhs[i];
- sqh->elink = xfer;
- sqh->qh.qh_elink = LE(xfer->physaddr);
+ sqh->elink = data;
+ sqh->qh.qh_elink = LE(data->physaddr);
}
splx(s);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
- printf("uhci_device_intr_transfer: xfer(2)\n");
- uhci_dump_tds(xfer);
+ DPRINTF(("uhci_device_intr_transfer: data(2)\n"));
+ uhci_dump_tds(data);
uhci_dump_qh(upipe->u.intr.qhs[0]);
}
#endif
return (USBD_IN_PROGRESS);
-
- ret2:
- if (len != 0)
- usb_freemem(sc->sc_dmatag, dmap);
- ret1:
- return (r);
}
/* Abort a device control request. */
@@ -1645,9 +1721,8 @@ uhci_device_request(reqh)
int addr = dev->address;
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
uhci_intr_info_t *ii = upipe->iinfo;
- uhci_soft_td_t *setup, *xfer, *stat, *next, *xferend;
+ uhci_soft_td_t *setup, *data, *stat, *next, *dataend;
uhci_soft_qh_t *sqh;
- usb_dma_t *dmap;
int len;
u_int32_t ls;
usbd_status r;
@@ -1667,30 +1742,24 @@ uhci_device_request(reqh)
setup = upipe->u.ctl.setup;
stat = upipe->u.ctl.stat;
sqh = upipe->u.ctl.sqh;
- dmap = &upipe->u.ctl.datadma;
/* Set up data transaction */
if (len != 0) {
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- goto ret1;
upipe->nexttoggle = 1;
r = uhci_alloc_std_chain(upipe, sc, len, isread,
reqh->flags & USBD_SHORT_XFER_OK,
- dmap, &xfer, &xferend);
+ &reqh->dmabuf, &data, &dataend);
if (r != USBD_NORMAL_COMPLETION)
- goto ret2;
- next = xfer;
- xferend->link.std = stat;
- xferend->td.td_link = LE(stat->physaddr);
+ return (r);
+ next = data;
+ dataend->link.std = stat;
+ dataend->td.td_link = LE(stat->physaddr);
} else {
next = stat;
}
upipe->u.ctl.length = len;
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
- if (!isread && len != 0)
- memcpy(KERNADDR(dmap), reqh->buffer, len);
setup->link.std = next;
setup->td.td_link = LE(next->physaddr);
@@ -1709,7 +1778,7 @@ uhci_device_request(reqh)
#ifdef USB_DEBUG
if (uhcidebug > 20) {
- printf("uhci_device_request: before transfer\n");
+ DPRINTF(("uhci_device_request: before transfer\n"));
uhci_dump_tds(setup);
}
#endif
@@ -1736,7 +1805,7 @@ uhci_device_request(reqh)
uhci_soft_qh_t *sxqh;
int maxqh = 0;
uhci_physaddr_t link;
- printf("uhci_enter_ctl_q: follow from [0]\n");
+ DPRINTF(("uhci_enter_ctl_q: follow from [0]\n"));
for (std = sc->sc_vframes[0].htd, link = 0;
(link & UHCI_PTR_Q) == 0;
std = std->link.std) {
@@ -1750,7 +1819,7 @@ uhci_device_request(reqh)
uhci_dump_qh(xqh);
uhci_dump_qh(sxqh);
}
- printf("Enqueued QH:\n");
+ DPRINTF(("Enqueued QH:\n"));
uhci_dump_qh(sqh);
uhci_dump_tds(sqh->elink);
}
@@ -1762,44 +1831,172 @@ uhci_device_request(reqh)
splx(s);
return (USBD_NORMAL_COMPLETION);
-
- ret2:
- if (len != 0)
- usb_freemem(sc->sc_dmatag, dmap);
- ret1:
- return (r);
}
usbd_status
uhci_device_isoc_transfer(reqh)
usbd_request_handle reqh;
{
+ usbd_status r;
+
+ DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh));
+
+ /* Put it on our queue, */
+ r = usb_insert_transfer(reqh);
+
+ /* bail out on error, */
+ if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS)
+ return (r);
+
+ /* XXX should check inuse here */
+
+ /* insert into schedule, */
+ uhci_device_isoc_enter(reqh);
+
+ /* 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));
+
+ return (r);
+}
+
+void
+uhci_device_isoc_enter(reqh)
+ usbd_request_handle reqh;
+{
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
-#ifdef USB_DEBUG
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
+ struct iso *iso = &upipe->u.iso;
+ uhci_soft_td_t *std;
+ u_int32_t buf, len, status;
+ int s, i, next, nframes;
+
+ DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p "
+ "nframes=%d\n",
+ iso->inuse, iso->next, reqh, reqh->nframes));
+
+ if (reqh->status == USBD_IN_PROGRESS) {
+ /* This request has already been entered into the frame list */
+ }
+
+#ifdef DIAGNOSTIC
+ if (iso->inuse >= UHCI_VFRAMELIST_COUNT)
+ printf("uhci_device_isoc_enter: overflow!\n");
#endif
- DPRINTFN(1,("uhci_device_isoc_transfer: sc=%p\n", sc));
- if (upipe->u.iso.bufsize == 0)
- return (USBD_INVAL);
+ next = iso->next;
+ if (next == -1) {
+ /* Not in use yet, schedule it a few frames ahead. */
+ next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT;
+ DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next));
+ }
+
+ reqh->status = USBD_IN_PROGRESS;
+ reqh->hcprivint = next;
- /* XXX copy data */
- return (USBD_XXX);
+ buf = DMAADDR(&reqh->dmabuf);
+ status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
+ UHCI_TD_ACTIVE |
+ UHCI_TD_IOS));
+ nframes = reqh->nframes;
+ s = splusb();
+ for (i = 0; i < nframes; i++) {
+ std = iso->stds[next];
+ if (++next >= UHCI_VFRAMELIST_COUNT)
+ next = 0;
+ len = reqh->frlengths[i];
+ std->td.td_buffer = LE(buf);
+ if (i == nframes - 1)
+ status |= LE(UHCI_TD_IOC);
+ std->td.td_status = status;
+ std->td.td_token &= LE(~UHCI_TD_MAXLEN_MASK);
+ std->td.td_token |= LE(UHCI_TD_SET_MAXLEN(len));
+#ifdef USB_DEBUG
+ if (uhcidebug > 5) {
+ DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i));
+ uhci_dump_td(std);
+ }
+#endif
+ buf += len;
+ }
+ iso->next = next;
+ iso->inuse += reqh->nframes;
+
+ splx(s);
}
usbd_status
uhci_device_isoc_start(reqh)
usbd_request_handle reqh;
{
- return (USBD_XXX);
+ struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->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;
+
+#ifdef DIAGNOSTIC
+ if (reqh->status != USBD_IN_PROGRESS)
+ printf("uhci_device_isoc_start: not in progress %p\n", reqh);
+#endif
+
+ /* Find the last TD */
+ i = reqh->hcprivint + reqh->nframes;
+ if (i >= UHCI_VFRAMELIST_COUNT)
+ i -= UHCI_VFRAMELIST_COUNT;
+ end = upipe->u.iso.stds[i];
+
+ s = splusb();
+
+ /* Set up interrupt info. */
+ ii->reqh = reqh;
+ ii->stdstart = end;
+ ii->stdend = end;
+#ifdef DIAGNOSTIC
+ ii->isdone = 0;
+#endif
+ LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
+
+ splx(s);
+
+ return (USBD_IN_PROGRESS);
}
void
uhci_device_isoc_abort(reqh)
usbd_request_handle reqh;
{
- /* XXX Can't abort this. */
+ struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->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;
+
+ /* make hardware ignore it, */
+ nframes = reqh->nframes;
+ n = reqh->hcprivint;
+ for (i = 0; i < nframes; i++) {
+ std = stds[n];
+ std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
+ if (++n >= UHCI_VFRAMELIST_COUNT)
+ n = 0;
+ }
+
+ reqh->hcpriv = ii;
+
+ /* make sure hardware has completed, */
+ if (reqh->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);
+ } else {
+ usb_delay_ms(reqh->pipe->device->bus, 1);
+ /* and call final part of interrupt handler. */
+ uhci_abort_req_end(reqh);
+ }
}
void
@@ -1809,6 +2006,7 @@ uhci_device_isoc_close(pipe)
struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
+ uhci_soft_td_t *std, *vstd;
struct iso *iso;
int i;
@@ -1826,10 +2024,8 @@ uhci_device_isoc_close(pipe)
uhci_lock_frames(sc);
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
- uhci_soft_td_t *std, *vstd;
-
std = iso->stds[i];
- for (vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
+ for (vstd = sc->sc_vframes[i].htd;
vstd && vstd->link.std != std;
vstd = vstd->link.std)
;
@@ -1845,78 +2041,46 @@ uhci_device_isoc_close(pipe)
}
uhci_unlock_frames(sc);
- for (i = 0; i < iso->nbuf; i++)
- usb_freemem(sc->sc_dmatag, &iso->bufs[i]);
free(iso->stds, M_USBHC);
- free(iso->bufs, M_USBHC);
-
- /* XXX what else? */
}
usbd_status
-uhci_device_isoc_setbuf(pipe, bufsize, nbuf)
+uhci_setup_isoc(pipe)
usbd_pipe_handle pipe;
- u_int bufsize;
- u_int nbuf;
{
struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
int addr = upipe->pipe.device->address;
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
- int rd = upipe->pipe.endpoint->edesc->bEndpointAddress & UE_IN;
+ int rd = UE_GET_DIR(endpt) == UE_DIR_IN;
+ uhci_soft_td_t *std, *vstd;
+ u_int32_t token;
struct iso *iso;
int i;
- usbd_status r;
-
- /*
- * For simplicity the number of buffers must fit nicely in the frame
- * list.
- */
- if (UHCI_VFRAMELIST_COUNT % nbuf != 0)
- return (USBD_INVAL);
iso = &upipe->u.iso;
- iso->bufsize = bufsize;
- iso->nbuf = nbuf;
-
- /* Allocate memory for buffers. */
- iso->bufs = malloc(nbuf * sizeof(usb_dma_t), M_USBHC, M_WAITOK);
iso->stds = malloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *),
M_USBHC, M_WAITOK);
- for (i = 0; i < nbuf; i++) {
- r = usb_allocmem(sc->sc_dmatag, bufsize, 0, &iso->bufs[i]);
- if (r != USBD_NORMAL_COMPLETION) {
- nbuf = i;
- goto bad1;
- }
- }
+ token = LE(rd ? UHCI_TD_IN (0, endpt, addr, 0) :
+ UHCI_TD_OUT(0, endpt, addr, 0));
- /* Allocate the TDs. */
+ /* Allocate the TDs and mark as inactive; */
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
- iso->stds[i] = uhci_alloc_std(sc);
- if (iso->stds[i] == 0)
- goto bad2;
+ std = uhci_alloc_std(sc);
+ if (std == 0)
+ goto bad;
+ std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
+ std->td.td_token = token;
+ iso->stds[i] = std;
}
- /* XXX check schedule */
-
- /* XXX interrupts */
-
- /* Insert TDs into schedule, all marked inactive. */
+ /* Insert TDs into schedule. */
uhci_lock_frames(sc);
for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
- uhci_soft_td_t *std, *vstd;
-
std = iso->stds[i];
- std->td.td_status = LE(UHCI_TD_IOS); /* iso, inactive */
- std->td.td_token =
- LE(rd ? UHCI_TD_IN (0, endpt, addr, 0) :
- UHCI_TD_OUT(0, endpt, addr, 0));
- std->td.td_buffer = LE(DMAADDR(&iso->bufs[i % nbuf]));
-
- vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
+ vstd = sc->sc_vframes[i].htd;
std->link = vstd->link;
std->td.td_link = vstd->td.td_link;
vstd->link.std = std;
@@ -1924,16 +2088,15 @@ uhci_device_isoc_setbuf(pipe, bufsize, nbuf)
}
uhci_unlock_frames(sc);
+ iso->next = -1;
+ iso->inuse = 0;
+
return (USBD_NORMAL_COMPLETION);
- bad2:
+ bad:
while (--i >= 0)
uhci_free_std(sc, iso->stds[i]);
- bad1:
- for (i = 0; i < nbuf; i++)
- usb_freemem(sc->sc_dmatag, &iso->bufs[i]);
free(iso->stds, M_USBHC);
- free(iso->bufs, M_USBHC);
return (USBD_NOMEM);
}
@@ -1941,7 +2104,14 @@ void
uhci_device_isoc_done(reqh)
usbd_request_handle reqh;
{
- /*uhci_intr_info_t *ii = v;*/
+ uhci_intr_info_t *ii = reqh->hcpriv;
+
+ DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen));
+
+ /* Turn off the interrupt since it is active even if the TD is not. */
+ ii->stdend->td.td_status &= LE(~UHCI_TD_IOC);
+
+ LIST_REMOVE(ii, list); /* remove from active list */
}
void
@@ -1951,14 +2121,11 @@ uhci_device_intr_done(reqh)
uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
- usb_dma_t *dma;
uhci_soft_qh_t *sqh;
int i, npoll;
DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen));
- dma = &upipe->u.intr.datadma;
- memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
npoll = upipe->u.intr.npoll;
for(i = 0; i < npoll; i++) {
sqh = upipe->u.intr.qhs[i];
@@ -1969,34 +2136,33 @@ uhci_device_intr_done(reqh)
/* XXX Wasteful. */
if (reqh->pipe->repeat) {
- uhci_soft_td_t *xfer, *xferend;
+ 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,
- dma, &xfer, &xferend);
- xferend->td.td_status |= LE(UHCI_TD_IOC);
+ &reqh->dmabuf, &data, &dataend);
+ dataend->td.td_status |= LE(UHCI_TD_IOC);
#ifdef USB_DEBUG
if (uhcidebug > 10) {
- printf("uhci_device_intr_done: xfer(1)\n");
- uhci_dump_tds(xfer);
+ DPRINTF(("uhci_device_intr_done: data(1)\n"));
+ uhci_dump_tds(data);
uhci_dump_qh(upipe->u.intr.qhs[0]);
}
#endif
- ii->stdstart = xfer;
- ii->stdend = xferend;
+ ii->stdstart = data;
+ ii->stdend = dataend;
#ifdef DIAGNOSTIC
ii->isdone = 0;
#endif
for (i = 0; i < npoll; i++) {
sqh = upipe->u.intr.qhs[i];
- sqh->elink = xfer;
- sqh->qh.qh_elink = LE(xfer->physaddr);
+ sqh->elink = data;
+ sqh->qh.qh_elink = LE(data->physaddr);
}
} else {
- usb_freemem(sc->sc_dmatag, dma);
ii->stdstart = 0; /* mark as inactive */
}
}
@@ -2009,11 +2175,9 @@ uhci_device_ctrl_done(reqh)
uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
- u_int len = upipe->u.ctl.length;
- usb_dma_t *dma;
#ifdef DIAGNOSTIC
- if (!reqh->isreq)
+ if (!(reqh->rqflags & URQ_REQUEST))
panic("uhci_ctrl_done: not a request\n");
#endif
@@ -2021,13 +2185,9 @@ uhci_device_ctrl_done(reqh)
uhci_remove_ctrl(sc, upipe->u.ctl.sqh);
- if (len != 0) {
- dma = &upipe->u.ctl.datadma;
- if (reqh->request.bmRequestType & UT_READ)
- memcpy(reqh->buffer, KERNADDR(dma), len);
+ if (upipe->u.ctl.length != 0)
uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
- usb_freemem(sc->sc_dmatag, dma);
- }
+
DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen));
}
@@ -2039,21 +2199,14 @@ uhci_device_bulk_done(reqh)
uhci_intr_info_t *ii = reqh->hcpriv;
uhci_softc_t *sc = ii->sc;
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
- u_int datalen = upipe->u.bulk.length;
- usb_dma_t *dma;
LIST_REMOVE(ii, list); /* remove from active list */
uhci_remove_bulk(sc, upipe->u.bulk.sqh);
- /* copy the data from dma memory to userland storage */
- dma = &upipe->u.bulk.datadma;
- if (upipe->u.bulk.isread)
- memcpy(reqh->buffer, KERNADDR(dma), datalen);
uhci_free_std_chain(sc, ii->stdstart, 0);
- usb_freemem(sc->sc_dmatag, dma);
- DPRINTFN(4, ("uhci_bulk_done: length=%d\n", reqh->actlen));
+ DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen));
}
/* Add interrupt QH, called with vflock. */
@@ -2091,7 +2244,7 @@ uhci_remove_intr(sc, n, sqh)
for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
if (LE(pqh->qh.qh_hlink) & UHCI_PTR_T) {
- printf("uhci_remove_intr: QH not found\n");
+ DPRINTF(("uhci_remove_intr: QH not found\n"));
return;
}
#else
@@ -2187,7 +2340,7 @@ uhci_open(pipe)
case USB_CONTROL_ENDPOINT:
pipe->methods = &uhci_root_ctrl_methods;
break;
- case UE_IN | UHCI_INTR_ENDPT:
+ case UE_DIR_IN | UHCI_INTR_ENDPT:
pipe->methods = &uhci_root_intr_methods;
break;
default:
@@ -2214,7 +2367,7 @@ uhci_open(pipe)
uhci_free_std(sc, upipe->u.ctl.setup);
goto bad;
}
- r = usb_allocmem(sc->sc_dmatag,
+ r = usb_allocmem(&sc->sc_bus,
sizeof(usb_device_request_t),
0, &upipe->u.ctl.reqdma);
if (r != USBD_NORMAL_COMPLETION) {
@@ -2229,8 +2382,7 @@ uhci_open(pipe)
return (uhci_device_setintr(sc, upipe, ed->bInterval));
case UE_ISOCHRONOUS:
pipe->methods = &uhci_device_isoc_methods;
- upipe->u.iso.nbuf = 0;
- return (USBD_NORMAL_COMPLETION);
+ return (uhci_setup_isoc(pipe));
case UE_BULK:
pipe->methods = &uhci_device_bulk_methods;
upipe->u.bulk.sqh = uhci_alloc_sqh(sc);
@@ -2290,7 +2442,7 @@ usb_interface_descriptor_t uhci_ifcd = {
usb_endpoint_descriptor_t uhci_endpd = {
USB_ENDPOINT_DESCRIPTOR_SIZE,
UDESC_ENDPOINT,
- UE_IN | UHCI_INTR_ENDPT,
+ UE_DIR_IN | UHCI_INTR_ENDPT,
UE_INTERRUPT,
{8},
255
@@ -2333,16 +2485,15 @@ usbd_status
uhci_root_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (uhci_root_ctrl_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
usbd_status
@@ -2353,14 +2504,15 @@ uhci_root_ctrl_start(reqh)
usb_device_request_t *req;
void *buf;
int port, x;
- int len, value, index, status, change, l, totlen = 0;
+ int s, len, value, index, status, change, l, totlen = 0;
usb_port_status_t ps;
usbd_status r;
- if (!reqh->isreq)
+#ifdef DIAGNOSTIC
+ if (!(reqh->rqflags & URQ_REQUEST))
panic("uhci_root_ctrl_transfer: not a request\n");
+#endif
req = &reqh->request;
- buf = reqh->buffer;
DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n",
req->bmRequestType, req->bRequest));
@@ -2368,6 +2520,14 @@ uhci_root_ctrl_start(reqh)
len = UGETW(req->wLength);
value = UGETW(req->wValue);
index = UGETW(req->wIndex);
+
+ if (len != 0)
+ buf = KERNADDR(&reqh->dmabuf);
+#ifdef DIAGNOSTIC
+ else
+ buf = 0;
+#endif
+
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
@@ -2663,7 +2823,9 @@ uhci_root_ctrl_start(reqh)
ret:
reqh->status = r;
reqh->hcpriv = 0;
+ s = splusb();
usb_transfer_complete(reqh);
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -2701,16 +2863,15 @@ usbd_status
uhci_root_intr_transfer(reqh)
usbd_request_handle reqh;
{
- int s;
usbd_status r;
- s = splusb();
+ /* Insert last in queue. */
r = usb_insert_transfer(reqh);
- splx(s);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- else
- return (uhci_root_intr_start(reqh));
+
+ /* Pipe isn't running, start first */
+ return (uhci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
}
/* Start a transfer on the root interrupt pipe */
@@ -2720,23 +2881,9 @@ uhci_root_intr_start(reqh)
{
usbd_pipe_handle pipe = reqh->pipe;
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
- struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
- usb_dma_t *dmap;
- usbd_status r;
- int len;
-
- DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p buf=%p len=%d "
- "flags=%d\n",
- reqh, reqh->buffer, reqh->length, reqh->flags));
- len = reqh->length;
- dmap = &upipe->u.intr.datadma;
- if (len == 0)
- return (USBD_INVAL); /* XXX should it be? */
-
- r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n",
+ reqh, reqh->length, reqh->flags));
sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval);
usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index 6e3215ba2e3..1a07dce5efe 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhcivar.h,v 1.3 1999/08/27 09:00:29 fgsch Exp $ */
-/* $NetBSD: uhcivar.h,v 1.12 1999/08/22 23:41:00 augustss Exp $ */
+/* $OpenBSD: uhcivar.h,v 1.4 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: uhcivar.h,v 1.14 1999/09/15 10:25:31 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -133,7 +133,6 @@ typedef struct uhci_softc {
#if defined(__NetBSD__) || defined(__OpenBSD__)
void *sc_ih; /* interrupt vectoring */
- bus_dma_tag_t sc_dmatag; /* DMA tag */
/* XXX should keep track of all DMA memory */
#endif /* defined(__FreeBSD__) */
@@ -157,7 +156,6 @@ typedef struct uhci_softc {
char sc_suspend;
usbd_request_handle sc_has_timo;
- int sc_intrs;
LIST_HEAD(, uhci_intr_info) sc_intrhead;
/* Info for the root hub interrupt channel. */
@@ -169,13 +167,15 @@ typedef struct uhci_softc {
char sc_vendor[16];
int sc_id_vendor;
+
+ void *sc_powerhook;
+ device_ptr_t sc_child;
} uhci_softc_t;
usbd_status uhci_init __P((uhci_softc_t *));
int uhci_intr __P((void *));
-#if 0
-void uhci_reset __P((void *));
-#endif
+int uhci_detach __P((device_ptr_t, int));
+int uhci_activate __P((device_ptr_t, enum devact));
#ifdef USB_DEBUG
#define DPRINTF(x) if (uhcidebug) printf x
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index a626d8d0d59..ca1ba498cd3 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhid.c,v 1.4 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: uhid.c,v 1.21 1999/08/23 22:55:14 augustss Exp $ */
+/* $OpenBSD: uhid.c,v 1.5 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: uhid.c,v 1.24 1999/09/05 19:32:18 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -82,7 +82,7 @@ int uhiddebug = 0;
#endif
struct uhid_softc {
- bdevice sc_dev; /* base device */
+ USBBASEDEVICE sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -203,11 +203,11 @@ USB_ATTACH(uhid)
" bInterval=%d\n",
ed->bLength, ed->bDescriptorType,
ed->bEndpointAddress & UE_ADDR,
- ed->bEndpointAddress & UE_IN ? "in" : "out",
+ UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
ed->bmAttributes & UE_XFERTYPE,
UGETW(ed->wMaxPacketSize), ed->bInterval));
- if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
+ if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
sc->sc_dying = 1;
@@ -240,7 +240,7 @@ USB_ATTACH(uhid)
int
uhid_activate(self, act)
- bdevice *self;
+ device_ptr_t self;
enum devact act;
{
struct uhid_softc *sc = (struct uhid_softc *)self;
@@ -259,7 +259,7 @@ uhid_activate(self, act)
int
uhid_detach(self, flags)
- bdevice *self;
+ device_ptr_t self;
int flags;
{
struct uhid_softc *sc = (struct uhid_softc *)self;
@@ -278,7 +278,7 @@ uhid_detach(self, flags)
/* Wake everyone */
wakeup(&sc->sc_q);
/* Wait for processes to go away. */
- usb_detach_wait(&sc->sc_dev);
+ usb_detach_wait(USBDEV(sc->sc_dev));
}
splx(s);
}
@@ -485,7 +485,7 @@ uhidread(dev, uio, flag)
sc->sc_refcnt++;
error = uhid_do_read(sc, uio, flag);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
@@ -537,7 +537,7 @@ uhidwrite(dev, uio, flag)
sc->sc_refcnt++;
error = uhid_do_write(sc, uio, flag);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
@@ -629,7 +629,7 @@ uhidioctl(dev, cmd, addr, flag, p)
sc->sc_refcnt++;
error = uhid_do_ioctl(sc, cmd, addr, flag, p);
if (--sc->sc_refcnt < 0)
- usb_detach_wakeup(&sc->sc_dev);
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
return (error);
}
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 0d0876b51fa..4c3352028cb 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhub.c,v 1.4 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: uhub.c,v 1.23 1999/08/23 22:55:14 augustss Exp $ */
+/* $OpenBSD: uhub.c,v 1.5 1999/09/27 18:03:55 fgsch Exp $ */
+/* $NetBSD: uhub.c,v 1.29 1999/09/15 10:25:31 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -54,6 +54,8 @@
#endif
#include <sys/proc.h>
+#include <machine/bus.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -69,7 +71,7 @@ extern int usbdebug;
#endif
struct uhub_softc {
- bdevice sc_dev; /* base device */
+ USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_hub; /* USB device */
usbd_pipe_handle sc_ipipe; /* interrupt pipe */
u_int8_t sc_status[1]; /* XXX more ports */
@@ -77,7 +79,6 @@ struct uhub_softc {
};
usbd_status uhub_init_port __P((struct usbd_port *));
-void uhub_disconnect_port __P((struct usbd_port *up));
usbd_status uhub_explore __P((usbd_device_handle hub));
void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
@@ -181,8 +182,7 @@ USB_ATTACH(uhub)
if (!dev->self_powered && dev->powersrc->parent &&
!dev->powersrc->parent->self_powered) {
printf("%s: bus powered hub connected to bus powered hub, "
- "ignored\n",
- USBDEVNAME(sc->sc_dev));
+ "ignored\n", USBDEVNAME(sc->sc_dev));
goto bad;
}
@@ -377,7 +377,7 @@ uhub_explore(dev)
DPRINTF(("uhub_explore: device %d disappeared "
"on port %d\n",
up->device->address, port));
- uhub_disconnect_port(up);
+ usb_disconnect_port(up);
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
@@ -396,7 +396,7 @@ uhub_explore(dev)
continue;
/* Get device info and set its address. */
- r = usbd_new_device(&sc->sc_dev, dev->bus,
+ r = usbd_new_device(USBDEV(sc->sc_dev), dev->bus,
dev->depth + 1, status & UPS_LOW_SPEED,
port, up);
/* XXX retry a few times? */
@@ -432,71 +432,29 @@ uhub_explore(dev)
return (USBD_NORMAL_COMPLETION);
}
-/*
- * The general mechanism for detaching drivers works as follows: Each
- * driver is responsible for maintaining a reference count on the
- * number of outstanding references to its softc (e.g. from
- * processing hanging in a read or write). The detach method of the
- * driver decrements this counter and flags in the softc that the
- * driver is dying and then wakes any sleepers. It then sleeps on the
- * softc. Each place that can sleep must maintain the reference
- * count. When the reference count drops to -1 (0 is the normal value
- * of the reference count) the a wakeup on the softc is performed
- * signaling to the detach waiter that all references are gone.
- */
-
-/*
- * Called from process context when we discover that a port has
- * been disconnected.
- */
-void
-uhub_disconnect_port(up)
- struct usbd_port *up;
-{
- usbd_device_handle dev = up->device;
- char *hubname;
- int i;
-
- DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
- up, dev, up->portno));
-
- if (!dev->cdesc) {
- /* Partially attached device, just drop it. */
- dev->bus->devices[dev->address] = 0;
- up->device = 0;
- return;
- }
-
- hubname = USBDEVNAME(*up->parent->subdevs[0]);
- for (i = 0; dev->subdevs[i]; i++) {
- printf("%s: at %s port %d (addr %d) disconnected\n",
- USBDEVNAME(*dev->subdevs[i]), hubname,
- up->portno, dev->address);
- config_detach(dev->subdevs[i], DETACH_FORCE);
- }
-
- dev->bus->devices[dev->address] = 0;
- up->device = 0;
- usb_free_device(dev);
-
-#if defined(__FreeBSD__)
- device_delete_child(
- device_get_parent(((struct softc *)dev->softc)->sc_dev),
- ((struct softc *)dev->softc)->sc_dev);
-#endif
-}
-
int
uhub_activate(self, act)
- bdevice *self;
+ device_ptr_t self;
enum devact act;
{
+ struct uhub_softc *sc = (struct uhub_softc *)self;
+ usbd_device_handle devhub = sc->sc_hub;
+ int nports, p, i;
+
switch (act) {
case DVACT_ACTIVATE:
return (EOPNOTSUPP);
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) {
+ for (i = 0; dev->subdevs[i]; i++)
+ config_deactivate(dev->subdevs[i]);
+ }
+ }
break;
}
return (0);
@@ -508,7 +466,7 @@ uhub_activate(self, act)
*/
int
uhub_detach(self, flags)
- bdevice *self;
+ device_ptr_t self;
int flags;
{
struct uhub_softc *sc = (struct uhub_softc *)self;
@@ -530,7 +488,7 @@ uhub_detach(self, flags)
for(p = 0; p < nports; p++) {
rup = &dev->hub->ports[p];
if (rup->device)
- uhub_disconnect_port(rup);
+ usb_disconnect_port(rup);
}
free(dev->hub, M_USBDEV);
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 6846597930b..8840397dec9 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb.c,v 1.4 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: usb.c,v 1.17 1999/08/17 16:06:21 augustss Exp $ */
+/* $OpenBSD: usb.c,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb.c,v 1.24 1999/09/15 21:10:11 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -58,6 +58,7 @@
#include <sys/uio.h>
#include <sys/conf.h>
#endif
+#include <sys/conf.h>
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/select.h>
@@ -74,6 +75,8 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
#include "usb_if.h"
#endif /* defined(__FreeBSD__) */
+#include <machine/bus.h>
+
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_quirks.h>
@@ -83,30 +86,29 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
int usbdebug = 0;
int uhcidebug;
int ohcidebug;
+int usb_noexplore = 0;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
+int usb_nbus = 0;
+
#define USBUNIT(dev) (minor(dev))
struct usb_softc {
- bdevice sc_dev; /* base device */
+ USBBASEDEVICE sc_dev; /* base device */
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
- char sc_running;
- char sc_exploring;
- struct selinfo sc_consel; /* waiting for connect change */
- int shutdown;
- struct proc *event_thread;
+
+ struct selinfo sc_consel; /* waiting for connect change */
+ struct proc *sc_event_thread;
+
+ char sc_dying;
};
#if defined(__NetBSD__) || defined(__OpenBSD__)
-int usbopen __P((dev_t, int, int, struct proc *));
-int usbclose __P((dev_t, int, int, struct proc *));
-int usbioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
-int usbpoll __P((dev_t, int, struct proc *));
-
+cdev_decl(usb);
#elif defined(__FreeBSD__)
d_open_t usbopen;
d_close_t usbclose;
@@ -125,6 +127,9 @@ usbd_status usb_discover __P((struct usb_softc *));
void usb_create_event_thread __P((void *));
void usb_event_thread __P((void *));
+/* Flag to see if we are in the cold boot process. */
+extern int cold;
+
USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usbd_print_child));
USB_MATCH(usb)
@@ -154,27 +159,36 @@ USB_ATTACH(usb)
usbd_init();
sc->sc_bus = aux;
sc->sc_bus->usbctl = sc;
- sc->sc_running = 1;
- sc->sc_bus->use_polling = 1;
sc->sc_port.power = USB_MAX_POWER;
- r = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0,0,0, &sc->sc_port);
+ r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
+ &sc->sc_port);
if (r == USBD_NORMAL_COMPLETION) {
dev = sc->sc_port.device;
if (!dev->hub) {
- sc->sc_running = 0;
+ sc->sc_dying = 1;
printf("%s: root device is not a hub\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
sc->sc_bus->root_hub = dev;
- dev->hub->explore(sc->sc_bus->root_hub);
+#if 1
+ /*
+ * Turning this code off will delay attachment of USB devices
+ * 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++;
+ 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);
- sc->sc_running = 0;
+ sc->sc_dying = 1;
}
- sc->sc_bus->use_polling = 0;
#if defined(__OpenBSD__)
kthread_create_deferred(usb_create_event_thread, sc);
@@ -182,6 +196,7 @@ USB_ATTACH(usb)
kthread_create(usb_create_event_thread, sc);
#endif
+ usb_nbus++;
USB_ATTACH_SUCCESS_RETURN;
}
@@ -192,9 +207,9 @@ usb_create_event_thread(arg)
struct usb_softc *sc = arg;
#if !defined(__OpenBSD__)
- if (kthread_create1(usb_event_thread, sc, &sc->event_thread,
+ if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
#else
- if (kthread_create(usb_event_thread, sc, &sc->event_thread,
+ if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
#endif
"%s", sc->sc_dev.dv_xname)) {
printf("%s: unable to create event thread for\n",
@@ -209,13 +224,16 @@ usb_event_thread(arg)
{
struct usb_softc *sc = arg;
- while (!sc->shutdown) {
+ while (!sc->sc_dying) {
+#ifdef USB_DEBUG
+ if (!usb_noexplore)
+#endif
+ usb_discover(sc);
(void)tsleep(&sc->sc_bus->needs_explore,
- PWAIT, "usbevt", hz*30);
+ PWAIT, "usbevt", hz*60);
DPRINTFN(2,("usb_event_thread: woke up\n"));
- usb_discover(sc);
}
- sc->event_thread = 0;
+ sc->sc_event_thread = 0;
/* In case parent is waiting for us to exit. */
wakeup(sc);
@@ -245,8 +263,10 @@ usbopen(dev, flag, mode, p)
{
USB_GET_SC_OPEN(usb, USBUNIT(dev), sc);
- if (sc == 0 || !sc->sc_running)
+ if (sc == 0)
return (ENXIO);
+ if (sc->sc_dying)
+ return (EIO);
return (0);
}
@@ -270,19 +290,15 @@ usbioctl(dev, cmd, data, flag, p)
{
USB_GET_SC(usb, USBUNIT(dev), sc);
- if (sc == 0 || !sc->sc_running)
- return (ENXIO);
+ if (sc->sc_dying)
+ return (EIO);
+
switch (cmd) {
#ifdef USB_DEBUG
case USB_SETDEBUG:
usbdebug = uhcidebug = ohcidebug = *(int *)data;
break;
#endif
-#if 0
- case USB_DISCOVER:
- usb_discover(sc);
- break;
-#endif
case USB_REQUEST:
{
struct usb_ctl_request *ur = (void *)data;
@@ -373,6 +389,9 @@ usbpoll(dev, events, p)
int revents, s;
USB_GET_SC(usb, USBUNIT(dev), sc);
+ if (sc->sc_dying)
+ return (EIO);
+
DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events));
s = splusb();
revents = 0;
@@ -390,59 +409,20 @@ usbpoll(dev, events, p)
return (revents);
}
-#if 0
-int
-usb_bus_count()
-{
- int i, n;
-
- for (i = n = 0; i < usb_cd.cd_ndevs; i++)
- if (usb_cd.cd_devs[i])
- n++;
- return (n);
-}
-#endif
-
-#if 0
-usbd_status
-usb_get_bus_handle(n, h)
- int n;
- usbd_bus_handle *h;
-{
- int i;
-
- for (i = 0; i < usb_cd.cd_ndevs; i++)
- if (usb_cd.cd_devs[i] && n-- == 0) {
- *h = usb_cd.cd_devs[i];
- return (USBD_NORMAL_COMPLETION);
- }
- return (USBD_INVAL);
-}
-#endif
-
+/* Explore device tree from the root. */
usbd_status
usb_discover(sc)
struct usb_softc *sc;
{
- int s;
-
- /* Explore device tree from the root */
- /* We need mutual exclusion while traversing the device tree. */
+ /*
+ * 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 {
- s = splusb();
- while (sc->sc_exploring)
- tsleep(&sc->sc_exploring, PRIBIO, "usbdis", 0);
- sc->sc_exploring = 1;
sc->sc_bus->needs_explore = 0;
- splx(s);
-
sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
-
- s = splusb();
- sc->sc_exploring = 0;
- wakeup(&sc->sc_exploring);
- splx(s);
- } while (sc->sc_bus->needs_explore);
+ } while (sc->sc_bus->needs_explore && !sc->sc_dying);
return (USBD_NORMAL_COMPLETION);
}
@@ -457,19 +437,61 @@ usb_needs_explore(bus)
int
usb_activate(self, act)
- bdevice *self;
+ device_ptr_t self;
enum devact act;
{
- panic("usb_activate\n");
- return (0);
+ struct usb_softc *sc = (struct usb_softc *)self;
+ usbd_device_handle dev = sc->sc_port.device;
+ int i, rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ if (dev && dev->cdesc && dev->subdevs) {
+ for (i = 0; dev->subdevs[i]; i++)
+ rv |= config_deactivate(dev->subdevs[i]);
+ }
+ break;
+ }
+ return (rv);
}
int
usb_detach(self, flags)
- bdevice *self;
+ device_ptr_t self;
int flags;
{
- panic("usb_detach\n");
+ struct usb_softc *sc = (struct usb_softc *)self;
+
+ sc->sc_dying = 1;
+
+ /* Make all devices disconnect. */
+ if (sc->sc_port.device)
+ usb_disconnect_port(&sc->sc_port);
+
+ /* Kill off event thread. */
+ if (sc->sc_event_thread) {
+ wakeup(&sc->sc_bus->needs_explore);
+ if (tsleep(sc, PWAIT, "usbdet", hz * 60))
+ printf("%s: event thread didn't die\n",
+ USBDEVNAME(sc->sc_dev));
+ }
+
+ usb_nbus--;
+ return (0);
+}
+
+int
+usbread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ /* XXX */
return (0);
}
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 5c6404bf172..c2dccc57706 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usb.h,v 1.4 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: usb.h,v 1.30 1999/08/29 22:45:41 augustss Exp $ */
+/* $OpenBSD: usb.h,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb.h,v 1.34 1999/09/16 21:53:58 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -220,12 +220,11 @@ typedef struct {
uByte bLength;
uByte bDescriptorType;
uByte bEndpointAddress;
-#define UE_IN 0x80
-#define UE_OUT 0x00
+#define UE_GET_DIR(a) ((a) & 0x80)
+#define UE_DIR_IN 0x80
+#define UE_DIR_OUT 0x00
#define UE_ADDR 0x0f
#define UE_GET_ADDR(a) ((a) & UE_ADDR)
-#define UE_GET_IN(a) (((a) >> 7) & 1)
-#define UE_GET_DIR(a) ((a) & 0x80)
uByte bmAttributes;
#define UE_XFERTYPE 0x03
#define UE_CONTROL 0x00
@@ -337,6 +336,7 @@ typedef struct {
#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
@@ -361,8 +361,8 @@ typedef struct {
#define USUBCLASS_SCSI 6
#define UPROTO_MASS_CBI_I 0
#define UPROTO_MASS_CBI 1
-#define UPROTO_MASS_BULK 80
-#define UPROTO_MASS_BULK2 2
+#define UPROTO_MASS_BULK 2
+#define UPROTO_MASS_BULK_P 80
#define UCLASS_HUB 9
#define USUBCLASS_HUB 0
#define UCLASS_DATA 10
@@ -408,8 +408,7 @@ struct usb_ctl_request {
usb_device_request_t request;
void *data;
int flags;
-/* XXX must match flags in usbdi.h */
-#define USBD_SHORT_XFER_OK 0x04
+#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
int actlen; /* actual length transferred */
};
diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c
index fee0b823a82..8117ceed68e 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.4 1999/08/27 09:00:29 fgsch Exp $ */
-/* $NetBSD: usb_mem.c,v 1.9 1999/08/16 20:19:55 augustss Exp $ */
+/* $OpenBSD: usb_mem.c,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb_mem.c,v 1.14 1999/09/13 19:18:17 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -50,15 +50,16 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/queue.h>
+#include <sys/device.h> /* for usbdivar.h */
+#include <machine/bus.h>
#ifdef DIAGNOSTIC
#include <sys/proc.h>
#endif
-#include <machine/bus.h>
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h> /* just for usb_dma_t */
#include <dev/usb/usb_mem.h>
#ifdef USB_DEBUG
@@ -81,11 +82,8 @@ struct usb_frag_dma {
LIST_ENTRY(usb_frag_dma) next;
};
-usbd_status usb_block_allocmem
- __P((bus_dma_tag_t, size_t, size_t, usb_dma_block_t **));
-#if 0
-void usb_block_real_freemem __P((usb_dma_block_t *));
-#endif
+usbd_status usb_block_allocmem __P((bus_dma_tag_t, size_t, size_t,
+ usb_dma_block_t **));
void usb_block_freemem __P((usb_dma_block_t *));
LIST_HEAD(, usb_dma_block) usb_blk_freelist =
@@ -212,12 +210,13 @@ usb_block_freemem(p)
}
usbd_status
-usb_allocmem(tag, size, align, p)
- bus_dma_tag_t tag;
+usb_allocmem(bus, size, align, p)
+ usbd_bus_handle bus;
size_t size;
size_t align;
usb_dma_t *p;
{
+ bus_dma_tag_t tag = bus->dmatag;
usbd_status r;
struct usb_frag_dma *f;
usb_dma_block_t *b;
@@ -266,8 +265,8 @@ usb_allocmem(tag, size, align, p)
}
void
-usb_freemem(tag, p)
- bus_dma_tag_t tag;
+usb_freemem(bus, p)
+ usbd_bus_handle bus;
usb_dma_t *p;
{
struct usb_frag_dma *f;
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index 9c5ae8f435c..cc44dbeca5c 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.2 1999/08/27 09:00:30 fgsch Exp $ */
-/* $NetBSD: usb_mem.h,v 1.4 1999/01/09 12:16:54 augustss Exp $ */
+/* $OpenBSD: usb_mem.h,v 1.3 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb_mem.h,v 1.8 1999/09/13 19:18:17 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,16 +51,11 @@ typedef struct usb_dma_block {
LIST_ENTRY(usb_dma_block) next;
} usb_dma_block_t;
-typedef struct {
- struct usb_dma_block *block;
- u_int offs;
-} usb_dma_t;
-
#define DMAADDR(dma) ((dma)->block->segs[0].ds_addr + (dma)->offs)
#define KERNADDR(dma) ((void *)((dma)->block->kaddr + (dma)->offs))
-usbd_status usb_allocmem __P((bus_dma_tag_t, size_t, size_t, usb_dma_t *));
-void usb_freemem __P((bus_dma_tag_t, usb_dma_t *));
+usbd_status usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *));
+void usb_freemem __P((usbd_bus_handle, usb_dma_t *));
#elif defined(__FreeBSD__)
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 98d7f0fb02d..e880e605bd5 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.4 1999/08/19 08:18:39 fgsch Exp $ */
-/* $NetBSD: usb_port.h,v 1.9 1999/08/17 16:06:21 augustss Exp $ */
+/* $OpenBSD: usb_port.h,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb_port.h,v 1.11 1999/09/11 08:19:27 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -43,16 +43,25 @@
* Macro's to cope with the differences between operating systems.
*/
+#if defined(__NetBSD__)
/*
* NetBSD
*/
-#if defined(__NetBSD__)
#include "opt_usbverbose.h"
+typedef struct device *device_ptr_t;
+#define USBBASEDEVICE struct device
+#define USBDEV(bdev) (&(bdev))
#define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
-typedef struct device bdevice; /* base device */
+#define DECLARE_USB_DMA_T \
+ struct usb_dma_block; \
+ typedef struct { \
+ struct usb_dma_block *block; \
+ u_int offs; \
+ } usb_dma_t
#define usb_timeout(f, d, t, h) timeout((f), (d), (t))
#define usb_untimeout(f, d, h) untimeout((f), (d))
@@ -124,15 +133,25 @@ __CONCAT(dname,_attach)(parent, self, aux) \
#define memcpy(d, s, l) bcopy((s),(d),(l))
#define memset(d, v, l) bzero((d),(l))
#define bswap32(x) swap32(x)
-#define powerhook_establish(h, sc) /* nothing */
+#define powerhook_establish(h, sc) NULL
+#define powerhook_disestablish(sc) /* nothing */
#define usbpoll usbselect
#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 USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
-typedef struct device bdevice; /* base device */
+#define DECLARE_USB_DMA_T \
+ struct usb_dma_block; \
+ typedef struct { \
+ struct usb_dma_block *block; \
+ u_int offs; \
+ } usb_dma_t
#define usb_timeout(f, d, t, h) timeout((f), (d), (t))
#define usb_untimeout(f, d, h) untimeout((f), (d))
@@ -203,12 +222,13 @@ __CONCAT(dname,_attach)(parent, self, aux) \
*/
#include "opt_usb.h"
-/*
- * The following is not a type def to avoid error messages
- * because of includes in the wrong order.
- */
-#define bdevice device_t
-#define USBDEVNAME(bdev) usbd_devname(&bdev)
+
+#define USBBASEDEVICE device_t
+#define USBDEV(bdev) (bdev)
+#define USBDEVNAME(bdev) usbd_devname(bdev)
+#define USBDEVPTRNAME(bdev) usbd_devname(bdev)
+
+#define DECLARE_USB_DMA_T typedef void * usb_dma_t
/* XXX Change this when FreeBSD has memset
*/
@@ -305,3 +325,8 @@ __CONCAT(dname,_attach)(device_t self)
#undef NONE
+
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+#elif defined(__FreeBSD__)
+#endif
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index 86c224981de..aa273cd8c27 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.1 1999/08/13 05:28:04 fgsch Exp $ */
-/* $NetBSD: usb_quirks.c,v 1.11 1999/06/26 00:09:15 augustss Exp $ */
+/* $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 $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -59,14 +59,14 @@ struct usbd_quirk_entry {
u_int16_t bcdDevice;
struct usbd_quirks quirks;
} quirks[] = {
- { USB_VENDOR_GENIUS, USB_PRODUCT_GENIUS_NICHE, 0x100, { UQ_NO_SET_PROTO}},
+ { 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_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }},
- { USB_VENDOR_JAZZ, USB_PRODUCT_JAZZ_J6502, 0x0a2, { UQ_BAD_ADC }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_USBPS2,0x110, { UQ_MS_REVZ }},
+ { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }},
+ { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48, 0x110, { UQ_MS_REVZ }},
{ 0, 0, 0, { 0 } }
};
@@ -86,9 +86,9 @@ usbd_find_quirk(d)
}
#ifdef USB_DEBUG
if (usbdebug && t->quirks.uq_flags)
- printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
- UGETW(d->idVendor), UGETW(d->idProduct),
- UGETW(d->bcdDevice), t->quirks.uq_flags);
+ logprintf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
+ UGETW(d->idVendor), UGETW(d->idProduct),
+ UGETW(d->bcdDevice), t->quirks.uq_flags);
#endif
return (&t->quirks);
}
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 981663dd903..3d38b7d3bbb 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.4 1999/08/27 09:00:30 fgsch Exp $ */
-/* $NetBSD: usb_subr.c,v 1.38 1999/08/17 20:59:04 augustss Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usb_subr.c,v 1.48 1999/09/16 19:20:34 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,6 +51,8 @@
#include <sys/proc.h>
#include <sys/select.h>
+#include <machine/bus.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -78,14 +80,14 @@ char *usbd_get_string __P((usbd_device_handle, int, char *));
int usbd_getnewaddr __P((usbd_bus_handle bus));
int usbd_print __P((void *aux, const char *pnp));
#if defined(__NetBSD__)
-int usbd_submatch __P((bdevice *, struct cfdata *cf, void *));
+int usbd_submatch __P((device_ptr_t, struct cfdata *cf, void *));
#elif defined(__OpenBSD__)
-int usbd_submatch __P((bdevice *, void *, void *));
+int usbd_submatch __P((device_ptr_t, void *, void *));
#endif
void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
void usbd_kill_pipe __P((usbd_pipe_handle));
usbd_status usbd_probe_and_attach
- __P((bdevice *parent, usbd_device_handle dev, int port, int addr));
+ __P((device_ptr_t parent, usbd_device_handle dev, int port, int addr));
#ifdef USBVERBOSE
@@ -106,8 +108,7 @@ struct usb_knowndev {
#include <dev/usb/usbdevs_data.h>
#endif /* USBVERBOSE */
-#ifdef USB_DEBUG
-char *usbd_error_strs[] = {
+const char *usbd_error_strs[] = {
"NORMAL_COMPLETION",
"IN_PROGRESS",
"PENDING_REQUESTS",
@@ -129,33 +130,23 @@ char *usbd_error_strs[] = {
"INTERRUPTED",
"XXX",
};
-#endif
-char *
+const char *
usbd_errstr(err)
usbd_status err;
{
static char buffer[5];
-#ifdef USB_DEBUG
- if ( err < USBD_ERROR_MAX ) {
+ if (err < USBD_ERROR_MAX) {
return usbd_error_strs[err];
} else {
#if !defined(__OpenBSD__)
snprintf(buffer, sizeof buffer, "%d", err);
#else
sprintf(buffer, "%d", err);
-#endif /* !defined(__OpenBSD__) */
+#endif
return buffer;
}
-#else
-#if !defined(__OpenBSD__)
- snprintf(buffer, sizeof buffer, "%d", err);
-#else
- sprintf(buffer, "%d", err);
-#endif /* !defined(__OpenBSD__) */
- return buffer;
-#endif
}
usbd_status
@@ -612,7 +603,7 @@ usbd_set_config_index(dev, index, msg)
selfpowered, cdp->bMaxPower * 2));
#ifdef USB_DEBUG
if (!dev->powersrc) {
- printf("usbd_set_config_index: No power source?\n");
+ DPRINTF(("usbd_set_config_index: No power source?\n"));
return (USBD_IOERROR);
}
#endif
@@ -694,7 +685,7 @@ usbd_setup_pipe(dev, iface, ep, pipe)
p->running = 0;
p->repeat = 0;
SIMPLEQ_INIT(&p->queue);
- r = dev->bus->open_pipe(p);
+ r = dev->bus->methods->open_pipe(p);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
"%s\n",
@@ -734,7 +725,7 @@ usbd_getnewaddr(bus)
usbd_status
usbd_probe_and_attach(parent, dev, port, addr)
- bdevice *parent;
+ device_ptr_t parent;
usbd_device_handle dev;
int port;
int addr;
@@ -742,7 +733,7 @@ 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;
- struct device *dv;
+ device_ptr_t dv;
usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
#if defined(__FreeBSD__)
@@ -750,7 +741,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
* XXX uaa is a static var. Not a problem as it _should_ be used only
* during probe and attach. Should be changed however.
*/
- bdevice bdev;
+ device_t bdev;
bdev = device_add_child(*parent, NULL, -1, &uaa);
if (!bdev) {
printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
@@ -791,11 +782,11 @@ usbd_probe_and_attach(parent, dev, port, addr)
if (r != USBD_NORMAL_COMPLETION) {
#ifdef USB_DEBUG
DPRINTF(("%s: port %d, set config at addr %d failed, "
- "error=%s\n", USBDEVNAME(*parent), port,
+ "error=%s\n", USBDEVPTRNAME(parent), port,
addr, usbd_errstr(r)));
#else
printf("%s: port %d, set config at addr %d failed\n",
- USBDEVNAME(*parent), port, addr);
+ USBDEVPTRNAME(parent), port, addr);
#endif
#if defined(__FreeBSD__)
device_delete_child(*parent, bdev);
@@ -880,7 +871,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
*/
usbd_status
usbd_new_device(parent, bus, depth, lowspeed, port, up)
- bdevice *parent;
+ device_ptr_t parent;
usbd_bus_handle bus;
int depth;
int lowspeed;
@@ -1183,3 +1174,67 @@ usb_free_device(dev)
free(dev->subdevs, M_USB);
free(dev, M_USB);
}
+
+/*
+ * The general mechanism for detaching drivers works as follows: Each
+ * driver is responsible for maintaining a reference count on the
+ * number of outstanding references to its softc (e.g. from
+ * processing hanging in a read or write). The detach method of the
+ * driver decrements this counter and flags in the softc that the
+ * driver is dying and then wakes any sleepers. It then sleeps on the
+ * softc. Each place that can sleep must maintain the reference
+ * count. When the reference count drops to -1 (0 is the normal value
+ * of the reference count) the a wakeup on the softc is performed
+ * signaling to the detach waiter that all references are gone.
+ */
+
+/*
+ * Called from process context when we discover that a port has
+ * been disconnected.
+ */
+void
+usb_disconnect_port(up)
+ struct usbd_port *up;
+{
+ usbd_device_handle dev = up->device;
+ char *hubname;
+ int i;
+
+ DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
+ up, dev, up->portno));
+
+#ifdef DIAGNOSTIC
+ if (!dev) {
+ 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) {
+ hubname = USBDEVPTRNAME(up->parent->subdevs[0]);
+ for (i = 0; dev->subdevs[i]; i++) {
+ printf("%s: at %s port %d (addr %d) disconnected\n",
+ USBDEVPTRNAME(dev->subdevs[i]), hubname,
+ up->portno, dev->address);
+ config_detach(dev->subdevs[i], DETACH_FORCE);
+ }
+ }
+
+ dev->bus->devices[dev->address] = 0;
+ up->device = 0;
+ usb_free_device(dev);
+
+#if defined(__FreeBSD__)
+ device_delete_child(
+ device_get_parent(((struct softc *)dev->softc)->sc_dev),
+ ((struct softc *)dev->softc)->sc_dev);
+#endif
+}
+
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 76e73d79ff7..3338e3ccafd 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi.c,v 1.5 1999/08/29 10:35:35 fgsch Exp $ */
-/* $NetBSD: usbdi.c,v 1.33 1999/08/28 10:04:01 augustss Exp $ */
+/* $OpenBSD: usbdi.c,v 1.6 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usbdi.c,v 1.43 1999/09/15 21:08:59 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,11 +51,13 @@
#include <sys/malloc.h>
#include <sys/proc.h>
-#include <dev/usb/usb.h>
+#include <machine/bus.h>
+#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
#if defined(__FreeBSD__)
#include "usb_if.h"
@@ -83,6 +85,18 @@ static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
extern struct cdevsw usb_cdevsw;
#endif
+static __inline int usbd_reqh_isread __P((usbd_request_handle reqh));
+static __inline int
+usbd_reqh_isread(reqh)
+ usbd_request_handle reqh;
+{
+ if (reqh->rqflags & URQ_REQUEST)
+ return (reqh->request.bmRequestType & UT_READ);
+ else
+ return (reqh->pipe->endpoint->edesc->bEndpointAddress &
+ UE_DIR_IN);
+}
+
#ifdef USB_DEBUG
void usbd_dump_queue __P((usbd_pipe_handle));
@@ -146,60 +160,30 @@ usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
usbd_request_handle reqh;
usbd_pipe_handle ipipe;
- reqh = usbd_alloc_request();
- if (reqh == 0)
- return (USBD_NOMEM);
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;
goto bad1;
- r = usbd_setup_request(reqh, ipipe, priv, buffer, length,
- USBD_XFER_IN | flags, USBD_NO_TIMEOUT, cb);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad2;
+ }
+ usbd_setup_request(reqh, ipipe, priv, buffer, length, flags,
+ USBD_NO_TIMEOUT, cb);
ipipe->intrreqh = reqh;
ipipe->repeat = 1;
r = usbd_transfer(reqh);
*pipe = ipipe;
if (r != USBD_IN_PROGRESS)
- goto bad3;
+ goto bad2;
return (USBD_NORMAL_COMPLETION);
- bad3:
+ bad2:
ipipe->intrreqh = 0;
ipipe->repeat = 0;
- bad2:
- usbd_close_pipe(ipipe);
- bad1:
usbd_free_request(reqh);
- return r;
-}
-
-usbd_status
-usbd_open_pipe_iso(iface, address, flags, pipe, priv, bufsize, nbuf)
- usbd_interface_handle iface;
- u_int8_t address;
- u_int8_t flags;
- usbd_pipe_handle *pipe;
- usbd_private_handle priv;
- u_int32_t bufsize;
- u_int32_t nbuf;
-{
- usbd_status r;
- usbd_pipe_handle p;
-
- r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &p);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
- if (!p->methods->isobuf) {
- usbd_close_pipe(p);
- return (USBD_INVAL);
- }
- r = p->methods->isobuf(p, bufsize, nbuf);
- if (r != USBD_NORMAL_COMPLETION) {
- usbd_close_pipe(p);
- return (r);
- }
- *pipe = p;
+ bad1:
+ usbd_close_pipe(ipipe);
return r;
}
@@ -232,7 +216,9 @@ usbd_transfer(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
+ usb_dma_t *dmap = &reqh->dmabuf;
usbd_status r;
+ u_int size;
int s;
DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
@@ -243,16 +229,47 @@ usbd_transfer(reqh)
#endif
reqh->done = 0;
+ size = reqh->length;
+ /* If there is no buffer, allocate one. */
+ if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) {
+ struct usbd_bus *bus = pipe->device->bus;
+
+#ifdef DIAGNOSTIC
+ if (reqh->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;
+ }
+
+ /* Copy data if going out. */
+ if (!(reqh->flags & USBD_NO_COPY) && size != 0 &&
+ !usbd_reqh_isread(reqh))
+ memcpy(KERNADDR(dmap), reqh->buffer, size);
+
r = pipe->methods->transfer(reqh);
+
+ if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) {
+ /* The transfer has not been queued, so free buffer. */
+ if (reqh->rqflags & URQ_AUTO_DMABUF) {
+ struct usbd_bus *bus = pipe->device->bus;
+
+ bus->methods->freem(bus, &reqh->dmabuf);
+ reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ }
+ }
+
if (!(reqh->flags & USBD_SYNCHRONOUS))
- return r;
+ return (r);
/* Sync transfer, wait for completion. */
if (r != USBD_IN_PROGRESS)
return (r);
s = splusb();
if (!reqh->done) {
- if (reqh->pipe->device->bus->use_polling)
+ if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done\n");
tsleep(reqh, PRIBIO, "usbsyn", 0);
}
@@ -269,8 +286,47 @@ usbd_sync_transfer(reqh)
return (usbd_transfer(reqh));
}
+void *
+usbd_alloc_buffer(reqh, size)
+ usbd_request_handle reqh;
+ u_int32_t size;
+{
+ struct usbd_bus *bus = reqh->device->bus;
+ usbd_status r;
+
+ r = bus->methods->allocm(bus, &reqh->dmabuf, size);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (0);
+ reqh->rqflags |= URQ_DEV_DMABUF;
+ return (KERNADDR(&reqh->dmabuf));
+}
+
+void
+usbd_free_buffer(reqh)
+ usbd_request_handle reqh;
+{
+#ifdef DIAGNOSTIC
+ if (!(reqh->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);
+}
+
+void *
+usbd_get_buffer(reqh)
+ usbd_request_handle reqh;
+{
+ if (!(reqh->rqflags & URQ_DEV_DMABUF))
+ return (0);
+ return (KERNADDR(&reqh->dmabuf));
+}
+
usbd_request_handle
-usbd_alloc_request()
+usbd_alloc_request(dev)
+ usbd_device_handle dev;
{
usbd_request_handle reqh;
@@ -282,7 +338,8 @@ usbd_alloc_request()
if (!reqh)
return (0);
memset(reqh, 0, sizeof *reqh);
- DPRINTFN(1,("usbd_alloc_request() = %p\n", reqh));
+ reqh->device = dev;
+ DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh));
return (reqh);
}
@@ -290,12 +347,14 @@ usbd_status
usbd_free_request(reqh)
usbd_request_handle reqh;
{
- DPRINTFN(1,("usbd_free_request: %p\n", reqh));
+ 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);
return (USBD_NORMAL_COMPLETION);
}
-usbd_status
+void
usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
usbd_request_handle reqh;
usbd_pipe_handle pipe;
@@ -317,11 +376,11 @@ usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
reqh->timeout = timeout;
reqh->status = USBD_NOT_STARTED;
reqh->callback = callback;
- reqh->isreq = 0;
- return (USBD_NORMAL_COMPLETION);
+ reqh->rqflags &= ~URQ_REQUEST;
+ reqh->nframes = 0;
}
-usbd_status
+void
usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
length, flags, callback)
usbd_request_handle reqh;
@@ -346,8 +405,32 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
reqh->status = USBD_NOT_STARTED;
reqh->callback = callback;
reqh->request = *req;
- reqh->isreq = 1;
- return (USBD_NORMAL_COMPLETION);
+ reqh->rqflags |= URQ_REQUEST;
+ reqh->nframes = 0;
+}
+
+void
+usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback)
+ usbd_request_handle reqh;
+ usbd_pipe_handle pipe;
+ usbd_private_handle priv;
+ u_int16_t *frlengths;
+ u_int32_t nframes;
+ 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;
}
void
@@ -512,6 +595,13 @@ usbd_device2interface_handle(dev, ifaceno, iface)
return (USBD_NORMAL_COMPLETION);
}
+usbd_device_handle
+usbd_pipe2device_handle(pipe)
+ usbd_pipe_handle pipe;
+{
+ return (pipe->device);
+}
+
/* XXXX use altno */
usbd_status
usbd_set_interface(iface, altidx)
@@ -592,6 +682,8 @@ usbd_ar_pipe(pipe)
{
usbd_request_handle reqh;
+ SPLUSBCHECK;
+
DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
#ifdef USB_DEBUG
if (usbdebug > 5)
@@ -607,11 +699,10 @@ usbd_ar_pipe(pipe)
return (USBD_NORMAL_COMPLETION);
}
-static int usbd_global_init_done = 0;
-
void
usbd_init()
{
+ static int usbd_global_init_done = 0;
#if defined(__FreeBSD__)
dev_t dev;
#endif
@@ -627,15 +718,19 @@ usbd_init()
}
}
+/* Called at splusb() */
void
usb_transfer_complete(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
+ usb_dma_t *dmap = &reqh->dmabuf;
int polling;
- DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p actlen=%d\n",
- pipe, reqh, reqh->actlen));
+ SPLUSBCHECK;
+
+ DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p status=%d actlen=%d\n",
+ pipe, reqh, reqh->status, reqh->actlen));
#ifdef DIAGNOSTIC
if (!pipe) {
@@ -643,13 +738,34 @@ usb_transfer_complete(reqh)
return;
}
#endif
- polling = reqh->pipe->device->bus->use_polling;
+ polling = pipe->device->bus->use_polling;
/* XXXX */
if (polling)
pipe->running = 0;
- if (reqh->pipe->methods->done)
- reqh->pipe->methods->done(reqh);
+ if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 &&
+ usbd_reqh_isread(reqh)) {
+#ifdef DIAGNOSTIC
+ if (reqh->actlen > reqh->length) {
+ printf("usb_transfer_complete: actlen > len %d > %d\n",
+ reqh->actlen, reqh->length);
+ reqh->actlen = reqh->length;
+ }
+#endif
+ memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
+ }
+
+ /* if we allocated the buffer in usbd_transfer() we free it here. */
+ if (reqh->rqflags & URQ_AUTO_DMABUF) {
+ if (!pipe->repeat) {
+ struct usbd_bus *bus = pipe->device->bus;
+ bus->methods->freem(bus, dmap);
+ reqh->rqflags &= ~URQ_AUTO_DMABUF;
+ }
+ }
+
+ if (pipe->methods->done)
+ pipe->methods->done(reqh);
/* Remove request from queue. */
SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
@@ -673,9 +789,14 @@ usb_transfer_complete(reqh)
if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
wakeup(reqh);
- if (!pipe->repeat &&
- reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT)
- usbd_start_next(pipe);
+ if (!pipe->repeat) {
+ /* XXX should we stop the queue on all errors? */
+ if (reqh->status == USBD_CANCELLED ||
+ reqh->status == USBD_TIMEOUT)
+ pipe->running = 0;
+ else
+ usbd_start_next(pipe);
+ }
}
usbd_status
@@ -683,16 +804,24 @@ usb_insert_transfer(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
+ usbd_status r;
+ int s;
- DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe,
- pipe->running));
+ DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
+ pipe, pipe->running, reqh->timeout));
+ s = splusb();
SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
if (pipe->running)
- return (USBD_IN_PROGRESS);
- pipe->running = 1;
- return (USBD_NORMAL_COMPLETION);
+ r = USBD_IN_PROGRESS;
+ else {
+ pipe->running = 1;
+ r = USBD_NORMAL_COMPLETION;
+ }
+ splx(s);
+ return (r);
}
+/* Called at splusb() */
void
usbd_start_next(pipe)
usbd_pipe_handle pipe;
@@ -700,6 +829,8 @@ usbd_start_next(pipe)
usbd_request_handle reqh;
usbd_status r;
+ SPLUSBCHECK;
+
DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
#ifdef DIAGNOSTIC
@@ -749,30 +880,27 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
usbd_status r;
#ifdef DIAGNOSTIC
- if (!curproc) {
+ if (dev->bus->intr_context) {
printf("usbd_do_request: not in process context\n");
- return (USBD_XXX);
+ return (USBD_INVAL);
}
#endif
- reqh = usbd_alloc_request();
+ reqh = usbd_alloc_request(dev);
if (reqh == 0)
return (USBD_NOMEM);
- r = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), flags, 0);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad;
+ usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
+ data, UGETW(req->wLength), flags, 0);
r = usbd_sync_transfer(reqh);
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
if (reqh->actlen > reqh->length)
- printf("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);
+ 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));
#endif
if (actlen)
*actlen = reqh->actlen;
@@ -792,11 +920,9 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
USETW(treq.wValue, 0);
USETW(treq.wIndex, 0);
USETW(treq.wLength, sizeof(usb_status_t));
- nr = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
- sizeof(usb_status_t), 0, 0);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
+ usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ &treq, &status,sizeof(usb_status_t),
+ 0, 0);
nr = usbd_sync_transfer(reqh);
if (nr != USBD_NORMAL_COMPLETION)
goto bad;
@@ -809,11 +935,8 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
USETW(treq.wValue, UF_ENDPOINT_HALT);
USETW(treq.wIndex, 0);
USETW(treq.wLength, 0);
- nr = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
- 0, 0, 0);
- if (nr != USBD_NORMAL_COMPLETION)
- goto bad;
+ usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+ &treq, &status, 0, 0, 0);
nr = usbd_sync_transfer(reqh);
if (nr != USBD_NORMAL_COMPLETION)
goto bad;
@@ -832,14 +955,14 @@ usbd_do_request_async_cb(reqh, priv, status)
{
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
if (reqh->actlen > reqh->length)
- printf("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);
+ 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));
#endif
usbd_free_request(reqh);
}
@@ -857,19 +980,17 @@ usbd_do_request_async(dev, req, data)
usbd_request_handle reqh;
usbd_status r;
- reqh = usbd_alloc_request();
+ reqh = usbd_alloc_request(dev);
if (reqh == 0)
return (USBD_NOMEM);
- r = usbd_setup_default_request(
- reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), 0, usbd_do_request_async_cb);
- if (r != USBD_NORMAL_COMPLETION) {
+ usbd_setup_default_request(reqh, 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);
}
- r = usbd_transfer(reqh);
- if (r != USBD_IN_PROGRESS)
- return (r);
return (USBD_NORMAL_COMPLETION);
}
@@ -889,7 +1010,7 @@ void
usbd_dopoll(iface)
usbd_interface_handle iface;
{
- iface->device->bus->do_poll(iface->device->bus);
+ iface->device->bus->methods->do_poll(iface->device->bus);
}
void
@@ -897,7 +1018,10 @@ usbd_set_polling(iface, on)
usbd_interface_handle iface;
int on;
{
- iface->device->bus->use_polling = on;
+ if (on)
+ iface->device->bus->use_polling++;
+ else
+ iface->device->bus->use_polling--;
}
@@ -1002,7 +1126,7 @@ usbd_device_set_desc(device_t device, char *devinfo)
}
char *
-usbd_devname(bdevice *bdev)
+usbd_devname(device_t bdev)
{
static char buf[20];
/*
@@ -1010,7 +1134,7 @@ usbd_devname(bdevice *bdev)
* but it's not fatal.
*/
- sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev));
+ sprintf(buf, "%s%d", device_get_name(bdev), device_get_unit(bdev));
return (buf);
}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 8832690e384..bfaa28d629e 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdi.h,v 1.4 1999/08/31 07:42:50 fgsch Exp $ */
-/* $NetBSD: usbdi.h,v 1.20 1999/06/30 06:44:23 augustss Exp $ */
+/* $OpenBSD: usbdi.h,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usbdi.h,v 1.29 1999/09/12 08:23:42 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -67,8 +67,6 @@ typedef enum {
USBD_STALLED,
USBD_INTERRUPTED,
- USBD_XXX,
-
USBD_ERROR_MAX, /* must be last */
} usbd_status;
@@ -81,10 +79,9 @@ typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle,
#define USBD_EXCLUSIVE_USE 0x01
/* Request flags */
-#define USBD_XFER_OUT 0x01
-#define USBD_XFER_IN 0x02
-#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
-#define USBD_SYNCHRONOUS 0x08 /* wait for completion */
+#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_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -94,18 +91,22 @@ usbd_status usbd_open_pipe
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((void));
+usbd_request_handle usbd_alloc_request __P((usbd_device_handle));
usbd_status usbd_free_request __P((usbd_request_handle reqh));
-usbd_status usbd_setup_request
+void usbd_setup_request
__P((usbd_request_handle reqh, usbd_pipe_handle pipe,
usbd_private_handle priv, void *buffer,
u_int32_t length, u_int16_t flags, u_int32_t timeout,
usbd_callback));
-usbd_status usbd_setup_default_request
+void usbd_setup_default_request
__P((usbd_request_handle reqh, 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,
+ 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 **buffer, u_int32_t *count, usbd_status *status));
@@ -123,17 +124,16 @@ usbd_status usbd_interface2device_handle
usbd_status usbd_device2interface_handle
__P((usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface));
-/* Non-standard */
+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));
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));
-usbd_status usbd_open_pipe_iso
- __P((usbd_interface_handle iface, u_int8_t address,
- u_int8_t flags, usbd_pipe_handle *pipe,
- usbd_private_handle priv, u_int32_t bufsize, u_int32_t nbuf));
usbd_status usbd_do_request
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usbd_status usbd_do_request_async
@@ -254,7 +254,7 @@ usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
#if defined(__FreeBSD__)
int usbd_driver_load __P((module_t mod, int what, void *arg));
void usbd_device_set_desc __P((device_t device, char *devinfo));
-char *usbd_devname(bdevice *bdev);
+char *usbd_devname(device_t *bdev);
bus_print_child_t usbd_print_child;
#endif
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 688c1c48f89..f576a18f7da 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.3 1999/08/27 09:00:30 fgsch Exp $ */
-/* $NetBSD: usbdi_util.c,v 1.16 1999/08/07 23:14:17 augustss Exp $ */
+/* $OpenBSD: usbdi_util.c,v 1.4 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usbdi_util.c,v 1.21 1999/09/09 12:26:48 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -513,10 +513,8 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
usbd_status r;
int s, error;
- r = usbd_setup_request(reqh, pipe, 0, buf, *size,
- flags, timeout, usbd_bulk_transfer_cb);
- if (r != USBD_NORMAL_COMPLETION)
- return (r);
+ usbd_setup_request(reqh, 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);
@@ -542,19 +540,19 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
void
usb_detach_wait(dv)
- bdevice *dv;
+ device_ptr_t dv;
{
- DPRINTF(("usb_detach_wait: waiting for %s\n", USBDEVNAME(*dv)));
+ DPRINTF(("usb_detach_wait: waiting for %s\n", USBDEVPTRNAME(dv)));
if (tsleep(dv, PZERO, "usbdet", hz * 60))
printf("usb_detach_wait: %s didn't detach\n",
- USBDEVNAME(*dv));
- DPRINTF(("usb_detach_wait: %s done\n", USBDEVNAME(*dv)));
+ USBDEVPTRNAME(dv));
+ DPRINTF(("usb_detach_wait: %s done\n", USBDEVPTRNAME(dv)));
}
void
usb_detach_wakeup(dv)
- bdevice *dv;
+ device_ptr_t dv;
{
- DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVNAME(*dv)));
+ DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv)));
wakeup(dv);
}
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index f77b789d522..e3c055e36d0 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.2 1999/08/27 09:00:30 fgsch Exp $ */
-/* $NetBSD: usbdi_util.h,v 1.14 1999/08/07 23:14:17 augustss Exp $ */
+/* $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 $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -93,6 +93,6 @@ usbd_status usbd_bulk_transfer
__P((usbd_request_handle reqh, 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((bdevice *));
-void usb_detach_wakeup __P((bdevice *));
+void usb_detach_wait __P((device_ptr_t));
+void usb_detach_wakeup __P((device_ptr_t));
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index 25b95d88506..92cd3232f05 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: usbdivar.h,v 1.4 1999/08/31 07:42:51 fgsch Exp $ */
-/* $NetBSD: usbdivar.h,v 1.24 1999/08/17 20:59:04 augustss Exp $ */
+/* $OpenBSD: usbdivar.h,v 1.5 1999/09/27 18:03:56 fgsch Exp $ */
+/* $NetBSD: usbdivar.h,v 1.35 1999/09/15 21:08:19 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -38,6 +38,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+/* From usb_mem.h */
+DECLARE_USB_DMA_T;
+
struct usbd_request;
struct usbd_pipe;
@@ -46,15 +49,21 @@ struct usbd_endpoint {
int refcnt;
};
-struct usbd_methods {
+struct usbd_bus_methods {
+ usbd_status (*open_pipe)__P((struct usbd_pipe *pipe));
+ 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_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));
void (*close)__P((usbd_pipe_handle pipe));
void (*cleartoggle)__P((usbd_pipe_handle pipe));
void (*done)__P((usbd_request_handle reqh));
- usbd_status (*isobuf)__P((usbd_pipe_handle pipe,
- u_int32_t bufsize,u_int32_t nbuf));
};
struct usbd_port {
@@ -80,10 +89,9 @@ struct usb_softc;
struct usbd_bus {
/* Filled by HC driver */
- bdevice bdev; /* base device, host adapter */
- usbd_status (*open_pipe)__P((struct usbd_pipe *pipe));
+ USBBASEDEVICE bdev; /* base device, host adapter */
+ struct usbd_bus_methods *methods;
u_int32_t pipe_size; /* size of a pipe struct */
- void (*do_poll)__P((struct usbd_bus *));
/* Filled by usb driver */
struct usbd_device *root_hub;
usbd_device_handle devices[USB_MAX_DEVICES];
@@ -91,6 +99,11 @@ struct usbd_bus {
char use_polling;
struct usb_softc *usbctl;
struct usb_device_stats stats;
+ int intr_context;
+ u_int no_intrs;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ bus_dma_tag_t dmatag; /* DMA tag */
+#endif
};
struct usbd_device {
@@ -112,7 +125,7 @@ struct usbd_device {
usb_config_descriptor_t *cdesc; /* full config descr */
struct usbd_quirks *quirks;
struct usbd_hub *hub; /* only if this is a hub */
- bdevice **subdevs; /* sub-devices, 0 terminated */
+ device_ptr_t *subdevs; /* sub-devices, 0 terminated */
};
struct usbd_interface {
@@ -138,7 +151,7 @@ struct usbd_pipe {
char repeat;
/* Filled by HC driver. */
- struct usbd_methods *methods;
+ struct usbd_pipe_methods *methods;
};
struct usbd_request {
@@ -153,12 +166,26 @@ struct usbd_request {
usbd_callback callback;
__volatile char done;
+ /* For control pipe */
usb_device_request_t request;
- char isreq;
+
+ /* For isoc */
+ u_int16_t *frlengths;
+ int nframes;
+
+ /* For memory allocation */
+ struct usbd_device *device;
+ usb_dma_t dmabuf;
+
+ int rqflags;
+#define URQ_REQUEST 0x01
+#define URQ_AUTO_DMABUF 0x10
+#define URQ_DEV_DMABUF 0x20
SIMPLEQ_ENTRY(usbd_request) next;
- void *hcpriv; /* XXX private use by the HC driver */
+ void *hcpriv; /* private use by the HC driver */
+ int hcprivint; /* ditto */
#if defined(__FreeBSD__)
struct callout_handle timo_handle;
@@ -177,7 +204,7 @@ usbd_status usbd_setup_pipe __P((usbd_device_handle dev,
usbd_interface_handle iface,
struct usbd_endpoint *,
usbd_pipe_handle *pipe));
-usbd_status usbd_new_device __P((bdevice *parent,
+usbd_status usbd_new_device __P((device_ptr_t parent,
usbd_bus_handle bus, int depth,
int lowspeed, int port,
struct usbd_port *));
@@ -190,12 +217,20 @@ 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));
+void usb_disconnect_port __P((struct usbd_port *up));
/* Routines from usb.c */
int usb_bus_count __P((void));
void usb_needs_explore __P((usbd_bus_handle));
-#if 0
-usbd_status usb_get_bus_handle __P((int, usbd_bus_handle *));
+
+#ifdef DIAGNOSTIC
+#define SPLUSBCHECK \
+ do { int _s = splusb(), _su = splusb(); \
+ if (_s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \
+ _s, _su, __FILE__, __LINE__); \
+ } while (0)
+#else
+#define SPLUSBCHECK
#endif
/* Locator stuff. */