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