From 3241be755096a340cd6ba126b6d88e362ad03b71 Mon Sep 17 00:00:00 2001 From: Nick Hibma Date: Wed, 17 Nov 1999 22:33:51 +0000 Subject: [PATCH] Synchronisation with NetBSD as of 1999/11/16: Cleaning up the code: - Declare many functions static - Change variable names to make them more self explanatory - Change usbd_request_handle -> usbd_xfer_handle - Syntactical changes - Remove some unused code - Other KNF changes Interrupt context handling - Change delay to usbd_delay_ms were possible (takes polling mode into account) - Change detection mechanism for interrupt context Add support for pre-allocation DMA-able memory by device driver Add preliminary support for isochronous to the UHCI driver (not for OHCI yet). usb.c, uhci.c, ohci.c - Initial attempt at detachable USB host controllers - Handle the use_polling flag with a lttle more care and only set it if we are cold booting. usb.c, uhci.c ohci.c, usbdi.c usbdi_util.c usb_subr.c - Make sure an aborted pipe is marked as not running. - Start queued request in the right order. - Insert some more DIAGNOSTIC sanity checks. - Remove (almost) unused definitions USBD_XFER_OUT and USBD_XFER_IN. usb.c, usb_subr.c - Add an event mechanism so that a userland process can watch devices come and go. ohci.c - Handle the case when a USB transfer is so long that it crosses two page (4K) boundaries. OHCI cannot do that with a single TD so we make a chain. ulpt.c - Use a bigger buffer when transferring data. - Pre-allocate the DMA buffer. This makes the driver slightly more efficient. - Comment out the GET_DEVICE_ID code, because for some unknown reason it causes printing to fail sometimes. usb.h - Add a macro to extract the isoc type. - Add a macro to check whether the routine has been entered after splusb and if not, complain. usbdi.c - Fix a glitch in dequeueing and aborting requests on interrupt pipes. - Add a flag in the request to determine if the data copying is done by the driver or the usbdi layer. --- sys/dev/usb/hid.c | 22 +- sys/dev/usb/hid.h | 2 +- sys/dev/usb/ohci.c | 1158 +++++++++++++++++++++--------------- sys/dev/usb/ohcireg.h | 6 +- sys/dev/usb/ohcivar.h | 25 +- sys/dev/usb/ugen.c | 338 ++++++----- sys/dev/usb/uhci.c | 1116 +++++++++++++++++++--------------- sys/dev/usb/uhcireg.h | 2 +- sys/dev/usb/uhcivar.h | 25 +- sys/dev/usb/uhid.c | 112 ++-- sys/dev/usb/uhub.c | 310 ++++------ sys/dev/usb/ukbd.c | 17 +- sys/dev/usb/ulpt.c | 78 +-- sys/dev/usb/umass.c | 16 +- sys/dev/usb/ums.c | 48 +- sys/dev/usb/usb.c | 455 ++++++++++---- sys/dev/usb/usb.h | 31 +- sys/dev/usb/usb_mem.h | 8 +- sys/dev/usb/usb_port.h | 59 +- sys/dev/usb/usb_quirks.c | 8 +- sys/dev/usb/usb_subr.c | 316 ++++++---- sys/dev/usb/usbcdc.h | 2 +- sys/dev/usb/usbdevs.h | 7 +- sys/dev/usb/usbdevs_data.h | 20 +- sys/dev/usb/usbdi.c | 663 ++++++++++++--------- sys/dev/usb/usbdi.h | 42 +- sys/dev/usb/usbdi_util.c | 130 ++-- sys/dev/usb/usbdi_util.h | 2 +- sys/dev/usb/usbdivar.h | 48 +- sys/dev/usb/usbhid.h | 2 +- 30 files changed, 2905 insertions(+), 2163 deletions(-) diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c index c782c50a3afc..32b8cf488d44 100644 --- a/sys/dev/usb/hid.c +++ b/sys/dev/usb/hid.c @@ -1,4 +1,4 @@ -/* $NetBSD: hid.c,v 1.8 1999/08/14 14:49:31 augustss Exp $ */ +/* $NetBSD: hid.c,v 1.9 1999/10/13 08:10:55 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -111,7 +111,7 @@ void hid_end_parse(s) struct hid_data *s; { - while (s->cur.next) { + while (s->cur.next != NULL) { struct hid_item *hi = s->cur.next->next; free(s->cur.next, M_TEMP); s->cur.next = hi; @@ -133,7 +133,7 @@ hid_get_item(s, h) int i; top: - if (s->multimax) { + if (s->multimax != 0) { if (s->multi < s->multimax) { c->usage = s->usages[min(s->multi, s->nu-1)]; s->multi++; @@ -380,11 +380,11 @@ hid_report_size(buf, len, k, idp) id = 0; for (d = hid_start_parse(buf, len, 1< #include -#include #include #if defined(__NetBSD__) || defined(__OpenBSD__) +#include #include #include #elif defined(__FreeBSD__) #include #include +#include +#include +#if defined(DIAGNOSTIC) && defined(__i386__) +#include +#endif #endif #include #include -#if defined(__FreeBSD__) -#include -#include -#endif - #include #include @@ -82,6 +82,12 @@ #define delay(d) DELAY(d) #endif +#if defined(__OpenBSD__) +struct cfdriver ohci_cd = { + NULL, "ohci", DV_DULL +}; +#endif + #ifdef OHCI_DEBUG #define DPRINTF(x) if (ohcidebug) logprintf x #define DPRINTFN(n,x) if (ohcidebug>(n)) logprintf x @@ -91,13 +97,6 @@ int ohcidebug = 1; #define DPRINTFN(n,x) #endif - -#if defined(__OpenBSD__) -struct cfdriver ohci_cd = { - NULL, "ohci", DV_DULL -}; -#endif - /* * The OHCI controller is little endian, so on big endian machines * the data strored in memory needs to be swapped. @@ -110,87 +109,102 @@ struct cfdriver ohci_cd = { struct ohci_pipe; -ohci_soft_ed_t *ohci_alloc_sed __P((ohci_softc_t *)); -void ohci_free_sed __P((ohci_softc_t *, ohci_soft_ed_t *)); +static ohci_soft_ed_t *ohci_alloc_sed __P((ohci_softc_t *)); +static 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 *)); +static ohci_soft_td_t *ohci_alloc_std __P((ohci_softc_t *)); +static void ohci_free_std __P((ohci_softc_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 *)); -void ohci_waitintr __P((ohci_softc_t *, usbd_request_handle)); -void ohci_rhsc __P((ohci_softc_t *, usbd_request_handle)); -void ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t)); +#if 0 +static void ohci_free_std_chain __P((ohci_softc_t *, + ohci_soft_td_t *, ohci_soft_td_t *)); +#endif +static 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 **)); -usbd_status ohci_device_request __P((usbd_request_handle reqh)); -void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); -void ohci_rem_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); -void ohci_hash_add_td __P((ohci_softc_t *, ohci_soft_td_t *)); -void ohci_hash_rem_td __P((ohci_softc_t *, ohci_soft_td_t *)); -ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, ohci_physaddr_t)); +static void ohci_power __P((int, void *)); +static usbd_status ohci_open __P((usbd_pipe_handle)); +static void ohci_poll __P((struct usbd_bus *)); +static void ohci_waitintr __P((ohci_softc_t *, + usbd_xfer_handle)); +static void ohci_rhsc __P((ohci_softc_t *, usbd_xfer_handle)); +static void ohci_process_done __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 *)); +static usbd_status ohci_device_request __P((usbd_xfer_handle xfer)); +static void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); +static void ohci_rem_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); +static void ohci_hash_add_td __P((ohci_softc_t *, + ohci_soft_td_t *)); +static void ohci_hash_rem_td __P((ohci_softc_t *, + ohci_soft_td_t *)); +static ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, + ohci_physaddr_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)); -void ohci_root_ctrl_close __P((usbd_pipe_handle)); +static usbd_status ohci_allocm __P((struct usbd_bus *, usb_dma_t *, + u_int32_t)); +static void ohci_freem __P((struct usbd_bus *, usb_dma_t *)); -usbd_status ohci_root_intr_transfer __P((usbd_request_handle)); -usbd_status ohci_root_intr_start __P((usbd_request_handle)); -void ohci_root_intr_abort __P((usbd_request_handle)); -void ohci_root_intr_close __P((usbd_pipe_handle)); -void ohci_root_intr_done __P((usbd_request_handle)); +static usbd_status ohci_root_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_root_ctrl_start __P((usbd_xfer_handle)); +static void ohci_root_ctrl_abort __P((usbd_xfer_handle)); +static void ohci_root_ctrl_close __P((usbd_pipe_handle)); -usbd_status ohci_device_ctrl_transfer __P((usbd_request_handle)); -usbd_status ohci_device_ctrl_start __P((usbd_request_handle)); -void ohci_device_ctrl_abort __P((usbd_request_handle)); -void ohci_device_ctrl_close __P((usbd_pipe_handle)); -void ohci_device_ctrl_done __P((usbd_request_handle)); +static usbd_status ohci_root_intr_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_root_intr_start __P((usbd_xfer_handle)); +static void ohci_root_intr_abort __P((usbd_xfer_handle)); +static void ohci_root_intr_close __P((usbd_pipe_handle)); +static void ohci_root_intr_done __P((usbd_xfer_handle)); -usbd_status ohci_device_bulk_transfer __P((usbd_request_handle)); -usbd_status ohci_device_bulk_start __P((usbd_request_handle)); -void ohci_device_bulk_abort __P((usbd_request_handle)); -void ohci_device_bulk_close __P((usbd_pipe_handle)); -void ohci_device_bulk_done __P((usbd_request_handle)); +static usbd_status ohci_device_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_device_ctrl_start __P((usbd_xfer_handle)); +static void ohci_device_ctrl_abort __P((usbd_xfer_handle)); +static void ohci_device_ctrl_close __P((usbd_pipe_handle)); +static void ohci_device_ctrl_done __P((usbd_xfer_handle)); -usbd_status ohci_device_intr_transfer __P((usbd_request_handle)); -usbd_status ohci_device_intr_start __P((usbd_request_handle)); -void ohci_device_intr_abort __P((usbd_request_handle)); -void ohci_device_intr_close __P((usbd_pipe_handle)); -void ohci_device_intr_done __P((usbd_request_handle)); +static usbd_status ohci_device_bulk_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_device_bulk_start __P((usbd_xfer_handle)); +static void ohci_device_bulk_abort __P((usbd_xfer_handle)); +static void ohci_device_bulk_close __P((usbd_pipe_handle)); +static void ohci_device_bulk_done __P((usbd_xfer_handle)); -usbd_status ohci_device_isoc_transfer __P((usbd_request_handle)); -usbd_status ohci_device_isoc_start __P((usbd_request_handle)); -void ohci_device_isoc_abort __P((usbd_request_handle)); -void ohci_device_isoc_close __P((usbd_pipe_handle)); -void ohci_device_isoc_done __P((usbd_request_handle)); +static usbd_status ohci_device_intr_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_device_intr_start __P((usbd_xfer_handle)); +static void ohci_device_intr_abort __P((usbd_xfer_handle)); +static void ohci_device_intr_close __P((usbd_pipe_handle)); +static void ohci_device_intr_done __P((usbd_xfer_handle)); -usbd_status ohci_device_setintr __P((ohci_softc_t *sc, - struct ohci_pipe *pipe, int ival)); +#if 0 +static usbd_status ohci_device_isoc_transfer __P((usbd_xfer_handle)); +static usbd_status ohci_device_isoc_start __P((usbd_xfer_handle)); +static void ohci_device_isoc_abort __P((usbd_xfer_handle)); +static void ohci_device_isoc_close __P((usbd_pipe_handle)); +static void ohci_device_isoc_done __P((usbd_xfer_handle)); +#endif -int ohci_str __P((usb_string_descriptor_t *, int, char *)); +static usbd_status ohci_device_setintr __P((ohci_softc_t *sc, + struct ohci_pipe *pipe, int ival)); -void ohci_timeout __P((void *)); -void ohci_rhsc_able __P((ohci_softc_t *, int)); +static int ohci_str __P((usb_string_descriptor_t *, int, char *)); -void ohci_close_pipe __P((usbd_pipe_handle pipe, - ohci_soft_ed_t *head)); -void ohci_abort_req __P((usbd_request_handle reqh, - usbd_status status)); -void ohci_abort_req_end __P((void *)); +static void ohci_timeout __P((void *)); +static void ohci_rhsc_able __P((ohci_softc_t *, int)); -void ohci_device_clear_toggle __P((usbd_pipe_handle pipe)); -void ohci_noop __P((usbd_pipe_handle pipe)); +static void ohci_close_pipe __P((usbd_pipe_handle pipe, + ohci_soft_ed_t *head)); +static void ohci_abort_req __P((usbd_xfer_handle xfer, + usbd_status status)); +static void ohci_abort_req_end __P((void *)); + +static void ohci_device_clear_toggle __P((usbd_pipe_handle pipe)); +static void ohci_noop __P((usbd_pipe_handle pipe)); #ifdef OHCI_DEBUG -ohci_softc_t *thesc; -void ohci_dumpregs __P((ohci_softc_t *)); -void ohci_dump_tds __P((ohci_soft_td_t *)); -void ohci_dump_td __P((ohci_soft_td_t *)); -void ohci_dump_ed __P((ohci_soft_ed_t *)); +static void ohci_dumpregs __P((ohci_softc_t *)); +static void ohci_dump_tds __P((ohci_soft_td_t *)); +static void ohci_dump_td __P((ohci_soft_td_t *)); +static void ohci_dump_ed __P((ohci_soft_ed_t *)); #endif #define OWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) @@ -214,7 +228,7 @@ struct ohci_pipe { struct { 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 { @@ -235,14 +249,14 @@ struct ohci_pipe { #define OHCI_INTR_ENDPT 1 -struct usbd_bus_methods ohci_bus_methods = { +static struct usbd_bus_methods ohci_bus_methods = { ohci_open, ohci_poll, ohci_allocm, ohci_freem, }; -struct usbd_pipe_methods ohci_root_ctrl_methods = { +static struct usbd_pipe_methods ohci_root_ctrl_methods = { ohci_root_ctrl_transfer, ohci_root_ctrl_start, ohci_root_ctrl_abort, @@ -251,7 +265,7 @@ struct usbd_pipe_methods ohci_root_ctrl_methods = { 0, }; -struct usbd_pipe_methods ohci_root_intr_methods = { +static struct usbd_pipe_methods ohci_root_intr_methods = { ohci_root_intr_transfer, ohci_root_intr_start, ohci_root_intr_abort, @@ -260,7 +274,7 @@ struct usbd_pipe_methods ohci_root_intr_methods = { ohci_root_intr_done, }; -struct usbd_pipe_methods ohci_device_ctrl_methods = { +static struct usbd_pipe_methods ohci_device_ctrl_methods = { ohci_device_ctrl_transfer, ohci_device_ctrl_start, ohci_device_ctrl_abort, @@ -269,7 +283,7 @@ struct usbd_pipe_methods ohci_device_ctrl_methods = { ohci_device_ctrl_done, }; -struct usbd_pipe_methods ohci_device_intr_methods = { +static struct usbd_pipe_methods ohci_device_intr_methods = { ohci_device_intr_transfer, ohci_device_intr_start, ohci_device_intr_abort, @@ -278,7 +292,7 @@ struct usbd_pipe_methods ohci_device_intr_methods = { ohci_device_intr_done, }; -struct usbd_pipe_methods ohci_device_bulk_methods = { +static struct usbd_pipe_methods ohci_device_bulk_methods = { ohci_device_bulk_transfer, ohci_device_bulk_start, ohci_device_bulk_abort, @@ -288,7 +302,7 @@ struct usbd_pipe_methods ohci_device_bulk_methods = { }; #if 0 -struct usbd_pipe_methods ohci_device_isoc_methods = { +static struct usbd_pipe_methods ohci_device_isoc_methods = { ohci_device_isoc_transfer, ohci_device_isoc_start, ohci_device_isoc_abort, @@ -298,20 +312,62 @@ struct usbd_pipe_methods ohci_device_isoc_methods = { }; #endif +#if defined(__NetBSD__) || defined(__OpenBSD__) +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(sc, flags) + struct ohci_softc *sc; + int flags; +{ + 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); +} +#endif + ohci_soft_ed_t * ohci_alloc_sed(sc) ohci_softc_t *sc; { ohci_soft_ed_t *sed; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freeeds) { + if (sc->sc_freeeds == NULL) { DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, OHCI_SED_SIZE * OHCI_SED_CHUNK, - OHCI_ED_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK, + OHCI_ED_ALIGN, &dma); + if (err) return (0); for(i = 0; i < OHCI_SED_CHUNK; i++) { offs = i * OHCI_SED_SIZE; @@ -342,15 +398,15 @@ ohci_alloc_std(sc) ohci_softc_t *sc; { ohci_soft_td_t *std; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freetds) { + if (sc->sc_freetds == NULL) { DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, OHCI_STD_SIZE * OHCI_STD_CHUNK, - OHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, + OHCI_TD_ALIGN, &dma); + if (err) return (0); for(i = 0; i < OHCI_STD_CHUNK; i++) { offs = i * OHCI_STD_SIZE; @@ -376,12 +432,93 @@ ohci_free_std(sc, std) sc->sc_freetds = 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); +} + +#if 0 +static 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); + } +} +#endif + usbd_status ohci_init(sc) ohci_softc_t *sc; { ohci_soft_ed_t *sed, *psed; - usbd_status r; + usbd_status err; int rev; int i; u_int32_t s, ctl, ival, hcr, fm, per; @@ -389,12 +526,13 @@ ohci_init(sc) DPRINTF(("ohci_init: start\n")); rev = OREAD4(sc, OHCI_REVISION); #if defined(__OpenBSD__) - printf(", OHCI version %d.%d%s\n", + printf(","); #else - printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev), + printf("%s", USBDEVNAME(sc->sc_bus.bdev)); #endif - OHCI_REV_HI(rev), OHCI_REV_LO(rev), + printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); + if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { printf("%s: unsupported OHCI revision\n", USBDEVNAME(sc->sc_bus.bdev)); @@ -405,25 +543,25 @@ ohci_init(sc) LIST_INIT(&sc->sc_hash_tds[i]); /* Allocate the HCCA area. */ - r = usb_allocmem(sc->sc_dmatag, OHCI_HCCA_SIZE, - OHCI_HCCA_ALIGN, &sc->sc_hccadma); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, + OHCI_HCCA_ALIGN, &sc->sc_hccadma); + if (err) + return (err); sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma); memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE); sc->sc_eintrs = OHCI_NORMAL_INTRS; sc->sc_ctrl_head = ohci_alloc_sed(sc); - if (!sc->sc_ctrl_head) { - r = USBD_NOMEM; + if (sc->sc_ctrl_head == NULL) { + err = USBD_NOMEM; goto bad1; } sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP); sc->sc_bulk_head = ohci_alloc_sed(sc); - if (!sc->sc_bulk_head) { - r = USBD_NOMEM; + if (sc->sc_bulk_head == NULL) { + err = USBD_NOMEM; goto bad2; } sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP); @@ -431,10 +569,10 @@ ohci_init(sc) /* Allocate all the dummy EDs that make up the interrupt tree. */ for (i = 0; i < OHCI_NO_EDS; i++) { sed = ohci_alloc_sed(sc); - if (!sed) { + if (sed == NULL) { while (--i >= 0) ohci_free_sed(sc, sc->sc_eds[i]); - r = USBD_NOMEM; + err = USBD_NOMEM; goto bad3; } /* All ED fields are set to 0. */ @@ -462,7 +600,7 @@ ohci_init(sc) s = OREAD4(sc, OHCI_COMMAND_STATUS); OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR); for (i = 0; i < 100 && (ctl & OHCI_IR); i++) { - delay(1000); + usb_delay_ms(&sc->sc_bus, 1); ctl = OREAD4(sc, OHCI_CONTROL); } if ((ctl & OHCI_IR) == 0) { @@ -476,13 +614,13 @@ ohci_init(sc) DPRINTF(("ohci_init: BIOS active\n")); if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) { OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL); - delay(USB_RESUME_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); } } else { DPRINTF(("ohci_init: cold started\n")); reset: /* Controller was cold started. */ - delay(USB_BUS_RESET_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); } /* @@ -491,7 +629,7 @@ ohci_init(sc) */ DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev))); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - delay(USB_BUS_RESET_DELAY * 1000); + usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* We now own the host controller and the bus has been reset. */ ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL)); @@ -506,11 +644,10 @@ ohci_init(sc) } if (hcr) { printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - r = USBD_IOERROR; + err = USBD_IOERROR; goto bad3; } #ifdef OHCI_DEBUG - thesc = sc; if (ohcidebug > 15) ohci_dumpregs(sc); #endif @@ -521,8 +658,10 @@ ohci_init(sc) OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma)); OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); + /* disable all interrupts and then switch on all desired interrupts */ OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE); + /* switch on desired functional features */ ctl = OREAD4(sc, OHCI_CONTROL); ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR); ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE | @@ -554,9 +693,7 @@ ohci_init(sc) sc->sc_bus.methods = &ohci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); -#if defined(__NetBSD__) - powerhook_establish(ohci_power, sc); -#endif + sc->sc_powerhook = powerhook_establish(ohci_power, sc); return (USBD_NORMAL_COMPLETION); @@ -565,8 +702,8 @@ ohci_init(sc) bad2: ohci_free_sed(sc, sc->sc_bulk_head); bad1: - usb_freemem(sc->sc_dmatag, &sc->sc_hccadma); - return (r); + usb_freemem(&sc->sc_bus, &sc->sc_hccadma); + return (err); } usbd_status @@ -579,7 +716,7 @@ ohci_allocm(bus, dma, size) struct ohci_softc *sc = (struct ohci_softc *)bus; #endif - return (usb_allocmem(sc->sc_dmatag, size, 0, dma)); + return (usb_allocmem(&sc->sc_bus, size, 0, dma)); } void @@ -591,7 +728,7 @@ ohci_freem(bus, dma) struct ohci_softc *sc = (struct ohci_softc *)bus; #endif - usb_freemem(sc->sc_dmatag, dma); + usb_freemem(&sc->sc_bus, dma); } #if defined(__NetBSD__) @@ -608,12 +745,9 @@ ohci_power(why, v) ohci_dumpregs(sc); #endif } -#endif /* !defined(__OpenBSD__) */ +#endif /* defined(__NetBSD__) */ #ifdef OHCI_DEBUG -void ohcidump(void); -void ohcidump(void) { ohci_dumpregs(thesc); } - void ohci_dumpregs(sc) ohci_softc_t *sc; @@ -655,11 +789,25 @@ ohci_dumpregs(sc) } #endif +static int ohci_intr1 __P((ohci_softc_t *)); + int ohci_intr(p) void *p; { ohci_softc_t *sc = p; + + /* If we get an interrupt while polling, then just ignore it. */ + if (sc->sc_bus.use_polling) + return (0); + + return (ohci_intr1(sc)); +} + +static int +ohci_intr1(sc) + ohci_softc_t *sc; +{ u_int32_t intrs, eintrs; ohci_physaddr_t done; @@ -681,15 +829,18 @@ ohci_intr(p) intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS); } else intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); + if (!intrs) return (0); + intrs &= ~OHCI_MIE; OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */ eintrs = intrs & sc->sc_eintrs; 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)); @@ -714,7 +865,7 @@ ohci_intr(p) /* XXX what else */ } if (eintrs & OHCI_RHSC) { - ohci_rhsc(sc, sc->sc_intrreqh); + ohci_rhsc(sc, sc->sc_intrxfer); intrs &= ~OHCI_RHSC; /* @@ -724,6 +875,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; @@ -769,8 +922,8 @@ ohci_process_done(sc, done) ohci_softc_t *sc; ohci_physaddr_t done; { - ohci_soft_td_t *std, *sdone; - usbd_request_handle reqh; + ohci_soft_td_t *std, *sdone, *stdnext; + usbd_xfer_handle xfer; int len, cc; DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done)); @@ -789,133 +942,138 @@ ohci_process_done(sc, done) } #endif - for (std = sdone; std; std = std->dnext) { - reqh = std->reqh; - DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n", - std, reqh, reqh->hcpriv)); + for (std = sdone; std; std = stdnext) { + xfer = std->xfer; + stdnext = std->dnext; + DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", + std, xfer, xfer->hcpriv)); cc = OHCI_TD_GET_CC(LE(std->td.td_flags)); - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) { + usb_untimeout(ohci_timeout, xfer, xfer->timo_handle); + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { DPRINTF(("ohci_process_done: cancel/timeout %p\n", - reqh)); + xfer)); /* Handled by abort routine. */ - 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) + xfer->actlen += len; if (std->flags & OHCI_CALL_DONE) { - reqh->status = USBD_NORMAL_COMPLETION; - usb_transfer_complete(reqh); + xfer->status = USBD_NORMAL_COMPLETION; + usb_transfer_complete(xfer); } + ohci_hash_rem_td(sc, std); + ohci_free_std(sc, std); } else { - 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) { + ohci_soft_td_t *p, *n; + struct ohci_pipe *opipe = + (struct ohci_pipe *)xfer->pipe; + + DPRINTF(("ohci_process_done: error cc=%d (%s)\n", + OHCI_TD_GET_CC(LE(std->td.td_flags)), + ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))])); + + /* remove TDs */ + for (p = std; p->xfer == xfer; 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; + xfer->status = USBD_STALLED; else - reqh->status = USBD_IOERROR; - usb_transfer_complete(reqh); + xfer->status = USBD_IOERROR; + usb_transfer_complete(xfer); } - ohci_hash_rem_td(sc, std); - ohci_free_std(sc, std); } } void -ohci_device_ctrl_done(reqh) - usbd_request_handle reqh; +ohci_device_ctrl_done(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh)); + DPRINTFN(10,("ohci_ctrl_done: xfer=%p\n", xfer)); #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) { + if (!(xfer->rqflags & URQ_REQUEST)) { panic("ohci_ctrl_done: not a request\n"); } #endif - reqh->hcpriv = 0; + xfer->hcpriv = NULL; } void -ohci_device_intr_done(reqh) - usbd_request_handle reqh; +ohci_device_intr_done(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *xfer, *tail; + ohci_soft_td_t *data, *tail; - DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n", - reqh, reqh->actlen)); + DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n", + xfer, xfer->actlen)); - reqh->hcpriv = 0; + xfer->hcpriv = NULL; - if (reqh->pipe->repeat) { - xfer = opipe->tail; + if (xfer->pipe->repeat) { + data = opipe->tail; tail = ohci_alloc_std(sc); /* XXX should reuse TD */ - if (!tail) { - reqh->status = USBD_NOMEM; + if (tail == NULL) { + xfer->status = USBD_NOMEM; return; } - tail->reqh = 0; + tail->xfer = NULL; - 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(&reqh->dmabuf)); - 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; + if (xfer->flags & USBD_SHORT_XFER_OK) + data->td.td_flags |= LE(OHCI_TD_R); + data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf)); + data->nexttd = tail; + data->td.td_nexttd = LE(tail->physaddr); + data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1); + data->len = xfer->length; + data->xfer = xfer; + data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; + xfer->hcpriv = data; + xfer->actlen = 0; - ohci_hash_add_td(sc, xfer); + ohci_hash_add_td(sc, data); sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; } } void -ohci_device_bulk_done(reqh) - usbd_request_handle reqh; +ohci_device_bulk_done(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n", - reqh, reqh->actlen)); + DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n", + xfer, xfer->actlen)); - reqh->hcpriv = 0; + xfer->hcpriv = NULL; } void -ohci_rhsc(sc, reqh) +ohci_rhsc(sc, xfer) ohci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { usbd_pipe_handle pipe; struct ohci_pipe *opipe; @@ -924,36 +1082,36 @@ ohci_rhsc(sc, reqh) int hstatus; hstatus = OREAD4(sc, OHCI_RH_STATUS); - DPRINTF(("ohci_rhsc: sc=%p reqh=%p hstatus=0x%08x\n", - sc, reqh, hstatus)); + DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", + sc, xfer, hstatus)); - if (reqh == 0) { + if (xfer == NULL) { /* Just ignore the change. */ return; } - pipe = reqh->pipe; + pipe = xfer->pipe; opipe = (struct ohci_pipe *)pipe; - p = KERNADDR(&reqh->dmabuf); - m = min(sc->sc_noport, reqh->length * 8 - 1); - memset(p, 0, reqh->length); + p = KERNADDR(&xfer->dmabuf); + m = min(sc->sc_noport, xfer->length * 8 - 1); + memset(p, 0, xfer->length); for (i = 1; i <= m; i++) { if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16) p[i/8] |= 1 << (i%8); } DPRINTF(("ohci_rhsc: change=0x%02x\n", *p)); - reqh->actlen = reqh->length; - reqh->status = USBD_NORMAL_COMPLETION; + xfer->actlen = xfer->length; + xfer->status = USBD_NORMAL_COMPLETION; - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); } void -ohci_root_intr_done(reqh) - usbd_request_handle reqh; +ohci_root_intr_done(xfer) + usbd_xfer_handle xfer; { - reqh->hcpriv = 0; + xfer->hcpriv = NULL; } /* @@ -962,15 +1120,15 @@ ohci_root_intr_done(reqh) * too long. */ void -ohci_waitintr(sc, reqh) +ohci_waitintr(sc, xfer) ohci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { - int timo = reqh->timeout; + int timo = xfer->timeout; int usecs; u_int32_t intrs; - reqh->status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { usb_delay_ms(&sc->sc_bus, 1); intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; @@ -980,16 +1138,16 @@ ohci_waitintr(sc, reqh) ohci_dumpregs(sc); #endif if (intrs) { - ohci_intr(sc); - if (reqh->status != USBD_IN_PROGRESS) + ohci_intr1(sc); + if (xfer->status != USBD_IN_PROGRESS) return; } } /* Timeout */ DPRINTF(("ohci_waitintr: timeout\n")); - reqh->status = USBD_TIMEOUT; - usb_transfer_complete(reqh); + xfer->status = USBD_TIMEOUT; + usb_transfer_complete(xfer); /* XXX should free TD */ } @@ -1000,23 +1158,23 @@ ohci_poll(bus) ohci_softc_t *sc = (ohci_softc_t *)bus; if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) - ohci_intr(sc); + ohci_intr1(sc); } usbd_status -ohci_device_request(reqh) - usbd_request_handle reqh; +ohci_device_request(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; - usb_device_request_t *req = &reqh->request; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; + usb_device_request_t *req = &xfer->request; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; int addr = dev->address; - ohci_soft_td_t *setup, *xfer = 0, *stat, *next, *tail; + ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail; ohci_soft_ed_t *sed; int isread; int len; - usbd_status r; + usbd_status err; int s; isread = req->bmRequestType & UT_READ; @@ -1030,16 +1188,16 @@ ohci_device_request(reqh) setup = opipe->tail; stat = ohci_alloc_std(sc); - if (!stat) { - r = USBD_NOMEM; + if (stat == NULL) { + err = USBD_NOMEM; goto bad1; } tail = ohci_alloc_std(sc); - if (!tail) { - r = USBD_NOMEM; + if (tail == NULL) { + err = USBD_NOMEM; goto bad2; } - tail->reqh = 0; + tail->xfer = NULL; sed = opipe->sed; opipe->u.ctl.length = len; @@ -1053,28 +1211,29 @@ ohci_device_request(reqh) /* Set up data transaction */ if (len != 0) { - xfer = ohci_alloc_std(sc); - if (!xfer) { - r = USBD_NOMEM; + data = ohci_alloc_std(sc); + if (data == NULL) { + err = USBD_NOMEM; goto bad3; } - 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(&reqh->dmabuf)); - 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; + (xfer->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0)); + data->td.td_cbp = LE(DMAADDR(&xfer->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->xfer = xfer; + data->flags = OHCI_ADD_LEN; - next = xfer; + 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); @@ -1086,9 +1245,9 @@ ohci_device_request(reqh) setup->td.td_nexttd = LE(next->physaddr); setup->td.td_be = LE(LE(setup->td.td_cbp) + sizeof *req - 1); setup->len = 0; /* XXX The number of byte we count */ - setup->reqh = reqh; + setup->xfer = xfer; setup->flags = 0; - reqh->hcpriv = setup; + xfer->hcpriv = setup; stat->td.td_flags = LE( (isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC | @@ -1098,7 +1257,7 @@ ohci_device_request(reqh) stat->td.td_nexttd = LE(tail->physaddr); stat->td.td_be = 0; stat->len = 0; - stat->reqh = reqh; + stat->xfer = xfer; #ifdef OHCI_DEBUG if (ohcidebug > 5) { @@ -1112,30 +1271,25 @@ 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; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(ohci_timeout, reqh, - MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, xfer, + MS_TO_TICKS(xfer->timeout), xfer->timo_handle); } splx(s); -#if 0 - This goes horribly wrong, printing thousands of descriptors, - because false references are followed due to the fact that the - TD is gone. #ifdef OHCI_DEBUG if (ohcidebug > 5) { - delay(5000); + usb_delay_ms(&sc->sc_bus, 5); DPRINTF(("ohci_device_request: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); ohci_dump_tds(setup); } -#endif #endif return (USBD_NORMAL_COMPLETION); @@ -1145,7 +1299,7 @@ ohci_device_request(reqh) bad2: ohci_free_std(sc, stat); bad1: - return (r); + return (err); } /* @@ -1156,6 +1310,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; @@ -1172,10 +1327,12 @@ ohci_rem_ed(sed, head) { ohci_soft_ed_t *p; + SPLUSBCHECK; + /* XXX */ - for (p = head; p && p->next != sed; p = p->next) + for (p = head; p == NULL && p->next != sed; p = p->next) ; - if (!p) + if (p == NULL) panic("ohci_rem_ed: ED not found\n"); p->next = sed->next; p->ed.ed_nexted = sed->ed.ed_nexted; @@ -1200,6 +1357,8 @@ ohci_hash_add_td(sc, std) { int h = HASH(std->physaddr); + SPLUSBCHECK; + LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); } @@ -1209,6 +1368,8 @@ ohci_hash_rem_td(sc, std) ohci_softc_t *sc; ohci_soft_td_t *std; { + SPLUSBCHECK; + LIST_REMOVE(std, hnext); } @@ -1221,7 +1382,7 @@ ohci_hash_find_td(sc, a) ohci_soft_td_t *std; for (std = LIST_FIRST(&sc->sc_hash_tds[h]); - std != 0; + std != NULL; std = LIST_NEXT(std, hnext)) if (std->physaddr == a) return (std); @@ -1232,10 +1393,16 @@ void ohci_timeout(addr) void *addr; { - usbd_request_handle reqh = addr; + usbd_xfer_handle xfer = addr; + int s; - DPRINTF(("ohci_timeout: reqh=%p\n", reqh)); - ohci_abort_req(reqh, USBD_TIMEOUT); + DPRINTF(("ohci_timeout: xfer=%p\n", xfer)); + + s = splusb(); + xfer->device->bus->intr_context++; + ohci_abort_req(xfer, USBD_TIMEOUT); + xfer->device->bus->intr_context--; + splx(s); } #ifdef OHCI_DEBUG @@ -1276,7 +1443,7 @@ ohci_dump_ed(sed) (int)LE(sed->ed.ed_flags), "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO", (u_long)LE(sed->ed.ed_tailp), - (int)LE(sed->ed.ed_headp), + (u_long)LE(sed->ed.ed_headp), "\20\1HALT\2CARRY", (u_long)LE(sed->ed.ed_nexted))); } @@ -1293,7 +1460,7 @@ ohci_open(pipe) u_int8_t addr = dev->address; ohci_soft_ed_t *sed; ohci_soft_td_t *std; - usbd_status r; + usbd_status err; int s; DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", @@ -1311,10 +1478,10 @@ ohci_open(pipe) } } else { sed = ohci_alloc_sed(sc); - if (sed == 0) + if (sed == NULL) goto bad0; std = ohci_alloc_std(sc); - if (std == 0) + if (std == NULL) goto bad1; opipe->sed = sed; opipe->tail = std; @@ -1331,10 +1498,10 @@ ohci_open(pipe) switch (ed->bmAttributes & UE_XFERTYPE) { case UE_CONTROL: pipe->methods = &ohci_device_ctrl_methods; - r = usb_allocmem(sc->sc_dmatag, - sizeof(usb_device_request_t), - 0, &opipe->u.ctl.reqdma); - if (r != USBD_NORMAL_COMPLETION) + err = usb_allocmem(&sc->sc_bus, + sizeof(usb_device_request_t), + 0, &opipe->u.ctl.reqdma); + if (err) goto bad; s = splusb(); ohci_add_ed(sed, sc->sc_ctrl_head); @@ -1387,7 +1554,7 @@ ohci_close_pipe(pipe, head) ohci_physaddr_t td = sed->ed.ed_headp; ohci_soft_td_t *std; for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]); - std != 0; + std != NULL; std = LIST_NEXT(std, hnext)) if (std->physaddr == td) break; @@ -1418,28 +1585,33 @@ ohci_close_pipe(pipe, head) * interrupt processing to process it. */ void -ohci_abort_req(reqh, status) - usbd_request_handle reqh; +ohci_abort_req(xfer, status) + usbd_xfer_handle xfer; usbd_status status; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_soft_ed_t *sed; - DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe)); + DPRINTF(("ohci_abort_req: xfer=%p pipe=%p\n", xfer, opipe)); - reqh->status = status; + xfer->status = status; - usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); + usb_untimeout(ohci_timeout, xfer, xfer->timo_handle); sed = opipe->sed; DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed)); sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */ - if (curproc) { - usb_delay_ms(opipe->pipe.device->bus, 1); - ohci_abort_req_end(reqh); + if (xfer->device->bus->intr_context) { + /* We have no process context, so we can't use tsleep(). */ + timeout(ohci_abort_req_end, xfer, hz / USB_FRAMES_PER_SECOND); } else { - timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); +#if defined(DIAGNOSTIC) && defined(__i386__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + usb_delay_ms(opipe->pipe.device->bus, 1); + ohci_abort_req_end(xfer); } } @@ -1447,8 +1619,8 @@ void ohci_abort_req_end(v) void *v; { - usbd_request_handle reqh = v; - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + usbd_xfer_handle xfer = v; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; ohci_soft_ed_t *sed; ohci_soft_td_t *p, *n; @@ -1456,14 +1628,14 @@ ohci_abort_req_end(v) s = splusb(); - p = reqh->hcpriv; + p = xfer->hcpriv; #ifdef DIAGNOSTIC - if (!p) { + if (p == NULL) { printf("ohci_abort_req: hcpriv==0\n"); return; } #endif - for (; p->reqh == reqh; p = n) { + for (; p->xfer == xfer; p = n) { n = p->nexttd; ohci_hash_rem_td(sc, p); ohci_free_std(sc, p); @@ -1475,7 +1647,7 @@ ohci_abort_req_end(v) sed->ed.ed_headp = p->physaddr; /* unlink TDs */ sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */ - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); } @@ -1483,7 +1655,7 @@ ohci_abort_req_end(v) /* * Data structures and routines to emulate the root hub. */ -usb_device_descriptor_t ohci_devd = { +static usb_device_descriptor_t ohci_devd = { USB_DEVICE_DESCRIPTOR_SIZE, UDESC_DEVICE, /* type */ {0x00, 0x01}, /* USB version */ @@ -1496,7 +1668,7 @@ usb_device_descriptor_t ohci_devd = { 1 /* # of configurations */ }; -usb_config_descriptor_t ohci_confd = { +static usb_config_descriptor_t ohci_confd = { USB_CONFIG_DESCRIPTOR_SIZE, UDESC_CONFIG, {USB_CONFIG_DESCRIPTOR_SIZE + @@ -1509,7 +1681,7 @@ usb_config_descriptor_t ohci_confd = { 0 /* max power */ }; -usb_interface_descriptor_t ohci_ifcd = { +static usb_interface_descriptor_t ohci_ifcd = { USB_INTERFACE_DESCRIPTOR_SIZE, UDESC_INTERFACE, 0, @@ -1521,7 +1693,7 @@ usb_interface_descriptor_t ohci_ifcd = { 0 }; -usb_endpoint_descriptor_t ohci_endpd = { +static usb_endpoint_descriptor_t ohci_endpd = { USB_ENDPOINT_DESCRIPTOR_SIZE, UDESC_ENDPOINT, UE_DIR_IN | OHCI_INTR_ENDPT, @@ -1530,7 +1702,7 @@ usb_endpoint_descriptor_t ohci_endpd = { 255 }; -usb_hub_descriptor_t ohci_hubd = { +static usb_hub_descriptor_t ohci_hubd = { USB_HUB_DESCRIPTOR_SIZE, UDESC_HUB, 0, @@ -1540,7 +1712,7 @@ usb_hub_descriptor_t ohci_hubd = { {0}, }; -int +static int ohci_str(p, l, s) usb_string_descriptor_t *p; int l; @@ -1563,39 +1735,41 @@ ohci_str(p, l, s) /* * Simulate a hardware hub by handling all the necessary requests. */ -usbd_status -ohci_root_ctrl_transfer(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_root_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (ohci_root_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running, start first */ + return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } -usbd_status -ohci_root_ctrl_start(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_root_ctrl_start(xfer) + usbd_xfer_handle xfer; { - ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus; + ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; usb_device_request_t *req; void *buf = NULL; int port, i; - int 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; + usbd_status err; u_int32_t v; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) /* XXX panic */ return (USBD_INVAL); #endif - req = &reqh->request; + req = &xfer->request; DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); @@ -1605,7 +1779,7 @@ ohci_root_ctrl_start(reqh) index = UGETW(req->wIndex); if (len != 0) - buf = KERNADDR(&reqh->dmabuf); + buf = KERNADDR(&xfer->dmabuf); #define C(x,y) ((x) | ((y) << 8)) switch(C(req->bRequest, req->bmRequestType)) { @@ -1628,7 +1802,7 @@ ohci_root_ctrl_start(reqh) switch(value >> 8) { case UDESC_DEVICE: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); @@ -1637,7 +1811,7 @@ ohci_root_ctrl_start(reqh) break; case UDESC_CONFIG: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); @@ -1668,7 +1842,7 @@ ohci_root_ctrl_start(reqh) } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -1693,14 +1867,14 @@ ohci_root_ctrl_start(reqh) break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): if (value >= USB_MAX_DEVICES) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_addr = value; break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): if (value != 0 && value != 1) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_conf = value; @@ -1710,7 +1884,7 @@ ohci_root_ctrl_start(reqh) case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): break; @@ -1724,7 +1898,7 @@ ohci_root_ctrl_start(reqh) "port=%d feature=%d\n", index, value)); if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } port = OHCI_RH_PORT_STATUS(index); @@ -1754,7 +1928,7 @@ ohci_root_ctrl_start(reqh) OWRITE4(sc, port, UPS_C_PORT_RESET << 16); break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -1773,7 +1947,7 @@ ohci_root_ctrl_start(reqh) break; case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if (value != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); @@ -1795,7 +1969,7 @@ ohci_root_ctrl_start(reqh) break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } memset(buf, 0, len); /* ? XXX */ @@ -1805,11 +1979,11 @@ ohci_root_ctrl_start(reqh) DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n", index)); if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } v = OREAD4(sc, OHCI_RH_PORT_STATUS(index)); @@ -1822,13 +1996,13 @@ ohci_root_ctrl_start(reqh) totlen = l; break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): if (index < 1 || index > sc->sc_noport) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } port = OHCI_RH_PORT_STATUS(index); @@ -1857,32 +2031,34 @@ ohci_root_ctrl_start(reqh) OWRITE4(sc, port, UPS_PORT_POWER); break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } - reqh->actlen = totlen; - r = USBD_NORMAL_COMPLETION; + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; ret: - reqh->status = r; - usb_transfer_complete(reqh); + xfer->status = err; + s = splusb(); + usb_transfer_complete(xfer); + splx(s); return (USBD_IN_PROGRESS); } /* Abort a root control request. */ -void -ohci_root_ctrl_abort(reqh) - usbd_request_handle reqh; +static void +ohci_root_ctrl_abort(xfer) + usbd_xfer_handle xfer; { /* Nothing to do, all transfers are synchronous. */ } /* Close the root pipe. */ -void +static void ohci_root_ctrl_close(pipe) usbd_pipe_handle pipe; { @@ -1890,41 +2066,52 @@ ohci_root_ctrl_close(pipe) /* Nothing to do. */ } -usbd_status -ohci_root_intr_transfer(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_root_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (ohci_root_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running, start first */ + return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } -usbd_status -ohci_root_intr_start(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_root_intr_start(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - sc->sc_intrreqh = reqh; + sc->sc_intrxfer = xfer; return (USBD_IN_PROGRESS); } /* Abort a root interrupt request. */ -void -ohci_root_intr_abort(reqh) - usbd_request_handle reqh; +static void +ohci_root_intr_abort(xfer) + usbd_xfer_handle xfer; { - /* No need to abort. */ + int s; + + if (xfer->pipe->intrxfer == xfer) { + DPRINTF(("ohci_root_intr_abort: remove\n")); + xfer->pipe->intrxfer = NULL; + } + xfer->status = USBD_CANCELLED; + s = splusb(); + usb_transfer_complete(xfer); + splx(s); } /* Close the root pipe. */ -void +static void ohci_root_intr_close(pipe) usbd_pipe_handle pipe; { @@ -1932,59 +2119,61 @@ ohci_root_intr_close(pipe) DPRINTF(("ohci_root_intr_close\n")); - sc->sc_intrreqh = 0; + sc->sc_intrxfer = NULL; } /************************/ -usbd_status -ohci_device_ctrl_transfer(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (ohci_device_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running, start first */ + return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } -usbd_status -ohci_device_ctrl_start(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_ctrl_start(xfer) + usbd_xfer_handle xfer; { - ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus; - usbd_status r; + ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) { + if (!(xfer->rqflags & URQ_REQUEST)) { /* XXX panic */ printf("ohci_device_ctrl_transfer: not a request\n"); return (USBD_INVAL); } #endif - r = ohci_device_request(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = ohci_device_request(xfer); + if (err) + return (err); if (sc->sc_bus.use_polling) - ohci_waitintr(sc, reqh); + ohci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } /* Abort a device control request. */ -void -ohci_device_ctrl_abort(reqh) - usbd_request_handle reqh; +static void +ohci_device_ctrl_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh)); - ohci_abort_req(reqh, USBD_CANCELLED); + DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); + ohci_abort_req(xfer, USBD_CANCELLED); } /* Close a device control pipe. */ -void +static void ohci_device_ctrl_close(pipe) usbd_pipe_handle pipe; { @@ -1996,7 +2185,7 @@ ohci_device_ctrl_close(pipe) /************************/ -void +static void ohci_device_clear_toggle(pipe) usbd_pipe_handle pipe; { @@ -2005,113 +2194,111 @@ ohci_device_clear_toggle(pipe) opipe->sed->ed.ed_tailp &= LE(~OHCI_TOGGLECARRY); } -void +static void ohci_noop(pipe) usbd_pipe_handle pipe; { } -usbd_status -ohci_device_bulk_transfer(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_bulk_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (ohci_device_bulk_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running, start first */ + return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } -usbd_status -ohci_device_bulk_start(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_bulk_start(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; int addr = dev->address; - ohci_soft_td_t *xfer, *tail; + ohci_soft_td_t *data, *tail, *tdp; ohci_soft_ed_t *sed; int s, len, isread, endpt; + usbd_status err; #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) { + if (xfer->rqflags & URQ_REQUEST) { /* XXX panic */ printf("ohci_device_bulk_start: a request\n"); return (USBD_INVAL); } #endif - len = reqh->length; - endpt = reqh->pipe->endpoint->edesc->bEndpointAddress; + len = xfer->length; + endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sed = opipe->sed; - DPRINTFN(4,("ohci_device_bulk_start: reqh=%p len=%d isread=%d " - "flags=%d endpt=%d\n", reqh, len, isread, reqh->flags, + DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " + "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, endpt)); opipe->u.bulk.isread = isread; opipe->u.bulk.length = len; - tail = ohci_alloc_std(sc); - if (!tail) - return (USBD_NOMEM); - 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(&reqh->dmabuf)); - 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; + /* Allocate a chain of new TDs (including a new tail). */ + data = opipe->tail; + err = ohci_alloc_std_chain(opipe, sc, len, isread, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, data, &tail); + if (err) + return (err); + + tail->xfer = NULL; + xfer->hcpriv = data; DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " "td_cbp=0x%08x td_be=0x%08x\n", - (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 OHCI_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->xfer = xfer; + ohci_hash_add_td(sc, tdp); + } sed->ed.ed_tailp = LE(tail->physaddr); opipe->tail = tail; sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(ohci_timeout, reqh, - MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, xfer, + MS_TO_TICKS(xfer->timeout), xfer->timo_handle); } -#ifdef OHCI_DEBUG +#if 0 +/* This goes wrong if we are too slow. */ if (ohcidebug > 5) { - delay(5000); + usb_delay_ms(&sc->sc_bus, 5); DPRINTF(("ohci_device_intr_transfer: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); - ohci_dump_tds(xfer); + ohci_dump_tds(data); } #endif @@ -2120,18 +2307,18 @@ ohci_device_bulk_start(reqh) return (USBD_IN_PROGRESS); } -void -ohci_device_bulk_abort(reqh) - usbd_request_handle reqh; +static void +ohci_device_bulk_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh)); - ohci_abort_req(reqh, USBD_CANCELLED); + DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); + ohci_abort_req(xfer, USBD_CANCELLED); } /* * Close a device bulk pipe. */ -void +static void ohci_device_bulk_close(pipe) usbd_pipe_handle pipe; { @@ -2143,88 +2330,92 @@ ohci_device_bulk_close(pipe) /************************/ -usbd_status -ohci_device_intr_transfer(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (ohci_device_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running, start first */ + return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } -usbd_status -ohci_device_intr_start(reqh) - usbd_request_handle reqh; +static usbd_status +ohci_device_intr_start(xfer) + usbd_xfer_handle xfer; { - struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; usbd_device_handle dev = opipe->pipe.device; ohci_softc_t *sc = (ohci_softc_t *)dev->bus; ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *xfer, *tail; + ohci_soft_td_t *data, *tail; int len; int s; - DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p len=%d " + DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d " "flags=%d priv=%p\n", - reqh, reqh->length, reqh->flags, reqh->priv)); + xfer, xfer->length, xfer->flags, xfer->priv)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("ohci_device_intr_transfer: a request\n"); #endif - len = reqh->length; + len = xfer->length; - xfer = opipe->tail; + data = opipe->tail; tail = ohci_alloc_std(sc); - if (!tail) + if (tail == NULL) return (USBD_NOMEM); - tail->reqh = 0; + tail->xfer = NULL; - 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(&reqh->dmabuf)); - 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 (xfer->flags & USBD_SHORT_XFER_OK) + data->td.td_flags |= LE(OHCI_TD_R); + data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf)); + data->nexttd = tail; + data->td.td_nexttd = LE(tail->physaddr); + data->td.td_be = LE(LE(data->td.td_cbp) + len - 1); + data->len = len; + data->xfer = xfer; + data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; + xfer->hcpriv = data; #ifdef OHCI_DEBUG if (ohcidebug > 5) { 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); #if 0 - this goes wrong if we are too slow with dumping the TDs -#ifdef OHCI_DEBUG +/* + * This goes horribly wrong, printing thousands of descriptors, + * because false references are followed due to the fact that the + * TD is gone. + */ if (ohcidebug > 5) { - delay(5000); + usb_delay_ms(&sc->sc_bus, 5); DPRINTF(("ohci_device_intr_transfer: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); ohci_dump_ed(sed); - ohci_dump_tds(xfer); + ohci_dump_tds(data); } -#endif #endif splx(s); @@ -2232,19 +2423,19 @@ ohci_device_intr_start(reqh) } /* Abort a device control request. */ -void -ohci_device_intr_abort(reqh) - usbd_request_handle reqh; +static void +ohci_device_intr_abort(xfer) + usbd_xfer_handle xfer; { - if (reqh->pipe->intrreqh == reqh) { + if (xfer->pipe->intrxfer == xfer) { DPRINTF(("ohci_device_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = NULL; } - ohci_abort_req(reqh, USBD_CANCELLED); + ohci_abort_req(xfer, USBD_CANCELLED); } /* Close a device interrupt pipe. */ -void +static void ohci_device_intr_close(pipe) usbd_pipe_handle pipe; { @@ -2266,8 +2457,10 @@ ohci_device_intr_close(pipe) for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) ; - if (!p) +#ifdef DIAGNOSTIC + if (p == NULL) panic("ohci_device_intr_close: ED not found\n"); +#endif p->next = sed->next; p->ed.ed_nexted = sed->ed.ed_nexted; splx(s); @@ -2279,7 +2472,7 @@ ohci_device_intr_close(pipe) ohci_free_sed(sc, opipe->sed); } -usbd_status +static usbd_status ohci_device_setintr(sc, opipe, ival) ohci_softc_t *sc; struct ohci_pipe *opipe; @@ -2343,4 +2536,3 @@ ohci_device_setintr(sc, opipe, ival) DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); return (USBD_NORMAL_COMPLETION); } - diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h index b56b017d6ca1..ba75709cafee 100644 --- a/sys/dev/usb/ohcireg.h +++ b/sys/dev/usb/ohcireg.h @@ -1,5 +1,6 @@ /* $NetBSD: ohcireg.h,v 1.8 1999/08/22 23:41:00 augustss Exp $ */ -/* $FreeBSD$ */ +/* $FreeBSD$ */ + /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -140,6 +141,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 b0abd151de74..cd61ee6fd397 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,5 +1,5 @@ -/* $NetBSD: ohcivar.h,v 1.8 1999/08/22 23:41:00 augustss Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: ohcivar.h,v 1.13 1999/10/13 08:10:55 augustss Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -52,11 +52,11 @@ typedef struct ohci_soft_td { struct ohci_soft_td *dnext; /* next in done list */ ohci_physaddr_t physaddr; LIST_ENTRY(ohci_soft_td) hnext; - usbd_request_handle reqh; + usbd_xfer_handle xfer; u_int16_t len; u_int16_t flags; #define OHCI_CALL_DONE 0x0001 -#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 @@ -69,12 +69,6 @@ typedef struct ohci_softc { struct usbd_bus sc_bus; /* base device */ bus_space_tag_t iot; bus_space_handle_t ioh; -#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__) */ usb_dma_t sc_hccadma; struct ohci_hcca *sc_hcca; @@ -94,15 +88,20 @@ typedef struct ohci_softc { ohci_soft_ed_t *sc_freeeds; ohci_soft_td_t *sc_freetds; - usbd_request_handle sc_intrreqh; - - int sc_intrs; + usbd_xfer_handle sc_intrxfer; 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 *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +int ohci_detach __P((ohci_softc_t *, int)); +int ohci_activate __P((device_ptr_t, enum devact)); +#endif #define MS_TO_TICKS(ms) ((ms) * hz / 1000) diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index 2d433d4b6053..5c3916040a24 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,4 +1,4 @@ -/* $NetBSD: ugen.c,v 1.23 1999/09/09 12:26:44 augustss Exp $ */ +/* $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -97,7 +97,7 @@ struct ugen_softc { USBBASEDEVICE sc_dev; /* base device */ usbd_device_handle sc_udev; - char sc_is_open[USB_MAX_ENDPOINTS][2]; + char sc_is_open[USB_MAX_ENDPOINTS]; struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; #define OUT 0 #define IN 1 @@ -136,18 +136,18 @@ static struct cdevsw ugen_cdevsw = { }; #endif -void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr, - usbd_status status)); +static void ugenintr __P((usbd_xfer_handle xfer, usbd_private_handle addr, + usbd_status status)); -int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int)); -int ugen_do_write __P((struct ugen_softc *, int, struct uio *, int)); -int ugen_do_ioctl __P((struct ugen_softc *, int, u_long, - caddr_t, int, struct proc *)); -int ugen_set_config __P((struct ugen_softc *sc, int configno)); -usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, int index, - int *lenp)); -usbd_status ugen_set_interface __P((struct ugen_softc *, int, int)); -int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx)); +static int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int)); +static int ugen_do_write __P((struct ugen_softc *, int, struct uio *, int)); +static int ugen_do_ioctl __P((struct ugen_softc *, int, u_long, + caddr_t, int, struct proc *)); +static int ugen_set_config __P((struct ugen_softc *sc, int configno)); +static usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, + int index, int *lenp)); +static usbd_status ugen_set_interface __P((struct ugen_softc *, int, int)); +static int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx)); #define UGENUNIT(n) ((minor(n) >> 4) & 0xf) #define UGENENDPOINT(n) (minor(n) & 0xf) @@ -169,7 +169,7 @@ USB_ATTACH(ugen) { USB_ATTACH_START(ugen, sc, uaa); char devinfo[1024]; - usbd_status r; + usbd_status err; int conf; usbd_devinfo(uaa->device, 0, devinfo); @@ -178,8 +178,8 @@ USB_ATTACH(ugen) sc->sc_udev = uaa->device; conf = 1; /* XXX should not hard code 1 */ - r = ugen_set_config(sc, conf); - if (r != USBD_NORMAL_COMPLETION) { + err = ugen_set_config(sc, conf); + if (err) { printf("%s: setting configuration %d failed\n", USBDEVNAME(sc->sc_dev), conf); sc->sc_dying = 1; @@ -195,10 +195,11 @@ USB_ATTACH(ugen) } } #endif + USB_ATTACH_SUCCESS_RETURN; } -int +static int ugen_set_config(sc, configno) struct ugen_softc *sc; int configno; @@ -209,30 +210,30 @@ ugen_set_config(sc, configno) struct ugen_endpoint *sce; u_int8_t niface, nendpt; int ifaceno, endptno, endpt; - usbd_status r; + usbd_status err; int dir; DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", USBDEVNAME(sc->sc_dev), configno, sc)); if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { /* Avoid setting the current value. */ - r = usbd_set_config_no(dev, configno, 0); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_config_no(dev, configno, 0); + if (err) + return (err); } - r = usbd_interface_count(dev, &niface); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface_count(dev, &niface); + if (err) + return (err); memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); for (ifaceno = 0; ifaceno < niface; ifaceno++) { DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); - r = usbd_device2interface_handle(dev, ifaceno, &iface); - if (r != USBD_NORMAL_COMPLETION) - return (r); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_device2interface_handle(dev, ifaceno, &iface); + if (err) + return (err); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -257,29 +258,31 @@ ugenopen(dev, flag, mode, p) int mode; struct proc *p; { + struct ugen_softc *sc; int unit = UGENUNIT(dev); int endpt = UGENENDPOINT(dev); usb_endpoint_descriptor_t *edesc; struct ugen_endpoint *sce; int dir, isize; - usbd_status r; + usbd_status err; USB_GET_SC_OPEN(ugen, unit, sc); + DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", flag, mode, unit, endpt)); - if (!sc || sc->sc_dying) + if (sc == NULL || sc->sc_dying) return (ENXIO); + if (sc->sc_is_open[endpt]) + return (EBUSY); + if (endpt == USB_CONTROL_ENDPOINT) { - sc->sc_is_open[USB_CONTROL_ENDPOINT][IN] = 1; + sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; return (0); } /* Make sure there are pipes for all directions. */ for (dir = OUT; dir <= IN; dir++) { - if (sc->sc_is_open[endpt][dir]) - return (EBUSY); - if (flag & (dir == OUT ? FWRITE : FREAD)) { sce = &sc->sc_endpoints[endpt][dir]; if (sce == 0 || sce->edesc == 0) @@ -298,8 +301,6 @@ ugenopen(dev, flag, mode, p) DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", sc, endpt, dir, sce)); edesc = sce->edesc; - if (!edesc) - return (ENXIO); switch (edesc->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: isize = UGETW(edesc->wMaxPacketSize); @@ -308,40 +309,31 @@ ugenopen(dev, flag, mode, p) sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK); DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", endpt, isize)); -#if defined(__NetBSD__) || defined(__OpenBSD__) - if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) - return (ENOMEM); -#elif defined(__FreeBSD__) - clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, 0); -#endif - r = usbd_open_pipe_intr(sce->iface, + if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) + return (ENOMEM); + err = usbd_open_pipe_intr(sce->iface, edesc->bEndpointAddress, USBD_SHORT_XFER_OK, &sce->pipeh, sce, sce->ibuf, isize, ugenintr); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { free(sce->ibuf, M_USBDEV); -#if defined(__NetBSD__) || defined(__OpenBSD__) clfree(&sce->q); -#elif defined(__FreeBSD__) - clist_free_cblocks(&sce->q); -#endif return (EIO); } DPRINTFN(5, ("ugenopen: interrupt open done\n")); break; case UE_BULK: - r = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, - &sce->pipeh); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_open_pipe(sce->iface, + edesc->bEndpointAddress, 0, &sce->pipeh); + if (err) return (EIO); break; case UE_CONTROL: case UE_ISOCHRONOUS: return (EINVAL); } - sc->sc_is_open[endpt][dir] = 1; } + sc->sc_is_open[endpt] = 1; return (0); } @@ -352,16 +344,18 @@ ugenclose(dev, flag, mode, p) int mode; struct proc *p; { - USB_GET_SC(ugen, UGENUNIT(dev), sc); int endpt = UGENENDPOINT(dev); + struct ugen_softc *sc; struct ugen_endpoint *sce; int dir; + USB_GET_SC(ugen, UGENUNIT(dev), sc); + DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", flag, mode, UGENUNIT(dev), endpt)); #ifdef DIAGNOSTIC - if (!sc->sc_is_open[endpt][IN] || !sc->sc_is_open[endpt][OUT] ) { + if (!sc->sc_is_open[endpt]) { printf("ugenclose: not open\n"); return (EINVAL); } @@ -369,7 +363,7 @@ ugenclose(dev, flag, mode, p) if (endpt == USB_CONTROL_ENDPOINT) { DPRINTFN(5, ("ugenclose: close control\n")); - sc->sc_is_open[USB_CONTROL_ENDPOINT][IN] = 0; + sc->sc_is_open[endpt] = 0; return (0); } @@ -377,31 +371,28 @@ ugenclose(dev, flag, mode, p) if (!(flag & (dir == OUT ? FWRITE : FREAD))) continue; sce = &sc->sc_endpoints[endpt][dir]; - if (!sce || !sce->pipeh) + if (sce == NULL || sce->pipeh == NULL) continue; DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", endpt, dir, sce)); usbd_abort_pipe(sce->pipeh); usbd_close_pipe(sce->pipeh); - sce->pipeh = 0; + sce->pipeh = NULL; - if (sce->ibuf) { + if (sce->ibuf != NULL) { free(sce->ibuf, M_USBDEV); - sce->ibuf = 0; -#if defined(__NetBSD__) || defined(__OpenBSD__) + sce->ibuf = NULL; clfree(&sce->q); -#elif defined(__FreeBSD__) - clist_free_cblocks(&sce->q); -#endif + } - sc->sc_is_open[endpt][dir] = 0; } + sc->sc_is_open[endpt] = 0; return (0); } -int +static int ugen_do_read(sc, endpt, uio, flag) struct ugen_softc *sc; int endpt; @@ -411,8 +402,8 @@ ugen_do_read(sc, endpt, uio, flag) struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; u_int32_t n, tn; char buf[UGEN_BBSIZE]; - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; int s; int error = 0; u_char buffer[UGEN_CHUNK]; @@ -420,15 +411,19 @@ ugen_do_read(sc, endpt, uio, flag) #ifdef __NetBSD__ DPRINTFN(5, ("ugenread: %d:%d\n", sc->sc_dev.dv_unit, endpt)); #endif + if (sc->sc_dying) return (EIO); + if (endpt == USB_CONTROL_ENDPOINT) + return (ENODEV); + #ifdef DIAGNOSTIC - if (!sce->edesc) { + if (sce->edesc == NULL) { printf("ugenread: no edesc\n"); return (EIO); } - if (!sce->pipeh) { + if (sce->pipeh == NULL) { printf("ugenread: no pipe\n"); return (EIO); } @@ -473,21 +468,21 @@ ugen_do_read(sc, endpt, uio, flag) } break; case UE_BULK: - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_request(sc->sc_udev); + if (xfer == 0) return (ENOMEM); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); tn = n; - r = usbd_bulk_transfer( - reqh, sce->pipeh, + err = usbd_bulk_transfer( + xfer, sce->pipeh, sce->state & UGEN_SHORT_OK ? USBD_SHORT_XFER_OK : 0, sce->timeout, buf, &tn, "ugenrb"); - if (r != USBD_NORMAL_COMPLETION) { - if (r == USBD_INTERRUPTED) + if (err) { + if (err == USBD_INTERRUPTED) error = EINTR; - else if (r == USBD_TIMEOUT) + else if (err == USBD_TIMEOUT) error = ETIMEDOUT; else error = EIO; @@ -498,7 +493,7 @@ ugen_do_read(sc, endpt, uio, flag) if (error || tn < n) break; } - usbd_free_request(reqh); + usbd_free_request(xfer); break; default: return (ENXIO); @@ -512,10 +507,12 @@ ugenread(dev, uio, flag) struct uio *uio; int flag; { - USB_GET_SC(ugen, UGENUNIT(dev), sc); int endpt = UGENENDPOINT(dev); + struct ugen_softc *sc; int error; + USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_read(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) @@ -523,7 +520,7 @@ ugenread(dev, uio, flag) return (error); } -int +static int ugen_do_write(sc, endpt, uio, flag) struct ugen_softc *sc; int endpt; @@ -534,45 +531,49 @@ ugen_do_write(sc, endpt, uio, flag) u_int32_t n; int error = 0; char buf[UGEN_BBSIZE]; - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; + + DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt)); if (sc->sc_dying) return (EIO); + if (endpt == USB_CONTROL_ENDPOINT) + return (ENODEV); + #ifdef DIAGNOSTIC - if (!sce->edesc) { + if (sce->edesc == NULL) { printf("ugenwrite: no edesc\n"); return (EIO); } - if (!sce->pipeh) { + if (sce->pipeh == NULL) { printf("ugenwrite: no pipe\n"); return (EIO); } #endif - DPRINTF(("ugenwrite\n")); switch (sce->edesc->bmAttributes & UE_XFERTYPE) { case UE_BULK: - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_request(sc->sc_udev); + if (xfer == 0) return (EIO); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { error = uiomove(buf, n, uio); if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - r = usbd_bulk_transfer(reqh, sce->pipeh, 0, - sce->timeout, buf, &n,"ugenwb"); - if (r != USBD_NORMAL_COMPLETION) { - if (r == USBD_INTERRUPTED) + err = usbd_bulk_transfer(xfer, sce->pipeh, 0, + sce->timeout, buf, &n,"ugenwb"); + if (err) { + if (err == USBD_INTERRUPTED) error = EINTR; else error = EIO; break; } } - usbd_free_request(reqh); + usbd_free_request(xfer); break; default: return (ENXIO); @@ -586,10 +587,12 @@ ugenwrite(dev, uio, flag) struct uio *uio; int flag; { - USB_GET_SC(ugen, UGENUNIT(dev), sc); int endpt = UGENENDPOINT(dev); + struct ugen_softc *sc; int error; + USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_write(sc, endpt, uio, flag); if (--sc->sc_refcnt < 0) @@ -597,7 +600,6 @@ ugenwrite(dev, uio, flag) return (error); } - #if defined(__NetBSD__) || defined(__OpenBSD__) int ugen_activate(self, act) @@ -669,9 +671,9 @@ USB_DETACH(ugen) return (0); } -void -ugenintr(reqh, addr, status) - usbd_request_handle reqh; +static void +ugenintr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { @@ -689,11 +691,11 @@ ugenintr(reqh, addr, status) return; } - usbd_get_request_status(reqh, 0, 0, &count, 0); + usbd_get_request_status(xfer, 0, 0, &count, 0); ibuf = sce->ibuf; - DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n", - reqh, status, count)); + DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", + xfer, status, count)); DPRINTFN(5, (" data = %02x %02x %02x\n", ibuf[0], ibuf[1], ibuf[2])); @@ -707,32 +709,32 @@ ugenintr(reqh, addr, status) selwakeup(&sce->rsel); } -usbd_status +static usbd_status ugen_set_interface(sc, ifaceidx, altno) struct ugen_softc *sc; int ifaceidx, altno; { usbd_interface_handle iface; usb_endpoint_descriptor_t *ed; - usbd_status r; + usbd_status err; struct ugen_endpoint *sce; u_int8_t niface, nendpt, endptno, endpt; int dir; DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); - r = usbd_interface_count(sc->sc_udev, &niface); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface_count(sc->sc_udev, &niface); + if (err) + return (err); if (ifaceidx < 0 || ifaceidx >= niface) return (USBD_INVAL); - r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (r != USBD_NORMAL_COMPLETION) - return (r); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); + if (err) + return (err); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -744,13 +746,13 @@ ugen_set_interface(sc, ifaceidx, altno) } /* change setting */ - r = usbd_set_interface(iface, altno); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_interface(iface, altno); + if (err) + return (err); - r = usbd_endpoint_count(iface, &nendpt); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_endpoint_count(iface, &nendpt); + if (err) + return (err); for (endptno = 0; endptno < nendpt; endptno++) { ed = usbd_interface2endpoint_descriptor(iface,endptno); endpt = ed->bEndpointAddress; @@ -764,7 +766,7 @@ ugen_set_interface(sc, ifaceidx, altno) } /* Retrieve a complete descriptor for a certain device and index. */ -usb_config_descriptor_t * +static usb_config_descriptor_t * ugen_get_cdesc(sc, index, lenp) struct ugen_softc *sc; int index; @@ -772,7 +774,7 @@ ugen_get_cdesc(sc, index, lenp) { usb_config_descriptor_t *cdesc, *tdesc, cdescr; int len; - usbd_status r; + usbd_status err; if (index == USB_CURRENT_CONFIG_INDEX) { tdesc = usbd_get_config_descriptor(sc->sc_udev); @@ -783,16 +785,16 @@ ugen_get_cdesc(sc, index, lenp) memcpy(cdesc, tdesc, len); DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); } else { - r = usbd_get_config_desc(sc->sc_udev, index, &cdescr); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); + if (err) return (0); len = UGETW(cdescr.wTotalLength); DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); if (lenp) *lenp = len; cdesc = malloc(len, M_TEMP, M_WAITOK); - r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); + if (err) { free(cdesc, M_TEMP); return (0); } @@ -800,21 +802,21 @@ ugen_get_cdesc(sc, index, lenp) return (cdesc); } -int +static int ugen_get_alt_index(sc, ifaceidx) struct ugen_softc *sc; int ifaceidx; { usbd_interface_handle iface; - usbd_status r; + usbd_status err; - r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); + if (err) return (-1); return (usbd_get_interface_altindex(iface)); } -int +static int ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) struct ugen_softc *sc; int endpt; @@ -824,7 +826,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) struct proc *p; { struct ugen_endpoint *sce; - usbd_status r; + usbd_status err; usbd_interface_handle iface; struct usb_config_desc *cd; usb_config_descriptor_t *cdesc; @@ -849,8 +851,10 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) if (endpt == USB_CONTROL_ENDPOINT) return (EINVAL); sce = &sc->sc_endpoints[endpt][IN]; + if (sce == NULL) + return (EINVAL); #ifdef DIAGNOSTIC - if (!sce->pipeh) { + if (sce->pipeh == NULL) { printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); return (EIO); } @@ -862,8 +866,10 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) return (0); case USB_SET_TIMEOUT: sce = &sc->sc_endpoints[endpt][IN]; + if (sce == NULL) + return (EINVAL); #ifdef DIAGNOSTIC - if (!sce->pipeh) { + if (sce->pipeh == NULL) { printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n"); return (EIO); } @@ -884,26 +890,26 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) break; #endif case USB_GET_CONFIG: - r = usbd_get_config(sc->sc_udev, &conf); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_config(sc->sc_udev, &conf); + if (err) return (EIO); *(int *)addr = conf; break; case USB_SET_CONFIG: if (!(flag & FWRITE)) return (EPERM); - r = ugen_set_config(sc, *(int *)addr); - if (r != USBD_NORMAL_COMPLETION) + err = ugen_set_config(sc, *(int *)addr); + if (err) return (EIO); break; case USB_GET_ALTINTERFACE: ai = (struct usb_alt_interface *)addr; - r = usbd_device2interface_handle(sc->sc_udev, - ai->interface_index, &iface); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_device2interface_handle(sc->sc_udev, + ai->interface_index, &iface); + if (err) return (EINVAL); idesc = usbd_get_interface_descriptor(iface); - if (!idesc) + if (idesc == NULL) return (EIO); ai->alt_no = idesc->bAlternateSetting; break; @@ -911,21 +917,21 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) if (!(flag & FWRITE)) return (EPERM); ai = (struct usb_alt_interface *)addr; - r = usbd_device2interface_handle(sc->sc_udev, - ai->interface_index, &iface); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_device2interface_handle(sc->sc_udev, + ai->interface_index, &iface); + if (err) return (EINVAL); - r = ugen_set_interface(sc, ai->interface_index, ai->alt_no); - if (r != USBD_NORMAL_COMPLETION) + err = ugen_set_interface(sc, ai->interface_index, ai->alt_no); + if (err) return (EINVAL); break; case USB_GET_NO_ALT: ai = (struct usb_alt_interface *)addr; cdesc = ugen_get_cdesc(sc, ai->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); idesc = usbd_find_idesc(cdesc, ai->interface_index, 0); - if (!idesc) { + if (idesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -939,7 +945,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_CONFIG_DESC: cd = (struct usb_config_desc *)addr; cdesc = ugen_get_cdesc(sc, cd->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); cd->desc = *cdesc; free(cdesc, M_TEMP); @@ -947,7 +953,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_INTERFACE_DESC: id = (struct usb_interface_desc *)addr; cdesc = ugen_get_cdesc(sc, id->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); if (id->config_index == USB_CURRENT_CONFIG_INDEX && id->alt_index == USB_CURRENT_ALT_INDEX) @@ -955,7 +961,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) else alt = id->alt_index; idesc = usbd_find_idesc(cdesc, id->interface_index, alt); - if (!idesc) { + if (idesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -965,7 +971,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) case USB_GET_ENDPOINT_DESC: ed = (struct usb_endpoint_desc *)addr; cdesc = ugen_get_cdesc(sc, ed->config_index, 0); - if (!cdesc) + if (cdesc == NULL) return (EINVAL); if (ed->config_index == USB_CURRENT_CONFIG_INDEX && ed->alt_index == USB_CURRENT_ALT_INDEX) @@ -974,7 +980,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) alt = ed->alt_index; edesc = usbd_find_edesc(cdesc, ed->interface_index, alt, ed->endpoint_index); - if (!edesc) { + if (edesc == NULL) { free(cdesc, M_TEMP); return (EINVAL); } @@ -1011,9 +1017,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) } case USB_GET_STRING_DESC: si = (struct usb_string_desc *)addr; - r = usbd_get_string_desc(sc->sc_udev, si->string_index, - si->language_id, &si->desc); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_string_desc(sc->sc_udev, si->string_index, + si->language_id, &si->desc); + if (err) return (EINVAL); break; case USB_DO_REQUEST: @@ -1023,7 +1029,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) struct iovec iov; struct uio uio; void *ptr = 0; - usbd_status r; + usbd_status err; int error = 0; if (!(flag & FWRITE)) @@ -1058,9 +1064,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) goto ret; } } - r = usbd_do_request_flags(sc->sc_udev, &ur->request, - ptr, ur->flags, &ur->actlen); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_do_request_flags(sc->sc_udev, &ur->request, + ptr, ur->flags, &ur->actlen); + if (err) { error = EIO; goto ret; } @@ -1078,7 +1084,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) } case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_udev, - (struct usb_device_info *)addr); + (struct usb_device_info *)addr); break; default: return (EINVAL); @@ -1094,10 +1100,12 @@ ugenioctl(dev, cmd, addr, flag, p) int flag; struct proc *p; { - USB_GET_SC(ugen, UGENUNIT(dev), sc); int endpt = UGENENDPOINT(dev); + struct ugen_softc *sc; int error; + USB_GET_SC(ugen, UGENUNIT(dev), sc); + sc->sc_refcnt++; error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) @@ -1111,16 +1119,20 @@ ugenpoll(dev, events, p) int events; struct proc *p; { - USB_GET_SC(ugen, UGENUNIT(dev), sc); + struct ugen_softc *sc; struct ugen_endpoint *sce; int revents = 0; int s; + USB_GET_SC(ugen, UGENUNIT(dev), sc); + if (sc->sc_dying) return (EIO); /* XXX always IN */ sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; + if (sce == NULL) + return (EINVAL); #ifdef DIAGNOSTIC if (!sce->edesc) { printf("ugenwrite: no edesc\n"); diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index ba8b15e41fa4..db8726af7329 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.49 1999/09/11 08:19:26 augustss Exp $ */ +/* $NetBSD: uhci.c,v 1.63 1999/11/12 00:34:57 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -58,13 +58,14 @@ #elif defined(__FreeBSD__) #include #include +#include +#if defined(DIAGNOSTIC) && defined(__i386__) +#include +#endif #endif #include #include -#if defined(__FreeBSD__) -#include -#endif #include #include @@ -83,6 +84,14 @@ #define delay(d) DELAY(d) #endif +#define MS_TO_TICKS(ms) ((ms) * hz / 1000) + +#if defined(__OpenBSD__) +struct cfdriver uhci_cd = { + NULL, "uhci", DV_DULL +}; +#endif + #ifdef UHCI_DEBUG #define DPRINTF(x) if (uhcidebug) printf x #define DPRINTFN(n,x) if (uhcidebug>(n)) printf x @@ -92,15 +101,6 @@ int uhcidebug = 0; #define DPRINTFN(n,x) #endif - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#if defined(__OpenBSD__) -struct cfdriver uhci_cd = { - NULL, "uhci", DV_DULL -}; -#endif - /* * The UHCI controller is little endian, so on big endian machines * the data strored in memory needs to be swapped. @@ -149,104 +149,108 @@ struct uhci_pipe { */ LIST_HEAD(, uhci_intr_info) uhci_ii_free; -void uhci_busreset __P((uhci_softc_t *)); -void uhci_power __P((int, void *)); -usbd_status uhci_run __P((uhci_softc_t *, int run)); -uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *)); -void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *)); -uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *)); -void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *)); -uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *)); -void uhci_free_intr_info __P((uhci_intr_info_t *ii)); +static void uhci_busreset __P((uhci_softc_t *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +static void uhci_power __P((int, void *)); +#endif +static usbd_status uhci_run __P((uhci_softc_t *, int run)); +static uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *)); +static void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *)); +static uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *)); +static void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *)); +static uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *)); +static void uhci_free_intr_info __P((uhci_intr_info_t *ii)); #if 0 -void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *, - uhci_intr_info_t *)); -void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *, + uhci_intr_info_t *)); +static void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *)); #endif -void uhci_free_std_chain __P((uhci_softc_t *, - uhci_soft_td_t *, uhci_soft_td_t *)); -usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *, - int, int, int, usb_dma_t *, - uhci_soft_td_t **, - uhci_soft_td_t **)); -void uhci_timo __P((void *)); -void uhci_waitintr __P((uhci_softc_t *, usbd_request_handle)); -void uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *)); -void uhci_idone __P((uhci_intr_info_t *)); -void uhci_abort_req __P((usbd_request_handle, usbd_status status)); -void uhci_abort_req_end __P((void *v)); -void uhci_timeout __P((void *)); -void uhci_wakeup_ctrl __P((void *, int, int, void *, int)); -void uhci_lock_frames __P((uhci_softc_t *)); -void uhci_unlock_frames __P((uhci_softc_t *)); -void uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); -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)); +static void uhci_free_std_chain __P((uhci_softc_t *, + uhci_soft_td_t *, uhci_soft_td_t *)); +static usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, + uhci_softc_t *, int, int, int, usb_dma_t *, + uhci_soft_td_t **, uhci_soft_td_t **)); +static void uhci_timo __P((void *)); +static void uhci_waitintr __P((uhci_softc_t *, + usbd_xfer_handle)); +static void uhci_check_intr __P((uhci_softc_t *, + uhci_intr_info_t *)); +static void uhci_idone __P((uhci_intr_info_t *)); +static void uhci_abort_req __P((usbd_xfer_handle, + usbd_status status)); +static void uhci_abort_req_end __P((void *v)); +static void uhci_timeout __P((void *)); +static void uhci_lock_frames __P((uhci_softc_t *)); +static void uhci_unlock_frames __P((uhci_softc_t *)); +static void uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *)); +static void uhci_remove_ctrl __P((uhci_softc_t *,uhci_soft_qh_t *)); +static void uhci_remove_bulk __P((uhci_softc_t *,uhci_soft_qh_t *)); +static int uhci_str __P((usb_string_descriptor_t *, int, char *)); +static usbd_status uhci_setup_isoc __P((usbd_pipe_handle pipe)); +static void uhci_device_isoc_enter __P((usbd_xfer_handle)); -void uhci_wakeup_cb __P((usbd_request_handle reqh)); +static usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, + u_int32_t)); +static void uhci_freem __P((struct usbd_bus *, usb_dma_t *)); -usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t)); -void uhci_freem __P((struct usbd_bus *, usb_dma_t *)); +static usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle)); +static void uhci_device_ctrl_abort __P((usbd_xfer_handle)); +static void uhci_device_ctrl_close __P((usbd_pipe_handle)); +static void uhci_device_ctrl_done __P((usbd_xfer_handle)); -usbd_status uhci_device_ctrl_transfer __P((usbd_request_handle)); -usbd_status uhci_device_ctrl_start __P((usbd_request_handle)); -void uhci_device_ctrl_abort __P((usbd_request_handle)); -void uhci_device_ctrl_close __P((usbd_pipe_handle)); -void uhci_device_ctrl_done __P((usbd_request_handle)); +static usbd_status uhci_device_intr_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_intr_start __P((usbd_xfer_handle)); +static void uhci_device_intr_abort __P((usbd_xfer_handle)); +static void uhci_device_intr_close __P((usbd_pipe_handle)); +static void uhci_device_intr_done __P((usbd_xfer_handle)); -usbd_status uhci_device_intr_transfer __P((usbd_request_handle)); -usbd_status uhci_device_intr_start __P((usbd_request_handle)); -void uhci_device_intr_abort __P((usbd_request_handle)); -void uhci_device_intr_close __P((usbd_pipe_handle)); -void uhci_device_intr_done __P((usbd_request_handle)); +static usbd_status uhci_device_bulk_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_bulk_start __P((usbd_xfer_handle)); +static void uhci_device_bulk_abort __P((usbd_xfer_handle)); +static void uhci_device_bulk_close __P((usbd_pipe_handle)); +static void uhci_device_bulk_done __P((usbd_xfer_handle)); -usbd_status uhci_device_bulk_transfer __P((usbd_request_handle)); -usbd_status uhci_device_bulk_start __P((usbd_request_handle)); -void uhci_device_bulk_abort __P((usbd_request_handle)); -void uhci_device_bulk_close __P((usbd_pipe_handle)); -void uhci_device_bulk_done __P((usbd_request_handle)); +static usbd_status uhci_device_isoc_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_device_isoc_start __P((usbd_xfer_handle)); +static void uhci_device_isoc_abort __P((usbd_xfer_handle)); +static void uhci_device_isoc_close __P((usbd_pipe_handle)); +static void uhci_device_isoc_done __P((usbd_xfer_handle)); -usbd_status uhci_device_isoc_transfer __P((usbd_request_handle)); -usbd_status uhci_device_isoc_start __P((usbd_request_handle)); -void uhci_device_isoc_abort __P((usbd_request_handle)); -void uhci_device_isoc_close __P((usbd_pipe_handle)); -void uhci_device_isoc_done __P((usbd_request_handle)); +static usbd_status uhci_root_ctrl_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_root_ctrl_start __P((usbd_xfer_handle)); +static void uhci_root_ctrl_abort __P((usbd_xfer_handle)); +static void uhci_root_ctrl_close __P((usbd_pipe_handle)); -usbd_status uhci_root_ctrl_transfer __P((usbd_request_handle)); -usbd_status uhci_root_ctrl_start __P((usbd_request_handle)); -void uhci_root_ctrl_abort __P((usbd_request_handle)); -void uhci_root_ctrl_close __P((usbd_pipe_handle)); +static usbd_status uhci_root_intr_transfer __P((usbd_xfer_handle)); +static usbd_status uhci_root_intr_start __P((usbd_xfer_handle)); +static void uhci_root_intr_abort __P((usbd_xfer_handle)); +static void uhci_root_intr_close __P((usbd_pipe_handle)); +static void uhci_root_intr_done __P((usbd_xfer_handle)); -usbd_status uhci_root_intr_transfer __P((usbd_request_handle)); -usbd_status uhci_root_intr_start __P((usbd_request_handle)); -void uhci_root_intr_abort __P((usbd_request_handle)); -void uhci_root_intr_close __P((usbd_pipe_handle)); -void uhci_root_intr_done __P((usbd_request_handle)); +static usbd_status uhci_open __P((usbd_pipe_handle)); +static void uhci_poll __P((struct usbd_bus *)); -usbd_status uhci_open __P((usbd_pipe_handle)); -void uhci_poll __P((struct usbd_bus *)); +static usbd_status uhci_device_request __P((usbd_xfer_handle xfer)); -usbd_status uhci_device_request __P((usbd_request_handle reqh)); +static void uhci_add_intr __P((uhci_softc_t *, int, + uhci_soft_qh_t *)); +static void uhci_remove_intr __P((uhci_softc_t *, int, + uhci_soft_qh_t *)); +static usbd_status uhci_device_setintr __P((uhci_softc_t *sc, + struct uhci_pipe *pipe, int ival)); -void uhci_add_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *)); -void uhci_remove_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *)); -usbd_status uhci_device_setintr __P((uhci_softc_t *sc, - struct uhci_pipe *pipe, int ival)); - -void uhci_device_clear_toggle __P((usbd_pipe_handle pipe)); -void uhci_noop __P((usbd_pipe_handle pipe)); +static void uhci_device_clear_toggle __P((usbd_pipe_handle pipe)); +static void uhci_noop __P((usbd_pipe_handle pipe)); #ifdef UHCI_DEBUG -static void uhci_dumpregs __P((uhci_softc_t *)); -void uhci_dump_tds __P((uhci_soft_td_t *)); -void uhci_dump_qh __P((uhci_soft_qh_t *)); -void uhci_dump __P((void)); -void uhci_dump_td __P((uhci_soft_td_t *)); +static void uhci_dumpregs __P((uhci_softc_t *)); +static void uhci_dump_qhs __P((uhci_soft_qh_t *)); +static void uhci_dump_qh __P((uhci_soft_qh_t *)); +static void uhci_dump_tds __P((uhci_soft_td_t *)); +static void uhci_dump_td __P((uhci_soft_td_t *)); #endif #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) @@ -338,7 +342,7 @@ usbd_status uhci_init(sc) uhci_softc_t *sc; { - usbd_status r; + usbd_status err; int i, j; uhci_soft_qh_t *csqh, *bsqh, *sqh; uhci_soft_td_t *std; @@ -356,18 +360,18 @@ uhci_init(sc) uhci_busreset(sc); /* Allocate and initialize real frame array. */ - r = usb_allocmem(sc->sc_dmatag, - UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), - UHCI_FRAMELIST_ALIGN, &sc->sc_dma); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usb_allocmem(&sc->sc_bus, + UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), + UHCI_FRAMELIST_ALIGN, &sc->sc_dma); + if (err) + return (err); sc->sc_pframes = KERNADDR(&sc->sc_dma); UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/ /* Allocate the dummy QH where bulk traffic will be queued. */ bsqh = uhci_alloc_sqh(sc); - if (!bsqh) + if (bsqh == NULL) return (USBD_NOMEM); bsqh->qh.qh_hlink = LE(UHCI_PTR_T); /* end of QH chain */ bsqh->qh.qh_elink = LE(UHCI_PTR_T); @@ -375,7 +379,7 @@ uhci_init(sc) /* Allocate the dummy QH where control traffic will be queued. */ csqh = uhci_alloc_sqh(sc); - if (!csqh) + if (csqh == NULL) return (USBD_NOMEM); csqh->hlink = bsqh; csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q); @@ -390,7 +394,7 @@ uhci_init(sc) for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = uhci_alloc_std(sc); sqh = uhci_alloc_sqh(sc); - if (!std || !sqh) + if (std == NULL || sqh == NULL) return (USBD_NOMEM); std->link.sqh = sqh; std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q); @@ -417,10 +421,8 @@ uhci_init(sc) sc->sc_bus.methods = &uhci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); -#if defined(__NetBSD__) sc->sc_suspend = PWR_RESUME; - powerhook_establish(uhci_power, sc); -#endif + sc->sc_powerhook = powerhook_establish(uhci_power, sc); DPRINTFN(1,("uhci_init: enabling\n")); UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | @@ -429,17 +431,56 @@ uhci_init(sc) return (uhci_run(sc, 1)); /* and here we go... */ } +#if defined(__NetBSD__) || defined(__OpenBSD__) +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(sc, flags) + struct uhci_softc *sc; + int flags; +{ + 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); +} +#endif + usbd_status uhci_allocm(bus, dma, size) struct usbd_bus *bus; usb_dma_t *dma; u_int32_t size; { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif - - return (usb_allocmem(sc->sc_dmatag, size, 0, dma)); + return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0, + dma)); } void @@ -447,11 +488,7 @@ uhci_freem(bus, dma) struct usbd_bus *bus; usb_dma_t *dma; { -#if defined(__NetBSD__) || defined(__OpenBSD__) - struct uhci_softc *sc = (struct uhci_softc *)bus; -#endif - - usb_freemem(sc->sc_dmatag, dma); + usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma); } #if defined(__NetBSD__) @@ -485,11 +522,12 @@ 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); sc->sc_suspend = why; + sc->sc_bus.use_polling--; DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); } else { /* @@ -497,6 +535,11 @@ uhci_power(why, v) * controller registers have been lost and BIOS has * not restored them. */ +#ifdef DIAGNOSTIC + if (sc->sc_suspend == PWR_RESUME) + printf("uhci_power: weird, resume without suspend.\n"); +#endif + sc->sc_bus.use_polling++; sc->sc_suspend = why; if (cmd & UHCI_CMD_RS) uhci_run(sc, 0); /* in case BIOS has started it */ @@ -507,7 +550,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); @@ -518,7 +561,7 @@ uhci_power(why, v) } splx(s); } -#endif /* !defined(__OpenBSD__) */ +#endif /* defined(__NetBSD__) */ #ifdef UHCI_DEBUG static void @@ -566,11 +609,11 @@ uhci_dump_td(p) } void -uhci_dump_qh(p) - uhci_soft_qh_t *p; +uhci_dump_qh(sqh) + uhci_soft_qh_t *sqh; { - DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, - (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink))); + DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh, + (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink))); } @@ -581,20 +624,63 @@ 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); } #endif + +void +uhci_dump_qhs(sqh) + uhci_soft_qh_t *sqh; +{ + uhci_dump_qh(sqh); + + /* uhci_dump_qhs displays all the QHs and TDs from the given QH onwards + * Traverses sideways first, then down. + * + * QH1 + * QH2 + * No QH + * TD2.1 + * TD2.2 + * TD1.1 + * etc. + * + * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1. + */ + + + if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T)) + uhci_dump_qhs(sqh->hlink); + else + DPRINTF(("No QH\n")); + + if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T)) + uhci_dump_tds(sqh->elink); + else + DPRINTF(("No TD\n")); +} + void uhci_dump_tds(std) uhci_soft_td_t *std; { - uhci_soft_td_t *p; + uhci_soft_td_t *td; - for(p = std; p; p = p->link.std) - uhci_dump_td(p); + for(td = std; td != NULL; td = td->link.std) { + uhci_dump_td(td); + + /* Check whether the link pointer in this TD marks + * the link pointer as end of queue. This avoids + * printing the free list in case the queue/TD has + * already been moved there (seatbelt). + */ + if (td->td.td_link & UHCI_PTR_T || + td->td.td_link == 0) + break; + } } #endif @@ -606,17 +692,17 @@ void uhci_timo(addr) void *addr; { - usbd_request_handle reqh = addr; - usbd_pipe_handle pipe = reqh->pipe; + usbd_xfer_handle xfer = addr; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; int s; u_char *p; - DPRINTFN(15, ("uhci_timo\n")); + DPRINTFN(20, ("uhci_timo\n")); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); - p = KERNADDR(&reqh->dmabuf); + p = KERNADDR(&xfer->dmabuf); p[0] = 0; if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) p[0] |= 1<<1; @@ -626,17 +712,19 @@ uhci_timo(addr) /* No change, try again in a while */ return; - reqh->actlen = 1; - reqh->status = USBD_NORMAL_COMPLETION; + xfer->actlen = 1; + xfer->status = USBD_NORMAL_COMPLETION; s = splusb(); - reqh->hcpriv = 0; - usb_transfer_complete(reqh); + xfer->hcpriv = 0; + xfer->device->bus->intr_context++; + usb_transfer_complete(xfer); + xfer->device->bus->intr_context--; splx(s); } void -uhci_root_intr_done(reqh) - usbd_request_handle reqh; +uhci_root_intr_done(xfer) + usbd_xfer_handle xfer; { } @@ -646,6 +734,7 @@ uhci_lock_frames(sc) uhci_softc_t *sc; { int s = splusb(); + while (sc->sc_vflock) { sc->sc_vflock |= UHCI_WANT_LOCK; tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0); @@ -659,6 +748,7 @@ uhci_unlock_frames(sc) uhci_softc_t *sc; { int s = splusb(); + sc->sc_vflock &= ~UHCI_HAS_LOCK; if (sc->sc_vflock & UHCI_WANT_LOCK) wakeup(&sc->sc_vflock); @@ -704,6 +794,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; @@ -721,6 +813,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(UHCI_DEBUG) @@ -745,6 +839,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; @@ -762,6 +858,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(UHCI_DEBUG) @@ -787,8 +885,6 @@ uhci_intr(arg) int ack; uhci_intr_info_t *ii; - sc->sc_intrs++; - #ifdef UHCI_DEBUG if (uhcidebug > 15) { DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev))); @@ -796,12 +892,15 @@ uhci_intr(arg) } #endif + status = UREAD2(sc, UHCI_STS); + if (status == 0) /* The interrupt was not for us. */ + return (0); + #if defined(DIAGNOSTIC) && defined(__NetBSD__) if (sc->sc_suspend != PWR_RESUME) printf("uhci_intr: suspended sts=0x%x\n", status); #endif - status = UREAD2(sc, UHCI_STS); ack = 0; if (status & UHCI_STS_USBINT) ack |= UHCI_STS_USBINT; @@ -831,6 +930,9 @@ uhci_intr(arg) 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 * interrupts because a transfer is completed there is no @@ -845,7 +947,9 @@ uhci_intr(arg) for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) uhci_check_intr(sc, ii); - DPRINTFN(10, ("uhci_intr: exit\n")); + DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev))); + + sc->sc_bus.intr_context--; return (1); } @@ -861,16 +965,16 @@ uhci_check_intr(sc, ii) DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii)); #ifdef DIAGNOSTIC - if (!ii) { + if (ii == NULL) { printf("uhci_check_intr: no ii? %p\n", ii); return; } #endif - if (!ii->stdstart) + if (ii->stdstart == NULL) return; lstd = ii->stdend; #ifdef DIAGNOSTIC - if (!lstd) { + if (lstd == NULL) { printf("uhci_check_intr: std==0\n"); return; } @@ -898,14 +1002,15 @@ uhci_check_intr(sc, ii) uhci_idone(ii); } +/* Called at splusb() */ void uhci_idone(ii) uhci_intr_info_t *ii; { - usbd_request_handle reqh = ii->reqh; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + usbd_xfer_handle xfer = ii->xfer; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_td_t *std; - u_int32_t status = 0; + u_int32_t status = 0, nstatus; int actlen; #ifdef DIAGNOSTIC @@ -921,22 +1026,22 @@ uhci_idone(ii) } #endif - if (reqh->status == USBD_CANCELLED || - reqh->status == USBD_TIMEOUT) { - DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh)); + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { + DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer)); return; } - if (reqh->nframes) { + if (xfer->nframes != 0) { /* Isoc transfer, do things differently. */ uhci_soft_td_t **stds = upipe->u.iso.stds; int i, n, nframes; DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii)); - nframes = reqh->nframes; + nframes = xfer->nframes; actlen = 0; - n = reqh->hcprivint; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; #ifdef UHCI_DEBUG @@ -951,10 +1056,10 @@ uhci_idone(ii) actlen += UHCI_TD_GET_ACTLEN(status); } upipe->u.iso.inuse -= nframes; - reqh->actlen = actlen; - reqh->status = USBD_NORMAL_COMPLETION; - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->actlen = actlen; + xfer->status = USBD_NORMAL_COMPLETION; + xfer->hcpriv = ii; + usb_transfer_complete(xfer); return; } @@ -965,43 +1070,42 @@ uhci_idone(ii) #endif /* The transfer is done, compute actual length and status. */ - /* XXX Is this correct for control xfers? */ actlen = 0; - status = 0; - for (std = ii->stdstart; std; std = std->link.std) { - if (LE(std->td.td_status) & UHCI_TD_ACTIVE) + for (std = ii->stdstart; std != NULL; std = std->link.std) { + nstatus = LE(std->td.td_status); + if (nstatus & UHCI_TD_ACTIVE) break; - status = LE(std->td.td_status); + status = nstatus; if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP) actlen += UHCI_TD_GET_ACTLEN(status); } /* If there are left over TDs we need to update the toggle. */ - if (std) + if (std != NULL) upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token)); status &= UHCI_TD_ERROR; DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n", actlen, status)); - reqh->actlen = actlen; + xfer->actlen = actlen; if (status != 0) { DPRINTFN((status&UHCI_TD_STALLED)*10, ("uhci_idone: error, addr=%d, endpt=0x%02x, " "status 0x%b\n", - reqh->pipe->device->address, - reqh->pipe->endpoint->edesc->bEndpointAddress, + xfer->pipe->device->address, + xfer->pipe->endpoint->edesc->bEndpointAddress, (int)status, "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE")); if (status == UHCI_TD_STALLED) - reqh->status = USBD_STALLED; + xfer->status = USBD_STALLED; else - reqh->status = USBD_IOERROR; /* more info XXX */ + xfer->status = USBD_IOERROR; /* more info XXX */ } else { - reqh->status = USBD_NORMAL_COMPLETION; + xfer->status = USBD_NORMAL_COMPLETION; } - reqh->hcpriv = ii; - usb_transfer_complete(reqh); + xfer->hcpriv = ii; + usb_transfer_complete(xfer); } /* @@ -1014,7 +1118,15 @@ uhci_timeout(addr) uhci_intr_info_t *ii = addr; DPRINTF(("uhci_timeout: ii=%p\n", ii)); - uhci_abort_req(ii->reqh, USBD_TIMEOUT); + +#ifdef UHCI_DEBUG + if (uhcidebug > 10) + uhci_dump_tds(ii->stdstart); +#endif + + ii->xfer->device->bus->intr_context++; + uhci_abort_req(ii->xfer, USBD_TIMEOUT); + ii->xfer->device->bus->intr_context--; } /* @@ -1024,22 +1136,22 @@ uhci_timeout(addr) * Only used during boot when interrupts are not enabled yet. */ void -uhci_waitintr(sc, reqh) +uhci_waitintr(sc, xfer) uhci_softc_t *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; { - int timo = reqh->timeout; + int timo = xfer->timeout; uhci_intr_info_t *ii; DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo)); - reqh->status = USBD_IN_PROGRESS; + xfer->status = USBD_IN_PROGRESS; for (; timo >= 0; timo--) { usb_delay_ms(&sc->sc_bus, 1); DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS))); if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) { uhci_intr(sc); - if (reqh->status != USBD_IN_PROGRESS) + if (xfer->status != USBD_IN_PROGRESS) return; } } @@ -1047,11 +1159,11 @@ uhci_waitintr(sc, reqh) /* Timeout */ DPRINTF(("uhci_waitintr: timeout\n")); for (ii = LIST_FIRST(&sc->sc_intrhead); - ii && ii->reqh != reqh; + ii != NULL && ii->xfer != xfer; ii = LIST_NEXT(ii, list)) ; #ifdef DIAGNOSTIC - if (!ii) + if (ii == NULL) panic("uhci_waitintr: lost intr_info\n"); #endif uhci_idone(ii); @@ -1129,19 +1241,19 @@ uhci_alloc_std(sc) uhci_softc_t *sc; { uhci_soft_td_t *std; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freetds) { + if (sc->sc_freetds == NULL) { DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, UHCI_STD_SIZE * UHCI_STD_CHUNK, - UHCI_TD_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) + err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, + UHCI_TD_ALIGN, &dma); + if (err) return (0); for(i = 0; i < UHCI_STD_CHUNK; i++) { offs = i * UHCI_STD_SIZE; - std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) +offs); + std = (uhci_soft_td_t *)((char *)KERNADDR(&dma) + offs); std->physaddr = DMAADDR(&dma) + offs; std->link.std = sc->sc_freetds; sc->sc_freetds = std; @@ -1160,7 +1272,7 @@ uhci_free_std(sc, std) { #ifdef DIAGNOSTIC #define TD_IS_FREE 0x12345678 - if (LE(std->td.td_token) == TD_IS_FREE) { + if (std->td.td_token == LE(TD_IS_FREE)) { printf("uhci_free_std: freeing free TD %p\n", std); return; } @@ -1175,16 +1287,16 @@ uhci_alloc_sqh(sc) uhci_softc_t *sc; { uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, offs; usb_dma_t dma; - if (!sc->sc_freeqhs) { + if (sc->sc_freeqhs == NULL) { DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - r = usb_allocmem(sc->sc_dmatag, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, - UHCI_QH_ALIGN, &dma); - if (r != USBD_NORMAL_COMPLETION) - return 0; + err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, + UHCI_QH_ALIGN, &dma); + if (err) + return (0); for(i = 0; i < UHCI_SQH_CHUNK; i++) { offs = i * UHCI_SQH_SIZE; sqh = (uhci_soft_qh_t *)((char *)KERNADDR(&dma) +offs); @@ -1282,20 +1394,12 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep) status |= UHCI_TD_SPD; for (i = ntd; i >= 0; i--) { p = uhci_alloc_std(sc); - if (!p) { + if (p == NULL) { uhci_free_std_chain(sc, lastp, 0); return (USBD_NOMEM); } p->link.std = lastp; - /* The if statement might be necessary to avoid confusing the - * VIA chipset. It doesn't like extra bits when UHCI_PTR_T - * is set. - */ - if (lastlink != UHCI_PTR_T) - p->td.td_link = LE(lastlink|UHCI_PTR_VF); - else - p->td.td_link = LE(lastlink); - + p->td.td_link = LE(lastlink); lastp = p; lastlink = p->physaddr; p->td.td_status = LE(status); @@ -1333,66 +1437,70 @@ uhci_noop(pipe) } usbd_status -uhci_device_bulk_transfer(reqh) - usbd_request_handle reqh; +uhci_device_bulk_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_bulk_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_bulk_start(reqh) - usbd_request_handle reqh; +uhci_device_bulk_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; - uhci_soft_td_t *xfer, *xferend; + uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int len, isread, endpt; int s; - DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_bulk_transfer: a request\n"); #endif - len = reqh->length; - endpt = reqh->pipe->endpoint->edesc->bEndpointAddress; + len = xfer->length; + endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; sqh = upipe->u.bulk.sqh; upipe->u.bulk.isread = isread; upipe->u.bulk.length = len; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - xferend->td.td_status |= LE(UHCI_TD_IOC); + err = uhci_alloc_std_chain(upipe, sc, len, isread, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 8) { - DPRINTF(("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->xfer = xfer; + ii->stdstart = data; + ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif @@ -1400,53 +1508,53 @@ uhci_device_bulk_start(reqh) 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(); uhci_add_bulk(sc, sqh); LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list); - if (reqh->timeout && !sc->sc_bus.use_polling) { - usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout), + if (xfer->timeout && !sc->sc_bus.use_polling) { + usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("uhci_device_bulk_transfer: xfer(2)\n")); - uhci_dump_tds(xfer); + DPRINTF(("uhci_device_bulk_transfer: data(2)\n")); + uhci_dump_tds(data); } #endif if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } /* Abort a device bulk request. */ void -uhci_device_bulk_abort(reqh) - usbd_request_handle reqh; +uhci_device_bulk_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_bulk_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } void -uhci_abort_req(reqh, status) - usbd_request_handle reqh; +uhci_abort_req(xfer, status) + usbd_xfer_handle xfer; usbd_status status; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *std; /* Make interrupt routine ignore it, */ - reqh->status = status; + xfer->status = status; /* don't timeout, */ usb_untimeout(uhci_timeout, ii, ii->timeout_handle); @@ -1455,16 +1563,20 @@ uhci_abort_req(reqh, status) for (std = ii->stdstart; std != 0; std = std->link.std) std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - reqh->hcpriv = ii; + xfer->hcpriv = ii; /* make sure hardware has completed, */ - if (curproc) { - usb_delay_ms(reqh->pipe->device->bus, 1); - /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); - } else { + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_req_end, xfer, hz / USB_FRAMES_PER_SECOND); + } else { +#if defined(DIAGNOSTIC) && defined(__i386__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + usb_delay_ms(xfer->pipe->device->bus, 1); + /* and call final part of interrupt handler. */ + uhci_abort_req_end(xfer); } } @@ -1472,11 +1584,11 @@ void uhci_abort_req_end(v) void *v; { - usbd_request_handle reqh = v; + usbd_xfer_handle xfer = v; int s; s = splusb(); - usb_transfer_complete(reqh); + usb_transfer_complete(xfer); splx(s); } @@ -1495,93 +1607,101 @@ uhci_device_bulk_close(pipe) } usbd_status -uhci_device_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; - usbd_status r; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_device_ctrl_transfer: not a request\n"); #endif - r = uhci_device_request(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = uhci_device_request(xfer); + if (err) + return (err); if (sc->sc_bus.use_polling) - uhci_waitintr(sc, reqh); + uhci_waitintr(sc, xfer); return (USBD_IN_PROGRESS); } usbd_status -uhci_device_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_device_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_device_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_device_intr_start(reqh) - usbd_request_handle reqh; +uhci_device_intr_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_intr_info_t *ii = upipe->iinfo; - uhci_soft_td_t *xfer, *xferend; + uhci_soft_td_t *data, *dataend; uhci_soft_qh_t *sqh; - usbd_status r; + usbd_status err; int i, s; - DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_REQUEST) + if (xfer->rqflags & URQ_REQUEST) panic("uhci_device_intr_transfer: a request\n"); #endif - r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - xferend->td.td_status |= LE(UHCI_TD_IOC); + err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("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 s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; - ii->stdstart = xfer; - ii->stdend = xferend; + ii->xfer = xfer; + ii->stdstart = data; + ii->stdend = dataend; #if defined(__FreeBSD__) callout_handle_init(&ii->timeout_handle); #endif @@ -1593,15 +1713,15 @@ 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 UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("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 @@ -1611,11 +1731,11 @@ uhci_device_intr_start(reqh) /* Abort a device control request. */ void -uhci_device_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_abort(xfer) + usbd_xfer_handle xfer; { DPRINTF(("uhci_device_ctrl_abort:\n")); - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } /* Close a device control pipe. */ @@ -1626,20 +1746,20 @@ uhci_device_ctrl_close(pipe) struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; uhci_free_intr_info(upipe->iinfo); - /* XXX free other resources */ + /* XXX free other resources? */ } /* Abort a device interrupt request. */ void -uhci_device_intr_abort(reqh) - usbd_request_handle reqh; +uhci_device_intr_abort(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(1,("uhci_device_intr_abort: reqh=%p\n", reqh)); - if (reqh->pipe->intrreqh == reqh) { + DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer)); + if (xfer->pipe->intrxfer == xfer) { DPRINTFN(1,("uhci_device_intr_abort: remove\n")); - reqh->pipe->intrreqh = 0; + xfer->pipe->intrxfer = 0; } - uhci_abort_req(reqh, USBD_CANCELLED); + uhci_abort_req(xfer, USBD_CANCELLED); } /* Close a device interrupt pipe. */ @@ -1680,21 +1800,21 @@ uhci_device_intr_close(pipe) } usbd_status -uhci_device_request(reqh) - usbd_request_handle reqh; +uhci_device_request(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; - usb_device_request_t *req = &reqh->request; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; + usb_device_request_t *req = &xfer->request; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; int addr = dev->address; 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; int len; u_int32_t ls; - usbd_status r; + usbd_status err; int isread; int s; @@ -1715,14 +1835,14 @@ uhci_device_request(reqh) /* Set up data transaction */ if (len != 0) { upipe->nexttoggle = 1; - r = uhci_alloc_std_chain(upipe, sc, len, isread, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - if (r != USBD_NORMAL_COMPLETION) - return (r); - next = xfer; - xferend->link.std = stat; - xferend->td.td_link = LE(stat->physaddr|UHCI_PTR_VF); + err = uhci_alloc_std_chain(upipe, sc, len, isread, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + if (err) + return (err); + next = data; + dataend->link.std = stat; + dataend->td.td_link = LE(stat->physaddr); } else { next = stat; } @@ -1731,7 +1851,7 @@ uhci_device_request(reqh) memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req); setup->link.std = next; - setup->td.td_link = LE(next->physaddr|UHCI_PTR_VF); + setup->td.td_link = LE(next->physaddr); setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE); setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr)); setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma)); @@ -1746,16 +1866,19 @@ uhci_device_request(reqh) stat->td.td_buffer = LE(0); #ifdef UHCI_DEBUG - if (uhcidebug > 20) { + if (uhcidebug > 10) { DPRINTF(("uhci_device_request: before transfer\n")); uhci_dump_tds(setup); } #endif /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = setup; ii->stdend = stat; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #ifdef DIAGNOSTIC ii->isdone = 0; #endif @@ -1781,21 +1904,22 @@ uhci_device_request(reqh) link = LE(std->td.td_link); uhci_dump_td(std); } - for (sxqh = xqh = (uhci_soft_qh_t *)std; - xqh; + sxqh = (uhci_soft_qh_t *)std; + uhci_dump_qh(sxqh); + for (xqh = sxqh; + xqh != NULL; xqh = (maxqh++ == 5 || xqh->hlink==sxqh || xqh->hlink==xqh ? NULL : xqh->hlink)) { uhci_dump_qh(xqh); - uhci_dump_qh(sxqh); } DPRINTF(("Enqueued QH:\n")); uhci_dump_qh(sqh); uhci_dump_tds(sqh->elink); } #endif - if (reqh->timeout && !sc->sc_bus.use_polling) { + if (xfer->timeout && !sc->sc_bus.use_polling) { usb_timeout(uhci_timeout, ii, - MS_TO_TICKS(reqh->timeout), ii->timeout_handle); + MS_TO_TICKS(xfer->timeout), ii->timeout_handle); } splx(s); @@ -1803,37 +1927,37 @@ uhci_device_request(reqh) } usbd_status -uhci_device_isoc_transfer(reqh) - usbd_request_handle reqh; +uhci_device_isoc_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh)); + DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer)); /* Put it on our queue, */ - r = usb_insert_transfer(reqh); + err = usb_insert_transfer(xfer); /* bail out on error, */ - if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS) - return (r); + if (err && err != USBD_IN_PROGRESS) + return (err); /* XXX should check inuse here */ /* insert into schedule, */ - uhci_device_isoc_enter(reqh); + uhci_device_isoc_enter(xfer); /* and put on interrupt list if the pipe wasn't running */ - if (r == USBD_NORMAL_COMPLETION) - uhci_device_isoc_start(reqh); + if (!err) + uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); - return (r); + return (err); } void -uhci_device_isoc_enter(reqh) - usbd_request_handle reqh; +uhci_device_isoc_enter(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; usbd_device_handle dev = upipe->pipe.device; uhci_softc_t *sc = (uhci_softc_t *)dev->bus; struct iso *iso = &upipe->u.iso; @@ -1841,11 +1965,11 @@ uhci_device_isoc_enter(reqh) u_int32_t buf, len, status; int s, i, next, nframes; - DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p " + DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p " "nframes=%d\n", - iso->inuse, iso->next, reqh, reqh->nframes)); + iso->inuse, iso->next, xfer, xfer->nframes)); - if (reqh->status == USBD_IN_PROGRESS) { + if (xfer->status == USBD_IN_PROGRESS) { /* This request has already been entered into the frame list */ } @@ -1861,20 +1985,20 @@ uhci_device_isoc_enter(reqh) DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next)); } - reqh->status = USBD_IN_PROGRESS; - reqh->hcprivint = next; + xfer->status = USBD_IN_PROGRESS; + xfer->hcprivint = next; - buf = DMAADDR(&reqh->dmabuf); + buf = DMAADDR(&xfer->dmabuf); status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | UHCI_TD_ACTIVE | UHCI_TD_IOS)); - nframes = reqh->nframes; + nframes = xfer->nframes; s = splusb(); for (i = 0; i < nframes; i++) { std = iso->stds[next]; if (++next >= UHCI_VFRAMELIST_COUNT) next = 0; - len = reqh->frlengths[i]; + len = xfer->frlengths[i]; std->td.td_buffer = LE(buf); if (i == nframes - 1) status |= LE(UHCI_TD_IOC); @@ -1890,28 +2014,28 @@ uhci_device_isoc_enter(reqh) buf += len; } iso->next = next; - iso->inuse += reqh->nframes; + iso->inuse += xfer->nframes; splx(s); } usbd_status -uhci_device_isoc_start(reqh) - usbd_request_handle reqh; +uhci_device_isoc_start(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t *end; int s, i; #ifdef DIAGNOSTIC - if (reqh->status != USBD_IN_PROGRESS) - printf("uhci_device_isoc_start: not in progress %p\n", reqh); + if (xfer->status != USBD_IN_PROGRESS) + printf("uhci_device_isoc_start: not in progress %p\n", xfer); #endif /* Find the last TD */ - i = reqh->hcprivint + reqh->nframes; + i = xfer->hcprivint + xfer->nframes; if (i >= UHCI_VFRAMELIST_COUNT) i -= UHCI_VFRAMELIST_COUNT; end = upipe->u.iso.stds[i]; @@ -1919,9 +2043,12 @@ uhci_device_isoc_start(reqh) s = splusb(); /* Set up interrupt info. */ - ii->reqh = reqh; + ii->xfer = xfer; ii->stdstart = end; ii->stdend = end; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #ifdef DIAGNOSTIC ii->isdone = 0; #endif @@ -1933,21 +2060,21 @@ uhci_device_isoc_start(reqh) } void -uhci_device_isoc_abort(reqh) - usbd_request_handle reqh; +uhci_device_isoc_abort(xfer) + usbd_xfer_handle xfer; { - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_intr_info_t *ii = upipe->iinfo; uhci_soft_td_t **stds = upipe->u.iso.stds; uhci_soft_td_t *std; int i, n, nframes; /* Make interrupt routine ignore it, */ - reqh->status = USBD_CANCELLED; + xfer->status = USBD_CANCELLED; /* make hardware ignore it, */ - nframes = reqh->nframes; - n = reqh->hcprivint; + nframes = xfer->nframes; + n = xfer->hcprivint; for (i = 0; i < nframes; i++) { std = stds[n]; std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); @@ -1955,16 +2082,16 @@ uhci_device_isoc_abort(reqh) n = 0; } - reqh->hcpriv = ii; + xfer->hcpriv = ii; /* make sure hardware has completed, */ - if (curproc) { - usb_delay_ms(reqh->pipe->device->bus, 1); - /* and call final part of interrupt handler. */ - uhci_abort_req_end(reqh); - } else { + if (xfer->device->bus->intr_context) { /* We have no process context, so we can't use tsleep(). */ - timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND); + timeout(uhci_abort_req_end, xfer, hz / USB_FRAMES_PER_SECOND); + } else { + usb_delay_ms(xfer->pipe->device->bus, 1); + /* and call final part of interrupt handler. */ + uhci_abort_req_end(xfer); } } @@ -1995,10 +2122,10 @@ uhci_device_isoc_close(pipe) for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { std = iso->stds[i]; for (vstd = sc->sc_vframes[i].htd; - vstd && vstd->link.std != std; + vstd != NULL && vstd->link.std != std; vstd = vstd->link.std) ; - if (!vstd) { + if (vstd == NULL) { /*panic*/ printf("uhci_device_isoc_close: %p not found\n", std); uhci_unlock_frames(sc); @@ -2070,12 +2197,12 @@ uhci_setup_isoc(pipe) } void -uhci_device_isoc_done(reqh) - usbd_request_handle reqh; +uhci_device_isoc_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; - DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen)); + DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen)); /* Turn off the interrupt since it is active even if the TD is not. */ ii->stdend->td.td_status &= LE(~UHCI_TD_IOC); @@ -2084,16 +2211,16 @@ uhci_device_isoc_done(reqh) } void -uhci_device_intr_done(reqh) - usbd_request_handle reqh; +uhci_device_intr_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_soft_qh_t *sqh; int i, npoll; - DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen)); npoll = upipe->u.intr.npoll; for(i = 0; i < npoll; i++) { @@ -2104,32 +2231,35 @@ uhci_device_intr_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); /* XXX Wasteful. */ - if (reqh->pipe->repeat) { - uhci_soft_td_t *xfer, *xferend; + if (xfer->pipe->repeat) { + uhci_soft_td_t *data, *dataend; /* This alloc cannot fail since we freed the chain above. */ - uhci_alloc_std_chain(upipe, sc, reqh->length, 1, - reqh->flags & USBD_SHORT_XFER_OK, - &reqh->dmabuf, &xfer, &xferend); - xferend->td.td_status |= LE(UHCI_TD_IOC); + uhci_alloc_std_chain(upipe, sc, xfer->length, 1, + xfer->flags & USBD_SHORT_XFER_OK, + &xfer->dmabuf, &data, &dataend); + dataend->td.td_status |= LE(UHCI_TD_IOC); #ifdef UHCI_DEBUG if (uhcidebug > 10) { - DPRINTF(("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; +#if defined(__FreeBSD__) + callout_handle_init(&ii->timeout_handle); +#endif #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 { ii->stdstart = 0; /* mark as inactive */ @@ -2138,15 +2268,15 @@ uhci_device_intr_done(reqh) /* Deallocate request data structures */ void -uhci_device_ctrl_done(reqh) - usbd_request_handle reqh; +uhci_device_ctrl_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_ctrl_done: not a request\n"); #endif @@ -2157,17 +2287,17 @@ uhci_device_ctrl_done(reqh) if (upipe->u.ctl.length != 0) uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); - DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen)); } /* Deallocate request data structures */ void -uhci_device_bulk_done(reqh) - usbd_request_handle reqh; +uhci_device_bulk_done(xfer) + usbd_xfer_handle xfer; { - uhci_intr_info_t *ii = reqh->hcpriv; + uhci_intr_info_t *ii = xfer->hcpriv; uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe; + struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; LIST_REMOVE(ii, list); /* remove from active list */ @@ -2175,7 +2305,7 @@ uhci_device_bulk_done(reqh) uhci_free_std_chain(sc, ii->stdstart, 0); - DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen)); + DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen)); } /* Add interrupt QH, called with vflock. */ @@ -2299,7 +2429,7 @@ uhci_open(pipe) uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", pipe, pipe->device->address, @@ -2323,23 +2453,23 @@ uhci_open(pipe) case UE_CONTROL: pipe->methods = &uhci_device_ctrl_methods; upipe->u.ctl.sqh = uhci_alloc_sqh(sc); - if (upipe->u.ctl.sqh == 0) + if (upipe->u.ctl.sqh == NULL) goto bad; upipe->u.ctl.setup = uhci_alloc_std(sc); - if (upipe->u.ctl.setup == 0) { + if (upipe->u.ctl.setup == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); goto bad; } upipe->u.ctl.stat = uhci_alloc_std(sc); - if (upipe->u.ctl.stat == 0) { + if (upipe->u.ctl.stat == NULL) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); goto bad; } - r = usb_allocmem(sc->sc_dmatag, - sizeof(usb_device_request_t), - 0, &upipe->u.ctl.reqdma); - if (r != USBD_NORMAL_COMPLETION) { + err = usb_allocmem(&sc->sc_bus, + sizeof(usb_device_request_t), + 0, &upipe->u.ctl.reqdma); + if (err) { uhci_free_sqh(sc, upipe->u.ctl.sqh); uhci_free_std(sc, upipe->u.ctl.setup); uhci_free_std(sc, upipe->u.ctl.stat); @@ -2355,7 +2485,7 @@ uhci_open(pipe) case UE_BULK: pipe->methods = &uhci_device_bulk_methods; upipe->u.bulk.sqh = uhci_alloc_sqh(sc); - if (upipe->u.bulk.sqh == 0) + if (upipe->u.bulk.sqh == NULL) goto bad; break; } @@ -2451,35 +2581,39 @@ uhci_str(p, l, s) * Simulate a hardware hub by handling all the necessary requests. */ usbd_status -uhci_root_ctrl_transfer(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_root_ctrl_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } usbd_status -uhci_root_ctrl_start(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_start(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; usb_device_request_t *req; void *buf = NULL; int port, x; - int 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; + usbd_status err; #ifdef DIAGNOSTIC - if (!(reqh->rqflags & URQ_REQUEST)) + if (!(xfer->rqflags & URQ_REQUEST)) panic("uhci_root_ctrl_transfer: not a request\n"); #endif - req = &reqh->request; + req = &xfer->request; DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); @@ -2489,7 +2623,7 @@ uhci_root_ctrl_start(reqh) index = UGETW(req->wIndex); if (len != 0) - buf = KERNADDR(&reqh->dmabuf); + buf = KERNADDR(&xfer->dmabuf); #define C(x,y) ((x) | ((y) << 8)) switch(C(req->bRequest, req->bmRequestType)) { @@ -2512,7 +2646,7 @@ uhci_root_ctrl_start(reqh) switch(value >> 8) { case UDESC_DEVICE: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); @@ -2521,7 +2655,7 @@ uhci_root_ctrl_start(reqh) break; case UDESC_CONFIG: if ((value & 0xff) != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); @@ -2552,7 +2686,7 @@ uhci_root_ctrl_start(reqh) } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2577,14 +2711,14 @@ uhci_root_ctrl_start(reqh) break; case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): if (value >= USB_MAX_DEVICES) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_addr = value; break; case C(UR_SET_CONFIG, UT_WRITE_DEVICE): if (value != 0 && value != 1) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } sc->sc_conf = value; @@ -2594,7 +2728,7 @@ uhci_root_ctrl_start(reqh) case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): break; @@ -2612,7 +2746,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2642,7 +2776,7 @@ uhci_root_ctrl_start(reqh) break; case UHF_C_PORT_RESET: sc->sc_isreset = 0; - r = USBD_NORMAL_COMPLETION; + err = USBD_NORMAL_COMPLETION; goto ret; case UHF_PORT_CONNECTION: case UHF_PORT_OVER_CURRENT: @@ -2650,7 +2784,7 @@ uhci_root_ctrl_start(reqh) case UHF_PORT_LOW_SPEED: case UHF_C_PORT_SUSPEND: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; @@ -2660,7 +2794,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len > 0) { @@ -2672,7 +2806,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if (value != 0) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } l = min(len, USB_HUB_DESCRIPTOR_SIZE); @@ -2681,7 +2815,7 @@ uhci_root_ctrl_start(reqh) break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } memset(buf, 0, len); @@ -2693,11 +2827,11 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } if (len != 4) { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } x = UREAD2(sc, port); @@ -2728,7 +2862,7 @@ uhci_root_ctrl_start(reqh) totlen = l; break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): break; @@ -2738,7 +2872,7 @@ uhci_root_ctrl_start(reqh) else if (index == 2) port = UHCI_PORTSC2; else { - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } switch(value) { @@ -2773,27 +2907,29 @@ uhci_root_ctrl_start(reqh) case UHF_C_PORT_SUSPEND: case UHF_C_PORT_RESET: default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } break; default: - r = USBD_IOERROR; + err = USBD_IOERROR; goto ret; } - reqh->actlen = totlen; - r = USBD_NORMAL_COMPLETION; + xfer->actlen = totlen; + err = USBD_NORMAL_COMPLETION; ret: - reqh->status = r; - reqh->hcpriv = 0; - usb_transfer_complete(reqh); + xfer->status = err; + xfer->hcpriv = 0; + s = splusb(); + usb_transfer_complete(xfer); + splx(s); return (USBD_IN_PROGRESS); } /* Abort a root control request. */ void -uhci_root_ctrl_abort(reqh) - usbd_request_handle reqh; +uhci_root_ctrl_abort(xfer) + usbd_xfer_handle xfer; { /* Nothing to do, all transfers are syncronous. */ } @@ -2811,42 +2947,53 @@ uhci_root_ctrl_close(pipe) /* Abort a root interrupt request. */ void -uhci_root_intr_abort(reqh) - usbd_request_handle reqh; +uhci_root_intr_abort(xfer) + usbd_xfer_handle xfer; { - uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus; + uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usb_untimeout(uhci_timo, reqh, reqh->timo_handle); + usb_untimeout(uhci_timo, xfer, xfer->timo_handle); sc->sc_has_timo = 0; + + if (xfer->pipe->intrxfer == xfer) { + DPRINTF(("uhci_root_intr_abort: remove\n")); + xfer->pipe->intrxfer = 0; + } + xfer->status = USBD_CANCELLED; + usb_transfer_complete(xfer); } usbd_status -uhci_root_intr_transfer(reqh) - usbd_request_handle reqh; +uhci_root_intr_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_status r; + usbd_status err; - r = usb_insert_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) - return (r); - else - return (uhci_root_intr_start(reqh)); + /* Insert last in queue. */ + err = usb_insert_transfer(xfer); + if (err) + return (err); + + /* Pipe isn't running (otherwise err would be USBD_INPROG), + * start first + */ + return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); } /* Start a transfer on the root interrupt pipe */ usbd_status -uhci_root_intr_start(reqh) - usbd_request_handle reqh; +uhci_root_intr_start(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n", - reqh, reqh->length, reqh->flags)); + DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n", + xfer, xfer->length, xfer->flags)); - sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval); - usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); - sc->sc_has_timo = reqh; + sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); + usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle); + sc->sc_has_timo = xfer; return (USBD_IN_PROGRESS); } @@ -2857,8 +3004,7 @@ uhci_root_intr_close(pipe) { uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle); + usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle); sc->sc_has_timo = 0; DPRINTF(("uhci_root_intr_close\n")); } - diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h index dfdff271b128..bcb5fcac2f7c 100644 --- a/sys/dev/usb/uhcireg.h +++ b/sys/dev/usb/uhcireg.h @@ -1,4 +1,4 @@ -/* $NetBSD: uhcireg.h,v 1.7 1999/08/22 23:19:57 augustss Exp $ */ +/* $NetBSD: uhcireg.h,v 1.6 1999/04/03 19:01:20 augustss Exp $ */ /* $FreeBSD$ */ /* diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index 1c2ad1b9557f..682a4958452d 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,5 +1,5 @@ -/* $NetBSD: uhcivar.h,v 1.12 1999/08/22 23:41:00 augustss Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: uhcivar.h,v 1.16 1999/10/13 08:10:56 augustss Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ typedef union { */ typedef struct uhci_intr_info { struct uhci_softc *sc; - usbd_request_handle reqh; + usbd_xfer_handle xfer; uhci_soft_td_t *stdstart; uhci_soft_td_t *stdend; LIST_ENTRY(uhci_intr_info) list; @@ -130,12 +130,6 @@ typedef struct uhci_softc { struct usbd_bus sc_bus; /* base device */ bus_space_tag_t iot; bus_space_handle_t ioh; -#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__) */ uhci_physaddr_t *sc_pframes; usb_dma_t sc_dma; @@ -154,12 +148,9 @@ typedef struct uhci_softc { char sc_isreset; -#if defined(__NetBSD__) char sc_suspend; -#endif - usbd_request_handle sc_has_timo; + usbd_xfer_handle sc_has_timo; - int sc_intrs; LIST_HEAD(, uhci_intr_info) sc_intrhead; /* Info for the root hub interrupt channel. */ @@ -171,11 +162,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 *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) +int uhci_detach __P((uhci_softc_t *, int)); +int uhci_activate __P((device_ptr_t, enum devact)); #endif diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index 719341c853b6..a38fbf4e924d 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhid.c,v 1.24 1999/09/05 19:32:18 augustss Exp $ */ +/* $NetBSD: uhid.c,v 1.26 1999/10/13 08:10:56 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -146,11 +146,13 @@ static struct cdevsw uhid_cdevsw = { }; #endif -void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); +static void uhid_intr __P((usbd_xfer_handle, usbd_private_handle, + usbd_status)); -int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int)); -int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int)); -int uhid_do_ioctl __P((struct uhid_softc *, u_long, caddr_t, int, struct proc *)); +static int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int)); +static int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int)); +static int uhid_do_ioctl __P((struct uhid_softc *, u_long, caddr_t, int, + struct proc *)); USB_DECLARE_DRIVER(uhid); @@ -159,10 +161,10 @@ USB_MATCH(uhid) USB_MATCH_START(uhid, uaa); usb_interface_descriptor_t *id; - if (!uaa->iface) + if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UCLASS_HID) + if (id == NULL || id->bInterfaceClass != UCLASS_HID) return (UMATCH_NONE); return (UMATCH_IFACECLASS_GENERIC); } @@ -175,7 +177,7 @@ USB_ATTACH(uhid) usb_endpoint_descriptor_t *ed; int size; void *desc; - usbd_status r; + usbd_status err; char devinfo[1024]; sc->sc_iface = iface; @@ -186,7 +188,7 @@ USB_ATTACH(uhid) devinfo, id->bInterfaceClass, id->bInterfaceSubClass); ed = usbd_interface2endpoint_descriptor(iface, 0); - if (!ed) { + if (ed == NULL) { printf("%s: could not read endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); sc->sc_dying = 1; @@ -212,11 +214,11 @@ USB_ATTACH(uhid) sc->sc_ep_addr = ed->bEndpointAddress; desc = 0; - r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV); + if (err) { printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev)); sc->sc_dying = 1; - if (desc) + if (desc != NULL) free(desc, M_USBDEV); USB_ATTACH_ERROR_RETURN; } @@ -272,12 +274,12 @@ USB_DETACH(uhid) int maj, mn; DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); -#elif defined(__FreeBSD__) +#else DPRINTF(("uhid_detach: sc=%p\n", sc)); #endif sc->sc_dying = 1; - if (sc->sc_intrpipe) + if (sc->sc_intrpipe != NULL) usbd_abort_pipe(sc->sc_intrpipe); if (sc->sc_state & UHID_OPEN) { @@ -310,8 +312,8 @@ USB_DETACH(uhid) } void -uhid_intr(reqh, addr, status) - usbd_request_handle reqh; +uhid_intr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { @@ -347,7 +349,9 @@ uhidopen(dev, flag, mode, p) int mode; struct proc *p; { - usbd_status r; + struct uhid_softc *sc; + usbd_status err; + USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc); DPRINTF(("uhidopen: sc=%p\n", sc)); @@ -359,26 +363,21 @@ uhidopen(dev, flag, mode, p) return (EBUSY); sc->sc_state |= UHID_OPEN; -#if defined(__NetBSD__) || defined(__OpenBSD__) if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { sc->sc_state &= ~UHID_OPEN; return (ENOMEM); } -#elif defined(__FreeBSD__) - clist_alloc_cblocks(&sc->sc_q, UHID_BSIZE, 0); -#endif sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); /* Set up interrupt pipe. */ - r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, - USBD_SHORT_XFER_OK, - &sc->sc_intrpipe, sc, sc->sc_ibuf, - sc->sc_isize, uhid_intr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, + sc->sc_isize, uhid_intr); + if (err) { DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " - "error=%d\n",r)); + "error=%d\n",err)); free(sc->sc_ibuf, M_USBDEV); free(sc->sc_obuf, M_USBDEV); sc->sc_state &= ~UHID_OPEN; @@ -397,6 +396,8 @@ uhidclose(dev, flag, mode, p) int mode; struct proc *p; { + struct uhid_softc *sc; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); DPRINTF(("uhidclose: sc=%p\n", sc)); @@ -406,11 +407,7 @@ uhidclose(dev, flag, mode, p) usbd_close_pipe(sc->sc_intrpipe); sc->sc_intrpipe = 0; -#if defined(__NetBSD__) || defined(__OpenBSD__) clfree(&sc->sc_q); -#elif defined(__FreeBSD__) - clist_free_cblocks(&sc->sc_q); -#endif free(sc->sc_ibuf, M_USBDEV); free(sc->sc_obuf, M_USBDEV); @@ -430,15 +427,15 @@ uhid_do_read(sc, uio, flag) int error = 0; size_t length; u_char buffer[UHID_CHUNK]; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhidread\n")); if (sc->sc_state & UHID_IMMED) { DPRINTFN(1, ("uhidread immed\n")); - r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, buffer, sc->sc_isize); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + sc->sc_iid, buffer, sc->sc_isize); + if (err) return (EIO); return (uiomove(buffer, sc->sc_isize, uio)); } @@ -491,9 +488,11 @@ uhidread(dev, uio, flag) struct uio *uio; int flag; { - USB_GET_SC(uhid, UHIDUNIT(dev), sc); + struct uhid_softc *sc; int error; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); + sc->sc_refcnt++; error = uhid_do_read(sc, uio, flag); if (--sc->sc_refcnt < 0) @@ -509,7 +508,7 @@ uhid_do_write(sc, uio, flag) { int error; int size; - usbd_status r; + usbd_status err; DPRINTFN(1, ("uhidwrite\n")); @@ -523,15 +522,13 @@ uhid_do_write(sc, uio, flag) error = uiomove(sc->sc_obuf, size, uio); if (!error) { if (sc->sc_oid) - r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - sc->sc_obuf[0], - sc->sc_obuf+1, size-1); + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + sc->sc_obuf[0], sc->sc_obuf+1, size-1); else - r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - 0, sc->sc_obuf, size); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + 0, sc->sc_obuf, size); + if (err) error = EIO; - } } return (error); @@ -543,9 +540,11 @@ uhidwrite(dev, uio, flag) struct uio *uio; int flag; { - USB_GET_SC(uhid, UHIDUNIT(dev), sc); + struct uhid_softc *sc; int error; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); + sc->sc_refcnt++; error = uhid_do_write(sc, uio, flag); if (--sc->sc_refcnt < 0) @@ -564,7 +563,7 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) struct usb_ctl_report_desc *rd; struct usb_ctl_report *re; int size, id; - usbd_status r; + usbd_status err; DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); @@ -585,11 +584,10 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) case USB_SET_IMMED: if (*(int *)addr) { - /* XXX should read into ibuf, but does it matter */ - r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, sc->sc_ibuf, - sc->sc_isize); - if (r != USBD_NORMAL_COMPLETION) + /* XXX should read into ibuf, but does it matter? */ + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + sc->sc_iid, sc->sc_ibuf, sc->sc_isize); + if (err) return (EOPNOTSUPP); sc->sc_state |= UHID_IMMED; @@ -615,9 +613,9 @@ uhid_do_ioctl(sc, cmd, addr, flag, p) default: return (EINVAL); } - r = usbd_get_report(sc->sc_iface, re->report, id, - re->data, size); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_report(sc->sc_iface, re->report, id, re->data, + size); + if (err) return (EIO); break; @@ -635,9 +633,11 @@ uhidioctl(dev, cmd, addr, flag, p) int flag; struct proc *p; { - USB_GET_SC(uhid, UHIDUNIT(dev), sc); + struct uhid_softc *sc; int error; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); + sc->sc_refcnt++; error = uhid_do_ioctl(sc, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) @@ -651,8 +651,10 @@ uhidpoll(dev, events, p) int events; struct proc *p; { + struct uhid_softc *sc; int revents = 0; int s; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_dying) diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 6b859b9d54c7..015dce995ed6 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhub.c,v 1.26 1999/09/05 19:32:18 augustss Exp $ */ +/* $NetBSD: uhub.c,v 1.32 1999/10/13 08:10:56 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -52,9 +52,10 @@ #elif defined(__FreeBSD__) #include #include +#include "bus_if.h" #endif -#include "bus_if.h" +#include #include #include @@ -78,22 +79,23 @@ struct uhub_softc { u_char sc_running; }; -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)); +static usbd_status uhub_init_port __P((struct usbd_port *)); +static usbd_status uhub_explore __P((usbd_device_handle hub)); +static void uhub_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); #if defined(__FreeBSD__) static bus_child_detached_t uhub_child_detached; #endif -/* We need two attachment points: + +/* + * We need two attachment points: * hub to usb and hub to hub * Every other driver only connects to hubs */ #if defined(__NetBSD__) || defined(__OpenBSD__) -USB_DECLARE_DRIVER(uhub); +USB_DECLARE_DRIVER(uhub) /* Create the driver instance for the hub connected to hub case */ struct cfattach uhub_uhub_ca = { @@ -101,8 +103,9 @@ struct cfattach uhub_uhub_ca = { uhub_detach, uhub_activate }; #elif defined(__FreeBSD__) -USB_DECLARE_DRIVER_INIT(uhub, DEVMETHOD(bus_child_detached, uhub_child_detached)); - +USB_DECLARE_DRIVER_INIT(uhub, + DEVMETHOD(bus_child_detached, uhub_child_detached)); + /* Create the driver instance for the hub connected to usb case. */ devclass_t uhubroot_devclass; @@ -121,7 +124,6 @@ static driver_t uhubroot_driver = { }; #endif - USB_MATCH(uhub) { USB_MATCH_START(uhub, uaa); @@ -132,7 +134,7 @@ USB_MATCH(uhub) * The subclass for hubs seems to be 0 for some and 1 for others, * so we just ignore the subclass. */ - if (uaa->iface == 0 && dd->bDeviceClass == UCLASS_HUB) + if (uaa->iface == NULL && dd->bDeviceClass == UCLASS_HUB) return (UMATCH_DEVCLASS_DEVSUBCLASS); return (UMATCH_NONE); } @@ -142,7 +144,7 @@ USB_ATTACH(uhub) USB_ATTACH_START(uhub, sc, uaa); usbd_device_handle dev = uaa->device; char devinfo[1024]; - usbd_status r; + usbd_status err; struct usbd_hub *hub; usb_device_request_t req; usb_hub_descriptor_t hubdesc; @@ -156,10 +158,10 @@ USB_ATTACH(uhub) USB_ATTACH_SETUP; printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - r = usbd_set_config_index(dev, 0, 1); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config_index(dev, 0, 1); + if (err) { DPRINTF(("%s: configuration failed, error=%s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(r))); + USBDEVNAME(sc->sc_dev), usbd_errstr(err))); USB_ATTACH_ERROR_RETURN; } @@ -176,15 +178,15 @@ USB_ATTACH(uhub) USETW(req.wIndex, 0); USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); DPRINTFN(1,("usb_init_hub: getting hub descriptor\n")); - r = usbd_do_request(dev, &req, &hubdesc); + err = usbd_do_request(dev, &req, &hubdesc); nports = hubdesc.bNbrPorts; - if (r == USBD_NORMAL_COMPLETION && nports > 7) { + if (!err && nports > 7) { USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8); - r = usbd_do_request(dev, &req, &hubdesc); + err = usbd_do_request(dev, &req, &hubdesc); } - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTF(("%s: getting hub descriptor failed, error=%s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(r))); + USBDEVNAME(sc->sc_dev), usbd_errstr(err))); USB_ATTACH_ERROR_RETURN; } @@ -194,11 +196,10 @@ USB_ATTACH(uhub) printf("%s: %d port%s with %d removable, %s powered\n", USBDEVNAME(sc->sc_dev), nports, nports != 1 ? "s" : "", nremov, dev->self_powered ? "self" : "bus"); - hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), M_USBDEV, M_NOWAIT); - if (hub == 0) + if (hub == NULL) USB_ATTACH_ERROR_RETURN; dev->hub = hub; dev->hub->hubsoftc = sc; @@ -211,7 +212,7 @@ USB_ATTACH(uhub) dev->powersrc->parent ? dev->powersrc->parent->self_powered : 0)); - if (!dev->self_powered && dev->powersrc->parent && + if (!dev->self_powered && dev->powersrc->parent != NULL && !dev->powersrc->parent->self_powered) { printf("%s: bus powered hub connected to bus powered hub, " "ignored\n", USBDEVNAME(sc->sc_dev)); @@ -219,13 +220,13 @@ USB_ATTACH(uhub) } /* Set up interrupt pipe. */ - r = usbd_device2interface_handle(dev, 0, &iface); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_device2interface_handle(dev, 0, &iface); + if (err) { printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev)); goto bad; } ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == 0) { + if (ed == NULL) { printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); goto bad; } @@ -234,11 +235,10 @@ USB_ATTACH(uhub) goto bad; } - r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK, - &sc->sc_ipipe, sc, sc->sc_status, - sizeof(sc->sc_status), - uhub_intr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, + USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, + sizeof(sc->sc_status), uhub_intr); + if (err) { printf("%s: cannot open interrupt pipe\n", USBDEVNAME(sc->sc_dev)); goto bad; @@ -252,16 +252,16 @@ USB_ATTACH(uhub) up->device = 0; up->parent = dev; up->portno = p+1; - r = uhub_init_port(up); - if (r != USBD_NORMAL_COMPLETION) + err = uhub_init_port(up); + if (err) printf("%s: init of port %d failed\n", - USBDEVNAME(sc->sc_dev), up->portno); + USBDEVNAME(sc->sc_dev), up->portno); } sc->sc_running = 1; USB_ATTACH_SUCCESS_RETURN; -bad: + bad: free(hub, M_USBDEV); dev->hub = 0; USB_ATTACH_ERROR_RETURN; @@ -273,12 +273,12 @@ uhub_init_port(up) { int port = up->portno; usbd_device_handle dev = up->parent; - usbd_status r; + usbd_status err; u_int16_t pstatus; - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_port_status(dev, port, &up->status); + if (err) + return (err); pstatus = UGETW(up->status.wPortStatus); DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x " "change=0x%04x\n", @@ -295,9 +295,9 @@ usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT); #endif /* then turn the power on. */ - r = usbd_set_port_feature(dev, port, UHF_PORT_POWER); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); + if (err) + return (err); DPRINTF(("usb_init_port: turn on port %d power status=0x%04x " "change=0x%04x\n", port, UGETW(up->status.wPortStatus), @@ -306,9 +306,9 @@ usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT); usbd_delay_ms(dev, dev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR); /* Get the port status again. */ - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_port_status(dev, port, &up->status); + if (err) + return (err); DPRINTF(("usb_init_port: after power on status=0x%04x " "change=0x%04x\n", UGETW(up->status.wPortStatus), @@ -341,7 +341,7 @@ uhub_explore(dev) usb_hub_descriptor_t *hd = &dev->hub->hubdesc; struct uhub_softc *sc = dev->hub->hubsoftc; struct usbd_port *up; - usbd_status r; + usbd_status err; int port; int change, status; @@ -356,11 +356,10 @@ uhub_explore(dev) for(port = 1; port <= hd->bNbrPorts; port++) { up = &dev->hub->ports[port-1]; - r = usbd_get_port_status(dev, port, &up->status); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_get_port_status(dev, port, &up->status); + if (err) { DPRINTF(("uhub_explore: get port status failed, " - "error=%s\n", - usbd_errstr(r))); + "error=%s\n", usbd_errstr(err))); continue; } status = UGETW(up->status.wPortStatus); @@ -404,13 +403,11 @@ uhub_explore(dev) * the disconnect. */ disco: - if (up->device) { + if (up->device != NULL) { /* Disconnected */ DPRINTF(("uhub_explore: device %d disappeared " - "on port %d\n", - up->device->address, port)); - uhub_disconnect_port(up); - + "on port %d\n", up->device->address, port)); + usb_disconnect_port(up, USBDEV(sc->sc_dev)); usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); } @@ -429,32 +426,26 @@ uhub_explore(dev) continue; /* Get device info and set its address. */ - r = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, - dev->depth + 1, status & UPS_LOW_SPEED, - port, up); + err = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, + dev->depth + 1, status & UPS_LOW_SPEED, + port, up); /* XXX retry a few times? */ - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTFN(-1,("uhub_explore: usb_new_device failed, " - "error=%s\n", usbd_errstr(r))); + "error=%s\n", usbd_errstr(err))); /* Avoid addressing problems by disabling. */ /* usbd_reset_port(dev, port, &up->status); */ -/* XXX - * What should we do. The device may or may not be at its - * assigned address. In any case we'd like to ignore it. - */ - if (r == USBD_SET_ADDR_FAILED || 1) {/* XXX */ - /* The unit refused to accept a new - * address, and since we cannot leave - * at 0 we have to disable the port - * instead. */ - printf("%s: device problem, disabling " - "port %d\n", - USBDEVNAME(sc->sc_dev), port); - usbd_clear_port_feature(dev, port, - UHF_PORT_ENABLE); - /* Make sure we don't try to restart it. */ - up->restartcnt = USBD_RESTART_MAX; - } + + /* + * The unit refused to accept a new address, or had + * some other serious problem. Since we cannot leave + * at 0 we have to disable the port instead. + */ + printf("%s: device problem, disabling port %d\n", + USBDEVNAME(sc->sc_dev), port); + usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE); + /* Make sure we don't try to restart it infinitely. */ + up->restartcnt = USBD_RESTART_MAX; } else { if (up->device->hub) up->device->hub->explore(up->device); @@ -463,112 +454,31 @@ 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; - int i; - - DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n", - up, dev, up->portno)); - - if (!dev) /* not even generic device was attached */ - return; - - if (!dev->cdesc) { - /* Partially attached device, just drop it. */ - dev->bus->devices[dev->address] = 0; - up->device = 0; - return; - } - - if (dev->subdevs) { - for (i = 0; dev->subdevs[i]; i++) { - if (!dev->subdevs[i]) /* skip empty elements */ - continue; - - printf("%s: at %s port %d (addr %d) disconnected\n", - USBDEVPTRNAME(dev->subdevs[i]), - USBDEVPTRNAME(up->parent->subdevs[0]), - up->portno, dev->address); #if defined(__NetBSD__) || defined(__OpenBSD__) - config_detach(dev->subdevs[i], DETACH_FORCE); -#elif defined(__FreeBSD__) - device_delete_child(device_get_parent(dev->subdevs[i]), - dev->subdevs[i]); -#endif - } - } - - dev->bus->devices[dev->address] = 0; - up->device = 0; - usb_free_device(dev); -} - -#if defined(__FreeBSD__) -/* Called when a device has been detached from it */ -static void -uhub_child_detached(self, child) - device_t self; - device_t child; -{ - struct uhub_softc *sc = device_get_softc(self); - usbd_device_handle dev = sc->sc_hub; - struct usbd_port *up; - int nports; - int port; - int i; - - if (!dev->hub) - /* should never happen; children are only created after init */ - panic("hub not fully initialised, but child deleted?"); - - nports = dev->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - up = &dev->hub->ports[port]; - if (up->device && up->device->subdevs) { - for (i = 0; up->device->subdevs[i]; i++) { - if (up->device->subdevs[i] == child) { - up->device->subdevs[i] = NULL; - return; - } - } - } - } -} -#endif - - -#if defined(__NetBSD__) int uhub_activate(self, act) device_ptr_t self; enum devact act; { + struct uhub_softc *sc = (struct uhub_softc *)self; + usbd_device_handle devhub = sc->sc_hub; + usbd_device_handle dev; + int nports, port, i; + switch (act) { case DVACT_ACTIVATE: return (EOPNOTSUPP); break; case DVACT_DEACTIVATE: + nports = devhub->hub->hubdesc.bNbrPorts; + for(port = 0; port < nports; port++) { + dev = devhub->hub->ports[port].device; + if (dev != NULL) { + for (i = 0; dev->subdevs[i]; i++) + config_deactivate(dev->subdevs[i]); + } + } break; } return (0); @@ -583,16 +493,16 @@ USB_DETACH(uhub) { USB_DETACH_START(uhub, sc); usbd_device_handle dev = sc->sc_hub; - struct usbd_port *up; + struct usbd_port *rup; int port, nports; #if defined(__NetBSD__) || defined(__OpenBSD__) - DPRINTF(("uhub_detach: sc=%port flags=%d\n", sc, flags)); + DPRINTF(("uhub_detach: sc=%p flags=%d\n", sc, flags)); #elif defined(__FreeBSD__) DPRINTF(("uhub_detach: sc=%port\n", sc)); #endif - if (!dev->hub) /* Must be partially working */ + if (dev->hub == NULL) /* Must be partially working */ return (0); usbd_abort_pipe(sc->sc_ipipe); @@ -600,21 +510,51 @@ USB_DETACH(uhub) nports = dev->hub->hubdesc.bNbrPorts; for(port = 0; port < nports; port++) { - up = &dev->hub->ports[port]; - if (up->device) { - DPRINTF(("uhub_detach: device %d disappeared " - "on port %d\n", - up->device->address, port)); - uhub_disconnect_port(up); - } + rup = &dev->hub->ports[port]; + if (rup->device) + usb_disconnect_port(rup, self); } free(dev->hub, M_USBDEV); - dev->hub = 0; + dev->hub = NULL; return (0); } +#if defined(__FreeBSD__) +/* Called when a device has been detached from it */ +static void +uhub_child_detached(self, child) + device_t self; + device_t child; +{ + struct uhub_softc *sc = device_get_softc(self); + usbd_device_handle devhub = sc->sc_hub; + usbd_device_handle dev; + int nports; + int port; + int i; + + if (!devhub->hub) + /* should never happen; children are only created after init */ + panic("hub not fully initialised, but child deleted?"); + + nports = devhub->hub->hubdesc.bNbrPorts; + for (port = 0; port < nports; port++) { + dev = devhub->hub->ports[port].device; + if (dev && dev->subdevs) { + for (i = 0; dev->subdevs[i]; i++) { + if (dev->subdevs[i] == child) { + dev->subdevs[i] = NULL; + return; + } + } + } + } +} +#endif + + /* * Hub interrupt. * This an indication that some port has changed status. @@ -622,8 +562,8 @@ USB_DETACH(uhub) * to be explored again. */ void -uhub_intr(reqh, addr, status) - usbd_request_handle reqh; +uhub_intr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c index 5ff4af61f10d..2870031254b7 100644 --- a/sys/dev/usb/ukbd.c +++ b/sys/dev/usb/ukbd.c @@ -1,4 +1,3 @@ -/* $NetBSD: ukbd.c,v 1.22 1999/01/09 12:10:36 drochner Exp $ */ /* $FreeBSD$ */ /* @@ -112,7 +111,7 @@ typedef struct ukbd_softc { #define UKBD_CHUNK 128 /* chunk size for read */ #define UKBD_BSIZE 1020 /* buffer size */ -typedef void usbd_intr_t(usbd_request_handle, usbd_private_handle, usbd_status); +typedef void usbd_intr_t(usbd_xfer_handle, usbd_private_handle, usbd_status); typedef void usbd_disco_t(void *); static usbd_intr_t ukbd_intr; @@ -209,7 +208,7 @@ ukbd_detach(device_t self) } void -ukbd_intr(usbd_request_handle reqh, usbd_private_handle addr, usbd_status status) +ukbd_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) { keyboard_t *kbd = (keyboard_t *)addr; @@ -582,7 +581,7 @@ static int ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func) { ukbd_state_t *state = (ukbd_state_t *)kbd->kb_data; - usbd_status r; + usbd_status err; if (on) { /* Set up interrupt pipe. */ @@ -590,12 +589,12 @@ ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func) return EBUSY; state->ks_ifstate |= INTRENABLED; - r = usbd_open_pipe_intr(state->ks_iface, state->ks_ep_addr, + err = usbd_open_pipe_intr(state->ks_iface, state->ks_ep_addr, USBD_SHORT_XFER_OK, &state->ks_intrpipe, kbd, &state->ks_ndata, sizeof(state->ks_ndata), func); - if (r != USBD_NORMAL_COMPLETION) + if (err) return (EIO); } else { /* Disable interrupts. */ @@ -1333,7 +1332,7 @@ static int init_keyboard(ukbd_state_t *state, int *type, int flags) { usb_endpoint_descriptor_t *ed; - usbd_status r; + usbd_status err; *type = KB_OTHER; @@ -1360,9 +1359,9 @@ bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketS } if ((usbd_get_quirks(state->ks_uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) { - r = usbd_set_protocol(state->ks_iface, 0); + err = usbd_set_protocol(state->ks_iface, 0); DPRINTFN(5, ("ukbd:init_keyboard: protocol set\n")); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { printf("ukbd: set protocol failed\n"); return EIO; } diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c index f2cd7411da1c..d183b00a50c2 100644 --- a/sys/dev/usb/ulpt.c +++ b/sys/dev/usb/ulpt.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulpt.c,v 1.23 1999/09/11 10:40:07 augustss Exp $ */ +/* $NetBSD: ulpt.c,v 1.27 1999/10/13 08:10:57 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -71,7 +71,7 @@ #define STEP hz/4 #define LPTPRI (PZERO+8) -#define ULPT_BSIZE 1024 +#define ULPT_BSIZE 16384 #ifdef ULPT_DEBUG #define DPRINTF(x) if (ulptdebug) logprintf x @@ -118,10 +118,7 @@ struct ulpt_softc { }; #if defined(__NetBSD__) || defined(__OpenBSD__) -int ulptopen __P((dev_t, int, int, struct proc *)); -int ulptclose __P((dev_t, int, int, struct proc *p)); -int ulptwrite __P((dev_t, struct uio *uio, int)); -int ulptioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); +cdev_decl(ulpt); #elif defined(__FreeBSD__) static d_open_t ulptopen; static d_close_t ulptclose; @@ -169,10 +166,10 @@ USB_MATCH(ulpt) usb_interface_descriptor_t *id; DPRINTFN(10,("ulpt_match\n")); - if (!uaa->iface) + if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); - if (id && + if (id != NULL && id->bInterfaceClass == UCLASS_PRINTER && id->bInterfaceSubClass == USUBCLASS_PRINTER && (id->bInterfaceProtocol == UPROTO_PRINTER_UNI || @@ -189,7 +186,7 @@ USB_ATTACH(ulpt) usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); char devinfo[1024]; usb_endpoint_descriptor_t *ed; - usbd_status r; + usbd_status err; DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); usbd_devinfo(dev, 0, devinfo); @@ -199,13 +196,13 @@ USB_ATTACH(ulpt) /* Figure out which endpoint is the bulk out endpoint. */ ed = usbd_interface2endpoint_descriptor(iface, 0); - if (!ed) + if (ed == NULL) goto nobulk; if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT || (ed->bmAttributes & UE_XFERTYPE) != UE_BULK) { /* In case we are using a bidir protocol... */ ed = usbd_interface2endpoint_descriptor(iface, 1); - if (!ed) + if (ed == NULL) goto nobulk; if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT || (ed->bmAttributes & UE_XFERTYPE) != UE_BULK) @@ -215,8 +212,8 @@ USB_ATTACH(ulpt) DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_bulk)); sc->sc_iface = iface; - r = usbd_interface2device_handle(iface, &sc->sc_udev); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_interface2device_handle(iface, &sc->sc_udev); + if (err) { sc->sc_dying = 1; USB_ATTACH_ERROR_RETURN; } @@ -238,8 +235,9 @@ USB_ATTACH(ulpt) USETW(req.wValue, cd->bConfigurationValue); USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); USETW(req.wLength, sizeof devinfo - 1); - r = usbd_do_request_flags(dev, &req, devinfo,USBD_SHORT_XFER_OK,&alen); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_do_request_flags(dev, &req, devinfo, USBD_SHORT_XFER_OK, + &alen); + if (err) { printf("%s: cannot get device id\n", USBDEVNAME(sc->sc_dev)); } else if (alen <= 2) { printf("%s: empty device id, no printer connected?\n", @@ -307,7 +305,7 @@ USB_DETACH(ulpt) #endif sc->sc_dying = 1; - if (sc->sc_bulkpipe) + if (sc->sc_bulkpipe != NULL) usbd_abort_pipe(sc->sc_bulkpipe); s = splusb(); @@ -342,7 +340,7 @@ ulpt_status(sc) struct ulpt_softc *sc; { usb_device_request_t req; - usbd_status r; + usbd_status err; u_char status; req.bmRequestType = UT_READ_CLASS_INTERFACE; @@ -350,9 +348,9 @@ ulpt_status(sc) USETW(req.wValue, 0); USETW(req.wIndex, sc->sc_ifaceno); USETW(req.wLength, 1); - r = usbd_do_request(sc->sc_udev, &req, &status); - DPRINTFN(1, ("ulpt_status: status=0x%02x r=%d\n", status, r)); - if (r == USBD_NORMAL_COMPLETION) + err = usbd_do_request(sc->sc_udev, &req, &status); + DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); + if (!err) return (status); else return (0); @@ -384,11 +382,13 @@ ulptopen(dev, flag, mode, p) struct proc *p; { u_char flags = ULPTFLAGS(dev); - usbd_status r; + struct ulpt_softc *sc; + usbd_status err; int spin, error; + USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc); - if (!sc || !sc->sc_iface || sc->sc_dying) + if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) return (ENXIO); if (sc->sc_state) @@ -423,8 +423,8 @@ ulptopen(dev, flag, mode, p) } } - r = usbd_open_pipe(sc->sc_iface, sc->sc_bulk, 0, &sc->sc_bulkpipe); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_open_pipe(sc->sc_iface, sc->sc_bulk, 0, &sc->sc_bulkpipe); + if (err) { sc->sc_state = 0; return (EIO); } @@ -463,6 +463,8 @@ ulptclose(dev, flag, mode, p) int mode; struct proc *p; { + struct ulpt_softc *sc; + USB_GET_SC(ulpt, ULPTUNIT(dev), sc); if (sc->sc_state != ULPT_OPEN) @@ -487,16 +489,16 @@ ulpt_do_write(sc, uio, flags) u_int32_t n; int error = 0; void *bufp; - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; DPRINTF(("ulptwrite\n")); - reqh = usbd_alloc_request(sc->sc_udev); - if (reqh == 0) + xfer = usbd_alloc_request(sc->sc_udev); + if (xfer == NULL) return (ENOMEM); - bufp = usbd_alloc_buffer(reqh, ULPT_BSIZE); - if (bufp == 0) { - usbd_free_request(reqh); + bufp = usbd_alloc_buffer(xfer, ULPT_BSIZE); + if (bufp == NULL) { + usbd_free_request(xfer); return (ENOMEM); } while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { @@ -505,15 +507,15 @@ ulpt_do_write(sc, uio, flags) if (error) break; DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); - r = usbd_bulk_transfer(reqh, sc->sc_bulkpipe, 0, - USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("ulptwrite: error=%d\n", r)); + err = usbd_bulk_transfer(xfer, sc->sc_bulkpipe, USBD_NO_COPY, + USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); + if (err) { + DPRINTF(("ulptwrite: error=%d\n", err)); error = EIO; break; } } - usbd_free_request(reqh); + usbd_free_request(xfer); return (error); } @@ -524,9 +526,11 @@ ulptwrite(dev, uio, flags) struct uio *uio; int flags; { - USB_GET_SC(ulpt, ULPTUNIT(dev), sc); + struct ulpt_softc *sc; int error; + USB_GET_SC(ulpt, ULPTUNIT(dev), sc); + if (sc->sc_dying) return (EIO); diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index 42fb25bd8297..867d049c7a6b 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -288,7 +288,7 @@ umass_usb_transfer(usbd_interface_handle iface, usbd_pipe_handle pipe, void *buf, int buflen, int flags, int *xfer_size) { usbd_device_handle dev; - usbd_request_handle reqh; + usbd_xfer_handle xfer; usbd_private_handle priv; void *buffer; int size; @@ -300,28 +300,28 @@ umass_usb_transfer(usbd_interface_handle iface, usbd_pipe_handle pipe, usbd_interface2device_handle(iface, &dev); - reqh = usbd_alloc_request(dev); - if (!reqh) { + xfer = usbd_alloc_request(dev); + if (!xfer) { DPRINTF(UDMASS_USB, ("Not enough memory\n")); return USBD_NOMEM; } - (void) usbd_setup_request(reqh, pipe, 0, buf, buflen, + (void) usbd_setup_request(xfer, pipe, 0, buf, buflen, flags, 3000 /*ms*/, NULL); - err = usbd_sync_transfer(reqh); + err = usbd_sync_transfer(xfer); if (err) { DPRINTF(UDMASS_USB, ("transfer failed, %s\n", usbd_errstr(err))); - usbd_free_request(reqh); + usbd_free_request(xfer); return(err); } - usbd_get_request_status(reqh, &priv, &buffer, &size, &err); + usbd_get_request_status(xfer, &priv, &buffer, &size, &err); if (xfer_size) *xfer_size = size; - usbd_free_request(reqh); + usbd_free_request(xfer); return(USBD_NORMAL_COMPLETION); } diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c index 20e6fcfb77e8..3a997e0a2b06 100644 --- a/sys/dev/usb/ums.c +++ b/sys/dev/usb/ums.c @@ -123,7 +123,7 @@ struct ums_softc { #define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) #define MOUSE_FLAGS (HIO_RELATIVE) -static void ums_intr __P((usbd_request_handle reqh, +static void ums_intr __P((usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)); static void ums_add_to_queue __P((struct ums_softc *sc, @@ -166,7 +166,7 @@ USB_MATCH(ums) usb_interface_descriptor_t *id; int size, ret; void *desc; - usbd_status r; + usbd_status err; if (!uaa->iface) return (UMATCH_NONE); @@ -174,8 +174,8 @@ USB_MATCH(ums) if (!id || id->bInterfaceClass != UCLASS_HID) return (UMATCH_NONE); - r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP); + if (err) return (UMATCH_NONE); if (hid_is_collection(desc, size, @@ -196,7 +196,7 @@ USB_ATTACH(ums) usb_endpoint_descriptor_t *ed; int size; void *desc; - usbd_status r; + usbd_status err; char devinfo[1024]; u_int32_t flags; int i; @@ -232,8 +232,8 @@ USB_ATTACH(ums) USB_ATTACH_ERROR_RETURN; } - r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP); + if (err) USB_ATTACH_ERROR_RETURN; if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), @@ -395,8 +395,8 @@ ums_detach(device_t self) } void -ums_intr(reqh, addr, status) - usbd_request_handle reqh; +ums_intr(xfer, addr, status) + usbd_xfer_handle xfer; usbd_private_handle addr; usbd_status status; { @@ -444,6 +444,12 @@ ums_intr(reqh, addr, status) sc->status.dy += dy; sc->status.dz += dz; + /* Discard data in case of full buffer */ + if (sc->qcount == sizeof(sc->qbuf)) { + DPRINTF(("Buffer full, discarded packet")); + return; + } + /* * The Qtronix keyboard has a built in PS/2 port for a mouse. * The firmware once in a while posts a spurious button up @@ -528,7 +534,7 @@ ums_enable(v) { struct ums_softc *sc = v; - usbd_status r; + usbd_status err; if (sc->sc_enabled) return EBUSY; @@ -543,12 +549,12 @@ ums_enable(v) callout_handle_init(&sc->timeout_handle); /* Set up interrupt pipe. */ - r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, sc->sc_isize, ums_intr); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTF(("ums_enable: usbd_open_pipe_intr failed, error=%d\n", - r)); + err)); sc->sc_enabled = 0; return (EIO); } @@ -576,6 +582,8 @@ ums_disable(priv) static int ums_open(dev_t dev, int flag, int fmt, struct proc *p) { + struct ums_softc *sc; + USB_GET_SC_OPEN(ums, UMSUNIT(dev), sc); return ums_enable(sc); @@ -584,6 +592,8 @@ ums_open(dev_t dev, int flag, int fmt, struct proc *p) static int ums_close(dev_t dev, int flag, int fmt, struct proc *p) { + struct ums_softc *sc; + USB_GET_SC(ums, UMSUNIT(dev), sc); if (!sc) @@ -598,12 +608,14 @@ ums_close(dev_t dev, int flag, int fmt, struct proc *p) static int ums_read(dev_t dev, struct uio *uio, int flag) { - USB_GET_SC(ums, UMSUNIT(dev), sc); + struct ums_softc *sc; int s; char buf[sizeof(sc->qbuf)]; int l = 0; int error; + USB_GET_SC(ums, UMSUNIT(dev), sc); + s = splusb(); if (!sc) { splx(s); @@ -666,10 +678,12 @@ ums_read(dev_t dev, struct uio *uio, int flag) static int ums_poll(dev_t dev, int events, struct proc *p) { - USB_GET_SC(ums, UMSUNIT(dev), sc); + struct ums_softc *sc; int revents = 0; int s; + USB_GET_SC(ums, UMSUNIT(dev), sc); + if (!sc) return 0; @@ -690,11 +704,13 @@ ums_poll(dev_t dev, int events, struct proc *p) int ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { - USB_GET_SC(ums, UMSUNIT(dev), sc); + struct ums_softc *sc; int error = 0; int s; mousemode_t mode; + USB_GET_SC(ums, UMSUNIT(dev), sc); + if (!sc) return EIO; diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index f774835af35f..5005a4d7be5e 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.19 1999/09/05 19:32:19 augustss Exp $ */ +/* $NetBSD: usb.c,v 1.28 1999/10/13 08:10:57 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -55,17 +55,21 @@ #elif defined(__FreeBSD__) #include #include -#include +#include #include -#include #endif +#include #include #include +#include +#include #include #include #include +#define USB_DEV_MINOR 255 + #if defined(__FreeBSD__) MALLOC_DEFINE(M_USB, "USB", "USB"); MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); @@ -74,6 +78,8 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); #include "usb_if.h" #endif /* defined(__FreeBSD__) */ +#include + #include #include @@ -81,35 +87,39 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x int usbdebug = 0; -extern int uhcidebug; -extern int ohcidebug; +#ifdef UHCI_DEBUG +extern int uhcidebug; +#endif +#ifdef OHCI_DEBUG +extern int ohcidebug; +#endif +int usb_noexplore = 0; #else #define DPRINTF(x) #define DPRINTFN(n,x) #endif -#define USBUNIT(dev) (minor(dev)) - struct usb_softc { - USBBASEDEVICE 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; + +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + struct selinfo sc_consel; /* waiting for connect change */ +#else + struct proc *sc_event_thread; +#endif + + char sc_dying; }; #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; +d_read_t usbread; d_ioctl_t usbioctl; int usbpoll __P((dev_t, int, struct proc *)); @@ -131,9 +141,28 @@ struct cdevsw usb_cdevsw = { }; #endif -usbd_status usb_discover __P((struct usb_softc *)); -void usb_create_event_thread __P((void *)); -void usb_event_thread __P((void *)); +static usbd_status usb_discover __P((struct usb_softc *)); +static void usb_create_event_thread __P((void *)); +static void usb_event_thread __P((void *)); + +#define USB_MAX_EVENTS 50 +struct usb_event_q { + struct usb_event ue; + SIMPLEQ_ENTRY(usb_event_q) next; +}; +static SIMPLEQ_HEAD(, usb_event_q) usb_events = + SIMPLEQ_HEAD_INITIALIZER(usb_events); +static int usb_nevents = 0; +static struct selinfo usb_selevent; +static struct proc *usb_async_proc; /* process who wants USB SIGIO */ +static int usb_dev_open = 0; + +static int usb_get_next_event __P((struct usb_event *)); + +#if defined(__NetBSD__) || defined(__OpenBSD__) +/* Flag to see if we are in the cold boot process. */ +extern int cold; +#endif USB_DECLARE_DRIVER(usb); @@ -152,7 +181,7 @@ USB_ATTACH(usb) void *aux = device_get_ivars(self); #endif usbd_device_handle dev; - usbd_status r; + usbd_status err; #if defined(__NetBSD__) || defined(__OpenBSD__) printf("\n"); @@ -161,38 +190,45 @@ USB_ATTACH(usb) #endif DPRINTF(("usbd_attach\n")); - + 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(USBDEV(sc->sc_dev), sc->sc_bus, 0,0,0, &sc->sc_port); + err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, + &sc->sc_port); - if (r == USBD_NORMAL_COMPLETION) { + if (!err) { dev = sc->sc_port.device; - if (!dev->hub) { - sc->sc_running = 0; + if (dev->hub == NULL) { + 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; + USBDEVNAME(sc->sc_dev), err); + sc->sc_dying = 1; } - sc->sc_bus->use_polling = 0; -#if defined(__NetBSD__) || defined(__OpenBSD__) kthread_create(usb_create_event_thread, sc); -#endif #if defined(__FreeBSD__) make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, - 0644, "usb%d", device_get_unit(self)); + 0644, "usb%d", device_get_unit(self)); #endif USB_ATTACH_SUCCESS_RETURN; @@ -205,7 +241,7 @@ usb_create_event_thread(arg) { struct usb_softc *sc = arg; - if (kthread_create1(usb_event_thread, sc, &sc->event_thread, + if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread, "%s", sc->sc_dev.dv_xname)) { printf("%s: unable to create event thread for\n", sc->sc_dev.dv_xname); @@ -219,17 +255,23 @@ usb_event_thread(arg) { struct usb_softc *sc = arg; - while (!sc->shutdown) { - (void)tsleep(&sc->sc_bus->needs_explore, - PWAIT, "usbevt", hz*30); - DPRINTFN(2,("usb_event_thread: woke up\n")); + DPRINTF(("usb_event_thread: start\n")); + + while (!sc->sc_dying) { +#ifdef USB_DEBUG + if (!usb_noexplore) +#endif usb_discover(sc); + (void)tsleep(&sc->sc_bus->needs_explore, + PWAIT, "usbevt", hz*60); + DPRINTFN(2,("usb_event_thread: woke up\n")); } - sc->event_thread = 0; + sc->sc_event_thread = 0; /* In case parent is waiting for us to exit. */ wakeup(sc); + DPRINTF(("usb_event_thread: exit\n")); kthread_exit(0); } @@ -244,7 +286,7 @@ usbctlprint(aux, pnp) return (UNCONF); } -#endif /* NetBSD && OpenBSD */ +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ int usbopen(dev, flag, mode, p) @@ -252,20 +294,74 @@ usbopen(dev, flag, mode, p) int flag, mode; struct proc *p; { - USB_GET_SC_OPEN(usb, USBUNIT(dev), sc); + int unit = minor(dev); + struct usb_softc *sc; - if (sc == 0 || !sc->sc_running) - return (ENXIO); + if (unit == USB_DEV_MINOR) { + if (usb_dev_open) + return (EBUSY); + usb_dev_open = 1; + usb_async_proc = 0; + return (0); + } + + USB_GET_SC_OPEN(usb, unit, sc); + + if (sc->sc_dying) + return (EIO); return (0); } +int +usbread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct usb_event ue; + int s, error, n; + + if (minor(dev) != USB_DEV_MINOR) + return (ENXIO); + + if (uio->uio_resid != sizeof(struct usb_event)) + return (EINVAL); + + error = 0; + s = splusb(); + for (;;) { + n = usb_get_next_event(&ue); + if (n != 0) + break; + if (flag & IO_NDELAY) { + error = EWOULDBLOCK; + break; + } + error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0); + if (error) + break; + } + splx(s); + if (!error) + error = uiomove((void *)&ue, uio->uio_resid, uio); + + return (error); +} + int usbclose(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p; { + int unit = minor(dev); + + if (unit == USB_DEV_MINOR) { + usb_async_proc = 0; + usb_dev_open = 0; + } + return (0); } @@ -277,19 +373,48 @@ usbioctl(devt, cmd, data, flag, p) int flag; struct proc *p; { - USB_GET_SC(usb, USBUNIT(devt), sc); + struct usb_softc *sc; + int unit = minor(devt); + + if (unit == USB_DEV_MINOR) { + switch (cmd) { + case FIONBIO: + /* All handled in the upper FS layer. */ + return (0); + + case FIOASYNC: + if (*(int *)data) + usb_async_proc = p; + else + usb_async_proc = 0; + return (0); + + default: + return (EINVAL); + } + } + + USB_GET_SC(usb, unit, sc); + + if (sc->sc_dying) + return (EIO); - if (sc == 0 || !sc->sc_running) - return (ENXIO); switch (cmd) { +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + case USB_DISCOVER: + usb_discover(sc); + break; +#endif #ifdef USB_DEBUG case USB_SETDEBUG: - usbdebug = uhcidebug = ohcidebug = *(int *)data; - break; + usbdebug = ((*(int *)data) & 0x000000ff); +#ifdef UHCI_DEBUG + uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8; +#endif +#ifdef OHCI_DEBUG + ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16; #endif -#if defined(__FreeBSD__) - case USB_DISCOVER: - usb_discover(sc); break; #endif case USB_REQUEST: @@ -300,7 +425,7 @@ usbioctl(devt, cmd, data, flag, p) struct uio uio; void *ptr = 0; int addr = ur->addr; - usbd_status r; + usbd_status err; int error = 0; DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); @@ -328,10 +453,9 @@ usbioctl(devt, cmd, data, flag, p) goto ret; } } - r = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->request, ptr, - ur->flags, &ur->actlen); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_do_request_flags(sc->sc_bus->devices[addr], + &ur->request, ptr, ur->flags, &ur->actlen); + if (err) { error = EIO; goto ret; } @@ -368,7 +492,7 @@ usbioctl(devt, cmd, data, flag, p) break; default: - return (ENXIO); + return (EINVAL); } return (0); } @@ -379,79 +503,77 @@ usbpoll(dev, events, p) int events; struct proc *p; { - int revents, s; - USB_GET_SC(usb, USBUNIT(dev), sc); + int revents, mask, s; - DPRINTFN(15, ("usbpoll: sc=%p events=0x%x\n", sc, events)); - s = splusb(); - revents = 0; - if (events & (POLLOUT | POLLWRNORM)) - if (sc->sc_bus->needs_explore) - revents |= events & (POLLOUT | POLLWRNORM); - DPRINTFN(15, ("usbpoll: revents=0x%x\n", revents)); - if (revents == 0) { - if (events & (POLLOUT | POLLWRNORM)) { - DPRINTFN(2, ("usbpoll: selrecord\n")); + if (minor(dev) == USB_DEV_MINOR) { + revents = 0; + mask = POLLIN | POLLRDNORM; + + s = splusb(); + if (events & mask && usb_nevents > 0) + revents |= events & mask; + if (revents == 0 && events & mask) + selrecord(p, &usb_selevent); + splx(s); + + return (revents); + } else { +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + struct usb_softc *sc; + int unit = minor(dev); + + USB_GET_SC(usb, unit, sc); + + revents = 0; + mask = POLLOUT | POLLRDNORM; + + s = splusb(); + if (events & mask && sc->sc_bus->needs_explore) + revents |= events & mask; + if (revents == 0 && events & mask) selrecord(p, &sc->sc_consel); - } + splx(s); + + return (revents); +#else + return (ENXIO); +#endif } - splx(s); - return (revents); } -#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; { +#if defined(__FreeBSD__) + /* The splxxx parts should be deleted when kthreads is available */ int s; +#endif - /* Explore device tree from the root */ - /* We need mutual exclusion while traversing the device tree. */ - do { - s = splusb(); - while (sc->sc_exploring) - tsleep(&sc->sc_exploring, PRIBIO, "usbdis", 0); - sc->sc_exploring = 1; + /* + * 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. + */ +#if defined(__FreeBSD__) + s = splusb(); +#endif + while (sc->sc_bus->needs_explore && !sc->sc_dying) { sc->sc_bus->needs_explore = 0; +#if defined(__FreeBSD__) splx(s); - +#endif sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); - +#if defined(__FreeBSD__) s = splusb(); - sc->sc_exploring = 0; - wakeup(&sc->sc_exploring); - splx(s); - } while (sc->sc_bus->needs_explore); +#endif + } +#if defined(__FreeBSD__) + splx(s); +#endif + return (USBD_NORMAL_COMPLETION); } @@ -460,18 +582,90 @@ usb_needs_explore(bus) usbd_bus_handle bus; { bus->needs_explore = 1; +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ selwakeup(&bus->usbctl->sc_consel); +#endif wakeup(&bus->needs_explore); } +/* Called at splusb() */ +int +usb_get_next_event(ue) + struct usb_event *ue; +{ + struct usb_event_q *ueq; + + if (usb_nevents <= 0) + return (0); + ueq = SIMPLEQ_FIRST(&usb_events); + *ue = ueq->ue; + SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next); + free(ueq, M_USBDEV); + usb_nevents--; + return (1); +} + +void +usbd_add_event(type, dev) + int type; + usbd_device_handle dev; +{ + struct usb_event_q *ueq; + struct usb_event ue; + struct timeval thetime; + int s; + + s = splusb(); + if (++usb_nevents >= USB_MAX_EVENTS) { + /* Too many queued events, drop an old one. */ + DPRINTFN(-1,("usb: event dropped\n")); + (void)usb_get_next_event(&ue); + } + /* Don't want to wait here inside splusb() */ + ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT); + if (ueq == NULL) { + printf("usb: no memory, event dropped\n"); + splx(s); + return; + } + ueq->ue.ue_type = type; + ueq->ue.ue_cookie = dev->cookie; + usbd_fill_deviceinfo(dev, &ueq->ue.ue_device); + microtime(&thetime); + TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); + SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); + wakeup(&usb_events); + selwakeup(&usb_selevent); + if (usb_async_proc != NULL) + psignal(usb_async_proc, SIGIO); + splx(s); +} + #if defined(__NetBSD__) || defined(__OpenBSD__) int usb_activate(self, act) 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 @@ -479,7 +673,26 @@ usb_detach(self, flags) device_ptr_t self; int flags; { - panic("usb_detach\n"); + struct usb_softc *sc = (struct usb_softc *)self; + + DPRINTF(("usb_detach: start\n")); + + sc->sc_dying = 1; + + /* Make all devices disconnect. */ + if (sc->sc_port.device) + usb_disconnect_port(&sc->sc_port, self); + + /* 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)); + DPRINTF(("usb_detach: event thread dead\n")); + } + + usbd_finish(); return (0); } #elif defined(__FreeBSD__) diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index 4152b72ff4fb..0d4703bafd6c 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb.h,v 1.33 1999/09/11 08:19:27 augustss Exp $ */ +/* $NetBSD: usb.h,v 1.37 1999/10/13 18:52:54 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -43,6 +43,7 @@ #define _USB_H_ #include +#include #if defined(__NetBSD__) || defined(__OpenBSD__) #include @@ -244,6 +245,7 @@ typedef struct { #define UE_ISO_ASYNC 0x04 #define UE_ISO_ADAPT 0x08 #define UE_ISO_SYNC 0x0c +#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) uWord wMaxPacketSize; uByte bInterval; } usb_endpoint_descriptor_t; @@ -339,13 +341,13 @@ typedef struct { #define USUBCLASS_AUDIOSTREAM 2 #define USUBCLASS_MIDISTREAM 3 #define UCLASS_CDC 2 /* communication */ -#define USUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 +#define USUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 #define USUBCLASS_ABSTRACT_CONTROL_MODEL 2 -#define USUBCLASS_TELEPHONE_CONTROL_MODEL 3 -#define USUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -#define USUBCLASS_CAPI_CONTROLMODEL 5 -#define USUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -#define USUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 +#define USUBCLASS_TELEPHONE_CONTROL_MODEL 3 +#define USUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 +#define USUBCLASS_CAPI_CONTROLMODEL 5 +#define USUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 +#define USUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 #define UPROTO_CDC_AT 1 #define UCLASS_HID 3 #define USUBCLASS_BOOT 1 @@ -379,7 +381,7 @@ typedef struct { #define UPROTO_DATA_V120 0x92 /* V.24 rate adaption */ #define UPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ #define UPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ -#define UPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc. */ +#define UPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ #define UPROTO_DATA_VENDOR 0xff /* Vendor specific */ @@ -494,7 +496,7 @@ struct usb_device_info { }; struct usb_ctl_report { - int report; + int report; u_char data[1024]; /* filled data size will vary */ }; @@ -502,6 +504,17 @@ struct usb_device_stats { u_long requests[4]; /* indexed by transfer type UE_* */ }; +typedef struct { u_int32_t cookie; } usb_event_cookie_t; +/* Events that can be read from /dev/usb */ +struct usb_event { + int ue_type; +#define USB_EVENT_ATTACH 1 +#define USB_EVENT_DETACH 2 + struct usb_device_info ue_device; + struct timespec ue_time; + usb_event_cookie_t ue_cookie; +}; + /* USB controller */ #define USB_REQUEST _IOWR('U', 1, struct usb_ctl_request) #define USB_SETDEBUG _IOW ('U', 2, int) diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h index e254fb42e058..2c12aab250db 100644 --- a/sys/dev/usb/usb_mem.h +++ b/sys/dev/usb/usb_mem.h @@ -1,5 +1,5 @@ -/* $NetBSD: usb_mem.h,v 1.7 1999/09/09 12:26:47 augustss Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: usb_mem.h,v 1.9 1999/10/13 08:10:58 augustss Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -54,8 +54,8 @@ typedef struct usb_dma_block { #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 55b4db2e65e1..82e072d8ff65 100644 --- a/sys/dev/usb/usb_port.h +++ b/sys/dev/usb/usb_port.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb_port.h,v 1.11 1999/09/11 08:19:27 augustss Exp $ */ +/* $NetBSD: usb_port.h,v 1.13 1999/10/13 08:10:58 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -50,6 +50,16 @@ #include "opt_usbverbose.h" +#ifdef USB_DEBUG +#define UHID_DEBUG 1 +#define OHCI_DEBUG 1 +#define UGEN_DEBUG 1 +#define UHCI_DEBUG 1 +#define UHUB_DEBUG 1 +#define ULPT_DEBUG 1 +#define UAUDIO_DEBUG 1 +#endif + typedef struct device *device_ptr_t; #define USBBASEDEVICE struct device #define USBDEV(bdev) (&(bdev)) @@ -123,7 +133,6 @@ __CONCAT(dname,_detach)(self, flags) \ (struct __CONCAT(dname,_softc) *)self #define USB_GET_SC_OPEN(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc; \ if (unit >= __CONCAT(dname,_cd).cd_ndevs) \ return (ENXIO); \ sc = __CONCAT(dname,_cd).cd_devs[unit]; \ @@ -131,7 +140,7 @@ __CONCAT(dname,_detach)(self, flags) \ return (ENXIO) #define USB_GET_SC(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc = __CONCAT(dname,_cd).cd_devs[unit] + sc = __CONCAT(dname,_cd).cd_devs[unit] #define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \ (config_found_sm(parent, args, print, sub)) @@ -140,6 +149,15 @@ __CONCAT(dname,_detach)(self, flags) \ /* * OpenBSD */ +#ifdef USB_DEBUG +#define UHID_DEBUG 1 +#define OHCI_DEBUG 1 +#define UGEN_DEBUG 1 +#define UHCI_DEBUG 1 +#define UHUB_DEBUG 1 +#define ULPT_DEBUG 1 +#endif + #define memcpy(d, s, l) bcopy((s),(d),(l)) #define memset(d, v, l) bzero((d),(l)) #define bswap32(x) swap32(x) @@ -150,6 +168,10 @@ __CONCAT(dname,_detach)(self, flags) \ #define uhidpoll uhidselect #define ugenpoll ugenselect +#define powerhook_establish(fn, sc) 0 +#define powerhook_disestablish(hdl) +#define PWR_RESUME 0 + typedef struct device device_ptr_t; #define USBBASEDEVICE struct device #define USBDEV(bdev) (&(bdev)) @@ -223,7 +245,6 @@ __CONCAT(dname,_detach)(self, flags) \ (struct __CONCAT(dname,_softc) *)self #define USB_GET_SC_OPEN(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc; \ if (unit >= __CONCAT(dname,_cd).cd_ndevs) \ return (ENXIO); \ sc = __CONCAT(dname,_cd).cd_devs[unit]; \ @@ -231,7 +252,7 @@ __CONCAT(dname,_detach)(self, flags) \ return (ENXIO) #define USB_GET_SC(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc = __CONCAT(dname,_cd).cd_devs[unit] + sc = __CONCAT(dname,_cd).cd_devs[unit] #define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \ (config_found_sm(parent, args, print, sub)) @@ -257,15 +278,22 @@ __CONCAT(dname,_detach)(self, flags) \ */ #define memcpy(d, s, l) bcopy((s),(d),(l)) #define memset(d, v, l) bzero((d),(l)) -#define bswap32(x) swap32(x) /* XXX not available in FreeBSD */ -#define kthread_create1 -#define kthread_create - +#define bswap32(x) swap32(x) +#define kthread_create1(function, sc, priv, string, name) +#define kthread_create(create_function, sc) +#define kthread_exit(err) #define usb_timeout(f, d, t, h) ((h) = timeout((f), (d), (t))) #define usb_untimeout(f, d, h) untimeout((f), (d), (h)) -#define USB_DECLARE_DRIVER_INIT(dname, init...) \ +#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (x)), 0) +#define clfree(p) clist_free_cblocks((p)) + +#define powerhook_establish(fn, sc) 0 +#define powerhook_disestablish(hdl) +#define PWR_RESUME 0 + +#define USB_DECLARE_DRIVER_INIT(dname, init) \ static device_probe_t __CONCAT(dname,_match); \ static device_attach_t __CONCAT(dname,_attach); \ static device_detach_t __CONCAT(dname,_detach); \ @@ -288,6 +316,7 @@ static driver_t __CONCAT(dname,_driver) = { \ #define METHODS_NONE {0,0} #define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE) + #define USB_MATCH(dname) \ static int \ __CONCAT(dname,_match)(device_t self) @@ -319,14 +348,12 @@ __CONCAT(dname,_detach)(device_t self) struct __CONCAT(dname,_softc) *sc = device_get_softc(self) #define USB_GET_SC_OPEN(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc = \ - devclass_get_softc(__CONCAT(dname,_devclass), unit); \ + sc = devclass_get_softc(__CONCAT(dname,_devclass), unit); \ if (!sc) \ return (ENXIO) #define USB_GET_SC(dname, unit, sc) \ - struct __CONCAT(dname,_softc) *sc = \ - devclass_get_softc(__CONCAT(dname,_devclass), unit) + sc = devclass_get_softc(__CONCAT(dname,_devclass), unit) #define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \ (device_probe_and_attach((bdev)) == 0 ? (bdev) : 0) @@ -355,7 +382,3 @@ __CONCAT(dname,_detach)(device_t self) #define logprintf printf #endif /* __FreeBSD__ */ - -#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 b596433c17e3..1075cfd0d6bc 100644 --- a/sys/dev/usb/usb_quirks.c +++ b/sys/dev/usb/usb_quirks.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb_quirks.c,v 1.13 1999/09/15 12:30:59 augustss Exp $ */ +/* $NetBSD: usb_quirks.c,v 1.14 1999/09/15 13:57:09 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -50,12 +50,12 @@ extern int usbdebug; #endif -struct usbd_quirk_entry { +static struct usbd_quirk_entry { u_int16_t idVendor; u_int16_t idProduct; u_int16_t bcdDevice; struct usbd_quirks quirks; -} quirks[] = { +} usb_quirks[] = { { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, 0x100, { UQ_NO_SET_PROTO}}, { USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, { UQ_SWAP_UNICODE}}, @@ -76,7 +76,7 @@ usbd_find_quirk(d) { struct usbd_quirk_entry *t; - for (t = quirks; t->idVendor != 0; t++) { + for (t = usb_quirks; t->idVendor != 0; t++) { if (t->idVendor == UGETW(d->idVendor) && t->idProduct == UGETW(d->idProduct) && t->bcdDevice == UGETW(d->bcdDevice)) diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index fb4ef4bf0bfc..b985a5e89640 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb_subr.c,v 1.45 1999/09/09 12:26:47 augustss Exp $ */ +/* $NetBSD: usb_subr.c,v 1.52 1999/10/13 08:10:58 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -51,6 +51,8 @@ #endif #include +#include + #include #include @@ -74,19 +76,20 @@ extern int usbdebug; #endif static usbd_status usbd_set_config __P((usbd_device_handle, int)); -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)); +static char *usbd_get_string __P((usbd_device_handle, int, char *)); +static int usbd_getnewaddr __P((usbd_bus_handle bus)); #if defined(__NetBSD__) -int usbd_submatch __P((device_ptr_t, struct cfdata *cf, void *)); +static int usbd_print __P((void *aux, const char *pnp)); +static int usbd_submatch __P((device_ptr_t, struct cfdata *cf, void *)); #elif defined(__OpenBSD__) -int usbd_submatch __P((device_ptr_t, void *, void *)); +static 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 +static void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno)); +static void usbd_kill_pipe __P((usbd_pipe_handle)); +static usbd_status usbd_probe_and_attach __P((device_ptr_t parent, usbd_device_handle dev, int port, int addr)); +static u_int32_t usb_cookie_no = 0; #ifdef USBVERBOSE typedef u_int16_t usb_vendor_id_t; @@ -104,9 +107,9 @@ struct usb_knowndev { #define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ #include -#endif +#endif /* USBVERBOSE */ -const char *usbd_error_strs[] = { +static const char *usbd_error_strs[] = { "NORMAL_COMPLETION", "IN_PROGRESS", "PENDING_REQUESTS", @@ -151,16 +154,16 @@ usbd_get_string_desc(dev, sindex, langid, sdesc) usb_string_descriptor_t *sdesc; { usb_device_request_t req; - usbd_status r; + usbd_status err; req.bmRequestType = UT_READ_DEVICE; req.bRequest = UR_GET_DESCRIPTOR; USETW2(req.wValue, UDESC_STRING, sindex); USETW(req.wIndex, langid); USETW(req.wLength, 1); /* only size byte first */ - r = usbd_do_request(dev, &req, sdesc); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_do_request(dev, &req, sdesc); + if (err) + return (err); USETW(req.wLength, sdesc->bLength); /* the whole string */ return (usbd_do_request(dev, &req, sdesc)); } @@ -176,7 +179,7 @@ usbd_get_string(dev, si, buf) char *s; int i, n; u_int16_t c; - usbd_status r; + usbd_status err; if (si == 0) return (0); @@ -184,16 +187,16 @@ usbd_get_string(dev, si, buf) return (0); if (dev->langid == USBD_NOLANG) { /* Set up default language */ - r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us); - if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) { + err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us); + if (err || us.bLength < 4) { dev->langid = 0; /* Well, just pick English then */ } else { /* Pick the first language as the default. */ dev->langid = UGETW(us.bString[0]); } } - r = usbd_get_string_desc(dev, si, dev->langid, &us); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_string_desc(dev, si, dev->langid, &us); + if (err) return (0); s = buf; n = us.bLength / 2 - 1; @@ -208,7 +211,7 @@ usbd_get_string(dev, si, buf) *s++ = '?'; } *s++ = 0; - return buf; + return (buf); } void @@ -222,7 +225,7 @@ usbd_devinfo_vp(dev, v, p) struct usb_knowndev *kdp; #endif - if (!dev) { + if (dev == NULL) { v[0] = p[0] = '\0'; return; } @@ -230,7 +233,7 @@ usbd_devinfo_vp(dev, v, p) vendor = usbd_get_string(dev, udd->iManufacturer, v); product = usbd_get_string(dev, udd->iProduct, p); #ifdef USBVERBOSE - if (!vendor) { + if (vendor == NULL) { for(kdp = usb_knowndevs; kdp->vendorname != NULL; kdp++) { @@ -248,12 +251,11 @@ usbd_devinfo_vp(dev, v, p) } } #endif - - if (vendor) + if (vendor != NULL) strcpy(v, vendor); else sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor)); - if (product) + if (product != NULL) strcpy(p, product); else sprintf(p, "product 0x%04x", UGETW(udd->idProduct)); @@ -322,7 +324,7 @@ usbd_reset_port(dev, port, ps) usb_port_status_t *ps; { usb_device_request_t req; - usbd_status r; + usbd_status err; int n; req.bmRequestType = UT_WRITE_CLASS_OTHER; @@ -330,34 +332,36 @@ usbd_reset_port(dev, port, ps) USETW(req.wValue, UHF_PORT_RESET); USETW(req.wIndex, port); USETW(req.wLength, 0); - r = usbd_do_request(dev, &req, 0); + err = usbd_do_request(dev, &req, 0); DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", - port, usbd_errstr(r))); - if (r != USBD_NORMAL_COMPLETION) - return (r); + port, usbd_errstr(err))); + if (err) + return (err); n = 10; do { /* Wait for device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_DELAY); - r = usbd_get_port_status(dev, port, ps); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("usbd_reset_port: get status failed %d\n",r)); - return (r); + err = usbd_get_port_status(dev, port, ps); + if (err) { + DPRINTF(("usbd_reset_port: get status failed %d\n", + err)); + return (err); } } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); if (n == 0) { printf("usbd_reset_port: timeout\n"); return (USBD_IOERROR); } - r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); + err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); #ifdef USB_DEBUG - if (r != USBD_NORMAL_COMPLETION) - DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r)); + if (err) + DPRINTF(("usbd_reset_port: clear port feature failed %d\n", + err)); #endif /* Wait for the device to recover from reset. */ usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); - return (r); + return (err); } usb_interface_descriptor_t * @@ -408,7 +412,7 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx) int curidx; d = usbd_find_idesc(cd, ifaceidx, altidx); - if (!d) + if (d == NULL) return (0); if (endptidx >= d->bNumEndpoints) /* quick exit */ return (0); @@ -524,14 +528,14 @@ usbd_set_config_no(dev, no, msg) { int index; usb_config_descriptor_t cd; - usbd_status r; + usbd_status err; DPRINTFN(5,("usbd_set_config_no: %d\n", no)); /* Figure out what config index to use. */ for (index = 0; index < dev->ddesc.bNumConfigurations; index++) { - r = usbd_get_config_desc(dev, index, &cd); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_config_desc(dev, index, &cd); + if (err) + return (err); if (cd.bConfigurationValue == no) return (usbd_set_config_index(dev, index, msg)); } @@ -546,7 +550,7 @@ usbd_set_config_index(dev, index, msg) { usb_status_t ds; usb_config_descriptor_t cd, *cdp; - usbd_status r; + usbd_status err; int ifcidx, nifc, len, selfpowered, power; DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); @@ -566,34 +570,34 @@ usbd_set_config_index(dev, index, msg) } /* Figure out what config number to use. */ - r = usbd_get_config_desc(dev, index, &cd); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_get_config_desc(dev, index, &cd); + if (err) + return (err); len = UGETW(cd.wTotalLength); cdp = malloc(len, M_USB, M_NOWAIT); - if (cdp == 0) + if (cdp == NULL) return (USBD_NOMEM); - r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); + if (err) goto bad; if (cdp->bDescriptorType != UDESC_CONFIG) { DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", cdp->bDescriptorType)); - r = USBD_INVAL; + err = USBD_INVAL; goto bad; } selfpowered = 0; - if (cdp->bmAttributes & UC_SELF_POWERED) { + if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) && + cdp->bmAttributes & UC_SELF_POWERED) { /* May be self powered. */ if (cdp->bmAttributes & UC_BUS_POWERED) { /* Must ask device. */ - r = usbd_get_device_status(dev, &ds); - if (r == USBD_NORMAL_COMPLETION && - (UGETW(ds.wStatus) & UDS_SELF_POWERED)) + err = usbd_get_device_status(dev, &ds); + if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED)) selfpowered = 1; DPRINTF(("usbd_set_config_index: status=0x%04x, " "error=%s\n", - UGETW(ds.wStatus), usbd_errstr(r))); + UGETW(ds.wStatus), usbd_errstr(err))); } else selfpowered = 1; } @@ -602,7 +606,7 @@ usbd_set_config_index(dev, index, msg) dev->address, cdp->bmAttributes, selfpowered, cdp->bMaxPower * 2)); #ifdef USB_DEBUG - if (!dev->powersrc) { + if (dev->powersrc == NULL) { DPRINTF(("usbd_set_config_index: No power source?\n")); return (USBD_IOERROR); } @@ -616,7 +620,7 @@ usbd_set_config_index(dev, index, msg) USBDEVNAME(dev->bus->bdev), dev->address, cdp->bConfigurationValue, power, dev->powersrc->power); - r = USBD_NO_POWER; + err = USBD_NO_POWER; goto bad; } dev->power = power; @@ -624,11 +628,11 @@ usbd_set_config_index(dev, index, msg) DPRINTF(("usbd_set_config_index: set config %d\n", cdp->bConfigurationValue)); - r = usbd_set_config(dev, cdp->bConfigurationValue); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config(dev, cdp->bConfigurationValue); + if (err) { DPRINTF(("usbd_set_config_index: setting config=%d failed, " "error=%s\n", - cdp->bConfigurationValue, usbd_errstr(r))); + cdp->bConfigurationValue, usbd_errstr(err))); goto bad; } DPRINTF(("usbd_set_config_index: setting new config %d\n", @@ -637,15 +641,15 @@ usbd_set_config_index(dev, index, msg) dev->ifaces = malloc(nifc * sizeof(struct usbd_interface), M_USB, M_NOWAIT); if (dev->ifaces == 0) { - r = USBD_NOMEM; + err = USBD_NOMEM; goto bad; } DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); dev->cdesc = cdp; dev->config = cdp->bConfigurationValue; for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - r = usbd_fill_iface_data(dev, ifcidx, 0); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_fill_iface_data(dev, ifcidx, 0); + if (err) { while (--ifcidx >= 0) usbd_free_iface_data(dev, ifcidx); goto bad; @@ -656,7 +660,7 @@ usbd_set_config_index(dev, index, msg) bad: free(cdp, M_USB); - return (r); + return (err); } /* XXX add function for alternate settings */ @@ -669,29 +673,29 @@ usbd_setup_pipe(dev, iface, ep, pipe) usbd_pipe_handle *pipe; { usbd_pipe_handle p; - usbd_status r; + usbd_status err; DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", dev, iface, ep, pipe)); p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT); - if (p == 0) + if (p == NULL) return (USBD_NOMEM); p->device = dev; p->iface = iface; p->endpoint = ep; ep->refcnt++; p->refcnt = 1; - p->intrreqh = 0; + p->intrxfer = 0; p->running = 0; p->repeat = 0; SIMPLEQ_INIT(&p->queue); - r = dev->bus->methods->open_pipe(p); - if (r != USBD_NORMAL_COMPLETION) { + err = dev->bus->methods->open_pipe(p); + if (err) { DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" "%s\n", - ep->edesc->bEndpointAddress, usbd_errstr(r))); + ep->edesc->bEndpointAddress, usbd_errstr(err))); free(p, M_USB); - return (r); + return (err); } /* Clear any stall and make sure DATA0 toggle will be used next. */ if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT) @@ -732,7 +736,8 @@ usbd_probe_and_attach(parent, dev, port, addr) { struct usb_attach_arg uaa; usb_device_descriptor_t *dd = &dev->ddesc; - int r, found, i, confi, nifaces; + int found, i, confi, nifaces; + usbd_status err; device_ptr_t dv; usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ @@ -779,12 +784,12 @@ usbd_probe_and_attach(parent, dev, port, addr) for (confi = 0; confi < dd->bNumConfigurations; confi++) { DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n", confi)); - r = usbd_set_config_index(dev, confi, 1); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_config_index(dev, confi, 1); + if (err) { #ifdef USB_DEBUG DPRINTF(("%s: port %d, set config at addr %d failed, " "error=%s\n", USBDEVPTRNAME(parent), port, - addr, usbd_errstr(r))); + addr, usbd_errstr(err))); #else printf("%s: port %d, set config at addr %d failed\n", USBDEVPTRNAME(parent), port, addr); @@ -792,8 +797,8 @@ usbd_probe_and_attach(parent, dev, port, addr) #if defined(__FreeBSD__) device_delete_child(parent, bdev); #endif - - return (r); + + return (err); } nifaces = dev->cdesc->bNumInterface; uaa.configno = dev->cdesc->bConfigurationValue; @@ -801,7 +806,6 @@ usbd_probe_and_attach(parent, dev, port, addr) ifaces[i] = &dev->ifaces[i]; uaa.ifaces = ifaces; uaa.nifaces = nifaces; - dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT); if (dev->subdevs == 0) { #if defined(__FreeBSD__) @@ -812,21 +816,20 @@ usbd_probe_and_attach(parent, dev, port, addr) found = 0; for (i = 0; i < nifaces; i++) { - if (!ifaces[i]) + if (ifaces[i] == NULL) continue; /* interface already claimed */ - uaa.iface = ifaces[i]; uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber; dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch); - if (dv) { + if (dv != NULL) { dev->subdevs[found++] = dv; dev->subdevs[found] = 0; ifaces[i] = 0; /* consumed */ #if defined(__FreeBSD__) /* create another child for the next iface */ - bdev = device_add_child(parent, NULL, -1, &uaa); + bdev = device_add_child(parent, NULL, -1,&uaa); if (!bdev) { printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev)); @@ -836,7 +839,6 @@ usbd_probe_and_attach(parent, dev, port, addr) #endif } } - if (found != 0) { #if defined(__FreeBSD__) /* remove the last created child again; it is unused */ @@ -844,7 +846,6 @@ usbd_probe_and_attach(parent, dev, port, addr) #endif return (USBD_NORMAL_COMPLETION); } - free(dev->subdevs, M_USB); dev->subdevs = 0; } @@ -864,7 +865,7 @@ usbd_probe_and_attach(parent, dev, port, addr) uaa.product = UHUB_UNK_PRODUCT; uaa.release = UHUB_UNK_RELEASE; dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch); - if (dv) { + if (dv != NULL) { dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT); if (dev->subdevs == 0) return (USBD_NOMEM); @@ -886,7 +887,6 @@ usbd_probe_and_attach(parent, dev, port, addr) } - /* * Called when a new device has been put in the powered state, * but not yet in the addressed state. @@ -904,7 +904,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) { usbd_device_handle dev; usb_device_descriptor_t *dd; - usbd_status r; + usbd_status err; int addr; int i; @@ -918,7 +918,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) } dev = malloc(sizeof *dev, M_USB, M_NOWAIT); - if (dev == 0) + if (dev == NULL) return (USBD_NOMEM); memset(dev, 0, sizeof(*dev)); @@ -942,30 +942,31 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) dev->depth = depth; dev->powersrc = up; dev->langid = USBD_NOLANG; + dev->cookie.cookie = ++usb_cookie_no; /* Establish the the default pipe. */ - r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe); + if (err) { usbd_remove_device(dev, up); - return (r); + return (err); } up->device = dev; dd = &dev->ddesc; /* Try a few times in case the device is slow (i.e. outside specs.) */ - for (i = 0; i < 5; i++) { + /* for (i = 0; i < 5; i++) { */ + for (i = 0; i < 3; i++) { /* Get the first 8 bytes of the device descriptor. */ - r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); - if (r == USBD_NORMAL_COMPLETION) + err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); + if (!err) break; usbd_delay_ms(dev, 200); } - if (r != USBD_NORMAL_COMPLETION) { + if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " - "failed\n", - addr)); + "failed\n", addr)); usbd_remove_device(dev, up); - return (r); + return (err); } DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " @@ -991,24 +992,24 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); /* Get the full device descriptor. */ - r = usbd_get_device_desc(dev, dd); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_get_device_desc(dev, dd); + if (err) { DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " "failed\n", addr)); usbd_remove_device(dev, up); - return (r); + return (err); } /* Figure out what's wrong with this device. */ dev->quirks = usbd_find_quirk(dd); /* Set the address */ - r = usbd_set_address(dev, addr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_set_address(dev, addr); + if (err) { DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr)); - r = USBD_SET_ADDR_FAILED; + err = USBD_SET_ADDR_FAILED; usbd_remove_device(dev, up); - return (r); + return (err); } /* Allow device time to set new address */ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); @@ -1023,12 +1024,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", addr, dev, parent)); - r = usbd_probe_and_attach(parent, dev, port, addr); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_probe_and_attach(parent, dev, port, addr); + if (err) { usbd_remove_device(dev, up); - return (r); + return (err); } + usbd_add_event(USB_EVENT_ATTACH, dev); return (USBD_NORMAL_COMPLETION); } @@ -1039,7 +1041,7 @@ usbd_remove_device(dev, up) { DPRINTF(("usbd_remove_device: %p\n", dev)); - if (dev->default_pipe) + if (dev->default_pipe != NULL) usbd_kill_pipe(dev->default_pipe); up->device = 0; dev->bus->devices[dev->address] = 0; @@ -1134,7 +1136,7 @@ usbd_fill_deviceinfo(dev, di) struct usb_device_info *di; { struct usbd_port *p; - int i, r, s; + int i, err, s; di->config = dev->config; usbd_devinfo_vp(dev, di->vendor, di->product); @@ -1152,19 +1154,19 @@ usbd_fill_deviceinfo(dev, di) i++) { p = &dev->hub->ports[i]; if (p->device) - r = p->device->address; + err = p->device->address; else { s = UGETW(p->status.wPortStatus); if (s & UPS_PORT_ENABLED) - r = USB_PORT_ENABLED; + err = USB_PORT_ENABLED; else if (s & UPS_SUSPEND) - r = USB_PORT_SUSPENDED; + err = USB_PORT_SUSPENDED; else if (s & UPS_PORT_POWER) - r = USB_PORT_POWERED; + err = USB_PORT_POWERED; else - r = USB_PORT_DISABLED; + err = USB_PORT_DISABLED; } - di->ports[i] = r; + di->ports[i] = err; } di->nports = dev->hub->hubdesc.bNbrPorts; } else @@ -1177,17 +1179,87 @@ usb_free_device(dev) { int ifcidx, nifc; - if (dev->default_pipe) + if (dev->default_pipe != NULL) usbd_kill_pipe(dev->default_pipe); - if (dev->ifaces) { + if (dev->ifaces != NULL) { nifc = dev->cdesc->bNumInterface; for (ifcidx = 0; ifcidx < nifc; ifcidx++) usbd_free_iface_data(dev, ifcidx); free(dev->ifaces, M_USB); } - if (dev->cdesc) + if (dev->cdesc != NULL) free(dev->cdesc, M_USB); - if (dev->subdevs) + if (dev->subdevs != NULL) free(dev->subdevs, M_USB); free(dev, M_USB); } + +/* + * 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, parent) + struct usbd_port *up; + device_ptr_t parent; +{ + usbd_device_handle dev = up->device; + char *hubname = USBDEVPTRNAME(parent); + 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 != NULL) { + for (i = 0; dev->subdevs[i]; i++) { + if (!dev->subdevs[i]) /* skip empty elements */ + continue; + + printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]), + hubname); + if (up->portno != 0) + printf(" port %d", up->portno); + printf(" (addr %d) disconnected\n", dev->address); +#if defined(__NetBSD__) || defined(__OpenBSD__) + config_detach(dev->subdevs[i], DETACH_FORCE); +#elif defined(__FreeBSD__) + device_delete_child(device_get_parent(dev->subdevs[i]), + dev->subdevs[i]); +#endif + + } + } + + usbd_add_event(USB_EVENT_DETACH, dev); + dev->bus->devices[dev->address] = 0; + up->device = 0; + usb_free_device(dev); +} + diff --git a/sys/dev/usb/usbcdc.h b/sys/dev/usb/usbcdc.h index 97bec799755c..e51fcc920e26 100644 --- a/sys/dev/usb/usbcdc.h +++ b/sys/dev/usb/usbcdc.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbcdc.h,v 1.4 1999/08/16 20:20:19 augustss Exp $ */ +/* $NetBSD: usbcdc.h,v 1.3 1999/01/03 01:09:18 augustss Exp $ */ /* $FreeBSD$ */ /* diff --git a/sys/dev/usb/usbdevs.h b/sys/dev/usb/usbdevs.h index 46c1cf14025e..a9e765e76c54 100644 --- a/sys/dev/usb/usbdevs.h +++ b/sys/dev/usb/usbdevs.h @@ -4,7 +4,7 @@ * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * NetBSD: usbdevs,v 1.58 1999/11/10 15:55:51 matt Exp + * NetBSD: usbdevs,v 1.59 1999/11/10 19:46:40 augustss Exp */ /* @@ -99,6 +99,7 @@ #define USB_VENDOR_INSYSTEM 0x05ab /* In-System Design */ #define USB_VENDOR_APPLE 0x05ac /* Apple Computer */ #define USB_VENDOR_QTRONIX 0x05c7 /* Qtronix Corp */ +#define USB_VENDOR_ELSA 0x05cc /* ELSA Gmbh */ #define USB_VENDOR_EIZONANAO 0x05e7 /* EIZO Nanao */ #define USB_VENDOR_PIENGINEERING 0x05f3 /* P.I. Engineering */ #define USB_VENDOR_CHIC 0x05fe /* Chic Technology */ @@ -135,6 +136,7 @@ /* CATC products */ #define USB_PRODUCT_CATC_ANDROMEDA 0x1237 /* Andromeda hub */ +#define USB_PRODUCT_CATC_CHIEF 0x000d /* USB Chief Bus & Protocol Analyzer */ /* Gravis products */ #define USB_PRODUCT_GRAVIS_GAMEPADPRO 0x4001 /* GamePad Pro */ @@ -276,6 +278,9 @@ /* Qtronix products */ #define USB_PRODUCT_QTRONIX_980N 0x2011 /* Scorpion-980N keyboard */ +/* Elsa products */ +#define USB_PRODUCT_ELSA_MODEM1 0x2265 /* ELSA Modem Board */ + /* Logitech products */ #define USB_PRODUCT_LOGITECH_M2452 0x0203 /* M2452 keyboard */ #define USB_PRODUCT_LOGITECH_M4848 0x0301 /* M4848 mouse */ diff --git a/sys/dev/usb/usbdevs_data.h b/sys/dev/usb/usbdevs_data.h index 98bbbc4c0d63..cf21c2bf8ac9 100644 --- a/sys/dev/usb/usbdevs_data.h +++ b/sys/dev/usb/usbdevs_data.h @@ -4,7 +4,7 @@ * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * NetBSD: usbdevs,v 1.58 1999/11/10 15:55:51 matt Exp + * NetBSD: usbdevs,v 1.59 1999/11/10 19:46:40 augustss Exp */ /* @@ -93,6 +93,12 @@ struct usb_knowndev usb_knowndevs[] = { "Computer Access Technology Corp.", "Andromeda hub", }, + { + USB_VENDOR_CATC, USB_PRODUCT_CATC_CHIEF, + 0, + "Computer Access Technology Corp.", + "USB Chief Bus & Protocol Analyzer", + }, { USB_VENDOR_GRAVIS, USB_PRODUCT_GRAVIS_GAMEPADPRO, 0, @@ -417,6 +423,12 @@ struct usb_knowndev usb_knowndevs[] = { "Qtronix Corp", "Scorpion-980N keyboard", }, + { + USB_VENDOR_ELSA, USB_PRODUCT_ELSA_MODEM1, + 0, + "ELSA Gmbh", + "ELSA Modem Board", + }, { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M2452, 0, @@ -903,6 +915,12 @@ struct usb_knowndev usb_knowndevs[] = { "Qtronix Corp", NULL, }, + { + USB_VENDOR_ELSA, 0, + USB_KNOWNDEV_NOPROD, + "ELSA Gmbh", + NULL, + }, { USB_VENDOR_EIZONANAO, 0, USB_KNOWNDEV_NOPROD, diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 72207f990746..c7aa594eebb3 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.37 1999/09/11 08:19:27 augustss Exp $ */ +/* $NetBSD: usbdi.c,v 1.47 1999/10/13 23:46:10 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -46,10 +46,16 @@ #elif defined(__FreeBSD__) #include #include +#include +#include "usb_if.h" +#if defined(DIAGNOSTIC) && defined(__i386__) +#include +#endif #endif #include #include +#include #include #include @@ -60,7 +66,7 @@ #if defined(__FreeBSD__) #include "usb_if.h" #endif - + #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x @@ -71,22 +77,47 @@ extern int usbdebug; #endif static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe)); -void usbd_do_request_async_cb - __P((usbd_request_handle, usbd_private_handle, usbd_status)); -void usbd_start_next __P((usbd_pipe_handle pipe)); +static void usbd_do_request_async_cb + __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); +static void usbd_start_next __P((usbd_pipe_handle pipe)); -static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests - = SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests); +static SIMPLEQ_HEAD(, usbd_xfer) usbd_free_requests = + SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests); -static __inline int usbd_reqh_isread __P((usbd_request_handle reqh)); -static __inline int -usbd_reqh_isread(reqh) - usbd_request_handle reqh; +static int usbd_nbuses = 0; + +void +usbd_init() { - if (reqh->rqflags & URQ_REQUEST) - return (reqh->request.bmRequestType & UT_READ); + usbd_nbuses++; +} + +void +usbd_finish() +{ + usbd_xfer_handle xfer; + + if (--usbd_nbuses == 0) { + /* Last controller is gone, free all requests. */ + for (;;) { + xfer = SIMPLEQ_FIRST(&usbd_free_requests); + if (xfer == NULL) + break; + SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, xfer, next); + free(xfer, M_USB); + } + } +} + +static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer)); +static __inline int +usbd_xfer_isread(xfer) + usbd_xfer_handle xfer; +{ + if (xfer->rqflags & URQ_REQUEST) + return (xfer->request.bmRequestType & UT_READ); else - return (reqh->pipe->endpoint->edesc->bEndpointAddress & + return (xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN); } @@ -97,13 +128,13 @@ void usbd_dump_queue(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; printf("usbd_dump_queue: pipe=%p\n", pipe); - for (reqh = SIMPLEQ_FIRST(&pipe->queue); - reqh; - reqh = SIMPLEQ_NEXT(reqh, next)) { - printf(" reqh=%p\n", reqh); + for (xfer = SIMPLEQ_FIRST(&pipe->queue); + xfer; + xfer = SIMPLEQ_NEXT(xfer, next)) { + printf(" xfer=%p\n", xfer); } } #endif @@ -117,7 +148,7 @@ usbd_open_pipe(iface, address, flags, pipe) { usbd_pipe_handle p; struct usbd_endpoint *ep; - usbd_status r; + usbd_status err; int i; for (i = 0; i < iface->idesc->bNumEndpoints; i++) { @@ -130,9 +161,9 @@ usbd_open_pipe(iface, address, flags, pipe) if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0) return (USBD_IN_USE); - r = usbd_setup_pipe(iface->device, iface, ep, &p); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_setup_pipe(iface->device, iface, ep, &p); + if (err) + return (err); LIST_INSERT_HEAD(&iface->pipes, p, next); *pipe = p; return (USBD_NORMAL_COMPLETION); @@ -149,35 +180,35 @@ usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb) u_int32_t length; usbd_callback cb; { - usbd_status r; - usbd_request_handle reqh; + usbd_status err; + usbd_xfer_handle xfer; usbd_pipe_handle ipipe; - r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe); - if (r != USBD_NORMAL_COMPLETION) - return (r); - reqh = usbd_alloc_request(iface->device); - if (reqh == 0) { - r = USBD_NOMEM; + err = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe); + if (err) + return (err); + xfer = usbd_alloc_request(iface->device); + if (xfer == NULL) { + err = USBD_NOMEM; goto bad1; } - usbd_setup_request(reqh, ipipe, priv, buffer, length, flags, + usbd_setup_request(xfer, ipipe, priv, buffer, length, flags, USBD_NO_TIMEOUT, cb); - ipipe->intrreqh = reqh; + ipipe->intrxfer = xfer; ipipe->repeat = 1; - r = usbd_transfer(reqh); + err = usbd_transfer(xfer); *pipe = ipipe; - if (r != USBD_IN_PROGRESS) + if (err != USBD_IN_PROGRESS) goto bad2; return (USBD_NORMAL_COMPLETION); bad2: - ipipe->intrreqh = 0; + ipipe->intrxfer = NULL; ipipe->repeat = 0; - usbd_free_request(reqh); + usbd_free_request(xfer); bad1: usbd_close_pipe(ipipe); - return r; + return (err); } usbd_status @@ -185,7 +216,7 @@ usbd_close_pipe(pipe) usbd_pipe_handle pipe; { #ifdef DIAGNOSTIC - if (pipe == 0) { + if (pipe == NULL) { printf("usbd_close_pipe: pipe==NULL\n"); return (USBD_NORMAL_COMPLETION); } @@ -198,175 +229,185 @@ usbd_close_pipe(pipe) LIST_REMOVE(pipe, next); pipe->endpoint->refcnt--; pipe->methods->close(pipe); - if (pipe->intrreqh) - usbd_free_request(pipe->intrreqh); + if (pipe->intrxfer != NULL) + usbd_free_request(pipe->intrxfer); free(pipe, M_USB); return (USBD_NORMAL_COMPLETION); } usbd_status -usbd_transfer(reqh) - usbd_request_handle reqh; +usbd_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; - usbd_status r; + usbd_pipe_handle pipe = xfer->pipe; + usb_dma_t *dmap = &xfer->dmabuf; + usbd_status err; u_int size; int s; - DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n", - reqh, reqh->flags, pipe, pipe->running)); + DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n", + xfer, xfer->flags, pipe, pipe->running)); #ifdef USB_DEBUG if (usbdebug > 5) usbd_dump_queue(pipe); #endif - reqh->done = 0; + xfer->done = 0; - size = reqh->length; - /* If there is no buffer, allocate one and copy data. */ - if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) { - usb_dma_t *dmap = &reqh->dmabuf; + size = xfer->length; + /* If there is no buffer, allocate one. */ + if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) { struct usbd_bus *bus = pipe->device->bus; #ifdef DIAGNOSTIC - if (reqh->rqflags & URQ_AUTO_DMABUF) + if (xfer->rqflags & URQ_AUTO_DMABUF) printf("usbd_transfer: has old buffer!\n"); #endif - r = bus->methods->allocm(bus, dmap, size); - if (r != USBD_NORMAL_COMPLETION) - return (r); - reqh->rqflags |= URQ_AUTO_DMABUF; - - /* finally copy data if going out */ - if (!usbd_reqh_isread(reqh)) - memcpy(KERNADDR(dmap), reqh->buffer, size); + err = bus->methods->allocm(bus, dmap, size); + if (err) + return (err); + xfer->rqflags |= URQ_AUTO_DMABUF; } - r = pipe->methods->transfer(reqh); + /* Copy data if going out. */ + if (!(xfer->flags & USBD_NO_COPY) && size != 0 && + !usbd_xfer_isread(xfer)) + memcpy(KERNADDR(dmap), xfer->buffer, size); - if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) { + err = pipe->methods->transfer(xfer); + + if (err != USBD_IN_PROGRESS && err) { /* The transfer has not been queued, so free buffer. */ - if (reqh->rqflags & URQ_AUTO_DMABUF) { + if (xfer->rqflags & URQ_AUTO_DMABUF) { struct usbd_bus *bus = pipe->device->bus; - bus->methods->freem(bus, &reqh->dmabuf); - reqh->rqflags &= ~URQ_AUTO_DMABUF; + bus->methods->freem(bus, &xfer->dmabuf); + xfer->rqflags &= ~URQ_AUTO_DMABUF; } } - if (!(reqh->flags & USBD_SYNCHRONOUS)) - return (r); + if (!(xfer->flags & USBD_SYNCHRONOUS)) + return (err); /* Sync transfer, wait for completion. */ - if (r != USBD_IN_PROGRESS) - return (r); + if (err != USBD_IN_PROGRESS) + return (err); s = splusb(); - if (!reqh->done) { + if (!xfer->done) { if (pipe->device->bus->use_polling) panic("usbd_transfer: not done\n"); - tsleep(reqh, PRIBIO, "usbsyn", 0); + tsleep(xfer, PRIBIO, "usbsyn", 0); } splx(s); - return (reqh->status); + return (xfer->status); } /* Like usbd_transfer(), but waits for completion. */ usbd_status -usbd_sync_transfer(reqh) - usbd_request_handle reqh; +usbd_sync_transfer(xfer) + usbd_xfer_handle xfer; { - reqh->flags |= USBD_SYNCHRONOUS; - return (usbd_transfer(reqh)); + xfer->flags |= USBD_SYNCHRONOUS; + return (usbd_transfer(xfer)); } void * -usbd_alloc_buffer(reqh, size) - usbd_request_handle reqh; +usbd_alloc_buffer(xfer, size) + usbd_xfer_handle xfer; u_int32_t size; { - struct usbd_bus *bus = reqh->device->bus; - usbd_status r; + struct usbd_bus *bus = xfer->device->bus; + usbd_status err; - r = bus->methods->allocm(bus, &reqh->dmabuf, size); - if (r != USBD_NORMAL_COMPLETION) + err = bus->methods->allocm(bus, &xfer->dmabuf, size); + if (err) return (0); - reqh->rqflags |= URQ_DEV_DMABUF; - return (KERNADDR(&reqh->dmabuf)); + xfer->rqflags |= URQ_DEV_DMABUF; + return (KERNADDR(&xfer->dmabuf)); } void -usbd_free_buffer(reqh) - usbd_request_handle reqh; +usbd_free_buffer(xfer) + usbd_xfer_handle xfer; { #ifdef DIAGNOSTIC - if (!(reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { + if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { printf("usbd_free_buffer: no buffer\n"); return; } #endif - reqh->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); - reqh->device->bus->methods->freem(reqh->device->bus, &reqh->dmabuf); + xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); + xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf); } -usbd_request_handle +void * +usbd_get_buffer(xfer) + usbd_xfer_handle xfer; +{ + if (!(xfer->rqflags & URQ_DEV_DMABUF)) + return (0); + return (KERNADDR(&xfer->dmabuf)); +} + +usbd_xfer_handle usbd_alloc_request(dev) usbd_device_handle dev; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; - reqh = SIMPLEQ_FIRST(&usbd_free_requests); - if (reqh) - SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next); + xfer = SIMPLEQ_FIRST(&usbd_free_requests); + if (xfer != NULL) + SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, xfer, next); else - reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT); - if (!reqh) + xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); + if (xfer == NULL) return (0); - memset(reqh, 0, sizeof *reqh); - reqh->device = dev; - DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh)); - return (reqh); + memset(xfer, 0, sizeof *xfer); + xfer->device = dev; + DPRINTFN(5,("usbd_alloc_request() = %p\n", xfer)); + return (xfer); } usbd_status -usbd_free_request(reqh) - usbd_request_handle reqh; +usbd_free_request(xfer) + usbd_xfer_handle xfer; { - DPRINTFN(5,("usbd_free_request: %p\n", reqh)); - if (reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) - usbd_free_buffer(reqh); - SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next); + DPRINTFN(5,("usbd_free_request: %p\n", xfer)); + if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) + usbd_free_buffer(xfer); + SIMPLEQ_INSERT_HEAD(&usbd_free_requests, xfer, next); return (USBD_NORMAL_COMPLETION); } void -usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback) - usbd_request_handle reqh; +usbd_setup_request(xfer, pipe, priv, buffer, length, flags, timeout, callback) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; usbd_private_handle priv; void *buffer; u_int32_t length; u_int16_t flags; u_int32_t timeout; - void (*callback) __P((usbd_request_handle, + void (*callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); { - reqh->pipe = pipe; - reqh->priv = priv; - reqh->buffer = buffer; - reqh->length = length; - reqh->actlen = 0; - reqh->flags = flags; - reqh->timeout = timeout; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->rqflags &= ~URQ_REQUEST; - reqh->nframes = 0; + xfer->pipe = pipe; + xfer->priv = priv; + xfer->buffer = buffer; + xfer->length = length; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = timeout; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->rqflags &= ~URQ_REQUEST; + xfer->nframes = 0; } void -usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, +usbd_setup_default_request(xfer, dev, priv, timeout, req, buffer, length, flags, callback) - usbd_request_handle reqh; + usbd_xfer_handle xfer; usbd_device_handle dev; usbd_private_handle priv; u_int32_t timeout; @@ -374,63 +415,64 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, void *buffer; u_int32_t length; u_int16_t flags; - void (*callback) __P((usbd_request_handle, + void (*callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); { - reqh->pipe = dev->default_pipe; - reqh->priv = priv; - reqh->buffer = buffer; - reqh->length = length; - reqh->actlen = 0; - reqh->flags = flags; - reqh->timeout = timeout; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->request = *req; - reqh->rqflags |= URQ_REQUEST; - reqh->nframes = 0; + xfer->pipe = dev->default_pipe; + xfer->priv = priv; + xfer->buffer = buffer; + xfer->length = length; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = timeout; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->request = *req; + xfer->rqflags |= URQ_REQUEST; + xfer->nframes = 0; } void -usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, callback) - usbd_request_handle reqh; +usbd_setup_isoc_request(xfer, pipe, priv, frlengths, nframes, flags, callback) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; usbd_private_handle priv; u_int16_t *frlengths; u_int32_t nframes; + u_int16_t flags; usbd_callback callback; { - reqh->pipe = pipe; - reqh->priv = priv; - reqh->buffer = 0; - reqh->length = 0; - reqh->actlen = 0; - reqh->flags = 0; - reqh->timeout = USBD_NO_TIMEOUT; - reqh->status = USBD_NOT_STARTED; - reqh->callback = callback; - reqh->rqflags &= ~URQ_REQUEST; - reqh->frlengths = frlengths; - reqh->nframes = nframes; + xfer->pipe = pipe; + xfer->priv = priv; + xfer->buffer = 0; + xfer->length = 0; + xfer->actlen = 0; + xfer->flags = flags; + xfer->timeout = USBD_NO_TIMEOUT; + xfer->status = USBD_NOT_STARTED; + xfer->callback = callback; + xfer->rqflags &= ~URQ_REQUEST; + xfer->frlengths = frlengths; + xfer->nframes = nframes; } void -usbd_get_request_status(reqh, priv, buffer, count, status) - usbd_request_handle reqh; +usbd_get_request_status(xfer, priv, buffer, count, status) + usbd_xfer_handle xfer; usbd_private_handle *priv; void **buffer; u_int32_t *count; usbd_status *status; { - if (priv) - *priv = reqh->priv; - if (buffer) - *buffer = reqh->buffer; - if (count) - *count = reqh->actlen; - if (status) - *status = reqh->status; + if (priv != NULL) + *priv = xfer->priv; + if (buffer != NULL) + *buffer = xfer->buffer; + if (count != NULL) + *count = xfer->actlen; + if (status != NULL) + *status = xfer->status; } usb_config_descriptor_t * @@ -468,19 +510,19 @@ usbd_status usbd_abort_pipe(pipe) usbd_pipe_handle pipe; { - usbd_status r; + usbd_status err; int s; #ifdef DIAGNOSTIC - if (pipe == 0) { + if (pipe == NULL) { printf("usbd_close_pipe: pipe==NULL\n"); return (USBD_NORMAL_COMPLETION); } #endif s = splusb(); - r = usbd_ar_pipe(pipe); + err = usbd_ar_pipe(pipe); splx(s); - return (r); + return (err); } usbd_status @@ -489,7 +531,7 @@ usbd_clear_endpoint_stall(pipe) { usbd_device_handle dev = pipe->device; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); @@ -504,15 +546,15 @@ usbd_clear_endpoint_stall(pipe) USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); USETW(req.wLength, 0); - r = usbd_do_request(dev, &req, 0); + err = usbd_do_request(dev, &req, 0); #if 0 XXX should we do this? - if (r == USBD_NORMAL_COMPLETION) { + if (!err) { pipe->state = USBD_PIPE_ACTIVE; /* XXX activate pipe */ } #endif - return (r); + return (err); } usbd_status @@ -521,7 +563,7 @@ usbd_clear_endpoint_stall_async(pipe) { usbd_device_handle dev = pipe->device; usb_device_request_t req; - usbd_status r; + usbd_status err; pipe->methods->cleartoggle(pipe); @@ -530,8 +572,8 @@ usbd_clear_endpoint_stall_async(pipe) USETW(req.wValue, UF_ENDPOINT_HALT); USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); USETW(req.wLength, 0); - r = usbd_do_request_async(dev, &req, 0); - return (r); + err = usbd_do_request_async(dev, &req, 0); + return (err); } usbd_status @@ -548,7 +590,7 @@ usbd_interface_count(dev, count) usbd_device_handle dev; u_int8_t *count; { - if (!dev->cdesc) + if (dev->cdesc == NULL) return (USBD_NOT_CONFIGURED); *count = dev->cdesc->bNumInterface; return (USBD_NORMAL_COMPLETION); @@ -569,7 +611,7 @@ usbd_device2interface_handle(dev, ifaceno, iface) u_int8_t ifaceno; usbd_interface_handle *iface; { - if (!dev->cdesc) + if (dev->cdesc == NULL) return (USBD_NOT_CONFIGURED); if (ifaceno >= dev->cdesc->bNumInterface) return (USBD_INVAL); @@ -591,7 +633,7 @@ usbd_set_interface(iface, altidx) int altidx; { usb_device_request_t req; - usbd_status r; + usbd_status err; if (LIST_FIRST(&iface->pipes) != 0) return (USBD_IN_USE); @@ -601,16 +643,16 @@ usbd_set_interface(iface, altidx) iface->endpoints = 0; iface->idesc = 0; - r = usbd_fill_iface_data(iface->device, iface->index, altidx); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_fill_iface_data(iface->device, iface->index, altidx); + if (err) + return (err); req.bmRequestType = UT_WRITE_INTERFACE; req.bRequest = UR_SET_INTERFACE; USETW(req.wValue, iface->idesc->bAlternateSetting); USETW(req.wIndex, iface->idesc->bInterfaceNumber); USETW(req.wLength, 0); - return usbd_do_request(iface->device, &req, 0); + return (usbd_do_request(iface->device, &req, 0)); } int @@ -652,7 +694,7 @@ usbd_get_interface(iface, aiface) USETW(req.wValue, 0); USETW(req.wIndex, iface->idesc->bInterfaceNumber); USETW(req.wLength, 1); - return usbd_do_request(iface->device, &req, aiface); + return (usbd_do_request(iface->device, &req, aiface)); } /*** Internal routines ***/ @@ -662,143 +704,167 @@ static usbd_status usbd_ar_pipe(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; + usbd_xfer_handle xfer; + + SPLUSBCHECK; DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); #ifdef USB_DEBUG if (usbdebug > 5) usbd_dump_queue(pipe); #endif - while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) { - DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n", - pipe, reqh, pipe->methods)); + pipe->repeat = 0; + while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { + DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", + pipe, xfer, pipe->methods)); /* Make the HC abort it (and invoke the callback). */ - pipe->methods->abort(reqh); + pipe->methods->abort(xfer); /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ } return (USBD_NORMAL_COMPLETION); } +/* Called at splusb() */ void -usb_transfer_complete(reqh) - usbd_request_handle reqh; +usb_transfer_complete(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; + usbd_pipe_handle pipe = xfer->pipe; + usb_dma_t *dmap = &xfer->dmabuf; + int repeat = pipe->repeat; 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 xfer=%p status=%d " + "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); #ifdef DIAGNOSTIC - if (!pipe) { - printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh); + if (pipe == NULL) { + printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); return; } #endif - polling = pipe->device->bus->use_polling; /* XXXX */ if (polling) pipe->running = 0; - /* if we allocated the buffer in usbd_transfer() we free it here. */ - if (reqh->rqflags & URQ_AUTO_DMABUF) { - usb_dma_t *dmap = &reqh->dmabuf; + if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 && + usbd_xfer_isread(xfer)) { +#ifdef DIAGNOSTIC + if (xfer->actlen > xfer->length) { + printf("usb_transfer_complete: actlen > len %d > %d\n", + xfer->actlen, xfer->length); + xfer->actlen = xfer->length; + } +#endif + memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen); + } - if (usbd_reqh_isread(reqh)) - memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen); - if (!pipe->repeat) { + /* if we allocated the buffer in usbd_transfer() we free it here. */ + if (xfer->rqflags & URQ_AUTO_DMABUF) { + if (!repeat) { struct usbd_bus *bus = pipe->device->bus; bus->methods->freem(bus, dmap); - reqh->rqflags &= ~URQ_AUTO_DMABUF; + xfer->rqflags &= ~URQ_AUTO_DMABUF; } } - if (pipe->methods->done) - pipe->methods->done(reqh); - - /* Remove request from queue. */ - if ( reqh == SIMPLEQ_FIRST(&pipe->queue) ) - SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next); - else - DPRINTF(("XXX duplicated call to usb_transfer_complete\n")); + if (pipe->methods->done != NULL) + pipe->methods->done(xfer); + if (!repeat) { + /* Remove request from queue. */ +#ifdef DIAGNOSTIC + if (xfer != SIMPLEQ_FIRST(&pipe->queue)) + printf("usb_transfer_complete: bad dequeue %p != %p\n", + xfer, SIMPLEQ_FIRST(&pipe->queue)); +#endif + SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next); + } /* Count completed transfers. */ ++pipe->device->bus->stats.requests [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; - reqh->done = 1; - if (reqh->status == USBD_NORMAL_COMPLETION && - reqh->actlen < reqh->length && - !(reqh->flags & USBD_SHORT_XFER_OK)) { - DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n", - reqh->actlen, reqh->length)); - reqh->status = USBD_SHORT_XFER; + xfer->done = 1; + if (xfer->status == USBD_NORMAL_COMPLETION && + xfer->actlen < xfer->length && + !(xfer->flags & USBD_SHORT_XFER_OK)) { + DPRINTFN(-1, ("usbd_transfer_cb: short transfer %d<%d\n", + xfer->actlen, xfer->length)); + xfer->status = USBD_SHORT_XFER; } - if (reqh->callback) - reqh->callback(reqh, reqh->priv, reqh->status); + if (xfer->callback) + xfer->callback(xfer, xfer->priv, xfer->status); - if ((reqh->flags & USBD_SYNCHRONOUS) && !polling) - wakeup(reqh); + if ((xfer->flags & USBD_SYNCHRONOUS) && !polling) + wakeup(xfer); - if (!pipe->repeat && - reqh->status != USBD_CANCELLED && reqh->status != USBD_TIMEOUT) - usbd_start_next(pipe); + if (!repeat) { + /* XXX should we stop the queue on all errors? */ + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) + pipe->running = 0; + else + usbd_start_next(pipe); + } } usbd_status -usb_insert_transfer(reqh) - usbd_request_handle reqh; +usb_insert_transfer(xfer) + usbd_xfer_handle xfer; { - usbd_pipe_handle pipe = reqh->pipe; - usbd_status r; + usbd_pipe_handle pipe = xfer->pipe; + usbd_status err; int s; - DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d\n", pipe, - pipe->running)); + DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", + pipe, pipe->running, xfer->timeout)); s = splusb(); - SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next); + SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); if (pipe->running) - r = USBD_IN_PROGRESS; + err = USBD_IN_PROGRESS; else { pipe->running = 1; - r = USBD_NORMAL_COMPLETION; + err = USBD_NORMAL_COMPLETION; } splx(s); - return (r); + return (err); } +/* Called at splusb() */ void usbd_start_next(pipe) usbd_pipe_handle pipe; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; + + SPLUSBCHECK; - DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe)); - #ifdef DIAGNOSTIC - if (!pipe) { - printf("usbd_start_next: pipe == 0\n"); + if (pipe == NULL) { + printf("usbd_start_next: pipe == NULL\n"); return; } - if (!pipe->methods || !pipe->methods->start) { - printf("usbd_start_next: no start method\n"); + if (pipe->methods == NULL || pipe->methods->start == NULL) { + printf("usbd_start_next: pipe=%p no start method\n", pipe); return; } #endif /* Get next request in queue. */ - reqh = SIMPLEQ_FIRST(&pipe->queue); - DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh)); - if (!reqh) + xfer = SIMPLEQ_FIRST(&pipe->queue); + DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); + if (xfer == NULL) { pipe->running = 0; - else { - r = pipe->methods->start(reqh); - if (r != USBD_IN_PROGRESS) { - printf("usbd_start_next: error=%d\n", r); + } else { + err = pipe->methods->start(xfer); + if (err != USBD_IN_PROGRESS) { + printf("usbd_start_next: error=%d\n", err); pipe->running = 0; /* XXX do what? */ } @@ -822,35 +888,39 @@ usbd_do_request_flags(dev, req, data, flags, actlen) u_int16_t flags; int *actlen; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; #ifdef DIAGNOSTIC - if (!curproc) { +#if defined(__i386__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + if (dev->bus->intr_context) { printf("usbd_do_request: not in process context\n"); return (USBD_INVAL); } #endif - reqh = usbd_alloc_request(dev); - if (reqh == 0) + xfer = usbd_alloc_request(dev); + if (xfer == NULL) return (USBD_NOMEM); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, + usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, UGETW(req->wLength), flags, 0); - r = usbd_sync_transfer(reqh); + err = usbd_sync_transfer(xfer); #if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (reqh->actlen > reqh->length) + if (xfer->actlen > xfer->length) DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - dev->address, reqh->request.bmRequestType, - reqh->request.bRequest, UGETW(reqh->request.wValue), - UGETW(reqh->request.wIndex), - UGETW(reqh->request.wLength), - reqh->length, reqh->actlen)); + dev->address, xfer->request.bmRequestType, + xfer->request.bRequest, UGETW(xfer->request.wValue), + UGETW(xfer->request.wIndex), + UGETW(xfer->request.wLength), + xfer->length, xfer->actlen)); #endif - if (actlen) - *actlen = reqh->actlen; - if (r == USBD_STALLED) { + if (actlen != NULL) + *actlen = xfer->actlen; + if (err == USBD_STALLED) { /* * The control endpoint has stalled. Control endpoints * should not halt, but some may do so anyway so clear @@ -859,18 +929,18 @@ usbd_do_request_flags(dev, req, data, flags, actlen) usb_device_request_t treq; usb_status_t status; u_int16_t s; - usbd_status nr; + usbd_status nerr; treq.bmRequestType = UT_READ_ENDPOINT; treq.bRequest = UR_GET_STATUS; USETW(treq.wValue, 0); USETW(treq.wIndex, 0); USETW(treq.wLength, sizeof(usb_status_t)); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, + usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,sizeof(usb_status_t), 0, 0); - nr = usbd_sync_transfer(reqh); - if (nr != USBD_NORMAL_COMPLETION) + nerr = usbd_sync_transfer(xfer); + if (nerr) goto bad; s = UGETW(status.wStatus); DPRINTF(("usbd_do_request: status = 0x%04x\n", s)); @@ -881,36 +951,36 @@ usbd_do_request_flags(dev, req, data, flags, actlen) USETW(treq.wValue, UF_ENDPOINT_HALT); USETW(treq.wIndex, 0); USETW(treq.wLength, 0); - usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, + usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status, 0, 0, 0); - nr = usbd_sync_transfer(reqh); - if (nr != USBD_NORMAL_COMPLETION) + nerr = usbd_sync_transfer(xfer); + if (nerr) goto bad; } bad: - usbd_free_request(reqh); - return (r); + usbd_free_request(xfer); + return (err); } void -usbd_do_request_async_cb(reqh, priv, status) - usbd_request_handle reqh; +usbd_do_request_async_cb(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { #if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (reqh->actlen > reqh->length) + if (xfer->actlen > xfer->length) DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - reqh->pipe->device->address, - reqh->request.bmRequestType, - reqh->request.bRequest, UGETW(reqh->request.wValue), - UGETW(reqh->request.wIndex), - UGETW(reqh->request.wLength), - reqh->length, reqh->actlen)); + xfer->pipe->device->address, + xfer->request.bmRequestType, + xfer->request.bRequest, UGETW(xfer->request.wValue), + UGETW(xfer->request.wIndex), + UGETW(xfer->request.wLength), + xfer->length, xfer->actlen)); #endif - usbd_free_request(reqh); + usbd_free_request(xfer); } /* @@ -923,19 +993,18 @@ usbd_do_request_async(dev, req, data) usb_device_request_t *req; void *data; { - usbd_request_handle reqh; - usbd_status r; + usbd_xfer_handle xfer; + usbd_status err; - reqh = usbd_alloc_request(dev); - if (reqh == 0) + xfer = usbd_alloc_request(dev); + if (xfer == NULL) return (USBD_NOMEM); - 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); + usbd_setup_default_request(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, + data, UGETW(req->wLength), 0, usbd_do_request_async_cb); + err = usbd_transfer(xfer); + if (err != USBD_IN_PROGRESS) { + usbd_free_request(xfer); + return (err); } return (USBD_NORMAL_COMPLETION); } @@ -964,7 +1033,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--; } @@ -989,7 +1061,8 @@ int usbd_driver_load(module_t mod, int what, void *arg) { /* XXX should implement something like a function that removes all generic devices */ - - return 0; /* nothing to do by us */ + + return (0); } + #endif diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 7fb44699f96e..fef131d93665 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.h,v 1.28 1999/09/11 08:19:27 augustss Exp $ */ +/* $NetBSD: usbdi.h,v 1.31 1999/10/13 08:10:58 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -42,11 +42,11 @@ typedef struct usbd_bus *usbd_bus_handle; typedef struct usbd_device *usbd_device_handle; typedef struct usbd_interface *usbd_interface_handle; typedef struct usbd_pipe *usbd_pipe_handle; -typedef struct usbd_request *usbd_request_handle; +typedef struct usbd_xfer *usbd_xfer_handle; typedef void *usbd_private_handle; -typedef enum { /* keep in sync with usbd_status_msgs */ - USBD_NORMAL_COMPLETION = 0, /* must be 0 */ +typedef enum { /* keep in sync with usbd_status_msgs */ + USBD_NORMAL_COMPLETION = 0, /* must be 0 */ USBD_IN_PROGRESS, /* errors */ USBD_PENDING_REQUESTS, @@ -72,15 +72,16 @@ typedef enum { /* keep in sync with usbd_status_msgs */ typedef int usbd_lock_token; -typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle, +typedef void (*usbd_callback) __P((usbd_xfer_handle, usbd_private_handle, usbd_status)); /* Open flags */ #define USBD_EXCLUSIVE_USE 0x01 /* Request flags */ +#define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */ +#define USBD_SYNCHRONOUS 0x02 /* wait for completion */ /* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */ -#define USBD_SYNCHRONOUS 0x08 /* wait for completion */ #define USBD_NO_TIMEOUT 0 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ @@ -93,25 +94,25 @@ usbd_status usbd_open_pipe __P((usbd_interface_handle iface, u_int8_t address, u_int8_t flags, usbd_pipe_handle *pipe)); usbd_status usbd_close_pipe __P((usbd_pipe_handle pipe)); -usbd_status usbd_transfer __P((usbd_request_handle req)); -usbd_request_handle usbd_alloc_request __P((usbd_device_handle)); -usbd_status usbd_free_request __P((usbd_request_handle reqh)); +usbd_status usbd_transfer __P((usbd_xfer_handle req)); +usbd_xfer_handle usbd_alloc_request __P((usbd_device_handle)); +usbd_status usbd_free_request __P((usbd_xfer_handle xfer)); void usbd_setup_request - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, usbd_private_handle priv, void *buffer, u_int32_t length, u_int16_t flags, u_int32_t timeout, usbd_callback)); void usbd_setup_default_request - __P((usbd_request_handle reqh, usbd_device_handle dev, + __P((usbd_xfer_handle xfer, usbd_device_handle dev, usbd_private_handle priv, u_int32_t timeout, usb_device_request_t *req, void *buffer, u_int32_t length, u_int16_t flags, usbd_callback)); void usbd_setup_isoc_request - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, usbd_private_handle priv, u_int16_t *frlengths, - u_int32_t nframes, usbd_callback)); + u_int32_t nframes, u_int16_t flags, usbd_callback)); void usbd_get_request_status - __P((usbd_request_handle reqh, usbd_private_handle *priv, + __P((usbd_xfer_handle xfer, usbd_private_handle *priv, void **buffer, u_int32_t *count, usbd_status *status)); usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor __P((usbd_interface_handle iface, u_int8_t address)); @@ -128,9 +129,10 @@ usbd_status usbd_device2interface_handle __P((usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface)); usbd_device_handle usbd_pipe2device_handle __P((usbd_pipe_handle)); -void *usbd_alloc_buffer __P((usbd_request_handle req, u_int32_t size)); -void usbd_free_buffer __P((usbd_request_handle req)); -usbd_status usbd_sync_transfer __P((usbd_request_handle req)); +void *usbd_alloc_buffer __P((usbd_xfer_handle req, u_int32_t size)); +void usbd_free_buffer __P((usbd_xfer_handle req)); +void *usbd_get_buffer __P((usbd_xfer_handle xfer)); +usbd_status usbd_sync_transfer __P((usbd_xfer_handle req)); usbd_status usbd_open_pipe_intr __P((usbd_interface_handle iface, u_int8_t address, u_int8_t flags, usbd_pipe_handle *pipe, @@ -166,6 +168,10 @@ usb_endpoint_descriptor_t *usbd_find_edesc void usbd_dopoll __P((usbd_interface_handle)); void usbd_set_polling __P((usbd_interface_handle iface, int on)); +const char *usbd_errstr __P((usbd_status err)); + +void usbd_add_event __P((int, usbd_device_handle)); + /* NetBSD attachment information */ /* Attach data */ @@ -229,8 +235,6 @@ void usbd_devinfo __P((usbd_device_handle, int, char *)); struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle)); usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor __P((usbd_interface_handle iface, u_int8_t address)); -const char *usbd_errstr __P((usbd_status)); - #if defined(__FreeBSD__) int usbd_driver_load __P((module_t mod, int what, void *arg)); diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index 69fa222bd905..ab54b1381c90 100644 --- a/sys/dev/usb/usbdi_util.c +++ b/sys/dev/usb/usbdi_util.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi_util.c,v 1.21 1999/09/09 12:26:48 augustss Exp $ */ +/* $NetBSD: usbdi_util.c,v 1.22 1999/10/13 08:10:59 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -87,13 +87,13 @@ usbd_get_config_desc(dev, conf, d) int conf; usb_config_descriptor_t *d; { - usbd_status r; + usbd_status err; DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf)); - r = usbd_get_desc(dev, UDESC_CONFIG, conf, + err = usbd_get_desc(dev, UDESC_CONFIG, conf, USB_CONFIG_DESCRIPTOR_SIZE, d); - if (r != USBD_NORMAL_COMPLETION) - return (r); + if (err) + return (err); if (d->bDescriptorType != UDESC_CONFIG) { DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n", conf, d->bDescriptorType)); @@ -253,17 +253,15 @@ usbd_set_protocol(iface, report) usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n", iface, report, id->bInterfaceNumber)); - if (!id) + if (id == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!id) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_PROTOCOL; USETW(req.wValue, report); @@ -283,16 +281,14 @@ usbd_set_report(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -312,16 +308,14 @@ usbd_set_report_async(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -341,16 +335,14 @@ usbd_get_report(iface, type, id, data, len) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (!id) + if (id == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); @@ -368,16 +360,14 @@ usbd_set_idle(iface, duration, id) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; - usbd_status r; + usbd_status err; DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id)); - if (!ifd) + if (ifd == NULL) return (USBD_IOERROR); - r = usbd_interface2device_handle(iface, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); - if (!ifd) - return (USBD_INVAL); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_IDLE; USETW2(req.wValue, duration, id); @@ -413,12 +403,12 @@ usbd_get_hid_descriptor(ifc) usb_config_descriptor_t *cdesc; usb_hid_descriptor_t *hd; char *p, *end; - usbd_status r; + usbd_status err; - if (!idesc) + if (idesc == NULL) return (0); - r = usbd_interface2device_handle(ifc, &dev); - if (r != USBD_NORMAL_COMPLETION) + err = usbd_interface2device_handle(ifc, &dev); + if (err) return (0); cdesc = usbd_get_config_descriptor(dev); @@ -450,27 +440,27 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem) usb_interface_descriptor_t *id; usb_hid_descriptor_t *hid; usbd_device_handle dev; - usbd_status r; + usbd_status err; - r = usbd_interface2device_handle(ifc, &dev); - if (r != USBD_NORMAL_COMPLETION) - return (r); + err = usbd_interface2device_handle(ifc, &dev); + if (err) + return (err); id = usbd_get_interface_descriptor(ifc); - if (!id) + if (id == NULL) return (USBD_INVAL); hid = usbd_get_hid_descriptor(ifc); - if (!hid) + if (hid == NULL) return (USBD_IOERROR); *sizep = UGETW(hid->descrs[0].wDescriptorLength); *descp = malloc(*sizep, mem, M_NOWAIT); - if (!*descp) + if (*descp == NULL) return (USBD_NOMEM); /* XXX should not use 0 Report ID */ - r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, + err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, *sizep, *descp); - if (r != USBD_NORMAL_COMPLETION) { + if (err) { free(*descp, mem); - return (r); + return (err); } return (USBD_NORMAL_COMPLETION); } @@ -490,20 +480,20 @@ usbd_get_config(dev, conf) return (usbd_do_request(dev, &req, conf)); } -static void usbd_bulk_transfer_cb __P((usbd_request_handle reqh, +static void usbd_bulk_transfer_cb __P((usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)); static void -usbd_bulk_transfer_cb(reqh, priv, status) - usbd_request_handle reqh; +usbd_bulk_transfer_cb(xfer, priv, status) + usbd_xfer_handle xfer; usbd_private_handle priv; usbd_status status; { - wakeup(reqh); + wakeup(xfer); } usbd_status -usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl) - usbd_request_handle reqh; +usbd_bulk_transfer(xfer, pipe, flags, timeout, buf, size, lbl) + usbd_xfer_handle xfer; usbd_pipe_handle pipe; u_int16_t flags; u_int32_t timeout; @@ -511,32 +501,32 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl) u_int32_t *size; char *lbl; { - usbd_status r; + usbd_status err; int s, error; - usbd_setup_request(reqh, pipe, 0, buf, *size, + usbd_setup_request(xfer, pipe, 0, buf, *size, flags, timeout, usbd_bulk_transfer_cb); DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size)); s = splusb(); /* don't want callback until tsleep() */ - r = usbd_transfer(reqh); - if (r != USBD_IN_PROGRESS) { + err = usbd_transfer(xfer); + if (err != USBD_IN_PROGRESS) { splx(s); - return (r); + return (err); } - error = tsleep((caddr_t)reqh, PZERO | PCATCH, lbl, 0); + error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0); splx(s); if (error) { DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error)); usbd_abort_pipe(pipe); return (USBD_INTERRUPTED); } - usbd_get_request_status(reqh, 0, 0, size, &r); + usbd_get_request_status(xfer, 0, 0, size, &err); DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTF(("usbd_bulk_transfer: error=%d\n", r)); + if (err) { + DPRINTF(("usbd_bulk_transfer: error=%d\n", err)); usbd_clear_endpoint_stall(pipe); } - return (r); + return (err); } void diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index 17d6d5b97d08..115bd9b10479 100644 --- a/sys/dev/usb/usbdi_util.h +++ b/sys/dev/usb/usbdi_util.h @@ -90,7 +90,7 @@ usbd_status usbd_set_config_index __P((usbd_device_handle dev, int index, int msg)); usbd_status usbd_bulk_transfer - __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags, + __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char *lbl)); void usb_detach_wait __P((device_ptr_t)); diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index d2a154461063..46cd1be3948f 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,5 +1,5 @@ -/* $NetBSD: usbdivar.h,v 1.30 1999/09/11 08:19:27 augustss Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: usbdivar.h,v 1.39 1999/11/10 04:19:59 mycroft Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ /* From usb_mem.h */ DECLARE_USB_DMA_T; -struct usbd_request; +struct usbd_xfer; struct usbd_pipe; struct usbd_endpoint { @@ -58,12 +58,12 @@ struct usbd_bus_methods { }; struct usbd_pipe_methods { - usbd_status (*transfer)__P((usbd_request_handle reqh)); - usbd_status (*start)__P((usbd_request_handle reqh)); - void (*abort)__P((usbd_request_handle reqh)); + usbd_status (*transfer)__P((usbd_xfer_handle xfer)); + usbd_status (*start)__P((usbd_xfer_handle xfer)); + void (*abort)__P((usbd_xfer_handle xfer)); void (*close)__P((usbd_pipe_handle pipe)); void (*cleartoggle)__P((usbd_pipe_handle pipe)); - void (*done)__P((usbd_request_handle reqh)); + void (*done)__P((usbd_xfer_handle xfer)); }; struct usbd_port { @@ -99,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,6 +117,7 @@ struct usbd_device { int config; int langid; /* language to use for strings */ #define USBD_NOLANG (-1) + usb_event_cookie_t cookie; /* unique connection id */ struct usbd_port *powersrc; struct usbd_endpoint def_ep; /* for pipe 0 */ usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ @@ -139,17 +145,17 @@ struct usbd_pipe { struct usbd_endpoint *endpoint; int refcnt; char running; - SIMPLEQ_HEAD(, usbd_request) queue; + SIMPLEQ_HEAD(, usbd_xfer) queue; LIST_ENTRY(usbd_pipe) next; - usbd_request_handle intrreqh; /* used for repeating requests */ + usbd_xfer_handle intrxfer; /* used for repeating requests */ char repeat; /* Filled by HC driver. */ struct usbd_pipe_methods *methods; }; -struct usbd_request { +struct usbd_xfer { struct usbd_pipe *pipe; void *priv; void *buffer; @@ -177,7 +183,7 @@ struct usbd_request { #define URQ_AUTO_DMABUF 0x10 #define URQ_DEV_DMABUF 0x20 - SIMPLEQ_ENTRY(usbd_request) next; + SIMPLEQ_ENTRY(usbd_xfer) next; void *hcpriv; /* private use by the HC driver */ int hcprivint; /* ditto */ @@ -187,6 +193,9 @@ struct usbd_request { #endif }; +void usbd_init __P((void)); +void usbd_finish __P((void)); + /* Routines from usb_subr.c */ int usbctlprint __P((void *, const char *)); void usb_delay_ms __P((usbd_bus_handle, u_int)); @@ -208,13 +217,26 @@ usbd_status usbd_fill_iface_data __P((usbd_device_handle dev, int i, int a)); void usb_free_device __P((usbd_device_handle)); -usbd_status usb_insert_transfer __P((usbd_request_handle reqh)); -void usb_transfer_complete __P((usbd_request_handle reqh)); +usbd_status usb_insert_transfer __P((usbd_xfer_handle xfer)); +void usb_transfer_complete __P((usbd_xfer_handle xfer)); +void usb_disconnect_port __P((struct usbd_port *up, device_ptr_t)); /* Routines from usb.c */ int usb_bus_count __P((void)); void usb_needs_explore __P((usbd_bus_handle)); +#ifdef DIAGNOSTIC +#define SPLUSBCHECK \ + do { int _s = splusb(), _su = splusb(); \ + extern int cold; \ + if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \ + _s, _su, __FILE__, __LINE__); \ + splx(_s); \ + } while (0) +#else +#define SPLUSBCHECK +#endif + /* Locator stuff. */ #if defined(__NetBSD__) diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h index 5858b42b6aaa..32b91e551cb3 100644 --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbhid.h,v 1.5 1999/05/13 23:29:11 augustss Exp $ */ +/* $NetBSD: usbhid.h,v 1.4 1999/04/22 01:57:01 augustss Exp $ */ /* $FreeBSD$ */ /*