diff options
65 files changed, 3902 insertions, 13568 deletions
diff --git a/sys/dev/usb/FILES b/sys/dev/usb/FILES index 166fecb2dcd..ed7b4094b13 100644 --- a/sys/dev/usb/FILES +++ b/sys/dev/usb/FILES @@ -5,9 +5,6 @@ Makefile to install .h files Makefile.usbdevs to run devlist2h.awk TODO just a list of things to do devlist2h.awk script to generate usbdevs*.h -ehci.c Host controller driver for EHCI (just a stub now) -ehcireg.h Hardware definitions for EHCI (just a stub now) -ehcivar.h API for ehci.c ezload.c EZ-USB firmware download subroutines ezload.h API for ezload.c files.usb config include file @@ -34,27 +31,13 @@ ugen.c generic driver that can handle access to any USB device uhci.c Host controller driver for UHCI uhcireg.h Hardware definitions for UHCI uhcivar.h API for uhci.c -uhid.c USB generic HID driver -uhidev.c USB HID class driver -uhidev.h and definitions for it +uhid.c USB HID class driver uhub.c USB hub driver ukbd.c USB keyboard driver ukbdmap.c wscons key mapping for ukbd ukbdvar.h API for ukbd.c ulpt.c USB printer class driver -umass.c USB mass storage wire protocol driver -umass_isdata.c In-System Design ATA over bulk-only driver -umass_isdata.h and definitions for it -umass_quirks.c Table of strange umass devices -umass_quirks.h and definitions for it -umass_scsipi.c umass command protocol driver -umass_scsipi.h and definitions for it -umassvar.h definitions for umass.c -umidi.c USB MIDI driver -umidi_quirks.c Strange MIDI devices -umidi_quirks.h and definitions for it -umidireg.h Protocol definitions for umidi.c -umidivar.h definitions for umidi.c +umass.c USB mass storage driver (bulk only for now) umodem.c USB modem (CDC ACM) driver ums.c USB mouse driver urio.c USB Diamond Rio500 driver diff --git a/sys/dev/usb/TODO b/sys/dev/usb/TODO index 2bc3497628a..28088a69fb3 100644 --- a/sys/dev/usb/TODO +++ b/sys/dev/usb/TODO @@ -85,8 +85,6 @@ Get rid of hcpriv. Keyspan serial driver -Clean up umass driver - Documentation: -------------- diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c deleted file mode 100644 index ea68e25be57..00000000000 --- a/sys/dev/usb/ehci.c +++ /dev/null @@ -1,2757 +0,0 @@ -/* $OpenBSD: ehci.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ehci.c,v 1.29 2001/12/31 12:16:57 augustss Exp $ */ - -/* - * TODO - * hold off explorations by companion controllers until ehci has started. - */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller. - * - * The EHCI 0.96 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r096.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/data/usb_20.zip - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/device.h> -#include <sys/select.h> -#include <sys/proc.h> -#include <sys/queue.h> - -#include <machine/bus.h> -#include <machine/endian.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usb_mem.h> -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/ehcireg.h> -#include <dev/usb/ehcivar.h> - -#if defined(__OpenBSD__) -struct cfdriver ehci_cd = { - NULL, "ehci", DV_DULL -}; -#endif - -#ifdef EHCI_DEBUG -#define DPRINTF(x) if (ehcidebug) printf x -#define DPRINTFN(n,x) if (ehcidebug>(n)) printf x -int ehcidebug = 0; -#ifndef __NetBSD__ -#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f)) -#endif -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct ehci_pipe { - struct usbd_pipe pipe; - ehci_soft_qh_t *sqh; - union { - ehci_soft_qtd_t *qtd; - /* ehci_soft_itd_t *itd; */ - } tail; - union { - /* Control pipe */ - struct { - usb_dma_t reqdma; - u_int length; - /*ehci_soft_qtd_t *setup, *data, *stat;*/ - } ctl; - /* Interrupt pipe */ - /* XXX */ - /* Bulk pipe */ - struct { - u_int length; - } bulk; - /* Iso pipe */ - /* XXX */ - } u; -}; - -Static void ehci_shutdown(void *); -Static void ehci_power(int, void *); - -Static usbd_status ehci_open(usbd_pipe_handle); -Static void ehci_poll(struct usbd_bus *); -Static void ehci_softintr(void *); -Static int ehci_intr1(ehci_softc_t *); -Static void ehci_waitintr(ehci_softc_t *, usbd_xfer_handle); -Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *); -Static void ehci_idone(struct ehci_xfer *); -Static void ehci_timeout(void *); -Static void ehci_timeout_task(void *); - -Static usbd_status ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -Static void ehci_freem(struct usbd_bus *, usb_dma_t *); - -Static usbd_xfer_handle ehci_allocx(struct usbd_bus *); -Static void ehci_freex(struct usbd_bus *, usbd_xfer_handle); - -Static usbd_status ehci_root_ctrl_transfer(usbd_xfer_handle); -Static usbd_status ehci_root_ctrl_start(usbd_xfer_handle); -Static void ehci_root_ctrl_abort(usbd_xfer_handle); -Static void ehci_root_ctrl_close(usbd_pipe_handle); -Static void ehci_root_ctrl_done(usbd_xfer_handle); - -Static usbd_status ehci_root_intr_transfer(usbd_xfer_handle); -Static usbd_status ehci_root_intr_start(usbd_xfer_handle); -Static void ehci_root_intr_abort(usbd_xfer_handle); -Static void ehci_root_intr_close(usbd_pipe_handle); -Static void ehci_root_intr_done(usbd_xfer_handle); - -Static usbd_status ehci_device_ctrl_transfer(usbd_xfer_handle); -Static usbd_status ehci_device_ctrl_start(usbd_xfer_handle); -Static void ehci_device_ctrl_abort(usbd_xfer_handle); -Static void ehci_device_ctrl_close(usbd_pipe_handle); -Static void ehci_device_ctrl_done(usbd_xfer_handle); - -Static usbd_status ehci_device_bulk_transfer(usbd_xfer_handle); -Static usbd_status ehci_device_bulk_start(usbd_xfer_handle); -Static void ehci_device_bulk_abort(usbd_xfer_handle); -Static void ehci_device_bulk_close(usbd_pipe_handle); -Static void ehci_device_bulk_done(usbd_xfer_handle); - -Static usbd_status ehci_device_intr_transfer(usbd_xfer_handle); -Static usbd_status ehci_device_intr_start(usbd_xfer_handle); -Static void ehci_device_intr_abort(usbd_xfer_handle); -Static void ehci_device_intr_close(usbd_pipe_handle); -Static void ehci_device_intr_done(usbd_xfer_handle); - -Static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle); -Static usbd_status ehci_device_isoc_start(usbd_xfer_handle); -Static void ehci_device_isoc_abort(usbd_xfer_handle); -Static void ehci_device_isoc_close(usbd_pipe_handle); -Static void ehci_device_isoc_done(usbd_xfer_handle); - -Static void ehci_device_clear_toggle(usbd_pipe_handle pipe); -Static void ehci_noop(usbd_pipe_handle pipe); - -Static int ehci_str(usb_string_descriptor_t *, int, char *); -Static void ehci_pcd(ehci_softc_t *, usbd_xfer_handle); -Static void ehci_pcd_able(ehci_softc_t *, int); -Static void ehci_pcd_enable(void *); -Static void ehci_disown(ehci_softc_t *, int, int); - -Static ehci_soft_qh_t *ehci_alloc_sqh(ehci_softc_t *); -Static void ehci_free_sqh(ehci_softc_t *, ehci_soft_qh_t *); - -Static ehci_soft_qtd_t *ehci_alloc_sqtd(ehci_softc_t *); -Static void ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *); -Static usbd_status ehci_alloc_sqtd_chain(struct ehci_pipe *, - ehci_softc_t *, int, int, usbd_xfer_handle, - ehci_soft_qtd_t **, ehci_soft_qtd_t **); -Static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qtd_t *, - ehci_soft_qtd_t *); - -Static usbd_status ehci_device_request(usbd_xfer_handle xfer); - -Static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *); -Static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *, - ehci_soft_qh_t *); -Static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *); -Static void ehci_sync_hc(ehci_softc_t *); - -Static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *); -Static void ehci_abort_xfer(usbd_xfer_handle, usbd_status); - -#ifdef EHCI_DEBUG -Static void ehci_dump_regs(ehci_softc_t *); -Static void ehci_dump(void); -Static ehci_softc_t *theehci; -Static void ehci_dump_link(ehci_link_t, int); -Static void ehci_dump_sqtds(ehci_soft_qtd_t *); -Static void ehci_dump_sqtd(ehci_soft_qtd_t *); -Static void ehci_dump_qtd(ehci_qtd_t *); -Static void ehci_dump_sqh(ehci_soft_qh_t *); -Static void ehci_dump_exfer(struct ehci_xfer *); -#endif - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#define EHCI_NULL htole32(EHCI_LINK_TERMINATE) - -#define EHCI_INTR_ENDPT 1 - -#define ehci_add_intr_list(sc, ex) \ - LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ex), inext); -#define ehci_del_intr_list(ex) \ - LIST_REMOVE((ex), inext) - -Static struct usbd_bus_methods ehci_bus_methods = { - ehci_open, - ehci_softintr, - ehci_poll, - ehci_allocm, - ehci_freem, - ehci_allocx, - ehci_freex, -}; - -Static struct usbd_pipe_methods ehci_root_ctrl_methods = { - ehci_root_ctrl_transfer, - ehci_root_ctrl_start, - ehci_root_ctrl_abort, - ehci_root_ctrl_close, - ehci_noop, - ehci_root_ctrl_done, -}; - -Static struct usbd_pipe_methods ehci_root_intr_methods = { - ehci_root_intr_transfer, - ehci_root_intr_start, - ehci_root_intr_abort, - ehci_root_intr_close, - ehci_noop, - ehci_root_intr_done, -}; - -Static struct usbd_pipe_methods ehci_device_ctrl_methods = { - ehci_device_ctrl_transfer, - ehci_device_ctrl_start, - ehci_device_ctrl_abort, - ehci_device_ctrl_close, - ehci_noop, - ehci_device_ctrl_done, -}; - -Static struct usbd_pipe_methods ehci_device_intr_methods = { - ehci_device_intr_transfer, - ehci_device_intr_start, - ehci_device_intr_abort, - ehci_device_intr_close, - ehci_device_clear_toggle, - ehci_device_intr_done, -}; - -Static struct usbd_pipe_methods ehci_device_bulk_methods = { - ehci_device_bulk_transfer, - ehci_device_bulk_start, - ehci_device_bulk_abort, - ehci_device_bulk_close, - ehci_device_clear_toggle, - ehci_device_bulk_done, -}; - -Static struct usbd_pipe_methods ehci_device_isoc_methods = { - ehci_device_isoc_transfer, - ehci_device_isoc_start, - ehci_device_isoc_abort, - ehci_device_isoc_close, - ehci_noop, - ehci_device_isoc_done, -}; - -usbd_status -ehci_init(ehci_softc_t *sc) -{ - u_int32_t version, sparams, cparams, hcr; - u_int i; - usbd_status err; - ehci_soft_qh_t *sqh; - - DPRINTF(("ehci_init: start\n")); -#ifdef EHCI_DEBUG - theehci = sc; -#endif - - sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); - - version = EREAD2(sc, EHCI_HCIVERSION); - printf("%s: EHCI version %x.%x\n", USBDEVNAME(sc->sc_bus.bdev), - version >> 8, version & 0xff); - - sparams = EREAD4(sc, EHCI_HCSPARAMS); - DPRINTF(("ehci_init: sparams=0x%x\n", sparams)); - sc->sc_npcomp = EHCI_HCS_N_PCC(sparams); - if (EHCI_HCS_N_CC(sparams) != sc->sc_ncomp) { - printf("%s: wrong number of companions (%d != %d)\n", - USBDEVNAME(sc->sc_bus.bdev), - EHCI_HCS_N_CC(sparams), sc->sc_ncomp); - return (USBD_IOERROR); - } - if (sc->sc_ncomp > 0) { - printf("%s: companion controller%s, %d port%s each:", - USBDEVNAME(sc->sc_bus.bdev), sc->sc_ncomp!=1 ? "s" : "", - EHCI_HCS_N_PCC(sparams), - EHCI_HCS_N_PCC(sparams)!=1 ? "s" : ""); - for (i = 0; i < sc->sc_ncomp; i++) - printf(" %s", USBDEVNAME(sc->sc_comps[i]->bdev)); - printf("\n"); - } - sc->sc_noport = EHCI_HCS_N_PORTS(sparams); - cparams = EREAD4(sc, EHCI_HCCPARAMS); - DPRINTF(("ehci_init: cparams=0x%x\n", cparams)); - - sc->sc_bus.usbrev = USBREV_2_0; - - /* Reset the controller */ - DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev))); - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - usb_delay_ms(&sc->sc_bus, 1); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - for (i = 0; i < 100; i++) { - delay(10); - hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; - if (!hcr) - break; - } - if (hcr) { - printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - return (USBD_IOERROR); - } - - /* frame list size at default, read back what we got and use that */ - switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) { - case 0: sc->sc_flsize = 1024*4; break; - case 1: sc->sc_flsize = 512*4; break; - case 2: sc->sc_flsize = 256*4; break; - case 3: return (USBD_IOERROR); - } - err = usb_allocmem(&sc->sc_bus, sc->sc_flsize, - EHCI_FLALIGN_ALIGN, &sc->sc_fldma); - if (err) - return (err); - DPRINTF(("%s: flsize=%d\n", USBDEVNAME(sc->sc_bus.bdev),sc->sc_flsize)); - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ehci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ehci_pipe); - - sc->sc_powerhook = powerhook_establish(ehci_power, sc); - sc->sc_shutdownhook = shutdownhook_establish(ehci_shutdown, sc); - - sc->sc_eintrs = EHCI_NORMAL_INTRS; - - /* Allocate dummy QH that starts the async list. */ - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) { - err = USBD_NOMEM; - goto bad1; - } - /* Fill the QH */ - sqh->qh.qh_endp = - htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL); - sqh->qh.qh_link = - htole32(sqh->physaddr | EHCI_LINK_QH); - sqh->qh.qh_curqtd = EHCI_NULL; - sqh->next = NULL; - /* Fill the overlay qTD */ - sqh->qh.qh_qtd.qtd_next = EHCI_NULL; - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED); - sqh->sqtd = NULL; -#ifdef EHCI_DEBUG - if (ehcidebug) { - ehci_dump_sqh(sqh); - } -#endif - - /* Point to async list */ - sc->sc_async_head = sqh; - EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH); - - usb_callout_init(sc->sc_tmo_pcd); - - lockinit(&sc->sc_doorbell_lock, PZERO, "ehcidb", 0, 0); - - /* Enable interrupts */ - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - - /* Turn on controller */ - EOWRITE4(sc, EHCI_USBCMD, - EHCI_CMD_ITC_8 | /* 8 microframes */ - (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) | - EHCI_CMD_ASE | - /* EHCI_CMD_PSE | */ - EHCI_CMD_RS); - - /* Take over port ownership */ - EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF); - - for (i = 0; i < 100; i++) { - delay(10); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (!hcr) - break; - } - if (hcr) { - printf("%s: run timeout\n", USBDEVNAME(sc->sc_bus.bdev)); - return (USBD_IOERROR); - } - - return (USBD_NORMAL_COMPLETION); - -#if 0 - bad2: - ehci_free_sqh(sc, sc->sc_async_head); -#endif - bad1: - usb_freemem(&sc->sc_bus, &sc->sc_fldma); - return (err); -} - -int -ehci_intr(void *v) -{ - ehci_softc_t *sc = v; - - if (sc == NULL || sc->sc_dying) - return (0); - - /* If we get an interrupt while polling, then just ignore it. */ - if (sc->sc_bus.use_polling) { -#ifdef DIAGNOSTIC - printf("ehci_intr: ignored interrupt while polling\n"); -#endif - return (0); - } - - return (ehci_intr1(sc)); -} - -Static int -ehci_intr1(ehci_softc_t *sc) -{ - u_int32_t intrs, eintrs; - - DPRINTFN(20,("ehci_intr1: enter\n")); - - /* In case the interrupt occurs before initialization has completed. */ - if (sc == NULL) { -#ifdef DIAGNOSTIC - printf("ehci_intr: sc == NULL\n"); -#endif - return (0); - } - - intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - - if (!intrs) - return (0); - - EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ - eintrs = intrs & sc->sc_eintrs; - DPRINTFN(7, ("ehci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", - sc, (u_int)intrs, EOREAD4(sc, EHCI_USBSTS), - (u_int)eintrs)); - if (!eintrs) - return (0); - - sc->sc_bus.intr_context++; - sc->sc_bus.no_intrs++; - if (eintrs & EHCI_STS_IAA) { - DPRINTF(("ehci_intr1: door bell\n")); - wakeup(&sc->sc_async_head); - eintrs &= ~EHCI_STS_IAA; - } - if (eintrs & (EHCI_STS_INT | EHCI_STS_ERRINT)) { - DPRINTF(("ehci_intr1: %s %s\n", - eintrs & EHCI_STS_INT ? "INT" : "", - eintrs & EHCI_STS_ERRINT ? "ERRINT" : "")); - usb_schedsoftintr(&sc->sc_bus); - eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT); - } - if (eintrs & EHCI_STS_HSE) { - printf("%s: unrecoverable error, controller halted\n", - USBDEVNAME(sc->sc_bus.bdev)); - /* XXX what else */ - } - if (eintrs & EHCI_STS_PCD) { - ehci_pcd(sc, sc->sc_intrxfer); - /* - * Disable PCD interrupt for now, because it will be - * on until the port has been reset. - */ - ehci_pcd_able(sc, 0); - /* Do not allow RHSC interrupts > 1 per second */ - usb_callout(sc->sc_tmo_pcd, hz, ehci_pcd_enable, sc); - eintrs &= ~EHCI_STS_PCD; - } - - sc->sc_bus.intr_context--; - - if (eintrs != 0) { - /* Block unprocessed interrupts. */ - sc->sc_eintrs &= ~eintrs; - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - printf("%s: blocking intrs 0x%x\n", - USBDEVNAME(sc->sc_bus.bdev), eintrs); - } - - return (1); -} - -void -ehci_pcd_able(ehci_softc_t *sc, int on) -{ - DPRINTFN(4, ("ehci_pcd_able: on=%d\n", on)); - if (on) - sc->sc_eintrs |= EHCI_STS_PCD; - else - sc->sc_eintrs &= ~EHCI_STS_PCD; - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); -} - -void -ehci_pcd_enable(void *v_sc) -{ - ehci_softc_t *sc = v_sc; - - ehci_pcd_able(sc, 1); -} - -void -ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe; - struct ehci_pipe *epipe; - u_char *p; - int i, m; - - if (xfer == NULL) { - /* Just ignore the change. */ - return; - } - - pipe = xfer->pipe; - epipe = (struct ehci_pipe *)pipe; - - p = KERNADDR(&xfer->dmabuf); - m = min(sc->sc_noport, xfer->length * 8 - 1); - memset(p, 0, xfer->length); - for (i = 1; i <= m; i++) { - /* Pick out CHANGE bits from the status reg. */ - if (EOREAD4(sc, EHCI_PORTSC(i)) & EHCI_PS_CLEAR) - p[i/8] |= 1 << (i%8); - } - DPRINTF(("ehci_pcd: change=0x%02x\n", *p)); - xfer->actlen = xfer->length; - xfer->status = USBD_NORMAL_COMPLETION; - - usb_transfer_complete(xfer); -} - -void -ehci_softintr(void *v) -{ - ehci_softc_t *sc = v; - struct ehci_xfer *ex; - - DPRINTFN(10,("%s: ehci_softintr (%d)\n", USBDEVNAME(sc->sc_bus.bdev), - sc->sc_bus.intr_context)); - - sc->sc_bus.intr_context++; - - /* - * The only explanation I can think of for why EHCI is as brain dead - * as UHCI interrupt-wise is that Intel was involved in both. - * An interrupt just tells us that something is done, we have no - * clue what, so we need to scan through all active transfers. :-( - */ - for (ex = LIST_FIRST(&sc->sc_intrhead); ex; ex = LIST_NEXT(ex, inext)) - ehci_check_intr(sc, ex); - - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } - - sc->sc_bus.intr_context--; -} - -/* Check for an interrupt. */ -void -ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex) -{ - ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status; - - DPRINTFN(/*15*/2, ("ehci_check_intr: ex=%p\n", ex)); - - if (ex->sqtdstart == NULL) { - printf("ehci_check_intr: sqtdstart=NULL\n"); - return; - } - lsqtd = ex->sqtdend; -#ifdef DIAGNOSTIC - if (lsqtd == NULL) { - printf("ehci_check_intr: sqtd==0\n"); - return; - } -#endif - /* - * If the last TD is still active we need to check whether there - * is a an error somewhere in the middle, or whether there was a - * short packet (SPD and not ACTIVE). - */ - if (le32toh(lsqtd->qtd.qtd_status) & EHCI_QTD_ACTIVE) { - DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex)); - for (sqtd = ex->sqtdstart; sqtd != lsqtd; sqtd=sqtd->nextqtd) { - status = le32toh(sqtd->qtd.qtd_status); - /* If there's an active QTD the xfer isn't done. */ - if (status & EHCI_QTD_ACTIVE) - break; - /* Any kind of error makes the xfer done. */ - if (status & EHCI_QTD_HALTED) - goto done; - /* We want short packets, and it is short: it's done */ - if (EHCI_QTD_SET_BYTES(status) != 0) - goto done; - } - DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n", - ex, ex->sqtdstart)); - return; - } - done: - DPRINTFN(12, ("ehci_check_intr: ex=%p done\n", ex)); - usb_uncallout(ex->xfer.timeout_handle, ehci_timeout, ex); - ehci_idone(ex); -} - -void -ehci_idone(struct ehci_xfer *ex) -{ - usbd_xfer_handle xfer = &ex->xfer; -#ifdef EHCI_DEBUG - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; -#endif - ehci_soft_qtd_t *sqtd; - u_int32_t status = 0, nstatus; - int actlen; - - DPRINTFN(/*12*/2, ("ehci_idone: ex=%p\n", ex)); -#ifdef DIAGNOSTIC - { - int s = splhigh(); - if (ex->isdone) { - splx(s); -#ifdef EHCI_DEBUG - printf("ehci_idone: ex is done!\n "); - ehci_dump_exfer(ex); -#else - printf("ehci_idone: ex=%p is done!\n", ex); -#endif - return; - } - ex->isdone = 1; - splx(s); - } -#endif - - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ehci_idone: aborted xfer=%p\n", xfer)); - return; - } - -#ifdef EHCI_DEBUG - DPRINTFN(/*10*/2, ("ehci_idone: xfer=%p, pipe=%p ready\n", xfer, epipe)); - if (ehcidebug > 10) - ehci_dump_sqtds(ex->sqtdstart); -#endif - - /* The transfer is done, compute actual length and status. */ - actlen = 0; - for (sqtd = ex->sqtdstart; sqtd != NULL; sqtd = sqtd->nextqtd) { - nstatus = le32toh(sqtd->qtd.qtd_status); - if (nstatus & EHCI_QTD_ACTIVE) - break; - - status = nstatus; - if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP) - actlen += sqtd->len - EHCI_QTD_GET_BYTES(status); - } - - /* If there are left over TDs we need to update the toggle. */ - if (sqtd != NULL) { - if (!(xfer->rqflags & URQ_REQUEST)) - printf("ehci_idone: need toggle update\n"); -#if 0 - epipe->nexttoggle = EHCI_TD_GET_DT(le32toh(std->td.td_token)); -#endif - } - - status &= EHCI_QTD_STATERRS; - DPRINTFN(/*10*/2, ("ehci_idone: len=%d, actlen=%d, status=0x%x\n", - xfer->length, actlen, status)); - xfer->actlen = actlen; - if (status != 0) { -#ifdef EHCI_DEBUG - char sbuf[128]; - - bitmask_snprintf((u_int32_t)status, - "\20\3MISSEDMICRO\4XACT\5BABBLE\6BABBLE" - "\7HALTED", - sbuf, sizeof(sbuf)); - - DPRINTFN((status == EHCI_QTD_HALTED)*/*10*/2, - ("ehci_idone: error, addr=%d, endpt=0x%02x, " - "status 0x%s\n", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, - sbuf)); - if (ehcidebug > 2) { - ehci_dump_sqh(epipe->sqh); - ehci_dump_sqtds(ex->sqtdstart); - } -#endif - if (status == EHCI_QTD_HALTED) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; /* more info XXX */ - } else { - xfer->status = USBD_NORMAL_COMPLETION; - } - - usb_transfer_complete(xfer); - DPRINTFN(/*12*/2, ("ehci_idone: ex=%p done\n", ex)); -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call ehci_intr and return. Use timeout to avoid waiting - * too long. - */ -void -ehci_waitintr(ehci_softc_t *sc, usbd_xfer_handle xfer) -{ - int timo = xfer->timeout; - int usecs; - u_int32_t intrs; - - xfer->status = USBD_IN_PROGRESS; - for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { - usb_delay_ms(&sc->sc_bus, 1); - if (sc->sc_dying) - break; - intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)) & - sc->sc_eintrs; - DPRINTFN(15,("ehci_waitintr: 0x%04x\n", intrs)); -#ifdef EHCI_DEBUG - if (ehcidebug > 15) - ehci_dump_regs(sc); -#endif - if (intrs) { - ehci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - } - - /* Timeout */ - DPRINTF(("ehci_waitintr: timeout\n")); - xfer->status = USBD_TIMEOUT; - usb_transfer_complete(xfer); - /* XXX should free TD */ -} - -void -ehci_poll(struct usbd_bus *bus) -{ - ehci_softc_t *sc = (ehci_softc_t *)bus; -#ifdef EHCI_DEBUG - static int last; - int new; - new = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - if (new != last) { - DPRINTFN(10,("ehci_poll: intrs=0x%04x\n", new)); - last = new; - } -#endif - - if (EOREAD4(sc, EHCI_USBSTS) & sc->sc_eintrs) - ehci_intr1(sc); -} - -int -ehci_detach(struct ehci_softc *sc, int flags) -{ - int rv = 0; - - if (sc->sc_child != NULL) - rv = config_detach(sc->sc_child, flags); - - if (rv != 0) - return (rv); - - usb_uncallout(sc->sc_tmo_pcd, ehci_pcd_enable, sc); - - if (sc->sc_powerhook != NULL) - powerhook_disestablish(sc->sc_powerhook); - if (sc->sc_shutdownhook != NULL) - shutdownhook_disestablish(sc->sc_shutdownhook); - - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - - /* XXX free other data structures XXX */ - - return (rv); -} - - -int -ehci_activate(device_ptr_t self, enum devact act) -{ - struct ehci_softc *sc = (struct ehci_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); - sc->sc_dying = 1; - break; - } - return (rv); -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an intterupt context. This is all right since we - * are almost suspended anyway. - */ -void -ehci_power(int why, void *v) -{ - ehci_softc_t *sc = v; - //u_int32_t ctl; - int s; - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why)); - ehci_dump_regs(sc); -#endif - - s = splhardusb(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - sc->sc_bus.use_polling++; -#if 0 -OOO - ctl = OREAD4(sc, EHCI_CONTROL) & ~EHCI_HCFS_MASK; - if (sc->sc_control == 0) { - /* - * Preserve register values, in case that APM BIOS - * does not recover them. - */ - sc->sc_control = ctl; - sc->sc_intre = OREAD4(sc, EHCI_INTERRUPT_ENABLE); - } - ctl |= EHCI_HCFS_SUSPEND; - OWRITE4(sc, EHCI_CONTROL, ctl); -#endif - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_bus.use_polling--; - break; - case PWR_RESUME: - sc->sc_bus.use_polling++; -#if 0 -OOO - /* Some broken BIOSes do not recover these values */ - OWRITE4(sc, EHCI_HCCA, DMAADDR(&sc->sc_hccadma)); - OWRITE4(sc, EHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); - OWRITE4(sc, EHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); - if (sc->sc_intre) - OWRITE4(sc, EHCI_INTERRUPT_ENABLE, - sc->sc_intre & (EHCI_ALL_INTRS | EHCI_MIE)); - if (sc->sc_control) - ctl = sc->sc_control; - else - ctl = OREAD4(sc, EHCI_CONTROL); - ctl |= EHCI_HCFS_RESUME; - OWRITE4(sc, EHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - ctl = (ctl & ~EHCI_HCFS_MASK) | EHCI_HCFS_OPERATIONAL; - OWRITE4(sc, EHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_control = sc->sc_intre = 0; -#endif - sc->sc_bus.use_polling--; - break; -#if defined(__NetBSD__) - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; -#endif - } - splx(s); -} - -/* - * Shut down the controller when the system is going down. - */ -void -ehci_shutdown(void *v) -{ - ehci_softc_t *sc = v; - - DPRINTF(("ehci_shutdown: stopping the HC\n")); - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); -} - -usbd_status -ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - usbd_status err; - - err = usb_allocmem(&sc->sc_bus, size, 0, dma); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_allocm: usb_allocmem()=%d\n", err); -#endif - return (err); -} - -void -ehci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - - usb_freemem(&sc->sc_bus, dma); -} - -usbd_xfer_handle -ehci_allocx(struct usbd_bus *bus) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("uhci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = malloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof (struct ehci_xfer)); -#ifdef DIAGNOSTIC - EXFER(xfer)->isdone = 1; - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -ehci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; - if (!EXFER(xfer)->isdone) { - printf("ehci_freex: !isdone\n"); - return; - } -#endif - SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -Static void -ehci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - - DPRINTF(("ehci_device_clear_toggle: epipe=%p status=0x%x\n", - epipe, epipe->sqh->qh.qh_qtd.qtd_status)); -#ifdef USB_DEBUG - if (ehcidebug) - usbd_dump_pipe(pipe); -#endif - epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE); -} - -Static void -ehci_noop(usbd_pipe_handle pipe) -{ -} - -#ifdef EHCI_DEBUG -void -ehci_dump_regs(ehci_softc_t *sc) -{ - int i; - printf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), - EOREAD4(sc, EHCI_USBSTS), - EOREAD4(sc, EHCI_USBINTR)); - printf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n", - EOREAD4(sc, EHCI_FRINDEX), - EOREAD4(sc, EHCI_CTRLDSSEGMENT), - EOREAD4(sc, EHCI_PERIODICLISTBASE), - EOREAD4(sc, EHCI_ASYNCLISTADDR)); - for (i = 1; i <= sc->sc_noport; i++) - printf("port %d status=0x%08x\n", i, - EOREAD4(sc, EHCI_PORTSC(i))); -} - -void -ehci_dump() -{ - ehci_dump_regs(theehci); -} - -void -ehci_dump_link(ehci_link_t link, int type) -{ - link = le32toh(link); - printf("0x%08x", link); - if (link & EHCI_LINK_TERMINATE) - printf("<T>"); - else { - printf("<"); - if (type) { - switch (EHCI_LINK_TYPE(link)) { - case EHCI_LINK_ITD: printf("ITD"); break; - case EHCI_LINK_QH: printf("QH"); break; - case EHCI_LINK_SITD: printf("SITD"); break; - case EHCI_LINK_FSTN: printf("FSTN"); break; - } - } - printf(">"); - } -} - -void -ehci_dump_sqtds(ehci_soft_qtd_t *sqtd) -{ - int i; - u_int32_t stop; - - stop = 0; - for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) { - ehci_dump_sqtd(sqtd); - stop = sqtd->qtd.qtd_next & EHCI_LINK_TERMINATE; - } - if (sqtd) - printf("dump aborted, too many TDs\n"); -} - -void -ehci_dump_sqtd(ehci_soft_qtd_t *sqtd) -{ - printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr); - ehci_dump_qtd(&sqtd->qtd); -} - -void -ehci_dump_qtd(ehci_qtd_t *qtd) -{ - u_int32_t s; - char sbuf[128]; - - printf(" next="); ehci_dump_link(qtd->qtd_next, 0); - printf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0); - printf("\n"); - s = le32toh(qtd->qtd_status); - bitmask_snprintf(EHCI_QTD_GET_STATUS(s), - "\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR" - "\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf)); - printf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n", - s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s), - EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s)); - printf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s), - EHCI_QTD_GET_PID(s), sbuf); - for (s = 0; s < 5; s++) - printf(" buffer[%d]=0x%08x\n", s, le32toh(qtd->qtd_buffer[s])); -} - -void -ehci_dump_sqh(ehci_soft_qh_t *sqh) -{ - ehci_qh_t *qh = &sqh->qh; - u_int32_t endp, endphub; - - printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr); - printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n"); - endp = le32toh(qh->qh_endp); - printf(" endp=0x%08x\n", endp); - printf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n", - EHCI_QH_GET_ADDR(endp), EHCI_QH_GET_INACT(endp), - EHCI_QH_GET_ENDPT(endp), EHCI_QH_GET_EPS(endp), - EHCI_QH_GET_DTC(endp), EHCI_QH_GET_HRECL(endp)); - printf(" mpl=0x%x ctl=%d nrl=%d\n", - EHCI_QH_GET_MPL(endp), EHCI_QH_GET_CTL(endp), - EHCI_QH_GET_NRL(endp)); - endphub = le32toh(qh->qh_endphub); - printf(" endphub=0x%08x\n", endphub); - printf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n", - EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub), - EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub), - EHCI_QH_GET_MULT(endphub)); - printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n"); - printf("Overlay qTD:\n"); - ehci_dump_qtd(&qh->qh_qtd); -} - -Static void -ehci_dump_exfer(struct ehci_xfer *ex) -{ - printf("ehci_dump_exfer: ex=%p\n", ex); -} -#endif - -usbd_status -ehci_open(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - u_int8_t addr = dev->address; - u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - ehci_soft_qh_t *sqh; - usbd_status err; - int s; - int speed, naks; - - DPRINTFN(1, ("ehci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, addr, ed->bEndpointAddress, sc->sc_addr)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - if (addr == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &ehci_root_ctrl_methods; - break; - case UE_DIR_IN | EHCI_INTR_ENDPT: - pipe->methods = &ehci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); - } - - /* XXX All this stuff is only valid for async. */ - switch (dev->speed) { - case USB_SPEED_LOW: speed = EHCI_QH_SPEED_LOW; break; - case USB_SPEED_FULL: speed = EHCI_QH_SPEED_FULL; break; - case USB_SPEED_HIGH: speed = EHCI_QH_SPEED_HIGH; break; - default: panic("ehci_open: bad device speed %d\n", dev->speed); - } - naks = 8; /* XXX */ - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) - goto bad0; - /* qh_link filled when the QH is added */ - sqh->qh.qh_endp = htole32( - EHCI_QH_SET_ADDR(addr) | - EHCI_QH_SET_ENDPT(ed->bEndpointAddress) | - EHCI_QH_SET_EPS(speed) | /* XXX */ - /* XXX EHCI_QH_DTC ? */ - EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) | - (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ? - EHCI_QH_CTL : 0) | - EHCI_QH_SET_NRL(naks) - ); - sqh->qh.qh_endphub = htole32( - EHCI_QH_SET_MULT(1) - /* XXX TT stuff */ - /* XXX interrupt mask */ - ); - sqh->qh.qh_curqtd = EHCI_NULL; - /* Fill the overlay qTD */ - sqh->qh.qh_qtd.qtd_next = EHCI_NULL; - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = htole32(0); - - epipe->sqh = sqh; - - switch (xfertype) { - case UE_CONTROL: - err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), - 0, &epipe->u.ctl.reqdma); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_open: usb_allocmem()=%d\n", err); -#endif - if (err) - goto bad1; - pipe->methods = &ehci_device_ctrl_methods; - s = splusb(); - ehci_add_qh(sqh, sc->sc_async_head); - splx(s); - break; - case UE_BULK: - pipe->methods = &ehci_device_bulk_methods; - s = splusb(); - ehci_add_qh(sqh, sc->sc_async_head); - splx(s); - break; - case UE_INTERRUPT: - pipe->methods = &ehci_device_intr_methods; - return (USBD_INVAL); - case UE_ISOCHRONOUS: - pipe->methods = &ehci_device_isoc_methods; - return (USBD_INVAL); - default: - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); - - bad1: - ehci_free_sqh(sc, sqh); - bad0: - return (USBD_NOMEM); -} - -/* - * Add an ED to the schedule. Called at splusb(). - */ -void -ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - SPLUSBCHECK; - - sqh->next = head->next; - sqh->qh.qh_link = head->qh.qh_link; - head->next = sqh; - head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH); - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - printf("ehci_add_qh:\n"); - ehci_dump_sqh(sqh); - } -#endif -} - -/* - * Remove an ED from the schedule. Called at splusb(). - */ -void -ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - ehci_soft_qh_t *p; - - SPLUSBCHECK; - /* XXX */ - for (p = head; p == NULL && p->next != sqh; p = p->next) - ; - if (p == NULL) - panic("ehci_rem_qh: ED not found\n"); - p->next = sqh->next; - p->qh.qh_link = sqh->qh.qh_link; - - ehci_sync_hc(sc); -} - -void -ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd) -{ - /* Halt while we are messing. */ - sqh->qh.qh_qtd.qtd_status |= htole32(EHCI_QTD_HALTED); - sqh->qh.qh_curqtd = 0; - sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr); - sqh->sqtd = sqtd; - /* Keep toggle, clear the rest, including length. */ - sqh->qh.qh_qtd.qtd_status &= htole32(EHCI_QTD_TOGGLE); -} - -/* - * Ensure that the HC has released all references to the QH. We do this - * by asking for a Async Advance Doorbell interrupt and then we wait for - * the interrupt. - * To make this easier we first obtain exclusive use of the doorbell. - */ -void -ehci_sync_hc(ehci_softc_t *sc) -{ - int s, error; - - if (sc->sc_dying) { - DPRINTFN(2,("ehci_sync_hc: dying\n")); - return; - } - DPRINTFN(2,("ehci_sync_hc: enter\n")); - - /* get doorbell */ - usb_lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE, NULL, curproc); - - s = splhardusb(); - /* ask for doorbell */ - EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) | EHCI_CMD_IAAD); - DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS))); - error = tsleep(&sc->sc_async_head, PZERO, "ehcidi", hz); /* bell wait */ - DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS))); - splx(s); - - /* release doorbell */ - usb_lockmgr(&sc->sc_doorbell_lock, LK_RELEASE, NULL, curproc); - -#ifdef DIAGNOSTIC - if (error) - printf("ehci_sync_hc: tsleep() = %d\n", error); -#endif - DPRINTFN(2,("ehci_sync_hc: exit\n")); -} - -/***********/ - -/* - * Data structures and routines to emulate the root hub. - */ -Static usb_device_descriptor_t ehci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_HSHUBSTT, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -Static usb_device_qualifier_t ehci_odevd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE_QUALIFIER, /* type */ - {0x00, 0x02}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - 1, /* # of configurations */ - 0 -}; - -Static usb_config_descriptor_t ehci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, - 1, - 0, - UC_SELF_POWERED, - 0 /* max power */ -}; - -Static usb_interface_descriptor_t ehci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_HSHUBSTT, - 0 -}; - -Static usb_endpoint_descriptor_t ehci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | EHCI_INTR_ENDPT, - UE_INTERRUPT, - {8, 0}, /* max packet */ - 255 -}; - -Static usb_hub_descriptor_t ehci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 0, - {0,0}, - 0, - 0, - {0}, -}; - -Static int -ehci_str(p, l, s) - usb_string_descriptor_t *p; - int l; - char *s; -{ - int i; - - if (l == 0) - return (0); - p->bLength = 2 * strlen(s) + 2; - if (l == 1) - return (1); - p->bDescriptorType = UDESC_STRING; - l -= 2; - for (i = 0; s[i] && l > 1; i++, l -= 2) - USETW2(p->bString[i], 0, s[i]); - return (2*i+2); -} - -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -Static usbd_status -ehci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); -} - -Static usbd_status -ehci_root_ctrl_start(usbd_xfer_handle xfer) -{ - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, i; - int s, len, value, index, l, totlen = 0; - usb_port_status_t ps; - usb_hub_descriptor_t hubd; - usbd_status err; - u_int32_t v; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - /* XXX panic */ - return (USBD_INVAL); -#endif - req = &xfer->request; - - DPRINTFN(4,("ehci_root_ctrl_control type=0x%02x request=%02x\n", - req->bmRequestType, req->bRequest)); - - len = UGETW(req->wLength); - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - if (len != 0) - buf = KERNADDR(&xfer->dmabuf); - -#define C(x,y) ((x) | ((y) << 8)) - switch(C(req->bRequest, req->bmRequestType)) { - case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): - case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): - case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* - * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops - * for the integrated root hub. - */ - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - DPRINTFN(8,("ehci_root_ctrl_control wValue=0x%04x\n", value)); - switch(value >> 8) { - case UDESC_DEVICE: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - USETW(ehci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &ehci_devd, l); - break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_DEVICE_QUALIFIER: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_odevd, l); - break; - /* - * We can't really operate at another speed, but the spec says - * we need this descriptor. - */ - case UDESC_OTHER_SPEED_CONFIGURATION: - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &ehci_confd, l); - ((usb_config_descriptor_t *)buf)->bDescriptorType = - value >> 8; - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ehci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 1: /* Vendor */ - totlen = ehci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = ehci_str(buf, len, "EHCI root hub"); - break; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED); - totlen = 2; - } - break; - case C(UR_GET_STATUS, UT_READ_INTERFACE): - case C(UR_GET_STATUS, UT_READ_ENDPOINT): - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - if (value >= USB_MAX_DEVICES) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - if (value != 0 && value != 1) { - err = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_DEVICE): - case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): - case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - break; - /* Hub requests */ - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): - DPRINTFN(8, ("ehci_root_ctrl_control: UR_CLEAR_PORT_FEATURE " - "port=%d feature=%d\n", - index, value)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - switch(value) { - case UHF_PORT_ENABLE: - EOWRITE4(sc, port, v &~ EHCI_PS_PE); - break; - case UHF_PORT_SUSPEND: - EOWRITE4(sc, port, v &~ EHCI_PS_SUSP); - break; - case UHF_PORT_POWER: - EOWRITE4(sc, port, v &~ EHCI_PS_PP); - break; - case UHF_PORT_TEST: - DPRINTFN(2,("ehci_root_ctrl_transfer: clear port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_transfer: clear port ind " - "%d\n", index)); - EOWRITE4(sc, port, v &~ EHCI_PS_PIC); - break; - case UHF_C_PORT_CONNECTION: - EOWRITE4(sc, port, v | EHCI_PS_CSC); - break; - case UHF_C_PORT_ENABLE: - EOWRITE4(sc, port, v | EHCI_PS_PEC); - break; - case UHF_C_PORT_SUSPEND: - /* how? */ - break; - case UHF_C_PORT_OVER_CURRENT: - EOWRITE4(sc, port, v | EHCI_PS_OCC); - break; - case UHF_C_PORT_RESET: - sc->sc_isreset = 0; - break; - default: - err = USBD_IOERROR; - goto ret; - } -#if 0 - switch(value) { - case UHF_C_PORT_CONNECTION: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_SUSPEND: - case UHF_C_PORT_OVER_CURRENT: - case UHF_C_PORT_RESET: - /* Enable RHSC interrupt if condition is cleared. */ - if ((OREAD4(sc, port) >> 16) == 0) - ehci_pcd_able(sc, 1); - break; - default: - break; - } -#endif - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if (value != 0) { - err = USBD_IOERROR; - goto ret; - } - hubd = ehci_hubd; - hubd.bNbrPorts = sc->sc_noport; - v = EOREAD4(sc, EHCI_HCSPARAMS); - USETW(hubd.wHubCharacteristics, - EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH | - EHCI_HCS_P_INCICATOR(EREAD4(sc, EHCI_HCSPARAMS)) - ? UHD_PORT_IND : 0); - hubd.bPwrOn2PwrGood = 200; /* XXX can't find out? */ - for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) - hubd.DeviceRemovable[i++] = 0; /* XXX can't find out? */ - hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i; - l = min(len, hubd.bDescLength); - totlen = l; - memcpy(buf, &hubd, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); /* ? XXX */ - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - DPRINTFN(8,("ehci_root_ctrl_transfer: get port status i=%d\n", - index)); - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - v = EOREAD4(sc, EHCI_PORTSC(index)); - DPRINTFN(8,("ehci_root_ctrl_transfer: port status=0x%04x\n", - v)); - i = UPS_HIGH_SPEED; - if (v & EHCI_PS_CS) i |= UPS_CURRENT_CONNECT_STATUS; - if (v & EHCI_PS_PE) i |= UPS_PORT_ENABLED; - if (v & EHCI_PS_SUSP) i |= UPS_SUSPEND; - if (v & EHCI_PS_OCA) i |= UPS_OVERCURRENT_INDICATOR; - if (v & EHCI_PS_PR) i |= UPS_RESET; - if (v & EHCI_PS_PP) i |= UPS_PORT_POWER; - USETW(ps.wPortStatus, i); - i = 0; - if (v & EHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS; - if (v & EHCI_PS_PEC) i |= UPS_C_PORT_ENABLED; - if (v & EHCI_PS_OCC) i |= UPS_C_OVERCURRENT_INDICATOR; - if (sc->sc_isreset) i |= UPS_C_PORT_RESET; - USETW(ps.wPortChange, i); - l = min(len, sizeof ps); - memcpy(buf, &ps, l); - totlen = l; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - err = USBD_IOERROR; - goto ret; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): - if (index < 1 || index > sc->sc_noport) { - err = USBD_IOERROR; - goto ret; - } - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - switch(value) { - case UHF_PORT_ENABLE: - EOWRITE4(sc, port, v | EHCI_PS_PE); - break; - case UHF_PORT_SUSPEND: - EOWRITE4(sc, port, v | EHCI_PS_SUSP); - break; - case UHF_PORT_RESET: - DPRINTFN(5,("ehci_root_ctrl_transfer: reset port %d\n", - index)); - if (EHCI_PS_IS_LOWSPEED(v)) { - /* Low speed device, give up ownership. */ - ehci_disown(sc, index, 1); - break; - } - /* Start reset sequence. */ - v &= ~ (EHCI_PS_PE | EHCI_PS_PR); - EOWRITE4(sc, port, v | EHCI_PS_PR); - /* Wait for reset to complete. */ - usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } - /* Terminate reset sequence. */ - EOWRITE4(sc, port, v); - /* Wait for HC to complete reset. */ - usb_delay_ms(&sc->sc_bus, EHCI_PORT_RESET_COMPLETE); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } - v = EOREAD4(sc, port); - DPRINTF(("ehci after reset, status=0x%08x\n", v)); - if (v & EHCI_PS_PR) { - printf("%s: port reset timeout\n", - USBDEVNAME(sc->sc_bus.bdev)); - return (USBD_TIMEOUT); - } - if (!(v & EHCI_PS_PE)) { - /* Not a high speed device, give up ownership.*/ - ehci_disown(sc, index, 0); - break; - } - sc->sc_isreset = 1; - DPRINTF(("ehci port %d reset, status = 0x%08x\n", - index, v)); - break; - case UHF_PORT_POWER: - DPRINTFN(2,("ehci_root_ctrl_transfer: set port power " - "%d\n", index)); - EOWRITE4(sc, port, v | EHCI_PS_PP); - break; - case UHF_PORT_TEST: - DPRINTFN(2,("ehci_root_ctrl_transfer: set port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_transfer: set port ind " - "%d\n", index)); - EOWRITE4(sc, port, v | EHCI_PS_PIC); - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER): - case C(UR_RESET_TT, UT_WRITE_CLASS_OTHER): - case C(UR_GET_TT_STATE, UT_READ_CLASS_OTHER): - case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER): - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - return (USBD_IN_PROGRESS); -} - -void -ehci_disown(ehci_softc_t *sc, int index, int lowspeed) -{ - int port; - u_int32_t v; - - DPRINTF(("ehci_disown: index=%d lowspeed=%d\n", index, lowspeed)); -#ifdef DIAGNOSTIC - if (sc->sc_npcomp != 0) { - int i = (index-1) / sc->sc_npcomp; - if (i >= sc->sc_ncomp) - printf("%s: strange port\n", - USBDEVNAME(sc->sc_bus.bdev)); - else - printf("%s: handing over %s speed device on " - "port %d to %s\n", - USBDEVNAME(sc->sc_bus.bdev), - lowspeed ? "low" : "full", - index, USBDEVNAME(sc->sc_comps[i]->bdev)); - } else { - printf("%s: npcomp == 0\n", USBDEVNAME(sc->sc_bus.bdev)); - } -#endif - port = EHCI_PORTSC(index); - v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR; - EOWRITE4(sc, port, v | EHCI_PS_PO); -} - -/* Abort a root control request. */ -Static void -ehci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -Static void -ehci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("ehci_root_ctrl_close\n")); - /* Nothing to do. */ -} - -void -ehci_root_intr_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -Static usbd_status -ehci_root_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); -} - -Static usbd_status -ehci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - if (sc->sc_dying) - return (USBD_IOERROR); - - sc->sc_intrxfer = xfer; - - return (USBD_IN_PROGRESS); -} - -/* Abort a root interrupt request. */ -Static void -ehci_root_intr_abort(usbd_xfer_handle xfer) -{ - int s; - - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ehci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - xfer->status = USBD_CANCELLED; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); -} - -/* Close the root pipe. */ -Static void -ehci_root_intr_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - DPRINTF(("ehci_root_intr_close\n")); - - sc->sc_intrxfer = NULL; -} - -void -ehci_root_ctrl_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -/************************/ - -ehci_soft_qh_t * -ehci_alloc_sqh(ehci_softc_t *sc) -{ - ehci_soft_qh_t *sqh; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeqhs == NULL) { - DPRINTFN(2, ("ehci_alloc_sqh: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, EHCI_SQH_SIZE * EHCI_SQH_CHUNK, - EHCI_PAGE_SIZE, &dma); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_alloc_sqh: usb_allocmem()=%d\n", err); -#endif - if (err) - return (NULL); - for(i = 0; i < EHCI_SQH_CHUNK; i++) { - offs = i * EHCI_SQH_SIZE; - sqh = (ehci_soft_qh_t *)((char *)KERNADDR(&dma) + offs); - sqh->physaddr = DMAADDR(&dma) + offs; - sqh->next = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; - } - } - sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->next; - memset(&sqh->qh, 0, sizeof(ehci_qh_t)); - sqh->next = NULL; - return (sqh); -} - -void -ehci_free_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh) -{ - sqh->next = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; -} - -ehci_soft_qtd_t * -ehci_alloc_sqtd(ehci_softc_t *sc) -{ - ehci_soft_qtd_t *sqtd; - usbd_status err; - int i, offs; - usb_dma_t dma; - int s; - - if (sc->sc_freeqtds == NULL) { - DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, EHCI_SQTD_SIZE*EHCI_SQTD_CHUNK, - EHCI_PAGE_SIZE, &dma); -#ifdef EHCI_DEBUG - if (err) - printf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err); -#endif - if (err) - return (NULL); - s = splusb(); - for(i = 0; i < EHCI_SQTD_CHUNK; i++) { - offs = i * EHCI_SQTD_SIZE; - sqtd = (ehci_soft_qtd_t *)((char *)KERNADDR(&dma)+offs); - sqtd->physaddr = DMAADDR(&dma) + offs; - sqtd->nextqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd; - } - splx(s); - } - - s = splusb(); - sqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd->nextqtd; - memset(&sqtd->qtd, 0, sizeof(ehci_qtd_t)); - sqtd->nextqtd = NULL; - sqtd->xfer = NULL; - splx(s); - - return (sqtd); -} - -void -ehci_free_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd) -{ - int s; - - s = splusb(); - sqtd->nextqtd = sc->sc_freeqtds; - sc->sc_freeqtds = sqtd; - splx(s); -} - -usbd_status -ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc, - int alen, int rd, usbd_xfer_handle xfer, - ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) -{ - ehci_soft_qtd_t *next, *cur; - ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys; - u_int32_t qtdstatus; - int len, curlen; - int i; - usb_dma_t *dma = &xfer->dmabuf; - - DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); - - len = alen; - dataphys = DMAADDR(dma); - dataphyslastpage = EHCI_PAGE(dataphys + len - 1); - qtdstatus = htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | - EHCI_QTD_SET_CERR(3) - /* IOC set below */ - /* BYTES set below */ - /* XXX Data toggle */ - ); - - cur = ehci_alloc_sqtd(sc); - *sp = cur; - if (cur == NULL) - goto nomem; - for (;;) { - dataphyspage = EHCI_PAGE(dataphys); - /* The EHCI hardware can handle at most 5 pages. */ - if (dataphyslastpage - dataphyspage < - EHCI_QTD_NBUFFERS * EHCI_PAGE_SIZE) { - /* we can handle it in this QTD */ - curlen = len; - } else { - /* must use multiple TDs, fill as much as possible. */ - curlen = EHCI_QTD_NBUFFERS * EHCI_PAGE_SIZE - - EHCI_PAGE_OFFSET(dataphys); -#ifdef DIAGNOSTIC - if (curlen > len) { - printf("ehci_alloc_sqtd_chain: curlen=0x%x " - "len=0x%x offs=0x%x\n", curlen, len, - EHCI_PAGE_OFFSET(dataphys)); - printf("lastpage=0x%x page=0x%x phys=0x%x\n", - dataphyslastpage, dataphyspage, - dataphys); - curlen = len; - } -#endif - - /* XXX true for EHCI? */ - /* the length must be a multiple of the max size */ - curlen -= curlen % UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); - DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, " - "curlen=%d\n", curlen)); -#ifdef DIAGNOSTIC - if (curlen == 0) - panic("ehci_alloc_std: curlen == 0\n"); -#endif - } - DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x " - "dataphyslastpage=0x%08x len=%d curlen=%d\n", - dataphys, dataphyslastpage, - len, curlen)); - len -= curlen; - - if (len != 0) { - next = ehci_alloc_sqtd(sc); - if (next == NULL) - goto nomem; - nextphys = next->physaddr; - } else { - next = NULL; - nextphys = EHCI_NULL; - } - - for (i = 0; i * EHCI_PAGE_SIZE < curlen; i++) { - ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE; - if (i != 0) /* use offset only in first buffer */ - a = EHCI_PAGE(a); - cur->qtd.qtd_buffer[i] = htole32(a); -#ifdef DIAGNOSTIC - if (i >= EHCI_QTD_NBUFFERS) { - printf("ehci_alloc_sqtd_chain: i=%d\n", i); - goto nomem; - } -#endif - } - cur->nextqtd = next; - cur->qtd.qtd_next = cur->qtd.qtd_altnext = htole32(nextphys); - cur->qtd.qtd_status = - qtdstatus | htole32(EHCI_QTD_SET_BYTES(curlen)); - cur->xfer = xfer; - cur->len = curlen; - DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n", - dataphys, dataphys + curlen)); - if (len == 0) - break; - DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); - dataphys += curlen; - cur = next; - } - cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC); - *ep = cur; - - DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n", - *sp, *ep)); - - return (USBD_NORMAL_COMPLETION); - - nomem: - /* XXX free chain */ - DPRINTFN(-1,("ehci_alloc_sqtd_chain: no memory\n")); - return (USBD_NOMEM); -} - -Static void -ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd, - ehci_soft_qtd_t *sqtdend) -{ - ehci_soft_qtd_t *p; - int i; - - DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p sqtdend=%p\n", - sqtd, sqtdend)); - - for (i = 0; sqtd != sqtdend; sqtd = p, i++) { - p = sqtd->nextqtd; - ehci_free_sqtd(sc, sqtd); - } -} - -/****************/ - -/* - * Close a reqular pipe. - * Assumes that there are no pending transactions. - */ -void -ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) -{ - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - ehci_soft_qh_t *sqh = epipe->sqh; - int s; - - s = splusb(); - ehci_rem_qh(sc, sqh, head); - splx(s); - ehci_free_sqh(sc, epipe->sqh); -} - -/* - * Abort a device request. - * If this routine is called at splusb() it guarantees that the request - * will be removed from the hardware scheduling and that the callback - * for it will be called with USBD_CANCELLED status. - * It's impossible to guarantee that the requested transfer will not - * have happened since the hardware runs concurrently. - * If the transaction has already happened we rely on the ordinary - * interrupt processing to process it. - * XXX This is most probably wrong. - */ -void -ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - ehci_soft_qh_t *sqh = epipe->sqh; - ehci_soft_qtd_t *sqtd; - ehci_physaddr_t cur; - u_int32_t qhstatus; - int s; - int hit; - - DPRINTF(("ehci_abort_xfer: xfer=%p pipe=%p\n", xfer, epipe)); - - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer); - usb_transfer_complete(xfer); - splx(s); - return; - } - - if (xfer->device->bus->intr_context || !curproc) - panic("ehci_abort_xfer: not in process context\n"); - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer); - qhstatus = sqh->qh.qh_qtd.qtd_status; - sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED); - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { - sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED); - if (sqtd == exfer->sqtdend) - break; - } - splx(s); - - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. Also make sure the soft interrupt routine - * has run. - */ - ehci_sync_hc(sc); - s = splusb(); - sc->sc_softwake = 1; - usb_schedsoftintr(&sc->sc_bus); - tsleep(&sc->sc_softwake, PZERO, "ehciab", 0); - splx(s); - - /* - * Step 3: Remove any vestiges of the xfer from the hardware. - * The complication here is that the hardware may have executed - * beyond the xfer we're trying to abort. So as we're scanning - * the TDs of this xfer we check if the hardware points to - * any of them. - */ - s = splusb(); /* XXX why? */ - cur = EHCI_LINK_ADDR(le32toh(sqh->qh.qh_curqtd)); - hit = 0; - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { - hit |= cur == sqtd->physaddr; - if (sqtd == exfer->sqtdend) - break; - } - sqtd = sqtd->nextqtd; - /* Zap curqtd register if hardware pointed inside the xfer. */ - if (hit && sqtd != NULL) { - DPRINTFN(1,("ehci_abort_xfer: cur=0x%08x\n", sqtd->physaddr)); - sqh->qh.qh_curqtd = htole32(sqtd->physaddr); /* unlink qTDs */ - sqh->qh.qh_qtd.qtd_status = qhstatus; - } else { - DPRINTFN(1,("ehci_abort_xfer: no hit\n")); - } - - /* - * Step 4: Execute callback. - */ -#ifdef DIAGNOSTIC - exfer->isdone = 1; -#endif - usb_transfer_complete(xfer); - - splx(s); -#undef exfer -} - -void -ehci_timeout(void *addr) -{ - struct ehci_xfer *exfer = addr; - struct ehci_pipe *epipe = (struct ehci_pipe *)exfer->xfer.pipe; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - - DPRINTF(("ehci_timeout: exfer=%p\n", exfer)); -#ifdef USB_DEBUG - if (ehcidebug > 1) - usbd_dump_pipe(exfer->xfer.pipe); -#endif - - if (sc->sc_dying) { - ehci_abort_xfer(&exfer->xfer, USBD_TIMEOUT); - return; - } - - /* Execute the abort in a process context. */ - usb_init_task(&exfer->abort_task, ehci_timeout_task, addr); - usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task); -} - -void -ehci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - int s; - - DPRINTF(("ehci_timeout_task: xfer=%p\n", xfer)); - - s = splusb(); - ehci_abort_xfer(xfer, USBD_TIMEOUT); - splx(s); -} - -/************************/ - -Static usbd_status -ehci_device_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); -} - -Static usbd_status -ehci_device_ctrl_start(usbd_xfer_handle xfer) -{ - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - /* XXX panic */ - printf("ehci_device_ctrl_transfer: not a request\n"); - return (USBD_INVAL); - } -#endif - - err = ehci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -void -ehci_device_ctrl_done(usbd_xfer_handle xfer) -{ - struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/ - - DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer)); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - panic("ehci_ctrl_done: not a request\n"); - } -#endif - - if (xfer->status != USBD_NOMEM) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL); - } - - DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen)); -} - -/* Abort a device control request. */ -Static void -ehci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ehci_device_ctrl_abort: xfer=%p\n", xfer)); - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -Static void -ehci_device_ctrl_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;*/ - - DPRINTF(("ehci_device_ctrl_close: pipe=%p\n", pipe)); - ehci_close_pipe(pipe, sc->sc_async_head); -} - -usbd_status -ehci_device_request(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - int addr = dev->address; - ehci_soft_qtd_t *setup, *stat, *next; - ehci_soft_qh_t *sqh; - int isread; - int len; - usbd_status err; - int s; - - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - DPRINTFN(3,("ehci_device_control type=0x%02x, request=0x%02x, " - "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", - req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), len, addr, - epipe->pipe.endpoint->edesc->bEndpointAddress)); - - setup = ehci_alloc_sqtd(sc); - if (setup == NULL) { - err = USBD_NOMEM; - goto bad1; - } - stat = ehci_alloc_sqtd(sc); - if (stat == NULL) { - err = USBD_NOMEM; - goto bad2; - } - - sqh = epipe->sqh; - epipe->u.ctl.length = len; - - /* XXX - * Since we're messing with the QH we must know the HC is in sync. - * This needs to go away since it slows down control transfers. - * Removing it entails: - * - fill the QH only once with addr & wMaxPacketSize - * - put the correct data toggles in the qtds and set DTC - */ - /* ehci_sync_hc(sc); */ - /* Update device address and length since they may have changed. */ - /* XXX This only needs to be done once, but it's too early in open. */ - /* XXXX Should not touch ED here! */ - sqh->qh.qh_endp = - (sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QG_MPLMASK))) | - htole32( - EHCI_QH_SET_ADDR(addr) | - /* EHCI_QH_DTC | */ - EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)) - ); - /* Clear toggle */ - sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE); - - /* Set up data transaction */ - if (len != 0) { - ehci_soft_qtd_t *end; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - &next, &end); - if (err) - goto bad3; - end->nextqtd = stat; - end->qtd.qtd_next = - end->qtd.qtd_altnext = htole32(stat->physaddr); - /* Start toggle at 1. */ - /*next->qtd.td_flags |= htole32(EHCI_QTD_TOGGLE);*/ - } else { - next = stat; - } - - memcpy(KERNADDR(&epipe->u.ctl.reqdma), req, sizeof *req); - - setup->qtd.qtd_status = htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_SET_BYTES(sizeof *req) - ); - setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma)); - setup->nextqtd = next; - setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr); - setup->xfer = xfer; - setup->len = sizeof *req; - - stat->qtd.qtd_status = htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_IOC - ); - stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */ - stat->nextqtd = NULL; - stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL; - stat->xfer = xfer; - stat->len = 0; - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_request:\n")); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(setup); - } -#endif - - exfer->sqtdstart = setup; - exfer->sqtdend = stat; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - printf("ehci_device_request: not done, exfer=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - /* Insert qTD in QH list. */ - s = splusb(); - ehci_set_qh_qtd(sqh, setup); - if (xfer->timeout && !sc->sc_bus.use_polling) { - usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - splx(s); - -#ifdef EHCI_DEBUG - if (ehcidebug > 10) { - DPRINTF(("ehci_device_request: status=%x\n", - EOREAD4(sc, EHCI_USBSTS))); - delay(10000); - ehci_dump_regs(sc); - ehci_dump_sqh(sc->sc_async_head); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(setup); - } -#endif - - return (USBD_NORMAL_COMPLETION); - - bad3: - ehci_free_sqtd(sc, stat); - bad2: - ehci_free_sqtd(sc, setup); - bad1: - DPRINTFN(-1,("ehci_device_request: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); -#undef exfer -} - -/************************/ - -Static usbd_status -ehci_device_bulk_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Insert last in queue. */ - err = usb_insert_transfer(xfer); - if (err) - return (err); - - /* Pipe isn't running, start first */ - return (ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -ehci_device_bulk_start(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = epipe->pipe.device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - ehci_soft_qtd_t *data, *dataend; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - int s; - - DPRINTFN(2, ("ehci_device_bulk_transfer: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_bulk_transfer: a request\n"); -#endif - - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = epipe->sqh; - - epipe->u.bulk.length = len; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data, - &dataend); - if (err) { - DPRINTFN(-1,("ehci_device_bulk_transfer: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_bulk_transfer: data(1)\n")); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - printf("ehci_device_bulk_transfer: not done, ex=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - s = splusb(); - ehci_set_qh_qtd(sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ehci_timeout, xfer); - } - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - splx(s); - -#ifdef EHCI_DEBUG - if (ehcidebug > 10) { - DPRINTF(("ehci_device_bulk_transfer: data(2)\n")); - delay(10000); - DPRINTF(("ehci_device_bulk_transfer: data(3)\n")); - ehci_dump_regs(sc); -#if 0 - printf("async_head:\n"); - ehci_dump_sqh(sc->sc_async_head); -#endif - printf("sqh:\n"); - ehci_dump_sqh(sqh); - ehci_dump_sqtds(data); - } -#endif - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -#undef exfer -} - -Static void -ehci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ehci_device_bulk_abort: xfer=%p\n", xfer)); - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * Close a device bulk pipe. - */ -Static void -ehci_device_bulk_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - - DPRINTF(("ehci_device_bulk_close: pipe=%p\n", pipe)); - ehci_close_pipe(pipe, sc->sc_async_head); -} - -void -ehci_device_bulk_done(usbd_xfer_handle xfer) -{ - struct ehci_xfer *ex = EXFER(xfer); - ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus; - /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/ - - DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - if (xfer->status != USBD_NOMEM) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, ex->sqtdstart, 0); - } - - DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen)); -} - -/************************/ - -Static usbd_status ehci_device_intr_transfer(usbd_xfer_handle xfer) { return USBD_IOERROR; } -Static usbd_status ehci_device_intr_start(usbd_xfer_handle xfer) { return USBD_IOERROR; } -Static void ehci_device_intr_abort(usbd_xfer_handle xfer) { } -Static void ehci_device_intr_close(usbd_pipe_handle pipe) { } -Static void ehci_device_intr_done(usbd_xfer_handle xfer) { } - -/************************/ - -Static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle xfer) { return USBD_IOERROR; } -Static usbd_status ehci_device_isoc_start(usbd_xfer_handle xfer) { return USBD_IOERROR; } -Static void ehci_device_isoc_abort(usbd_xfer_handle xfer) { } -Static void ehci_device_isoc_close(usbd_pipe_handle pipe) { } -Static void ehci_device_isoc_done(usbd_xfer_handle xfer) { } diff --git a/sys/dev/usb/ehcireg.h b/sys/dev/usb/ehcireg.h deleted file mode 100644 index 341644210b1..00000000000 --- a/sys/dev/usb/ehcireg.h +++ /dev/null @@ -1,288 +0,0 @@ -/* $OpenBSD: ehcireg.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ehcireg.h,v 1.13 2001/11/23 01:16:27 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * The EHCI 0.96 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r096.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/data/usb_20.zip - */ - -#ifndef _DEV_PCI_EHCIREG_H_ -#define _DEV_PCI_EHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_CBMEM 0x10 /* configuration base MEM */ - -#define PCI_INTERFACE_EHCI 0x20 - -#define PCI_USBREV 0x60 /* RO USB protocol revision */ -#define PCI_USBREV_MASK 0xff -#define PCI_USBREV_PRE_1_0 0x00 -#define PCI_USBREV_1_0 0x10 -#define PCI_USBREV_1_1 0x11 -#define PCI_USBREV_2_0 0x20 - -#define PCI_EHCI_FLADJ 0x61 /*RW Frame len adj, SOF=59488+6*fladj */ - -#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */ - -/* Regs ar EECP + offset */ -#define PCI_EHCI_USBLEGSUP 0x00 -#define PCI_EHCI_USBLEGCTLSTS 0x04 - -/*** EHCI capability registers ***/ - -#define EHCI_CAPLENGTH 0x00 /*RO Capability register length field */ -/* reserved 0x01 */ -#define EHCI_HCIVERSION 0x02 /* RO Interface version number */ - -#define EHCI_HCSPARAMS 0x04 /* RO Structural parameters */ -#define EHCI_HCS_DEBUGPORT(x) (((x) >> 20) & 0xf) -#define EHCI_HCS_P_INCICATOR(x) ((x) & 0x10000) -#define EHCI_HCS_N_CC(x) (((x) >> 12) & 0xf) /* # of companion ctlrs */ -#define EHCI_HCS_N_PCC(x) (((x) >> 8) & 0xf) /* # of ports per comp. */ -#define EHCI_HCS_PPC(x) ((x) & 0x10) /* port power control */ -#define EHCI_HCS_N_PORTS(x) ((x) & 0xf) /* # of ports */ - -#define EHCI_HCCPARAMS 0x08 /* RO Capability parameters */ -#define EHCI_HCC_EECP(x) (((x) >> 8) & 0xff) /* extended ports caps */ -#define EHCI_HCC_IST(x) (((x) >> 4) & 0xf) /* isoc sched threshold */ -#define EHCI_HCC_ASPC(x) ((x) & 0x4) /* async sched park cap */ -#define EHCI_HCC_PFLF(x) ((x) & 0x2) /* prog frame list flag */ -#define EHCI_HCC_64BIT(x) ((x) & 0x1) /* 64 bit address cap */ - -#define EHCI_HCSP_PORTROUTE 0x0c /*RO Companion port route description */ - -/* EHCI operational registers. Offset given by EHCI_CAPLENGTH register */ -#define EHCI_USBCMD 0x00 /* RO, RW, WO Command register */ -#define EHCI_CMD_ITC_M 0x00ff0000 /* RW interrupt threshold ctrl */ -#define EHCI_CMD_ITC_1 0x00010000 -#define EHCI_CMD_ITC_2 0x00020000 -#define EHCI_CMD_ITC_4 0x00040000 -#define EHCI_CMD_ITC_8 0x00080000 -#define EHCI_CMD_ITC_16 0x00100000 -#define EHCI_CMD_ITC_32 0x00200000 -#define EHCI_CMD_ITC_64 0x00400000 -#define EHCI_CMD_ASPME 0x00000800 /* RW/RO async park enable */ -#define EHCI_CMD_ASPMC 0x00000300 /* RW/RO async park count */ -#define EHCI_CMD_LHCR 0x00000080 /* RW light host ctrl reset */ -#define EHCI_CMD_IAAD 0x00000040 /* RW intr on async adv door bell */ -#define EHCI_CMD_ASE 0x00000020 /* RW async sched enable */ -#define EHCI_CMD_PSE 0x00000010 /* RW periodic sched enable */ -#define EHCI_CMD_FLS_M 0x0000000c /* RW/RO frame list size */ -#define EHCI_CMD_FLS(x) (((x) >> 2) & 3) /* RW/RO frame list size */ -#define EHCI_CMD_HCRESET 0x00000002 /* RW reset */ -#define EHCI_CMD_RS 0x00000001 /* RW run/stop */ - -#define EHCI_USBSTS 0x04 /* RO, RW, RWC Status register */ -#define EHCI_STS_ASS 0x00008000 /* RO async sched status */ -#define EHCI_STS_PSS 0x00004000 /* RO periodic sched status */ -#define EHCI_STS_REC 0x00002000 /* RO reclamation */ -#define EHCI_STS_HCH 0x00001000 /* RO host controller halted */ -#define EHCI_STS_IAA 0x00000020 /* RWC interrupt on async adv */ -#define EHCI_STS_HSE 0x00000010 /* RWC host system error */ -#define EHCI_STS_FLR 0x00000008 /* RWC frame list rollover */ -#define EHCI_STS_PCD 0x00000004 /* RWC port change detect */ -#define EHCI_STS_ERRINT 0x00000002 /* RWC error interrupt */ -#define EHCI_STS_INT 0x00000001 /* RWC interrupt */ -#define EHCI_STS_INTRS(x) ((x) & 0x3f) - -#define EHCI_NORMAL_INTRS (EHCI_STS_IAA | EHCI_STS_HSE | EHCI_STS_PCD | EHCI_STS_ERRINT | EHCI_STS_INT) - -#define EHCI_USBINTR 0x08 /* RW Interrupt register */ -#define EHCI_INTR_IAAE 0x00000020 /* interrupt on async advance ena */ -#define EHCI_INTR_HSEE 0x00000010 /* host system error ena */ -#define EHCI_INTR_FLRE 0x00000008 /* frame list rollover ena */ -#define EHCI_INTR_PCIE 0x00000004 /* port change ena */ -#define EHCI_INTR_UEIE 0x00000002 /* USB error intr ena */ -#define EHCI_INTR_UIE 0x00000001 /* USB intr ena */ - -#define EHCI_FRINDEX 0x0c /* RW Frame Index register */ - -#define EHCI_CTRLDSSEGMENT 0x10 /* RW Control Data Structure Segment */ - -#define EHCI_PERIODICLISTBASE 0x14 /* RW Periodic List Base */ -#define EHCI_ASYNCLISTADDR 0x18 /* RW Async List Base */ - -#define EHCI_CONFIGFLAG 0x40 /* RW Configure Flag register */ -#define EHCI_CONF_CF 0x00000001 /* RW configure flag */ - -#define EHCI_PORTSC(n) (0x40+4*(n)) /* RO, RW, RWC Port Status reg */ -#define EHCI_PS_WKOC_E 0x00400000 /* RW wake on over current ena */ -#define EHCI_PS_WKDSCNNT_E 0x00200000 /* RW wake on disconnect ena */ -#define EHCI_PS_WKCNNT_E 0x00100000 /* RW wake on connect ena */ -#define EHCI_PS_PTC 0x000f0000 /* RW port test control */ -#define EHCI_PS_PIC 0x0000c000 /* RW port indicator control */ -#define EHCI_PS_PO 0x00002000 /* RW port owner */ -#define EHCI_PS_PP 0x00001000 /* RW,RO port power */ -#define EHCI_PS_LS 0x00000c00 /* RO line status */ -#define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == 0x00000400) -#define EHCI_PS_PR 0x00000100 /* RW port reset */ -#define EHCI_PS_SUSP 0x00000080 /* RW suspend */ -#define EHCI_PS_FPR 0x00000040 /* RW force port resume */ -#define EHCI_PS_OCC 0x00000020 /* RWC over current change */ -#define EHCI_PS_OCA 0x00000010 /* RO over current active */ -#define EHCI_PS_PEC 0x00000008 /* RWC port enable change */ -#define EHCI_PS_PE 0x00000004 /* RW port enable */ -#define EHCI_PS_CSC 0x00000002 /* RWC connect status change */ -#define EHCI_PS_CS 0x00000001 /* RO connect status */ -#define EHCI_PS_CLEAR (EHCI_PS_OCC|EHCI_PS_PEC|EHCI_PS_CSC) - -#define EHCI_PORT_RESET_COMPLETE 2 /* ms */ - -#define EHCI_FLALIGN_ALIGN 0x1000 - -/* No data structure may cross a page boundary. */ -#define EHCI_PAGE_SIZE 0x1000 -#define EHCI_PAGE(x) ((x) &~ 0xfff) -#define EHCI_PAGE_OFFSET(x) ((x) & 0xfff) - -typedef u_int32_t ehci_link_t; -#define EHCI_LINK_TERMINATE 0x00000001 -#define EHCI_LINK_TYPE(x) ((x) & 0x00000006) -#define EHCI_LINK_ITD 0x0 -#define EHCI_LINK_QH 0x2 -#define EHCI_LINK_SITD 0x4 -#define EHCI_LINK_FSTN 0x6 -#define EHCI_LINK_ADDR(x) ((x) &~ 0x1f) - -typedef u_int32_t ehci_physaddr_t; - -/* Isochronous Transfer Descriptor */ -typedef struct { - ehci_link_t itd_next; - /* XXX many more */ -} ehci_itd_t; -#define EHCI_ITD_ALIGN 32 - -/* Split Transaction Isochronous Transfer Descriptor */ -typedef struct { - ehci_link_t sitd_next; - /* XXX many more */ -} ehci_sitd_t; -#define EHCI_SITD_ALIGN 32 - -/* Queue Element Transfer Descriptor */ -#define EHCI_QTD_NBUFFERS 5 -typedef struct { - ehci_link_t qtd_next; - ehci_link_t qtd_altnext; - u_int32_t qtd_status; -#define EHCI_QTD_GET_STATUS(x) (((x) >> 0) & 0xff) -#define EHCI_QTD_ACTIVE 0x80 -#define EHCI_QTD_HALTED 0x40 -#define EHCI_QTD_BUFERR 0x20 -#define EHCI_QTD_BABBLE 0x10 -#define EHCI_QTD_XACTERR 0x08 -#define EHCI_QTD_MISSEDMICRO 0x04 -#define EHCI_QTD_SPLITXSTATE 0x02 -#define EHCI_QTD_PINGSTATE 0x01 -#define EHCI_QTD_STATERRS 0x7c -#define EHCI_QTD_GET_PID(x) (((x) >> 8) & 0x3) -#define EHCI_QTD_SET_PID(x) ((x) << 8) -#define EHCI_QTD_PID_OUT 0x0 -#define EHCI_QTD_PID_IN 0x1 -#define EHCI_QTD_PID_SETUP 0x2 -#define EHCI_QTD_GET_CERR(x) (((x) >> 10) & 0x3) -#define EHCI_QTD_SET_CERR(x) ((x) << 10) -#define EHCI_QTD_GET_C_PAGE(x) (((x) >> 12) & 0x7) -#define EHCI_QTD_SET_C_PAGE(x) ((x) << 12) -#define EHCI_QTD_GET_IOC(x) (((x) >> 15) & 0x1) -#define EHCI_QTD_IOC 0x00008000 -#define EHCI_QTD_GET_BYTES(x) (((x) >> 16) & 0x7fff) -#define EHCI_QTD_SET_BYTES(x) ((x) << 16) -#define EHCI_QTD_GET_TOGGLE(x) (((x) >> 31) & 0x1) -#define EHCI_QTD_TOGGLE 0x80000000 - ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS]; -} ehci_qtd_t; -#define EHCI_QTD_ALIGN 32 - -/* Queue Head */ -typedef struct { - ehci_link_t qh_link; - u_int32_t qh_endp; -#define EHCI_QH_GET_ADDR(x) (((x) >> 0) & 0x7f) /* endpoint addr */ -#define EHCI_QH_SET_ADDR(x) (x) -#define EHCI_QH_ADDRMASK 0x0000007f -#define EHCI_QH_GET_INACT(x) (((x) >> 7) & 0x01) /* inactivate on next */ -#define EHCI_QH_INACT 0x00000080 -#define EHCI_QH_GET_ENDPT(x) (((x) >> 8) & 0x0f) /* endpoint no */ -#define EHCI_QH_SET_ENDPT(x) ((x) << 8) -#define EHCI_QH_GET_EPS(x) (((x) >> 12) & 0x03) /* endpoint speed */ -#define EHCI_QH_SET_EPS(x) ((x) << 12) -#define EHCI_QH_SPEED_FULL 0x0 -#define EHCI_QH_SPEED_LOW 0x1 -#define EHCI_QH_SPEED_HIGH 0x2 -#define EHCI_QH_GET_DTC(x) (((x) >> 14) & 0x01) /* data toggle control */ -#define EHCI_QH_DTC 0x00004000 -#define EHCI_QH_GET_HRECL(x) (((x) >> 15) & 0x01) /* head of reclamation */ -#define EHCI_QH_HRECL 0x00008000 -#define EHCI_QH_GET_MPL(x) (((x) >> 16) & 0x7ff) /* max packet len */ -#define EHCI_QH_SET_MPL(x) ((x) << 16) -#define EHCI_QG_MPLMASK 0x07ff0000 -#define EHCI_QH_GET_CTL(x) (((x) >> 26) & 0x01) /* control endpoint */ -#define EHCI_QH_CTL 0x08000000 -#define EHCI_QH_GET_NRL(x) (((x) >> 28) & 0x0f) /* NAK reload */ -#define EHCI_QH_SET_NRL(x) ((x) << 28) - u_int32_t qh_endphub; -#define EHCI_QH_GET_SMASK(x) (((x) >> 0) & 0xff) /* intr sched mask */ -#define EHCI_QH_SET_SMASK(x) ((x) << 0) -#define EHCI_QH_GET_CMASK(x) (((x) >> 8) & 0xff) /* split completion mask */ -#define EHCI_QH_SET_CMASK(x) ((x) << 8) -#define EHCI_QH_GET_HUBA(x) (((x) >> 16) & 0x7f) /* hub address */ -#define EHCI_QH_SET_HUBA(x) ((x) << 16) -#define EHCI_QH_GET_PORT(x) (((x) >> 23) & 0x7f) /* hub port */ -#define EHCI_QH_SET_PORT(x) ((x) << 23) -#define EHCI_QH_GET_MULT(x) (((x) >> 30) & 0x03) /* pipe multiplier */ -#define EHCI_QH_SET_MULT(x) ((x) << 30) - ehci_link_t qh_curqtd; - ehci_qtd_t qh_qtd; -} ehci_qh_t; -#define EHCI_QH_ALIGN 32 - -/* Periodic Frame Span Traversal Node */ -typedef struct { - ehci_link_t fstn_link; - ehci_link_t fstn_back; -} ehci_fstn_t; -#define EHCI_FSTN_ALIGN 32 - -#endif /* _DEV_PCI_EHCIREG_H_ */ diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h deleted file mode 100644 index 1aa7c866580..00000000000 --- a/sys/dev/usb/ehcivar.h +++ /dev/null @@ -1,138 +0,0 @@ -/* $OpenBSD: ehcivar.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ehcivar.h,v 1.12 2001/12/31 12:16:57 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -typedef struct ehci_soft_qtd { - ehci_qtd_t qtd; - struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */ - ehci_physaddr_t physaddr; - usbd_xfer_handle xfer; - LIST_ENTRY(ehci_soft_qtd) hnext; - u_int16_t len; -} ehci_soft_qtd_t; -#define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / EHCI_QTD_ALIGN * EHCI_QTD_ALIGN) -#define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE) - -typedef struct ehci_soft_qh { - ehci_qh_t qh; - struct ehci_soft_qh *next; - struct ehci_soft_qtd *sqtd; - ehci_physaddr_t physaddr; -} ehci_soft_qh_t; -#define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN) -#define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE) - -struct ehci_xfer { - struct usbd_xfer xfer; - struct usb_task abort_task; - LIST_ENTRY(ehci_xfer) inext; /* list of active xfers */ - ehci_soft_qtd_t *sqtdstart; - ehci_soft_qtd_t *sqtdend; -#ifdef DIAGNOSTIC - int isdone; -#endif -}; -#define EXFER(xfer) ((struct ehci_xfer *)(xfer)) - - -#define EHCI_HASH_SIZE 128 -#define EHCI_COMPANION_MAX 8 - -typedef struct ehci_softc { - struct usbd_bus sc_bus; /* base device */ - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - u_int sc_offs; /* offset to operational regs */ - - char sc_vendor[16]; /* vendor string for root hub */ - int sc_id_vendor; /* vendor ID for root hub */ - - void *sc_powerhook; /* cookie from power hook */ - void *sc_shutdownhook; /* cookie from shutdown hook */ - - u_int sc_ncomp; - u_int sc_npcomp; - struct usbd_bus *sc_comps[EHCI_COMPANION_MAX]; - - usb_dma_t sc_fldma; - u_int sc_flsize; - - LIST_HEAD(, ehci_xfer) sc_intrhead; - - ehci_soft_qh_t *sc_freeqhs; - ehci_soft_qtd_t *sc_freeqtds; - - int sc_noport; - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - usbd_xfer_handle sc_intrxfer; - char sc_isreset; - char sc_softwake; - - u_int32_t sc_eintrs; - ehci_soft_qh_t *sc_async_head; - - SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - struct lock sc_doorbell_lock; - - usb_callout_t sc_tmo_pcd; - - device_ptr_t sc_child; /* /dev/usb# device */ - - char sc_dying; -} ehci_softc_t; - -#define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a)) -#define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a)) -#define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a)) -#define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x)) -#define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x)) -#define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x)) -#define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) -#define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) -#define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) -#define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) - -usbd_status ehci_init(ehci_softc_t *); -int ehci_intr(void *); -int ehci_detach(ehci_softc_t *, int); -int ehci_activate(device_ptr_t, enum devact); diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 77fa22bf4ab..2d6d6b5ce34 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,5 +1,5 @@ -# $OpenBSD: files.usb,v 1.22 2002/05/07 18:08:04 nate Exp $ -# $NetBSD: files.usb,v 1.38 2002/01/02 03:21:36 augustss Exp $ +# $OpenBSD: files.usb,v 1.23 2002/05/07 18:29:18 nate Exp $ +# $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. # Included by ports that need it. Ports that use it must provide @@ -7,7 +7,8 @@ device usb { } attach usb at usbus -file dev/usb/usb.c usb needs-flag +file dev/usb/hid.c usb +file dev/usb/usb.c usb needs-flag file dev/usb/usbdi.c usb file dev/usb/usbdi_util.c usb file dev/usb/usb_mem.c usb @@ -34,91 +35,62 @@ device uaudio: audio, auconv, mulaw attach uaudio at uhub file dev/usb/uaudio.c uaudio -# MIDI devices -device umidi: midibus -attach umidi at uhub -file dev/usb/umidi.c umidi -file dev/usb/umidi_quirks.c umidi - # Modem and com serial port device ucom attach ucom at ucombus -file dev/usb/ucom.c ucom | ucombus needs-flag - +file dev/usb/ucom.c ucom | ucombus needs-flag # Generic devices device ugen attach ugen at uhub -file dev/usb/ugen.c ugen needs-flag - - -# HID -# HID "bus" -define uhidbus {[ reportid = -1 ]} - -# HID processing -define hid -file dev/usb/hid.c hid - -# HID root device for multiple report IDs -device uhidev: hid, uhidbus -attach uhidev at uhub -file dev/usb/uhidev.c uhidev +file dev/usb/ugen.c ugen needs-flag # Generic HID devices -device uhid: hid -attach uhid at uhidbus -file dev/usb/uhid.c uhid needs-flag +device uhid +attach uhid at uhub +file dev/usb/uhid.c uhid needs-flag # Keyboards -device ukbd: hid, wskbddev -attach ukbd at uhidbus -file dev/usb/ukbd.c ukbd needs-flag -file dev/usb/ukbdmap.c ukbd - -# Mice -device ums: hid, wsmousedev -attach ums at uhidbus -file dev/usb/ums.c ums - +device ukbd: wskbddev +attach ukbd at uhub +file dev/usb/ukbd.c ukbd needs-flag +file dev/usb/ukbdmap.c ukbd # Printers device ulpt attach ulpt at uhub -file dev/usb/ulpt.c ulpt needs-flag - +file dev/usb/ulpt.c ulpt needs-flag # Mass storage -device umass: scsi, atapi, ata +device umass: scsi, atapi attach umass at uhub file dev/usb/umass.c umass -#file dev/usb/umass_isdata.c umass & wd -file dev/usb/umass_quirks.c umass -file dev/usb/umass_scsi.c umass & (scsibus | atapiscsi) +# Modems +device umodem: ucombus +attach umodem at uhub +file dev/usb/umodem.c umodem + +# Mice +device ums: wsmousedev +attach ums at uhub +file dev/usb/ums.c ums -# Misc # Diamond Multimedia Rio 500 device urio attach urio at uhub -file dev/usb/urio.c urio needs-flag +file dev/usb/urio.c urio needs-flag # Handspring Visor device uvisor: ucombus attach uvisor at uhub file dev/usb/uvisor.c uvisor -# YAP phone firmware loader +# YAP firmware loader device uyap: ezload attach uyap at uhub file dev/usb/uyap.c uyap -# D-Link DSB-R100 FM radio -device udsbr: radio -attach udsbr at uhub -file dev/usb/udsbr.c udsbr - - # Ethernet adapters # ADMtek AN986 Pegasus device aue: ether, ifnet, mii, ifmedia @@ -136,48 +108,25 @@ attach kue at uhub file dev/usb/if_kue.c kue # Prolific PL2302 host-host -device upl: ether, ifnet, ifmedia +device upl: ifnet attach upl at uhub file dev/usb/if_upl.c upl -# Realtek RTL8150L(M) -device url: ether, ifnet, mii -attach url at uhub -file dev/usb/if_url.c url - - # Serial drivers -# Modems -device umodem: ucombus -attach umodem at uhub -file dev/usb/umodem.c umodem - # FTDI serial driver device uftdi: ucombus attach uftdi at uhub file dev/usb/uftdi.c uftdi # Prolific PL2303 serial driver -device uplcom: ucombus -attach uplcom at uhub -file dev/usb/uplcom.c uplcom - -# MCT USB-232 serial driver -device umct: ucombus -attach umct at uhub -file dev/usb/umct.c umct - -# SUNTAC Slipper U VS-10U driver -device uvscom: ucombus -attach uvscom at uhub -file dev/usb/uvscom.c uvscom - +device uplcom: ucombus +attach uplcom at uhub +file dev/usb/uplcom.c uplcom # Scanners -# Generic scanner support device uscanner attach uscanner at uhub -file dev/usb/uscanner.c uscanner needs-flag +file dev/usb/uscanner.c uscanner needs-flag # Avision SCSI over USB, HP5300 device usscanner: scsi diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c index 2a8a91a35cb..d14721fe107 100644 --- a/sys/dev/usb/hid.c +++ b/sys/dev/usb/hid.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hid.c,v 1.10 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: hid.c,v 1.22 2002/01/12 17:11:03 tsutsui Exp $ */ +/* $OpenBSD: hid.c,v 1.11 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: hid.c,v 1.16 2000/06/01 14:28:57 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/hid.c,v 1.11 1999/11/17 22:33:39 n_hibma Exp $ */ /* @@ -51,10 +51,10 @@ #include <dev/usb/hid.h> -#ifdef UHIDEV_DEBUG -#define DPRINTF(x) if (uhidevdebug) logprintf x -#define DPRINTFN(n,x) if (uhidevdebug>(n)) logprintf x -extern int uhidevdebug; +#ifdef UHID_DEBUG +#define DPRINTF(x) if (usbdebug) logprintf x +#define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x +extern int usbdebug; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -62,7 +62,7 @@ extern int uhidevdebug; Static void hid_clear_local(struct hid_item *); -#define MAXUSAGE 256 +#define MAXUSAGE 100 struct hid_data { u_char *start; u_char *end; @@ -73,14 +73,13 @@ struct hid_data { int minset; int multi; int multimax; - enum hid_kind kind; + int kindset; }; Static void hid_clear_local(struct hid_item *c) { - DPRINTFN(5,("hid_clear_local\n")); c->usage = 0; c->usage_minimum = 0; c->usage_maximum = 0; @@ -94,18 +93,15 @@ hid_clear_local(struct hid_item *c) } struct hid_data * -hid_start_parse(void *d, int len, enum hid_kind kind) +hid_start_parse(void *d, int len, int kindset) { struct hid_data *s; s = malloc(sizeof *s, M_TEMP, M_WAITOK); - if (s == NULL) - panic("hid_start_parse"); memset(s, 0, sizeof *s); - s->start = s->p = d; s->end = (char *)d + len; - s->kind = kind; + s->kindset = kindset; return (s); } @@ -132,19 +128,15 @@ hid_get_item(struct hid_data *s, struct hid_item *h) u_char *p; struct hid_item *hi; int i; - enum hid_kind retkind; top: - DPRINTFN(5,("hid_get_item: multi=%d multimax=%d\n", - s->multi, s->multimax)); if (s->multimax != 0) { if (s->multi < s->multimax) { c->usage = s->usages[min(s->multi, s->nu-1)]; s->multi++; *h = *c; c->loc.pos += c->loc.size; - h->next = NULL; - DPRINTFN(5,("return multi\n")); + h->next = 0; return (1); } else { c->loc.count = s->multimax; @@ -182,12 +174,12 @@ hid_get_item(struct hid_data *s, struct hid_item *h) dval = 0; break; case 1: - dval = /*(int8_t)*/ *data++; + dval = (int8_t)*data++; break; case 2: dval = *data++; dval |= *data++ << 8; - dval = /*(int16_t)*/ dval; + dval = (int16_t)dval; break; case 4: dval = *data++; @@ -200,22 +192,15 @@ hid_get_item(struct hid_data *s, struct hid_item *h) continue; } - DPRINTFN(5,("hid_get_item: bType=%d bTag=%d dval=%d\n", - bType, bTag, dval)); switch (bType) { case 0: /* Main */ switch (bTag) { case 8: /* Input */ - retkind = hid_input; - ret: - if (s->kind != retkind) { - s->minset = 0; - s->nu = 0; - hid_clear_local(c); + if (!(s->kindset & (1 << hid_input))) continue; - } - c->kind = retkind; + c->kind = hid_input; c->flags = dval; + ret: if (c->flags & HIO_VARIABLE) { s->multimax = c->loc.count; s->multi = 0; @@ -232,18 +217,19 @@ hid_get_item(struct hid_data *s, struct hid_item *h) } goto top; } else { - c->usage = c->_usage_page; /* XXX */ *h = *c; - h->next = NULL; + h->next = 0; c->loc.pos += - c->loc.size * c->loc.count; - s->minset = 0; - s->nu = 0; + c->loc.size * c->loc.count; hid_clear_local(c); + s->minset = 0; return (1); } case 9: /* Output */ - retkind = hid_output; + if (!(s->kindset & (1 << hid_output))) + continue; + c->kind = hid_output; + c->flags = dval; goto ret; case 10: /* Collection */ c->kind = hid_collection; @@ -254,12 +240,16 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->nu = 0; return (1); case 11: /* Feature */ - retkind = hid_feature; + if (!(s->kindset & (1 << hid_feature))) + continue; + c->kind = hid_feature; + c->flags = dval; goto ret; case 12: /* End collection */ c->kind = hid_endcollection; c->collevel--; *h = *c; + hid_clear_local(c); s->nu = 0; return (1); default: @@ -295,7 +285,6 @@ hid_get_item(struct hid_data *s, struct hid_item *h) break; case 8: c->report_ID = dval; - c->loc.pos = 0; break; case 9: c->loc.count = dval; @@ -378,51 +367,35 @@ hid_get_item(struct hid_data *s, struct hid_item *h) } int -hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t id) +hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t *idp) { struct hid_data *d; struct hid_item h; - int lo, hi; + int size, id; - h.report_ID = 0; - lo = hi = -1; - DPRINTFN(2,("hid_report_size: kind=%d id=%d\n", k, id)); - for (d = hid_start_parse(buf, len, k); hid_get_item(d, &h); ) { - DPRINTFN(2,("hid_report_size: item kind=%d id=%d pos=%d " - "size=%d count=%d\n", - h.kind, h.report_ID, h.loc.pos, h.loc.size, - h.loc.count)); - if (h.report_ID == id && h.kind == k) { - if (lo < 0) { - lo = h.loc.pos; -#ifdef DIAGNOSTIC - if (lo != 0) { - printf("hid_report_size: lo != 0\n"); - } -#endif - } - hi = h.loc.pos + h.loc.size * h.loc.count; - DPRINTFN(2,("hid_report_size: lo=%d hi=%d\n", lo, hi)); - } - } + id = 0; + for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); ) + if (h.report_ID != 0) + id = h.report_ID; hid_end_parse(d); - return ((hi - lo + 7) / 8); + size = h.loc.pos; + if (id != 0) { + size += 8; + *idp = id; /* XXX wrong */ + } else + *idp = 0; + return ((size + 7) / 8); } int -hid_locate(void *desc, int size, u_int32_t u, u_int8_t id, enum hid_kind k, +hid_locate(void *desc, int size, u_int32_t u, enum hid_kind k, struct hid_location *loc, u_int32_t *flags) { struct hid_data *d; struct hid_item h; - h.report_ID = 0; - DPRINTFN(5,("hid_locate: enter usage=0x%x kind=%d id=%d\n", u, k, id)); - for (d = hid_start_parse(desc, size, k); hid_get_item(d, &h); ) { - DPRINTFN(5,("hid_locate: usage=0x%x kind=%d id=%d flags=0x%x\n", - h.usage, h.kind, h.report_ID, h.flags)); - if (h.kind == k && !(h.flags & HIO_CONST) && - h.usage == u && h.report_ID == id) { + for (d = hid_start_parse(desc, size, 1<<k); hid_get_item(d, &h); ) { + if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) { if (loc != NULL) *loc = h.loc; if (flags != NULL) @@ -464,33 +437,19 @@ hid_get_data(u_char *buf, struct hid_location *loc) } int -hid_is_collection(void *desc, int size, u_int8_t id, u_int32_t usage) +hid_is_collection(void *desc, int size, u_int32_t usage) { struct hid_data *hd; struct hid_item hi; - u_int32_t coll_usage = ~0; + int err; - hd = hid_start_parse(desc, size, hid_none); + hd = hid_start_parse(desc, size, hid_input); if (hd == NULL) return (0); - DPRINTFN(2,("hid_is_collection: id=%d usage=0x%x\n", id, usage)); - while (hid_get_item(hd, &hi)) { - DPRINTFN(2,("hid_is_collection: kind=%d id=%d usage=0x%x" - "(0x%x)\n", - hi.kind, hi.report_ID, hi.usage, coll_usage)); - if (hi.kind == hid_collection && - hi.collection == HCOLL_APPLICATION) - coll_usage = hi.usage; - if (hi.kind == hid_endcollection && - coll_usage == usage && - hi.report_ID == id) { - DPRINTFN(2,("hid_is_collection: found\n")); - hid_end_parse(hd); - return (1); - } - } - DPRINTFN(2,("hid_is_collection: not found\n")); + err = hid_get_item(hd, &hi) && + hi.kind == hid_collection && + hi.usage == usage; hid_end_parse(hd); - return (0); + return (err); } diff --git a/sys/dev/usb/hid.h b/sys/dev/usb/hid.h index 928a86ce337..096a34e270f 100644 --- a/sys/dev/usb/hid.h +++ b/sys/dev/usb/hid.h @@ -1,5 +1,5 @@ -/* $OpenBSD: hid.h,v 1.5 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: hid.h,v 1.7 2001/12/28 17:32:36 augustss Exp $ */ +/* $OpenBSD: hid.h,v 1.6 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: hid.h,v 1.6 2000/06/01 14:28:57 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/hid.h,v 1.7 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -40,12 +40,7 @@ */ enum hid_kind { - hid_input, - hid_output, - hid_feature, - hid_collection, - hid_endcollection, - hid_none + hid_input, hid_output, hid_feature, hid_collection, hid_endcollection }; struct hid_location { @@ -86,11 +81,11 @@ struct hid_item { struct hid_item *next; }; -struct hid_data *hid_start_parse(void *d, int len, enum hid_kind kind); +struct hid_data *hid_start_parse(void *d, int len, int kindset); void hid_end_parse(struct hid_data *s); int hid_get_item(struct hid_data *s, struct hid_item *h); -int hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t id); -int hid_locate(void *desc, int size, u_int32_t usage, u_int8_t id, - enum hid_kind kind, struct hid_location *loc, u_int32_t *flags); +int hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t *id); +int hid_locate(void *desc, int size, u_int32_t usage, enum hid_kind kind, + struct hid_location *loc, u_int32_t *flags); u_long hid_get_data(u_char *buf, struct hid_location *loc); -int hid_is_collection(void *desc, int size, u_int8_t id, u_int32_t usage); +int hid_is_collection(void *desc, int size, u_int32_t usage); diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index 49e29bdce8b..d6b566156b3 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_upl.c,v 1.6 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: if_upl.c,v 1.17 2002/03/05 04:12:59 itojun Exp $ */ +/* $OpenBSD: if_upl.c,v 1.7 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: if_upl.c,v 1.15 2001/06/14 05:44:27 itojun Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. @@ -78,19 +78,27 @@ #include <net/bpf.h> #endif +#if defined(__NetBSD__) #ifdef INET #include <netinet/in.h> #include <netinet/in_var.h> -#if defined(__NetBSD__) #include <netinet/if_inarp.h> -#elif defined(__OpenBSD__) +#else +#error upl without INET? +#endif +#endif + +#if defined(__OpenBSD__) +#ifdef INET +#include <netinet/in.h> #include <netinet/in_systm.h> +#include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/if_ether.h> -#endif #else #error upl without INET? #endif +#endif #ifdef NS #include <netns/ns.h> @@ -325,22 +333,20 @@ USB_ATTACH(upl) ifp->if_addrlen = 0; ifp->if_hdrlen = 0; ifp->if_output = upl_output; - ifp->if_baudrate = 12000000; #if defined(__NetBSD__) ifp->if_input = upl_input; - ifp->if_dlt = DLT_RAW; #endif + ifp->if_baudrate = 12000000; IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); -#if defined(__NetBSD__) - if_alloc_sadl(ifp); -#endif -#if defined(__NetBSD__) && NBPFILTER > 0 +#if NBPFILTER > 0 +#if defined(__NetBSD__) || defined(__FreeBSD__) bpfattach(ifp, DLT_RAW, 0); #endif +#endif #if NRND > 0 rnd_attach_source(&sc->sc_rnd_source, USBDEVNAME(sc->sc_dev), RND_TYPE_NET, 0); diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c deleted file mode 100644 index d0d542a4171..00000000000 --- a/sys/dev/usb/if_url.c +++ /dev/null @@ -1,1609 +0,0 @@ -/* $OpenBSD: if_url.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: if_url.c,v 1.2 2002/03/28 21:49:19 ichiro Exp $ */ -/* - * Copyright (c) 2001, 2002 - * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Shingo WATANABE. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/* - * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at - * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf - * ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf - */ - -/* - * TODO: - * Interrupt Endpoint support - * External PHYs - * powerhook() support? - */ - -#include "opt_inet.h" -#include "opt_ns.h" -#include "bpfilter.h" -#include "rnd.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/socket.h> - -#include <sys/device.h> -#if NRND > 0 -#include <sys/rnd.h> -#endif - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_media.h> - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif -#define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m)) - -#include <net/if_ether.h> -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_inarp.h> -#endif -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> -#include <dev/mii/urlphyreg.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdevs.h> - -#include <dev/usb/if_urlreg.h> - - -/* Function declarations */ -USB_DECLARE_DRIVER(url); - -Static int url_openpipes(struct url_softc *); -Static int url_rx_list_init(struct url_softc *); -Static int url_tx_list_init(struct url_softc *); -Static int url_newbuf(struct url_softc *, struct url_chain *, struct mbuf *); -Static void url_start(struct ifnet *); -Static int url_send(struct url_softc *, struct mbuf *, int); -Static void url_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -Static void url_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -Static void url_tick(void *); -Static void url_tick_task(void *); -Static int url_ioctl(struct ifnet *, u_long, caddr_t); -Static void url_stop_task(struct url_softc *); -Static void url_stop(struct ifnet *, int); -Static void url_watchdog(struct ifnet *); -Static int url_ifmedia_change(struct ifnet *); -Static void url_ifmedia_status(struct ifnet *, struct ifmediareq *); -Static void url_lock_mii(struct url_softc *); -Static void url_unlock_mii(struct url_softc *); -Static int url_int_miibus_readreg(device_ptr_t, int, int); -Static void url_int_miibus_writereg(device_ptr_t, int, int, int); -Static void url_miibus_statchg(device_ptr_t); -Static int url_init(struct ifnet *); -Static void url_setmulti(struct url_softc *); -Static void url_reset(struct url_softc *); - -Static int url_csr_read_1(struct url_softc *, int); -Static int url_csr_read_2(struct url_softc *, int); -Static int url_csr_write_1(struct url_softc *, int, int); -Static int url_csr_write_2(struct url_softc *, int, int); -Static int url_csr_write_4(struct url_softc *, int, int); -Static int url_mem(struct url_softc *, int, int, void *, int); - -/* Macros */ -#ifdef URL_DEBUG -#define DPRINTF(x) if (urldebug) logprintf x -#define DPRINTFN(n,x) if (urldebug >= (n)) logprintf x -int urldebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define URL_SETBIT(sc, reg, x) \ - url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) | (x)) - -#define URL_SETBIT2(sc, reg, x) \ - url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) | (x)) - -#define URL_CLRBIT(sc, reg, x) \ - url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) & ~(x)) - -#define URL_CLRBIT2(sc, reg, x) \ - url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) & ~(x)) - -static const struct url_type { - struct usb_devno url_dev; - u_int16_t url_flags; -#define URL_EXT_PHY 0x0001 -} url_devs [] = { - /* MELCO LUA-KTX */ - {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0}, - /* GREEN HOUSE USBKR100 */ - {{ USB_VENDOR_GREENHOUSE2, USB_PRODUCT_GREENHOUSE2_USBKR100}, 0} -}; -#define url_lookup(v, p) ((struct url_type *)usb_lookup(url_devs, v, p)) - - -/* Probe */ -USB_MATCH(url) -{ - USB_MATCH_START(url, uaa); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (url_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} -/* Attach */ -USB_ATTACH(url) -{ - USB_ATTACH_START(url, sc, uaa); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usbd_status err; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - char devinfo[1024]; - char *devname = USBDEVNAME(sc->sc_dev); - struct ifnet *ifp; - struct mii_data *mii; - u_char eaddr[ETHER_ADDR_LEN]; - int i, s; - - usbd_devinfo(dev, 0, devinfo); - USB_ATTACH_SETUP; - printf("%s: %s\n", devname, devinfo); - - /* Move the device into the configured state. */ - err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); - if (err) { - printf("%s: setting config no failed\n", devname); - goto bad; - } - - usb_init_task(&sc->sc_tick_task, url_tick_task, sc); - lockinit(&sc->sc_mii_lock, PZERO, "urlmii", 0, 0); - usb_init_task(&sc->sc_stop_task, (void (*)(void *)) url_stop_task, sc); - - /* get control interface */ - err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); - if (err) { - printf("%s: failed to get interface, err=%s\n", devname, - usbd_errstr(err)); - goto bad; - } - - sc->sc_udev = dev; - sc->sc_ctl_iface = iface; - sc->sc_flags = url_lookup(uaa->vendor, uaa->product)->url_flags; - - /* get interface descriptor */ - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); - - /* find endpoints */ - sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); - if (ed == NULL) { - printf("%s: couldn't get endpoint %d\n", devname, i); - goto bad; - } - if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ - else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) - sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ - else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ - } - - if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || - sc->sc_intrin_no == -1) { - printf("%s: missing endpoint\n", devname); - goto bad; - } - - s = splnet(); - - /* reset the adapter */ - url_reset(sc); - - /* Get Ethernet Address */ - err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr, - ETHER_ADDR_LEN); - if (err) { - printf("%s: read MAC address faild\n", devname); - splx(s); - goto bad; - } - - /* Print Ethernet Address */ - printf("%s: Ethernet address %s\n", devname, ether_sprintf(eaddr)); - - /* initialize interface infomation */ - ifp = GET_IFP(sc); - ifp->if_softc = sc; - strncpy(ifp->if_xname, devname, IFNAMSIZ); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_start = url_start; - ifp->if_ioctl = url_ioctl; - ifp->if_watchdog = url_watchdog; - ifp->if_init = url_init; - ifp->if_stop = url_stop; - - IFQ_SET_READY(&ifp->if_snd); - - /* - * Do ifmedia setup. - */ - mii = &sc->sc_mii; - mii->mii_ifp = ifp; - mii->mii_readreg = url_int_miibus_readreg; - mii->mii_writereg = url_int_miibus_writereg; -#if 0 - if (sc->sc_flags & URL_EXT_PHY) { - mii->mii_readreg = url_ext_miibus_readreg; - mii->mii_writereg = url_ext_miibus_writereg; - } -#endif - mii->mii_statchg = url_miibus_statchg; - mii->mii_flags = MIIF_AUTOTSLEEP; - ifmedia_init(&mii->mii_media, 0, - url_ifmedia_change, url_ifmedia_status); - mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); - if (LIST_FIRST(&mii->mii_phys) == NULL) { - ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); - } else - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); - - /* attach the interface */ - if_attach(ifp); - Ether_ifattach(ifp, eaddr); - -#if NRND > 0 - rnd_attach_source(&sc->rnd_source, devname, RND_TYPE_NET, 0); -#endif - - usb_callout_init(sc->sc_stat_ch); - sc->sc_attached = 1; - splx(s); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev)); - - USB_ATTACH_SUCCESS_RETURN; - - bad: - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; -} - -/* detach */ -USB_DETACH(url) -{ - USB_DETACH_START(url, sc); - struct ifnet *ifp = GET_IFP(sc); - int s; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - /* Detached before attached finished */ - if (!sc->sc_attached) - return (0); - - usb_uncallout(sc->sc_stat_ch, url_tick, sc); - - /* Remove any pending tasks */ - usb_rem_task(sc->sc_udev, &sc->sc_tick_task); - usb_rem_task(sc->sc_udev, &sc->sc_stop_task); - - s = splusb(); - - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away */ - usb_detach_wait(USBDEV(sc->sc_dev)); - } - - if (ifp->if_flags & IFF_RUNNING) - url_stop(GET_IFP(sc), 1); - -#if NRND > 0 - rnd_detach_source(&sc->rnd_source); -#endif - mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); - ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); - ether_ifdetach(ifp); - if_detach(ifp); - -#ifdef DIAGNOSTIC - if (sc->sc_pipe_tx != NULL) - printf("%s: detach has active tx endpoint.\n", - USBDEVNAME(sc->sc_dev)); - if (sc->sc_pipe_rx != NULL) - printf("%s: detach has active rx endpoint.\n", - USBDEVNAME(sc->sc_dev)); - if (sc->sc_pipe_intr != NULL) - printf("%s: detach has active intr endpoint.\n", - USBDEVNAME(sc->sc_dev)); -#endif - - sc->sc_attached = 0; - - splx(s); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - return (0); -} - -/* read/write memory */ -Static int -url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc == NULL) - return (0); - - DPRINTFN(0x200, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (0); - - if (cmd == URL_CMD_READMEM) - req.bmRequestType = UT_READ_VENDOR_DEVICE; - else - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URL_REQ_MEM; - USETW(req.wValue, offset); - USETW(req.wIndex, 0x0000); - USETW(req.wLength, len); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - if (err) { - DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", - USBDEVNAME(sc->sc_dev), - cmd == URL_CMD_READMEM ? "read" : "write", - offset, err)); - } - - return (err); -} - -/* read 1byte from register */ -Static int -url_csr_read_1(struct url_softc *sc, int reg) -{ - u_int8_t val = 0; - - DPRINTFN(0x100, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (0); - - return (url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val); -} - -/* read 2bytes from register */ -Static int -url_csr_read_2(struct url_softc *sc, int reg) -{ - uWord val; - - DPRINTFN(0x100, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (0); - - USETW(val, 0); - return (url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val)); -} - -/* write 1byte to register */ -Static int -url_csr_write_1(struct url_softc *sc, int reg, int aval) -{ - u_int8_t val = aval; - - DPRINTFN(0x100, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (0); - - return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0); -} - -/* write 2bytes to register */ -Static int -url_csr_write_2(struct url_softc *sc, int reg, int aval) -{ - uWord val; - - DPRINTFN(0x100, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - USETW(val, aval); - - if (sc->sc_dying) - return (0); - - return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0); -} - -/* write 4bytes to register */ -Static int -url_csr_write_4(struct url_softc *sc, int reg, int aval) -{ - uDWord val; - - DPRINTFN(0x100, - ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - USETDW(val, aval); - - if (sc->sc_dying) - return (0); - - return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0); -} - -Static int -url_init(struct ifnet *ifp) -{ - struct url_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - u_char *eaddr; - int i, s; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (EIO); - - s = splnet(); - - /* Cancel pending I/O and free all TX/RX buffers */ - url_stop(ifp, 1); - - eaddr = LLADDR(ifp->if_sadl); - for (i = 0; i < ETHER_ADDR_LEN; i++) - url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); - - /* Init transmission control register */ - URL_CLRBIT(sc, URL_TCR, - URL_TCR_TXRR1 | URL_TCR_TXRR0 | - URL_TCR_IFG1 | URL_TCR_IFG0 | - URL_TCR_NOCRC); - - /* Init receive control register */ - URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); - if (ifp->if_flags & IFF_BROADCAST) - URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); - else - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); - - /* If we want promiscuous mode, accept all physical frames. */ - if (ifp->if_flags & IFF_PROMISC) - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - else - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - - - /* Initialize transmit ring */ - if (url_tx_list_init(sc) == ENOBUFS) { - printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev)); - splx(s); - return (EIO); - } - - /* Initialize receive ring */ - if (url_rx_list_init(sc) == ENOBUFS) { - printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev)); - splx(s); - return (EIO); - } - - /* Load the multicast filter */ - url_setmulti(sc); - - /* Enable RX and TX */ - URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); - - mii_mediachg(mii); - - if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { - if (url_openpipes(sc)) { - splx(s); - return (EIO); - } - } - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - splx(s); - - usb_callout(sc->sc_stat_ch, hz, url_tick, sc); - - return (0); -} - -Static void -url_reset(struct url_softc *sc) -{ - int i; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return; - - URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST); - - for (i = 0; i < URL_TX_TIMEOUT; i++) { - if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST)) - break; - delay(10); /* XXX */ - } - - delay(10000); /* XXX */ -} - -int -url_activate(device_ptr_t self, enum devact act) -{ - struct url_softc *sc = (struct url_softc *)self; - - DPRINTF(("%s: %s: enter, act=%d\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__, act)); - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - break; - - case DVACT_DEACTIVATE: - if_deactivate(&sc->sc_ec.ec_if); - sc->sc_dying = 1; - break; - } - - return (0); -} - -#define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) - - -Static void -url_setmulti(struct url_softc *sc) -{ - struct ifnet *ifp; - struct ether_multi *enm; - struct ether_multistep step; - u_int32_t hashes[2] = { 0, 0 }; - int h = 0; - int mcnt = 0; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return; - - ifp = GET_IFP(sc); - - if (ifp->if_flags & IFF_PROMISC) { - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - return; - } else if (ifp->if_flags & IFF_ALLMULTI) { - allmulti: - ifp->if_flags |= IFF_ALLMULTI; - URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); - return; - } - - /* first, zot all the existing hash bits */ - url_csr_write_4(sc, URL_MAR0, 0); - url_csr_write_4(sc, URL_MAR4, 0); - - /* now program new ones */ - ETHER_FIRST_MULTI(step, &sc->sc_ec, enm); - while (enm != NULL) { - if (memcmp(enm->enm_addrlo, enm->enm_addrhi, - ETHER_ADDR_LEN) != 0) - goto allmulti; - - h = url_calchash(enm->enm_addrlo); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h -32)); - mcnt++; - ETHER_NEXT_MULTI(step, enm); - } - - ifp->if_flags &= ~IFF_ALLMULTI; - - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); - - if (mcnt){ - URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); - } else { - URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); - } - url_csr_write_4(sc, URL_MAR0, hashes[0]); - url_csr_write_4(sc, URL_MAR4, hashes[1]); -} - -Static int -url_openpipes(struct url_softc *sc) -{ - struct url_chain *c; - usbd_status err; - int i; - int error = 0; - - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - - /* Open RX pipe */ - err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); - if (err) { - printf("%s: open rx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } - - /* Open TX pipe */ - err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); - if (err) { - printf("%s: open tx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } - -#if 0 - /* XXX: interrupt endpoint is not yet supported */ - /* Open Interrupt pipe */ - err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, - &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN, - url_intr, URL_INTR_INTERVAL); - if (err) { - printf("%s: open intr pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } -#endif - - - /* Start up the receive pipe. */ - for (i = 0; i < URL_RX_LIST_CNT; i++) { - c = &sc->sc_cdata.url_rx_chain[i]; - usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx, - c, c->url_buf, URL_BUFSZ, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, url_rxeof); - (void)usbd_transfer(c->url_xfer); - DPRINTF(("%s: %s: start read\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__)); - } - - done: - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - - return (error); -} - -Static int -url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (m == NULL) { - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", USBDEVNAME(sc->sc_dev)); - return (ENOBUFS); - } - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", USBDEVNAME(sc->sc_dev)); - m_freem(m_new); - return (ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->url_mbuf = m_new; - - return (0); -} - - -Static int -url_rx_list_init(struct url_softc *sc) -{ - struct url_cdata *cd; - struct url_chain *c; - int i; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - cd = &sc->sc_cdata; - for (i = 0; i < URL_RX_LIST_CNT; i++) { - c = &cd->url_rx_chain[i]; - c->url_sc = sc; - c->url_idx = i; - if (url_newbuf(sc, c, NULL) == ENOBUFS) - return (ENOBUFS); - if (c->url_xfer == NULL) { - c->url_xfer = usbd_alloc_xfer(sc->sc_udev); - if (c->url_xfer == NULL) - return (ENOBUFS); - c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); - if (c->url_buf == NULL) { - usbd_free_xfer(c->url_xfer); - return (ENOBUFS); - } - } - } - - return (0); -} - -Static int -url_tx_list_init(struct url_softc *sc) -{ - struct url_cdata *cd; - struct url_chain *c; - int i; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - cd = &sc->sc_cdata; - for (i = 0; i < URL_TX_LIST_CNT; i++) { - c = &cd->url_tx_chain[i]; - c->url_sc = sc; - c->url_idx = i; - c->url_mbuf = NULL; - if (c->url_xfer == NULL) { - c->url_xfer = usbd_alloc_xfer(sc->sc_udev); - if (c->url_xfer == NULL) - return (ENOBUFS); - c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); - if (c->url_buf == NULL) { - usbd_free_xfer(c->url_xfer); - return (ENOBUFS); - } - } - } - - return (0); -} - -Static void -url_start(struct ifnet *ifp) -{ - struct url_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - DPRINTF(("%s: %s: enter, link=%d\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__, sc->sc_link)); - - if (sc->sc_dying) - return; - - if (!sc->sc_link) - return; - - if (ifp->if_flags & IFF_OACTIVE) - return; - - IFQ_POLL(&ifp->if_snd, m_head); - if (m_head == NULL) - return; - - if (url_send(sc, m_head, 0)) { - ifp->if_flags |= IFF_OACTIVE; - return; - } - - IFQ_DEQUEUE(&ifp->if_snd, m_head); - -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m_head); -#endif - - ifp->if_flags |= IFF_OACTIVE; - - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; -} - -Static int -url_send(struct url_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct url_chain *c; - usbd_status err; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__)); - - c = &sc->sc_cdata.url_tx_chain[idx]; - - /* Copy the mbuf data into a contiguous buffer */ - m_copydata(m, 0, m->m_pkthdr.len, c->url_buf); - c->url_mbuf = m; - total_len = m->m_pkthdr.len; - - if (total_len < URL_MIN_FRAME_LEN) - total_len = URL_MIN_FRAME_LEN; - usbd_setup_xfer(c->url_xfer, sc->sc_pipe_tx, c, c->url_buf, total_len, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, - URL_TX_TIMEOUT, url_txeof); - - /* Transmit */ - sc->sc_refcnt++; - err = usbd_transfer(c->url_xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - if (err != USBD_IN_PROGRESS) { - printf("%s: url_send error=%s\n", USBDEVNAME(sc->sc_dev), - usbd_errstr(err)); - /* Stop the interface */ - usb_add_task(sc->sc_udev, &sc->sc_stop_task); - return (EIO); - } - - DPRINTF(("%s: %s: send %d bytes\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__, total_len)); - - sc->sc_cdata.url_tx_cnt++; - - return (0); -} - -Static void -url_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct url_chain *c = priv; - struct url_softc *sc = c->url_sc; - struct ifnet *ifp = GET_IFP(sc); - int s; - - if (sc->sc_dying) - return; - - s = splnet(); - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - splx(s); - return; - } - ifp->if_oerrors++; - printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev), - usbd_errstr(status)); - if (status == USBD_STALLED) { - sc->sc_refcnt++; - usbd_clear_endpoint_stall(sc->sc_pipe_tx); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - } - splx(s); - return; - } - - ifp->if_opackets++; - - m_free(c->url_mbuf); - c->url_mbuf = NULL; - - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - url_start(ifp); - - splx(s); -} - -Static void -url_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct url_chain *c = priv; - struct url_softc *sc = c->url_sc; - struct ifnet *ifp = GET_IFP(sc); - struct mbuf *m; - u_int32_t total_len; - url_rxhdr_t rxhdr; - int s; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__)); - - if (sc->sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - sc->sc_rx_errs++; - if (usbd_ratecheck(&sc->sc_rx_notice)) { - printf("%s: %u usb errors on rx: %s\n", - USBDEVNAME(sc->sc_dev), sc->sc_rx_errs, - usbd_errstr(status)); - sc->sc_rx_errs = 0; - } - if (status == USBD_STALLED) { - sc->sc_refcnt++; - usbd_clear_endpoint_stall(sc->sc_pipe_rx); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - } - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len); - - if (total_len <= ETHER_CRC_LEN) { - ifp->if_ierrors++; - goto done; - } - - memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); - - DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", - USBDEVNAME(sc->sc_dev), - UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, - UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", - UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", - UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", - UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); - - if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { - ifp->if_ierrors++; - goto done; - } - - ifp->if_ipackets++; - total_len -= ETHER_CRC_LEN; - - m = c->url_mbuf; - m->m_pkthdr.len = m->m_len = total_len; - m->m_pkthdr.rcvif = ifp; - - s = splnet(); - - if (url_newbuf(sc, c, NULL) == ENOBUFS) { - ifp->if_ierrors++; - goto done1; - } - -#if NBPFILTER > 0 - if (ifp->if_bpf) - BPF_MTAP(ifp, m); -#endif - - DPRINTF(("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__, m->m_len)); - IF_INPUT(ifp, m); - - done1: - splx(s); - - done: - /* Setup new transfer */ - usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->url_buf, URL_BUFSZ, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, url_rxeof); - sc->sc_refcnt++; - usbd_transfer(xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); - - DPRINTF(("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); -} - -#if 0 -Static void url_intr() -{ -} -#endif - -Static int -url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct url_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - int s, error = 0; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (EIO); - - s = splnet(); - - switch (cmd) { - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); - break; - - default: - error = ether_ioctl(ifp, cmd, data); - if (error == ENETRESET) { - url_setmulti(sc); - error = 0; - } - break; - } - - splx(s); - - return (error); -} - -Static void -url_watchdog(struct ifnet *ifp) -{ - struct url_softc *sc = ifp->if_softc; - struct url_chain *c; - usbd_status stat; - int s; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - ifp->if_oerrors++; - printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev)); - - s = splusb(); - c = &sc->sc_cdata.url_tx_chain[0]; - usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat); - url_txeof(c->url_xfer, c, stat); - - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - url_start(ifp); - splx(s); -} - -Static void -url_stop_task(struct url_softc *sc) -{ - url_stop(GET_IFP(sc), 1); -} - -/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ -Static void -url_stop(struct ifnet *ifp, int disable) -{ - struct url_softc *sc = ifp->if_softc; - usbd_status err; - int i; - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - ifp->if_timer = 0; - - url_reset(sc); - - usb_uncallout(sc->sc_stat_ch, url_tick, sc); - - /* Stop transfers */ - /* RX endpoint */ - if (sc->sc_pipe_rx != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_rx); - if (err) - printf("%s: abort rx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_rx); - if (err) - printf("%s: close rx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_rx = NULL; - } - - /* TX endpoint */ - if (sc->sc_pipe_tx != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_tx); - if (err) - printf("%s: abort tx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_tx); - if (err) - printf("%s: close tx pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_tx = NULL; - } - -#if 0 - /* XXX: Interrupt endpoint is not yet supported!! */ - /* Interrupt endpoint */ - if (sc->sc_pipe_intr != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_intr); - if (err) - printf("%s: abort intr pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_intr); - if (err) - printf("%s: close intr pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_intr = NULL; - } -#endif - - /* Free RX resources. */ - for (i = 0; i < URL_RX_LIST_CNT; i++) { - if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) { - m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf); - sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL; - } - if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) { - usbd_free_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer); - sc->sc_cdata.url_rx_chain[i].url_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < URL_TX_LIST_CNT; i++) { - if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) { - m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf); - sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL; - } - if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) { - usbd_free_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer); - sc->sc_cdata.url_tx_chain[i].url_xfer = NULL; - } - } - - sc->sc_link = 0; - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); -} - -/* Set media options */ -Static int -url_ifmedia_change(struct ifnet *ifp) -{ - struct url_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return (0); - - sc->sc_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; - miisc = LIST_NEXT(miisc, mii_list)) - mii_phy_reset(miisc); - } - - return (mii_mediachg(mii)); -} - -/* Report current media status. */ -Static void -url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct url_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); - - if (sc->sc_dying) - return; - - if ((ifp->if_flags & IFF_RUNNING) == 0) { - ifmr->ifm_active = IFM_ETHER | IFM_NONE; - ifmr->ifm_status = 0; - return; - } - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; -} - -Static void -url_tick(void *xsc) -{ - struct url_softc *sc = xsc; - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__)); - - if (sc->sc_dying) - return; - - /* Perform periodic stuff in process context */ - usb_add_task(sc->sc_udev, &sc->sc_tick_task); -} - -Static void -url_tick_task(void *xsc) -{ - struct url_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; - int s; - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__)); - - if (sc->sc_dying) - return; - - ifp = GET_IFP(sc); - mii = GET_MII(sc); - - if (mii == NULL) - return; - - s = splnet(); - - mii_tick(mii); - if (!sc->sc_link) { - mii_pollstat(mii); - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - DPRINTF(("%s: %s: got link\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__)); - sc->sc_link++; - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - url_start(ifp); - } - } - - usb_callout(sc->sc_stat_ch, hz, url_tick, sc); - - splx(s); -} - -/* Get exclusive access to the MII registers */ -Static void -url_lock_mii(struct url_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__)); - - sc->sc_refcnt++; - lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL); -} - -Static void -url_unlock_mii(struct url_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__)); - - lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_dev)); -} - -Static int -url_int_miibus_readreg(device_ptr_t dev, int phy, int reg) -{ - struct url_softc *sc; - u_int16_t val; - - if (dev == NULL) - return (0); - - sc = USBGETSOFTC(dev); - - DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__); -#endif - return (0); - } - - /* XXX: one PHY only for the RTL8150 internal PHY */ - if (phy != 0) { - DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy)); - return (0); - } - - url_lock_mii(sc); - - switch (reg) { - case MII_BMCR: /* Control Register */ - reg = URL_BMCR; - break; - case MII_BMSR: /* Status Register */ - reg = URL_BMSR; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - val = 0; - goto R_DONE; - break; - case MII_ANAR: /* Autonegotiation advertisement */ - reg = URL_ANAR; - break; - case MII_ANLPAR: /* Autonegotiation link partner abilities */ - reg = URL_ANLP; - break; - case URLPHY_MSR: /* Media Status Register */ - reg = URL_MSR; - break; - default: - printf("%s: %s: bad register %04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, reg); - val = 0; - goto R_DONE; - break; - } - - if (reg == URL_MSR) - val = url_csr_read_1(sc, reg); - else - val = url_csr_read_2(sc, reg); - - R_DONE: - DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg, val)); - - url_unlock_mii(sc); - return (val); -} - -Static void -url_int_miibus_writereg(device_ptr_t dev, int phy, int reg, int data) -{ - struct url_softc *sc; - - if (dev == NULL) - return; - - sc = USBGETSOFTC(dev); - - DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg, data)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__); -#endif - return; - } - - /* XXX: one PHY only for the RTL8150 internal PHY */ - if (phy != 0) { - DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy)); - return; - } - - url_lock_mii(sc); - - switch (reg) { - case MII_BMCR: /* Control Register */ - reg = URL_BMCR; - break; - case MII_BMSR: /* Status Register */ - reg = URL_BMSR; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - goto W_DONE; - break; - case MII_ANAR: /* Autonegotiation advertisement */ - reg = URL_ANAR; - break; - case MII_ANLPAR: /* Autonegotiation link partner abilities */ - reg = URL_ANLP; - break; - case URLPHY_MSR: /* Media Status Register */ - reg = URL_MSR; - break; - default: - printf("%s: %s: bad register %04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, reg); - goto W_DONE; - break; - } - - if (reg == URL_MSR) - url_csr_write_1(sc, reg, data); - else - url_csr_write_2(sc, reg, data); - W_DONE: - - url_unlock_mii(sc); - return; -} - -Static void -url_miibus_statchg(device_ptr_t dev) -{ -#ifdef URL_DEBUG - struct url_softc *sc; - - if (dev == NULL) - return; - - sc = USBGETSOFTC(dev); - DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__)); -#endif - /* Nothing to do */ -} - -#if 0 -/* - * external PHYs support, but not test. - */ -Static int -url_ext_miibus_redreg(device_ptr_t dev, int phy, int reg) -{ - struct url_softc *sc = USBGETSOFTC(dev); - u_int16_t val; - - DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__); -#endif - return (0); - } - - url_lock_mii(sc); - - url_csr_write_1(sc, URL_PHYADD, phy & URL_PHYADD_MASK); - /* - * RTL8150L will initiate a MII management data transaction - * if PHYCNT_OWN bit is set 1 by software. After transaction, - * this bit is auto cleared by TRL8150L. - */ - url_csr_write_1(sc, URL_PHYCNT, - (reg | URL_PHYCNT_PHYOWN) & ~URL_PHYCNT_RWCR); - for (i = 0; i < URL_TIMEOUT; i++) { - if ((url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) == 0) - break; - } - if (i == URL_TIMEOUT) { - printf("%s: MII read timed out\n", USBDEVNAME(sc->sc_dev)); - } - - val = url_csr_read_2(sc, URL_PHYDAT); - - DPRINTF(("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg, val)); - - url_unlock_mii(sc); - return (val); -} - -Static void -url_ext_miibus_writereg(device_ptr_t dev, int phy, int reg, int data) -{ - struct url_softc *sc = USBGETSOFTC(dev); - - DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", - USBDEVNAME(sc->sc_dev), __FUNCTION__, phy, reg, data)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev), - __FUNCTION__); -#endif - return; - } - - url_lock_mii(sc); - - url_csr_write_2(sc, URL_PHYDAT, data); - url_csr_write_1(sc, URL_PHYADD, phy); - url_csr_write_1(sc, URL_PHYCNT, reg | URL_PHYCNT_RWCR); /* Write */ - - for (i=0; i < URL_TIMEOUT; i++) { - if (url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) - break; - } - - if (i == URL_TIMEOUT) { - printf("%s: MII write timed out\n", - USBDEVNAME(sc->sc_dev)); - } - - url_unlock_mii(sc); - return; -} -#endif - diff --git a/sys/dev/usb/if_urlreg.h b/sys/dev/usb/if_urlreg.h deleted file mode 100644 index f76bb380f00..00000000000 --- a/sys/dev/usb/if_urlreg.h +++ /dev/null @@ -1,195 +0,0 @@ -/* $OpenBSD: if_urlreg.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: if_urlreg.h,v 1.1 2002/03/28 21:09:11 ichiro Exp $ */ -/* - * Copyright (c) 2001, 2002 - * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Shingo WATANABE. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define URL_IFACE_INDEX 0 -#define URL_CONFIG_NO 1 - -#define URL_TX_LIST_CNT 1 -#define URL_RX_LIST_CNT 1 - -#define URL_TX_TIMEOUT 1000 -#define URL_TIMEOUT 10000 - -#define ETHER_ALIGN 2 - - -/* Packet length */ -#define URL_MAX_MTU 1536 -#define URL_MIN_FRAME_LEN 60 -#define URL_BUFSZ URL_MAX_MTU - -/* Request */ -#define URL_REQ_MEM 0x05 - -#define URL_CMD_READMEM 1 -#define URL_CMD_WRITEMEM 2 - -/* Registers */ -#define URL_IDR0 0x0120 /* Ethernet Address, load from 93C46 */ -#define URL_IDR1 0x0121 /* Ethernet Address, load from 93C46 */ -#define URL_IDR2 0x0122 /* Ethernet Address, load from 93C46 */ -#define URL_IDR3 0x0123 /* Ethernet Address, load from 93C46 */ -#define URL_IDR4 0x0124 /* Ethernet Address, load from 93C46 */ -#define URL_IDR5 0x0125 /* Ethernet Address, load from 93C46 */ - -#define URL_MAR0 0x0126 /* Multicast register */ -#define URL_MAR1 0x0127 /* Multicast register */ -#define URL_MAR2 0x0128 /* Multicast register */ -#define URL_MAR3 0x0129 /* Multicast register */ -#define URL_MAR4 0x012a /* Multicast register */ -#define URL_MAR5 0x012b /* Multicast register */ -#define URL_MAR6 0x012c /* Multicast register */ -#define URL_MAR7 0x012d /* Multicast register */ -#define URL_MAR URL_MAR0 - -#define URL_CR 0x012e /* Command Register */ -#define URL_CR_WEPROM (1<<5) /* EEPROM Write Enable */ -#define URL_CR_SOFT_RST (1<<4) /* Software Reset */ -#define URL_CR_RE (1<<3) /* Ethernet Receive Enable */ -#define URL_CR_TE (1<<2) /* Ethernet Transmit Enable */ -#define URL_CR_EP3CLREN (1<<1) /* Enable clearing the performance counter */ -#define URL_CR_AUTOLOAD (1<<0) /* Auto-load the contents of 93C46 */ - -#define URL_TCR 0x012f /* Transmit Control Register */ -#define URL_TCR_TXRR1 (1<<7) /* TX Retry Count */ -#define URL_TCR_TXRR0 (1<<6) /* TX Retry Count */ -#define URL_TCR_IFG1 (1<<4) /* Interframe Gap Time */ -#define URL_TCR_IFG0 (1<<4) /* Interframe Gap Time */ -#define URL_TCR_NOCRC (1<<0) /* no CRC Append */ - -#define URL_RCR 0x0130 /* Receive Configuration Register */ -#define URL_RCR_TAIL (1<<7) -#define URL_RCR_AER (1<<6) -#define URL_RCR_AR (1<<5) -#define URL_RCR_AM (1<<4) -#define URL_RCR_AB (1<<3) -#define URL_RCR_AD (1<<2) -#define URL_RCR_AAM (1<<1) -#define URL_RCR_AAP (1<<0) - -#define URL_MSR 0x137 /* Media Status Register */ -#define URL_MSR_TXFCE (1<<7) -#define URL_MSR_RXFCE (1<<6) -#define URL_MSR_DUPLEX (1<<4) -#define URL_MSR_SPEED_100 (1<<3) -#define URL_MSR_LINK (1<<2) -#define URL_MSR_TXPF (1<<1) -#define URL_MSR_RXPF (1<<0) - -#define URL_PHYADD 0x138 /* MII PHY Address select */ -#define URL_PHYADD_MASK 0x1f /* MII PHY Address select */ - -#define URL_PHYDAT 0x139 /* MII PHY data */ - -#define URL_PHYCNT 0x13b /* MII PHY control */ -#define URL_PHYCNT_PHYOWN (1<<6) /* Own bit */ -#define URL_PHYCNT_RWCR (1<<5) /* MII management data R/W control */ -#define URL_PHY_PHYOFF_MASK 0x1f /* PHY register offset */ - -#define URL_BMCR 0x140 /* Basic mode control register */ -#define URL_BMSR 0x142 /* Basic mode status register */ -#define URL_ANAR 0x144 /* Auto-negotiation advertisement register */ -#define URL_ANLP 0x146 /* Auto-negotiation link partner ability register */ - - -typedef uWord url_rxhdr_t; /* Recive Header */ -#define URL_RXHDR_BYTEC_MASK (0x0fff) /* RX bytes count */ -#define URL_RXHDR_VALID_MASK (0x1000) /* Valid packet */ -#define URL_RXHDR_RUNTPKT_MASK (0x2000) /* Runt packet */ -#define URL_RXHDR_PHYPKT_MASK (0x4000) /* Physical match packet */ -#define URL_RXHDR_MCASTPKT_MASK (0x8000) /* Multicast packet */ - -#define GET_IFP(sc) (&(sc)->sc_ec.ec_if) -#define GET_MII(sc) (&(sc)->sc_mii) - -struct url_chain { - struct url_softc *url_sc; - usbd_xfer_handle url_xfer; - char *url_buf; - struct mbuf *url_mbuf; - int url_idx; -}; - -struct url_cdata { - struct url_chain url_tx_chain[URL_TX_LIST_CNT]; - struct url_chain url_rx_chain[URL_TX_LIST_CNT]; -#if 0 - /* XXX: Intrrupt Endpoint is not yet supported! */ - struct url_intrpkg url_ibuf; -#endif - int url_tx_prod; - int url_tx_cons; - int url_tx_cnt; - int url_rx_prod; -}; - -struct url_softc { - USBBASEDEVICE sc_dev; /* base device */ - usbd_device_handle sc_udev; - - /* USB */ - usbd_interface_handle sc_ctl_iface; - /* int sc_ctl_iface_no; */ - int sc_bulkin_no; /* bulk in endpoint */ - int sc_bulkout_no; /* bulk out endpoint */ - int sc_intrin_no; /* intr in endpoint */ - usbd_pipe_handle sc_pipe_rx; - usbd_pipe_handle sc_pipe_tx; - usbd_pipe_handle sc_pipe_intr; - usb_callout_t sc_stat_ch; - u_int sc_rx_errs; - /* u_int sc_intr_errs; */ - struct timeval sc_rx_notice; - - /* Ethernet */ - struct ethercom sc_ec; /* ethernet common */ - struct mii_data sc_mii; - struct lock sc_mii_lock; - int sc_link; -#define sc_media url_mii.mii_media -#if NRND > 0 - rndsource_element_t rnd_source; -#endif - struct url_cdata sc_cdata; - - int sc_attached; - int sc_dying; - int sc_refcnt; - - struct usb_task sc_tick_task; - struct usb_task sc_stop_task; - - u_int16_t sc_flags; -}; diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 4e1107f020f..008038435de 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ohci.c,v 1.27 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ohci.c,v 1.122 2002/03/17 18:02:52 augustss Exp $ */ +/* $OpenBSD: ohci.c,v 1.28 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ohci.c,v 1.104 2001/09/28 23:57:21 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -198,18 +198,18 @@ Static void ohci_device_isoc_abort(usbd_xfer_handle); Static void ohci_device_isoc_close(usbd_pipe_handle); Static void ohci_device_isoc_done(usbd_xfer_handle); -Static usbd_status ohci_device_setintr(ohci_softc_t *sc, +Static usbd_status ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *pipe, int ival); -Static int ohci_str(usb_string_descriptor_t *, int, const char *); +Static int ohci_str(usb_string_descriptor_t *, int, char *); Static void ohci_timeout(void *); -Static void ohci_timeout_task(void *); Static void ohci_rhsc_able(ohci_softc_t *, int); -Static void ohci_rhsc_enable(void *); +Static void ohci_rhsc_enable(void *sc); Static void ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *); Static void ohci_abort_xfer(usbd_xfer_handle, usbd_status); +Static void ohci_abort_xfer_end(void *); Static void ohci_device_clear_toggle(usbd_pipe_handle pipe); Static void ohci_noop(usbd_pipe_handle pipe); @@ -236,7 +236,7 @@ Static void ohci_dump_itds(ohci_soft_itd_t *); #define OREAD4(sc, r) (OBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r))) /* Reverse the bits in a value 0 .. 31 */ -Static u_int8_t revbits[OHCI_NO_INTRS] = +Static u_int8_t revbits[OHCI_NO_INTRS] = { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, @@ -286,7 +286,7 @@ Static struct usbd_bus_methods ohci_bus_methods = { ohci_freex, }; -Static struct usbd_pipe_methods ohci_root_ctrl_methods = { +Static struct usbd_pipe_methods ohci_root_ctrl_methods = { ohci_root_ctrl_transfer, ohci_root_ctrl_start, ohci_root_ctrl_abort, @@ -295,7 +295,7 @@ Static struct usbd_pipe_methods ohci_root_ctrl_methods = { ohci_root_ctrl_done, }; -Static struct usbd_pipe_methods ohci_root_intr_methods = { +Static struct usbd_pipe_methods ohci_root_intr_methods = { ohci_root_intr_transfer, ohci_root_intr_start, ohci_root_intr_abort, @@ -304,7 +304,7 @@ Static struct usbd_pipe_methods ohci_root_intr_methods = { ohci_root_intr_done, }; -Static struct usbd_pipe_methods ohci_device_ctrl_methods = { +Static struct usbd_pipe_methods ohci_device_ctrl_methods = { ohci_device_ctrl_transfer, ohci_device_ctrl_start, ohci_device_ctrl_abort, @@ -313,7 +313,7 @@ Static struct usbd_pipe_methods ohci_device_ctrl_methods = { ohci_device_ctrl_done, }; -Static struct usbd_pipe_methods ohci_device_intr_methods = { +Static struct usbd_pipe_methods ohci_device_intr_methods = { ohci_device_intr_transfer, ohci_device_intr_start, ohci_device_intr_abort, @@ -322,7 +322,7 @@ Static struct usbd_pipe_methods ohci_device_intr_methods = { ohci_device_intr_done, }; -Static struct usbd_pipe_methods ohci_device_bulk_methods = { +Static struct usbd_pipe_methods ohci_device_bulk_methods = { ohci_device_bulk_transfer, ohci_device_bulk_start, ohci_device_bulk_abort, @@ -368,19 +368,15 @@ ohci_detach(struct ohci_softc *sc, int flags) if (sc->sc_child != NULL) rv = config_detach(sc->sc_child, flags); - + if (rv != 0) return (rv); - usb_uncallout(sc->sc_tmo_rhsc, ohci_rhsc_enable, sc); - #if defined(__NetBSD__) || defined(__OpenBSD__) powerhook_disestablish(sc->sc_powerhook); shutdownhook_disestablish(sc->sc_shutdownhook); #endif - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - /* free data structures XXX */ return (rv); @@ -492,7 +488,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, dataphys = DMAADDR(dma); dataphysend = OHCI_PAGE(dataphys + len - 1); tdflags = htole32( - (rd ? OHCI_TD_IN : OHCI_TD_OUT) | + (rd ? OHCI_TD_IN : OHCI_TD_OUT) | (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) | OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); @@ -508,7 +504,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, curlen = len; } else { /* must use multiple TDs, fill as much as possible. */ - curlen = 2 * OHCI_PAGE_SIZE - + curlen = 2 * OHCI_PAGE_SIZE - (dataphys & (OHCI_PAGE_SIZE-1)); /* the length must be a multiple of the max size */ curlen -= curlen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize); @@ -569,7 +565,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, #if 0 Static void -ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std, +ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std, ohci_soft_td_t *stdend) { ohci_soft_td_t *p; @@ -641,6 +637,15 @@ ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) splx(s); } +void +ohci_reset(ohci_softc_t *sc) +{ + ohci_shutdown(sc); + /* disable all interrupts and then switch on all desired + interrupts */ + OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); +} + usbd_status ohci_init(ohci_softc_t *sc) { @@ -660,7 +665,7 @@ ohci_init(ohci_softc_t *sc) OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { - printf("%s: unsupported OHCI revision\n", + printf("%s: unsupported OHCI revision\n", USBDEVNAME(sc->sc_bus.bdev)); sc->sc_bus.usbrev = USBREV_UNKNOWN; return (USBD_INVAL); @@ -676,7 +681,7 @@ ohci_init(ohci_softc_t *sc) /* XXX determine alignment by R/W */ /* Allocate the HCCA area. */ - err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, + err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, OHCI_HCCA_ALIGN, &sc->sc_hccadma); if (err) return (err); @@ -728,12 +733,12 @@ ohci_init(ohci_softc_t *sc) sed->next = psed; sed->ed.ed_nexted = htole32(psed->physaddr); } - /* + /* * Fill HCCA interrupt table. The bit reversal is to get * the tree set up properly to spread the interrupts. */ for (i = 0; i < OHCI_NO_INTRS; i++) - sc->sc_hcca->hcca_interrupt_table[revbits[i]] = + sc->sc_hcca->hcca_interrupt_table[revbits[i]] = htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr); #ifdef OHCI_DEBUG @@ -856,7 +861,7 @@ ohci_init(ohci_softc_t *sc) if (ohcidebug > 5) ohci_dumpregs(sc); #endif - + /* Set up the bus struct. */ sc->sc_bus.methods = &ohci_bus_methods; sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); @@ -870,8 +875,6 @@ ohci_init(ohci_softc_t *sc) timeout_set(&sc->sc_tmo_rhsc, ohci_rhsc_enable, sc); #endif - usb_callout_init(sc->sc_tmo_rhsc); - return (USBD_NORMAL_COMPLETION); bad5: @@ -915,23 +918,12 @@ ohci_allocx(struct usbd_bus *bus) usbd_xfer_handle xfer; xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { + if (xfer != NULL) SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer, - xfer->busy_free); - } -#endif - } else { - xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof (struct ohci_xfer)); -#ifdef DIAGNOSTIC - xfer->busy_free = XFER_BUSY; -#endif - } + else + xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); + if (xfer != NULL) + memset(xfer, 0, sizeof *xfer); return (xfer); } @@ -940,14 +932,6 @@ ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) { struct ohci_softc *sc = (struct ohci_softc *)bus; -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; -#endif SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); } @@ -1081,22 +1065,15 @@ ohci_intr(void *p) { ohci_softc_t *sc = p; - if (sc == NULL || sc->sc_dying) - return (0); - /* If we get an interrupt while polling, then just ignore it. */ if (sc->sc_bus.use_polling) { #ifdef DIAGNOSTIC - static int repeat = 0; - if (repeat < 10) { - printf("ohci_intr: ignored interrupt while polling\n"); - ++repeat; - } + printf("ohci_intr: ignored interrupt while polling\n"); #endif return (0); } - return (ohci_intr1(sc)); + return (ohci_intr1(sc)); } Static int @@ -1105,8 +1082,6 @@ ohci_intr1(ohci_softc_t *sc) u_int32_t intrs, eintrs; ohci_physaddr_t done; - DPRINTFN(14,("ohci_intr1: enter\n")); - /* In case the interrupt occurs before initialization has completed. */ if (sc == NULL || sc->sc_hcca == NULL) { #ifdef DIAGNOSTIC @@ -1136,7 +1111,7 @@ ohci_intr1(ohci_softc_t *sc) sc->sc_bus.intr_context++; sc->sc_bus.no_intrs++; - DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", + DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), (u_int)eintrs)); @@ -1148,13 +1123,13 @@ ohci_intr1(ohci_softc_t *sc) sc->sc_overrun_cnt = 0; } /* XXX do what */ - eintrs &= ~OHCI_SO; + intrs &= ~OHCI_SO; } if (eintrs & OHCI_WDH) { ohci_add_done(sc, done &~ OHCI_DONE_INTRS); sc->sc_hcca->hcca_done_head = 0; usb_schedsoftintr(&sc->sc_bus); - eintrs &= ~OHCI_WDH; + intrs &= ~OHCI_WDH; } if (eintrs & OHCI_RD) { printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev)); @@ -1168,28 +1143,24 @@ ohci_intr1(ohci_softc_t *sc) } if (eintrs & OHCI_RHSC) { ohci_rhsc(sc, sc->sc_intrxfer); - /* + intrs &= ~OHCI_RHSC; + + /* * Disable RHSC interrupt for now, because it will be * on until the port has been reset. */ ohci_rhsc_able(sc, 0); - DPRINTFN(2, ("%s: rhsc interrupt disabled\n", - USBDEVNAME(sc->sc_bus.bdev))); - +#if defined (__OpenBSD__) /* Do not allow RHSC interrupts > 1 per second */ - usb_callout(sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc); - eintrs &= ~OHCI_RHSC; + timeout_add(&sc->sc_tmo_rhsc, hz); +#endif } sc->sc_bus.intr_context--; - if (eintrs != 0) { - /* Block unprocessed interrupts. XXX */ - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs); - sc->sc_eintrs &= ~eintrs; - printf("%s: blocking intrs 0x%x\n", - USBDEVNAME(sc->sc_bus.bdev), eintrs); - } + /* Block unprocessed interrupts. XXX */ + OWRITE4(sc, OHCI_INTERRUPT_DISABLE, intrs); + sc->sc_eintrs &= ~intrs; return (1); } @@ -1212,10 +1183,6 @@ ohci_rhsc_enable(void *v_sc) { ohci_softc_t *sc = v_sc; - ohci_rhsc(sc, sc->sc_intrxfer); - DPRINTFN(2, ("%s: rhsc interrupt enabled\n", - USBDEVNAME(sc->sc_bus.bdev))); - ohci_rhsc_able(sc, 1); } @@ -1286,8 +1253,6 @@ ohci_softintr(void *v) usbd_xfer_handle xfer; int len, cc, s; - DPRINTFN(10,("ohci_softintr: enter\n:")); - sc->sc_bus.intr_context++; s = splhardusb(); @@ -1297,7 +1262,7 @@ ohci_softintr(void *v) sc->sc_sidone = NULL; splx(s); - DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone)); + DPRINTFN(10,("ohci_process_done: sdone=%p sidone=%p\n", sdone, sidone)); #ifdef OHCI_DEBUG if (ohcidebug > 10) { @@ -1312,11 +1277,9 @@ ohci_softintr(void *v) DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", std, xfer, xfer ? xfer->hcpriv : 0)); if (xfer == NULL) { - /* - * xfer == NULL: There seems to be no xfer associated + /* xfer == NULL: There seems to be no xfer associated * with this TD. It is tailp that happened to end up on * the done queue. - * Shouldn't happen, but some chips are broken(?). */ continue; } @@ -1350,7 +1313,7 @@ ohci_softintr(void *v) * the endpoint. */ ohci_soft_td_t *p, *n; - struct ohci_pipe *opipe = + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n", @@ -1377,7 +1340,7 @@ ohci_softintr(void *v) #ifdef OHCI_DEBUG if (ohcidebug > 10) { - DPRINTF(("ohci_softintr: ITD done:\n")); + DPRINTF(("ohci_process_done: ITD done:\n")); ohci_dump_itds(sidone); } #endif @@ -1404,7 +1367,7 @@ ohci_softintr(void *v) cc = OHCI_ITD_GET_CC(le32toh(sitd->itd.itd_flags)); if (cc == OHCI_CC_NO_ERROR) { /* XXX compute length for input */ - struct ohci_pipe *opipe = + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; if (sitd->flags & OHCI_CALL_DONE) { opipe->u.iso.inuse -= xfer->nframes; @@ -1420,13 +1383,7 @@ ohci_softintr(void *v) } } - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } - sc->sc_bus.intr_context--; - DPRINTFN(10,("ohci_softintr: done:\n")); } void @@ -1451,7 +1408,7 @@ ohci_device_intr_done(usbd_xfer_handle xfer) ohci_soft_td_t *data, *tail; - DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n", + DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n", xfer, xfer->actlen)); xfer->hcpriv = NULL; @@ -1464,9 +1421,9 @@ ohci_device_intr_done(usbd_xfer_handle xfer) return; } tail->xfer = NULL; - + data->td.td_flags = htole32( - OHCI_TD_IN | OHCI_TD_NOCC | + OHCI_TD_IN | OHCI_TD_NOCC | OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); if (xfer->flags & USBD_SHORT_XFER_OK) data->td.td_flags |= htole32(OHCI_TD_R); @@ -1489,7 +1446,7 @@ ohci_device_intr_done(usbd_xfer_handle xfer) void ohci_device_bulk_done(usbd_xfer_handle xfer) { - DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n", + DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n", xfer, xfer->actlen)); xfer->hcpriv = NULL; @@ -1505,7 +1462,7 @@ ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer) int hstatus; hstatus = OREAD4(sc, OHCI_RH_STATUS); - DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", + DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", sc, xfer, hstatus)); if (xfer == NULL) { @@ -1558,8 +1515,6 @@ ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer) xfer->status = USBD_IN_PROGRESS; for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { usb_delay_ms(&sc->sc_bus, 1); - if (sc->sc_dying) - break; intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs)); #ifdef OHCI_DEBUG @@ -1584,15 +1539,6 @@ void ohci_poll(struct usbd_bus *bus) { ohci_softc_t *sc = (ohci_softc_t *)bus; -#ifdef OHCI_DEBUG - static int last; - int new; - new = OREAD4(sc, OHCI_INTERRUPT_STATUS); - if (new != last) { - DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new)); - last = new; - } -#endif if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) ohci_intr1(sc); @@ -1619,7 +1565,7 @@ ohci_device_request(usbd_xfer_handle xfer) DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, " "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), len, addr, + UGETW(req->wIndex), len, addr, opipe->pipe.endpoint->edesc->bEndpointAddress)); setup = opipe->tail.td; @@ -1705,15 +1651,11 @@ ohci_device_request(usbd_xfer_handle xfer) } splx(s); -#ifdef OHCI_DEBUG - if (ohcidebug > 20) { +#if 0 + if (ohcidebug > 10) { delay(10000); DPRINTF(("ohci_device_request: status=%x\n", OREAD4(sc, OHCI_COMMAND_STATUS))); - ohci_dumpregs(sc); - printf("ctrl head:\n"); - ohci_dump_ed(sc->sc_ctrl_head); - printf("sed:\n"); ohci_dump_ed(sed); ohci_dump_tds(setup); } @@ -1735,8 +1677,6 @@ ohci_device_request(usbd_xfer_handle xfer) void ohci_add_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) { - DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); - SPLUSBCHECK; sed->next = head->next; sed->ed.ed_nexted = head->ed.ed_nexted; @@ -1750,7 +1690,7 @@ ohci_add_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) void ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) { - ohci_soft_ed_t *p; + ohci_soft_ed_t *p; SPLUSBCHECK; @@ -1800,7 +1740,7 @@ ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) int h = HASH(a); ohci_soft_td_t *std; - for (std = LIST_FIRST(&sc->sc_hash_tds[h]); + for (std = LIST_FIRST(&sc->sc_hash_tds[h]); std != NULL; std = LIST_NEXT(std, hnext)) if (std->physaddr == a) @@ -1816,7 +1756,7 @@ ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) SPLUSBCHECK; - DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", + DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", sitd, (u_long)sitd->physaddr)); LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); @@ -1828,7 +1768,7 @@ ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) { SPLUSBCHECK; - DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", + DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", sitd, (u_long)sitd->physaddr)); LIST_REMOVE(sitd, hnext); @@ -1840,7 +1780,7 @@ ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) int h = HASH(a); ohci_soft_itd_t *sitd; - for (sitd = LIST_FIRST(&sc->sc_hash_itds[h]); + for (sitd = LIST_FIRST(&sc->sc_hash_itds[h]); sitd != NULL; sitd = LIST_NEXT(sitd, hnext)) if (sitd->physaddr == a) @@ -1851,32 +1791,15 @@ ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) void ohci_timeout(void *addr) { - struct ohci_xfer *oxfer = addr; - struct ohci_pipe *opipe = (struct ohci_pipe *)oxfer->xfer.pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - - DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer)); - - if (sc->sc_dying) { - ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT); - return; - } - - /* Execute the abort in a process context. */ - usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr); - usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task); -} - -void -ohci_timeout_task(void *addr) -{ usbd_xfer_handle xfer = addr; int s; - DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer)); + DPRINTF(("ohci_timeout: xfer=%p\n", xfer)); s = splusb(); + xfer->device->bus->intr_context++; ohci_abort_xfer(xfer, USBD_TIMEOUT); + xfer->device->bus->intr_context--; splx(s); } @@ -1893,19 +1816,19 @@ ohci_dump_td(ohci_soft_td_t *std) { char sbuf[128]; - bitmask_snprintf((u_int32_t)le32toh(std->td.td_flags), + bitmask_snprintf((int)le32toh(std->td.td_flags), "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE", sbuf, sizeof(sbuf)); - printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx " - "nexttd=0x%08lx be=0x%08lx\n", - std, (u_long)std->physaddr, sbuf, - OHCI_TD_GET_DI(le32toh(std->td.td_flags)), - OHCI_TD_GET_EC(le32toh(std->td.td_flags)), - OHCI_TD_GET_CC(le32toh(std->td.td_flags)), - (u_long)le32toh(std->td.td_cbp), - (u_long)le32toh(std->td.td_nexttd), - (u_long)le32toh(std->td.td_be)); + DPRINTF(("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx " + "nexttd=0x%08lx be=0x%08lx\n", + std, (u_long)std->physaddr, sbuf, + OHCI_TD_GET_DI(le32toh(std->td.td_flags)), + OHCI_TD_GET_EC(le32toh(std->td.td_flags)), + OHCI_TD_GET_CC(le32toh(std->td.td_flags)), + (u_long)le32toh(std->td.td_cbp), + (u_long)le32toh(std->td.td_nexttd), + (u_long)le32toh(std->td.td_be))); } void @@ -1913,20 +1836,20 @@ ohci_dump_itd(ohci_soft_itd_t *sitd) { int i; - printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n" - "bp0=0x%08lx next=0x%08lx be=0x%08lx\n", - sitd, (u_long)sitd->physaddr, - OHCI_ITD_GET_SF(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_DI(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_FC(le32toh(sitd->itd.itd_flags)), - OHCI_ITD_GET_CC(le32toh(sitd->itd.itd_flags)), - (u_long)le32toh(sitd->itd.itd_bp0), - (u_long)le32toh(sitd->itd.itd_nextitd), - (u_long)le32toh(sitd->itd.itd_be)); + DPRINTF(("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n" + "bp0=0x%08lx next=0x%08lx be=0x%08lx\n", + sitd, (u_long)sitd->physaddr, + OHCI_ITD_GET_SF(le32toh(sitd->itd.itd_flags)), + OHCI_ITD_GET_DI(le32toh(sitd->itd.itd_flags)), + OHCI_ITD_GET_FC(le32toh(sitd->itd.itd_flags)), + OHCI_ITD_GET_CC(le32toh(sitd->itd.itd_flags)), + (u_long)le32toh(sitd->itd.itd_bp0), + (u_long)le32toh(sitd->itd.itd_nextitd), + (u_long)le32toh(sitd->itd.itd_be))); for (i = 0; i < OHCI_ITD_NOFFSET; i++) - printf("offs[%d]=0x%04x ", i, - (u_int)le16toh(sitd->itd.itd_offset[i])); - printf("\n"); + DPRINTF(("offs[%d]=0x%04x ", i, + (u_int)le16toh(sitd->itd.itd_offset[i]))); + DPRINTF(("\n")); } void @@ -1941,21 +1864,21 @@ ohci_dump_ed(ohci_soft_ed_t *sed) { char sbuf[128], sbuf2[128]; - bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_flags), + bitmask_snprintf((int)le32toh(sed->ed.ed_flags), "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO", sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_headp), + bitmask_snprintf((u_long)le32toh(sed->ed.ed_headp), "\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2)); - printf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\n" - "tailp=0x%08lx headflags=%s headp=0x%08lx nexted=0x%08lx\n", - sed, (u_long)sed->physaddr, - OHCI_ED_GET_FA(le32toh(sed->ed.ed_flags)), - OHCI_ED_GET_EN(le32toh(sed->ed.ed_flags)), - OHCI_ED_GET_MAXP(le32toh(sed->ed.ed_flags)), sbuf, - (u_long)le32toh(sed->ed.ed_tailp), sbuf2, - (u_long)le32toh(sed->ed.ed_headp), - (u_long)le32toh(sed->ed.ed_nexted)); + DPRINTF(("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d %s\ntailp=0x%08lx " + "headflags=%s headp=0x%08lx nexted=0x%08lx\n", + sed, (u_long)sed->physaddr, + OHCI_ED_GET_FA(le32toh(sed->ed.ed_flags)), + OHCI_ED_GET_EN(le32toh(sed->ed.ed_flags)), + OHCI_ED_GET_MAXP(le32toh(sed->ed.ed_flags)), sbuf, + (u_long)le32toh(sed->ed.ed_tailp), sbuf2, + (u_long)le32toh(sed->ed.ed_headp), + (u_long)le32toh(sed->ed.ed_nexted))); } #endif @@ -1980,9 +1903,6 @@ ohci_open(usbd_pipe_handle pipe) DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", pipe, addr, ed->bEndpointAddress, sc->sc_addr)); - if (sc->sc_dying) - return (USBD_IOERROR); - std = NULL; sed = NULL; @@ -2026,17 +1946,17 @@ ohci_open(usbd_pipe_handle pipe) fmt = OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD; } sed->ed.ed_flags = htole32( - OHCI_ED_SET_FA(addr) | + OHCI_ED_SET_FA(addr) | OHCI_ED_SET_EN(ed->bEndpointAddress) | - (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) | - fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); + (dev->lowspeed ? OHCI_ED_SPEED : 0) | fmt | + OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); sed->ed.ed_headp = sed->ed.ed_tailp = htole32(tdphys); switch (xfertype) { case UE_CONTROL: pipe->methods = &ohci_device_ctrl_methods; - err = usb_allocmem(&sc->sc_bus, - sizeof(usb_device_request_t), + err = usb_allocmem(&sc->sc_bus, + sizeof(usb_device_request_t), 0, &opipe->u.ctl.reqdma); if (err) goto bad; @@ -2071,7 +1991,7 @@ ohci_open(usbd_pipe_handle pipe) ohci_free_sed(sc, sed); bad0: return (USBD_NOMEM); - + } /* @@ -2089,25 +2009,22 @@ ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) s = splusb(); #ifdef DIAGNOSTIC sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != + if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) { + ohci_physaddr_t td = le32toh(sed->ed.ed_headp); ohci_soft_td_t *std; - std = ohci_hash_find_td(sc, le32toh(sed->ed.ed_headp)); + for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]); + std != NULL; + std = LIST_NEXT(std, hnext)) + if (std->physaddr == td) + break; printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " "tl=0x%x pipe=%p, std=%p\n", sed, (int)le32toh(sed->ed.ed_headp), (int)le32toh(sed->ed.ed_tailp), pipe, std); -#ifdef USB_DEBUG - usbd_dump_pipe(&opipe->pipe); -#endif -#ifdef OHCI_DEBUG - ohci_dump_ed(sed); - if (std) - ohci_dump_td(std); -#endif usb_delay_ms(&sc->sc_bus, 2); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != + if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) printf("ohci_close_pipe: pipe still not empty\n"); } @@ -2117,7 +2034,7 @@ ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) ohci_free_sed(sc, opipe->sed); } -/* +/* * Abort a device request. * If this routine is called at splusb() it guarantees that the request * will be removed from the hardware scheduling and that the callback @@ -2131,96 +2048,68 @@ void ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) { struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *p, *n; - ohci_physaddr_t headp; - int s, hit; + ohci_soft_ed_t *sed; - DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe, - sed)); + DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p\n", xfer, opipe)); - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer); - usb_transfer_complete(xfer); - splx(s); - } + xfer->status = status; - if (xfer->device->bus->intr_context || !curproc) - panic("ohci_abort_xfer: not in process context\n"); - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - s = splusb(); - xfer->status = status; /* make software ignore it */ usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer); - splx(s); + + sed = opipe->sed; DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed)); sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */ - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. Also make sure the soft interrupt routine - * has run. - */ - usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */ +#if 1 + if (xfer->device->bus->intr_context) { + /* We have no process context, so we can't use tsleep(). */ + usb_callout(xfer->pipe->abort_handle, + hz / USB_FRAMES_PER_SECOND, ohci_abort_xfer_end, xfer); + } else { +#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) + KASSERT(intr_nesting_level == 0, + ("ohci_abort_req in interrupt context")); +#endif + usb_delay_ms(opipe->pipe.device->bus, 1); + ohci_abort_xfer_end(xfer); + } +#else + delay(1000); + ohci_abort_xfer_end(xfer); +#endif +} + +void +ohci_abort_xfer_end(void *v) +{ + usbd_xfer_handle xfer = v; + struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; + ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; + ohci_soft_ed_t *sed; + ohci_soft_td_t *p, *n; + int s; + s = splusb(); - sc->sc_softwake = 1; - usb_schedsoftintr(&sc->sc_bus); - tsleep(&sc->sc_softwake, PZERO, "ohciab", 0); - splx(s); - /* - * Step 3: Remove any vestiges of the xfer from the hardware. - * The complication here is that the hardware may have executed - * beyond the xfer we're trying to abort. So as we're scanning - * the TDs of this xfer we check if the hardware points to - * any of them. - */ - s = splusb(); /* XXX why? */ p = xfer->hcpriv; #ifdef DIAGNOSTIC if (p == NULL) { splx(s); - printf("ohci_abort_xfer: hcpriv is NULL\n"); + printf("ohci_abort_xfer: hcpriv==0\n"); return; } #endif -#ifdef OHCI_DEBUG - if (ohcidebug > 1) { - DPRINTF(("ohci_abort_xfer: sed=\n")); - ohci_dump_ed(sed); - ohci_dump_tds(p); - } -#endif - headp = le32toh(sed->ed.ed_headp) & OHCI_HEADMASK; - hit = 0; for (; p->xfer == xfer; p = n) { - hit |= headp == p->physaddr; n = p->nexttd; ohci_free_std(sc, p); } - /* Zap headp register if hardware pointed inside the xfer. */ - if (hit) { - DPRINTFN(1,("ohci_abort_xfer: set hd=0x08%x, tl=0x%08x\n", - (int)p->physaddr, (int)le32toh(sed->ed.ed_tailp))); - sed->ed.ed_headp = htole32(p->physaddr); /* unlink TDs */ - } else { - DPRINTFN(1,("ohci_abort_xfer: no hit\n")); - } - /* - * Step 4: Turn on hardware again. - */ + sed = opipe->sed; + DPRINTFN(2,("ohci_abort_xfer: set hd=%x, tl=%x\n", + (int)p->physaddr, (int)le32toh(sed->ed.ed_tailp))); + sed->ed.ed_headp = htole32(p->physaddr); /* unlink TDs */ sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */ - /* - * Step 5: Execute callback. - */ usb_transfer_complete(xfer); splx(s); @@ -2235,7 +2124,7 @@ Static usb_device_descriptor_t ohci_devd = { {0x00, 0x01}, /* USB version */ UDCLASS_HUB, /* class */ UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, + 0, /* protocol */ 64, /* max packet */ {0},{0},{0x00,0x01}, /* device id */ 1,2,0, /* string indicies */ @@ -2263,7 +2152,7 @@ Static usb_interface_descriptor_t ohci_ifcd = { 1, UICLASS_HUB, UISUBCLASS_HUB, - UIPROTO_FSHUB, + 0, 0 }; @@ -2287,7 +2176,10 @@ Static usb_hub_descriptor_t ohci_hubd = { }; Static int -ohci_str(usb_string_descriptor_t *p, int l, const char *s) +ohci_str(p, l, s) + usb_string_descriptor_t *p; + int l; + char *s; { int i; @@ -2343,7 +2235,7 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer) #endif req = &xfer->request; - DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", + DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); len = UGETW(req->wLength); @@ -2358,7 +2250,7 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer) case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* + /* * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops * for the integrated root hub. */ @@ -2527,13 +2419,13 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer) hubd = ohci_hubd; hubd.bNbrPorts = sc->sc_noport; USETW(hubd.wHubCharacteristics, - (v & OHCI_NPS ? UHD_PWR_NO_SWITCH : + (v & OHCI_NPS ? UHD_PWR_NO_SWITCH : v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL) /* XXX overcurrent */ ); hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v); v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B); - for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) + for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8) hubd.DeviceRemovable[i++] = (u_int8_t)v; hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i; l = min(len, hubd.bDescLength); @@ -2590,13 +2482,8 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer) DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n", index)); OWRITE4(sc, port, UPS_RESET); - for (i = 0; i < 5; i++) { - usb_delay_ms(&sc->sc_bus, - USB_PORT_ROOT_RESET_DELAY); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto ret; - } + for (i = 0; i < 10; i++) { + usb_delay_ms(&sc->sc_bus, 10); /* XXX */ if ((OREAD4(sc, port) & UPS_RESET) == 0) break; } @@ -2691,7 +2578,7 @@ Static void ohci_root_intr_close(usbd_pipe_handle pipe) { ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - + DPRINTF(("ohci_root_intr_close\n")); sc->sc_intrxfer = NULL; @@ -2894,7 +2781,7 @@ ohci_device_bulk_abort(usbd_xfer_handle xfer) ohci_abort_xfer(xfer, USBD_CANCELLED); } -/* +/* * Close a device bulk pipe. */ Static void @@ -2956,7 +2843,7 @@ ohci_device_intr_start(usbd_xfer_handle xfer) tail->xfer = NULL; data->td.td_flags = htole32( - OHCI_TD_IN | OHCI_TD_NOCC | + OHCI_TD_IN | OHCI_TD_NOCC | OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY); if (xfer->flags & USBD_SHORT_XFER_OK) data->td.td_flags |= htole32(OHCI_TD_R); @@ -3029,7 +2916,7 @@ ohci_device_intr_close(usbd_pipe_handle pipe) pipe, nslots, pos)); s = splusb(); sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != + if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) usb_delay_ms(&sc->sc_bus, 2); @@ -3092,7 +2979,7 @@ ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival) bestbw = bw; } } - DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", + DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", best, slow, shigh, bestbw)); s = splusb(); @@ -3148,7 +3035,7 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) ohci_softc_t *sc = (ohci_softc_t *)dev->bus; ohci_soft_ed_t *sed = opipe->sed; struct iso *iso = &opipe->u.iso; - ohci_soft_itd_t *sitd, *nsitd; + ohci_soft_itd_t *sitd, *nsitd; ohci_physaddr_t buf, offs, noffs, bp0; int i, ncur, nframes; int s; @@ -3163,7 +3050,7 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) if (iso->next == -1) { /* Not in use yet, schedule it a few frames ahead. */ iso->next = le32toh(sc->sc_hcca->hcca_frame_number) + 5; - DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n", + DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n", iso->next)); } @@ -3177,7 +3064,7 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) noffs = offs + xfer->frlengths[i]; if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */ OHCI_PAGE(buf + noffs) > bp0 + OHCI_PAGE_SIZE) { /* too many page crossings */ - + /* Allocate next ITD */ nsitd = ohci_alloc_sitd(sc); if (nsitd == NULL) { @@ -3189,7 +3076,7 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) /* Fill current ITD */ sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | + OHCI_ITD_NOCC | OHCI_ITD_SET_SF(iso->next) | OHCI_ITD_SET_DI(6) | /* delay intr a little */ OHCI_ITD_SET_FC(ncur)); @@ -3201,7 +3088,7 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) sitd->flags = 0; sitd = nsitd; - iso->next = iso->next + ncur; + iso->next = iso->next + ncur; bp0 = OHCI_PAGE(buf + offs); ncur = 0; } @@ -3211,13 +3098,13 @@ ohci_device_isoc_enter(usbd_xfer_handle xfer) nsitd = ohci_alloc_sitd(sc); if (nsitd == NULL) { /* XXX what now? */ - printf("%s: isoc TD alloc failed\n", + printf("%s: isoc TD alloc failed\n", USBDEVNAME(sc->sc_bus.bdev)); return; } /* Fixup last used ITD */ sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | + OHCI_ITD_NOCC | OHCI_ITD_SET_SF(iso->next) | OHCI_ITD_SET_DI(0) | OHCI_ITD_SET_FC(ncur)); @@ -3273,7 +3160,7 @@ ohci_device_isoc_start(usbd_xfer_handle xfer) #ifdef DIAGNOSTIC if (xfer->status != USBD_IN_PROGRESS) - printf("ohci_device_isoc_start: not in progress %p\n", xfer); + printf("uhci_device_isoc_start: not in progress %p\n", xfer); #endif /* XXX anything to do? */ @@ -3295,7 +3182,7 @@ ohci_device_isoc_abort(usbd_xfer_handle xfer) DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && + if (xfer->status != USBD_NOT_STARTED && xfer->status != USBD_IN_PROGRESS) { splx(s); printf("ohci_device_isoc_abort: early return\n"); @@ -3343,7 +3230,7 @@ ohci_device_isoc_done(usbd_xfer_handle xfer) { struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus; - ohci_soft_itd_t *sitd, *nsitd; + ohci_soft_itd_t *sitd, *nsitd; DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer)); diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 19f4d228691..396f9dacf65 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ohcivar.h,v 1.16 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ohcivar.h,v 1.30 2001/12/31 12:20:35 augustss Exp $ */ +/* $OpenBSD: ohcivar.h,v 1.17 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ohcivar.h,v 1.28 2001/09/28 23:57:21 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.13 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -106,7 +106,6 @@ typedef struct ohci_softc { int sc_noport; u_int8_t sc_addr; /* device address */ u_int8_t sc_conf; /* device configuration */ - char sc_softwake; ohci_soft_ed_t *sc_freeeds; ohci_soft_td_t *sc_freetds; @@ -139,18 +138,13 @@ typedef struct ohci_softc { char sc_dying; } ohci_softc_t; -struct ohci_xfer { - struct usbd_xfer xfer; - struct usb_task abort_task; -}; - -#define OXFER(xfer) ((struct ehci_xfer *)(xfer)) - +void ohci_reset(ohci_softc_t *); usbd_status ohci_init(ohci_softc_t *); int ohci_intr(void *); #if defined(__NetBSD__) || defined(__OpenBSD__) int ohci_detach(ohci_softc_t *, int); int ohci_activate(device_ptr_t, enum devact); #endif +Static void ohci_rhsc_enable(void *sc); #define MS_TO_TICKS(ms) ((ms) * hz / 1000) diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c index eb32bd3ad49..0c2a8d88ff6 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ucom.c,v 1.10 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ +/* $OpenBSD: ucom.c,v 1.11 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ucom.c,v 1.39 2001/08/16 22:31:24 augustss Exp $ */ /* * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -85,16 +85,12 @@ int ucomdebug = 0; #define UCOMUNIT_MASK 0x3ffff #define UCOMDIALOUT_MASK 0x80000 #define UCOMCALLUNIT_MASK 0x40000 - -#define LINESW(tp, func) ((tp)->t_linesw->func) #endif #if defined(__OpenBSD__) #define UCOMUNIT_MASK 0x3f #define UCOMDIALOUT_MASK 0x80 #define UCOMCALLUNIT_MASK 0x40 - -#define LINESW(tp, func) (linesw[(tp)->t_line].func) #endif #define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) @@ -151,7 +147,7 @@ Static int ucomparam(struct tty *, struct termios *); Static void ucomstart(struct tty *); Static void ucom_shutdown(struct ucom_softc *); Static int ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t, - int, usb_proc_ptr); + int, struct proc *); Static void ucom_dtr(struct ucom_softc *, int); Static void ucom_rts(struct ucom_softc *, int); Static void ucom_break(struct ucom_softc *, int); @@ -301,7 +297,7 @@ ucom_shutdown(struct ucom_softc *sc) } int -ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p) +ucomopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = UCOMUNIT(dev); usbd_status err; @@ -467,7 +463,7 @@ ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p) if (error) goto bad; - error = (*LINESW(tp, l_open))(dev, tp); + error = (*linesw[tp->t_line].l_open)(dev, tp); if (error) goto bad; @@ -508,7 +504,7 @@ bad: } int -ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +ucomclose(dev_t dev, int flag, int mode, struct proc *p) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; struct tty *tp = sc->sc_tty; @@ -519,7 +515,7 @@ ucomclose(dev_t dev, int flag, int mode, usb_proc_ptr p) sc->sc_refcnt++; - (*LINESW(tp, l_close))(tp, flag); + (*linesw[tp->t_line].l_close)(tp, flag); ttyclose(tp); #if defined(__NetBSD__) @@ -555,7 +551,7 @@ ucomread(dev_t dev, struct uio *uio, int flag) return (EIO); sc->sc_refcnt++; - error = (*LINESW(tp, l_read))(tp, uio, flag); + error = ((*linesw[tp->t_line].l_read)(tp, uio, flag)); if (--sc->sc_refcnt < 0) usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); @@ -572,15 +568,18 @@ ucomwrite(dev_t dev, struct uio *uio, int flag) return (EIO); sc->sc_refcnt++; - error = (*LINESW(tp, l_write))(tp, uio, flag); + error = ((*linesw[tp->t_line].l_write)(tp, uio, flag)); if (--sc->sc_refcnt < 0) usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); } -#if defined(__NetBSD__) +#if 0 int -ucompoll(dev_t dev, int events, usb_proc_ptr p) +ucompoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; struct tty *tp = sc->sc_tty; @@ -590,7 +589,7 @@ ucompoll(dev_t dev, int events, usb_proc_ptr p) return (EIO); sc->sc_refcnt++; - error = (*LINESW(tp, l_poll))(tp, events, p); + error = ((*linesw[tp->t_line].l_poll)(tp, events, p)); if (--sc->sc_refcnt < 0) usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); @@ -607,7 +606,7 @@ ucomtty(dev_t dev) } int -ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) +ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; int error; @@ -621,7 +620,7 @@ ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) Static int ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data, - int flag, usb_proc_ptr p) + int flag, struct proc *p) { struct tty *tp = sc->sc_tty; int error; @@ -632,7 +631,7 @@ ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data, DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd)); - error = (*LINESW(tp, l_ioctl))(tp, cmd, data, flag, p); + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); if (error >= 0) return (error); @@ -806,7 +805,7 @@ ucom_status_change(struct ucom_softc *sc) sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, &sc->sc_lsr, &sc->sc_msr); if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) - (*LINESW(tp, l_modem))(tp, + (*linesw[tp->t_line].l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); } else { sc->sc_lsr = 0; @@ -867,7 +866,7 @@ ucomparam(struct tty *tp, struct termios *t) * explicit request. */ DPRINTF(("ucomparam: l_modem\n")); - (void) (*LINESW(tp, l_modem))(tp, 1 /* XXX carrier */ ); + (void) (*linesw[tp->t_line].l_modem)(tp, 1 /* XXX carrier */ ); #if 0 XXX what if the hardware is not open @@ -1034,7 +1033,7 @@ ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) CLR(tp->t_state, TS_FLUSH); else ndflush(&tp->t_outq, cc); - (*LINESW(tp, l_start))(tp); + (*linesw[tp->t_line].l_start)(tp); splx(s); return; @@ -1068,7 +1067,7 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) { struct ucom_softc *sc = (struct ucom_softc *)p; struct tty *tp = sc->sc_tty; - int (*rint)(int c, struct tty *tp) = LINESW(tp, l_rint); + int (*rint)(int c, struct tty *tp) = linesw[tp->t_line].l_rint; usbd_status err; u_int32_t cc; u_char *cp; @@ -1169,9 +1168,9 @@ ucomsubmatch(struct device *parent, void *match, void *aux) ucomsubmatch(struct device *parent, struct cfdata *cf, void *aux) #endif { - struct ucom_attach_args *uca = aux; + struct ucom_attach_args *uca = aux; #if defined(__OpenBSD__) - struct cfdata *cf = match; + struct cfdata *cf = match; #endif if (uca->portno != UCOM_UNK_PORTNO && diff --git a/sys/dev/usb/ucomvar.h b/sys/dev/usb/ucomvar.h index 0e4e9b40a7a..3899af5c7bd 100644 --- a/sys/dev/usb/ucomvar.h +++ b/sys/dev/usb/ucomvar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: ucomvar.h,v 1.9 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ucomvar.h,v 1.10 2001/12/31 12:15:21 augustss Exp $ */ +/* $OpenBSD: ucomvar.h,v 1.10 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -56,7 +56,7 @@ struct ucom_methods { #define UCOM_SET_BREAK 3 int (*ucom_param)(void *sc, int portno, struct termios *); int (*ucom_ioctl)(void *sc, int portno, u_long cmd, - caddr_t data, int flag, usb_proc_ptr p); + caddr_t data, int flag, struct proc *p); int (*ucom_open)(void *sc, int portno); void (*ucom_close)(void *sc, int portno); void (*ucom_read)(void *sc, int portno, u_char **ptr, u_int32_t *count); @@ -105,11 +105,10 @@ struct ucom_attach_args { void *arg; }; -#if defined(__NetBSD__) -int ucomsubmatch(struct device *, struct cfdata *, void *); +int ucomprint(void *aux, const char *pnp); +#if defined(__OpenBSD__) +int ucomsubmatch(struct device *parent, void *cf, void *aux); #else -int ucomsubmatch(struct device *, void *, void *); +int ucomsubmatch(struct device *parent, struct cfdata *cf, void *aux); #endif - -int ucomprint(void *aux, const char *pnp); void ucom_status_change(struct ucom_softc *); diff --git a/sys/dev/usb/udsbr.c b/sys/dev/usb/udsbr.c deleted file mode 100644 index dc7a35abb09..00000000000 --- a/sys/dev/usb/udsbr.c +++ /dev/null @@ -1,279 +0,0 @@ -/* $OpenBSD: udsbr.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: udsbr.c,v 1.6 2002/02/12 10:51:49 tron Exp $ */ - -/* - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Driver for the D-Link DSB-R100 FM radio. - * I apologize for the magic hex constants, but this is what happens - * when you have to reverse engineer the driver. - * Parts of the code borrowed from Linux and parts from Warner Losh's - * FreeBSD driver. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> - -#include <sys/radioio.h> -#include <dev/radio_if.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include <dev/usb/usbdevs.h> - -#ifdef UDSBR_DEBUG -#define DPRINTF(x) if (udsbrdebug) logprintf x -#define DPRINTFN(n,x) if (udsbrdebug>(n)) logprintf x -int udsbrdebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UDSBR_CONFIG_NO 1 - -Static int udsbr_get_info(void *, struct radio_info *); -Static int udsbr_set_info(void *, struct radio_info *); - -struct radio_hw_if udsbr_hw_if = { - NULL, /* open */ - NULL, /* close */ - udsbr_get_info, - udsbr_set_info, - NULL -}; - -struct udsbr_softc { - USBBASEDEVICE sc_dev; - usbd_device_handle sc_udev; - - char sc_mute; - char sc_vol; - u_int32_t sc_freq; - - struct device *sc_child; - - char sc_dying; -}; - -Static int udsbr_req(struct udsbr_softc *sc, int ureq, int value, - int index); -Static void udsbr_start(struct udsbr_softc *sc); -Static void udsbr_stop(struct udsbr_softc *sc); -Static void udsbr_setfreq(struct udsbr_softc *sc, int freq); -Static int udsbr_status(struct udsbr_softc *sc); - -USB_DECLARE_DRIVER(udsbr); - -USB_MATCH(udsbr) -{ - USB_MATCH_START(udsbr, uaa); - - DPRINTFN(50,("udsbr_match\n")); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - if (uaa->vendor != USB_VENDOR_CYPRESS || - uaa->product != USB_PRODUCT_CYPRESS_FMRADIO) - return (UMATCH_NONE); - return (UMATCH_VENDOR_PRODUCT); -} - -USB_ATTACH(udsbr) -{ - USB_ATTACH_START(udsbr, sc, uaa); - usbd_device_handle dev = uaa->device; - char devinfo[1024]; - usbd_status err; - - DPRINTFN(10,("udsbr_attach: sc=%p\n", sc)); - - usbd_devinfo(dev, 0, devinfo); - USB_ATTACH_SETUP; - printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - - err = usbd_set_config_no(dev, UDSBR_CONFIG_NO, 1); - if (err) { - printf("%s: setting config no failed\n", - USBDEVNAME(sc->sc_dev)); - USB_ATTACH_ERROR_RETURN; - } - - sc->sc_udev = dev; - - DPRINTFN(10, ("udsbr_attach: %p\n", sc->sc_udev)); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - sc->sc_child = radio_attach_mi(&udsbr_hw_if, sc, USBDEV(sc->sc_dev)); - - USB_ATTACH_SUCCESS_RETURN; -} - -USB_DETACH(udsbr) -{ - USB_DETACH_START(udsbr, sc); - int rv = 0; - - if (sc->sc_child != NULL) - rv = config_detach(sc->sc_child, flags); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - return (rv); -} - -int -udsbr_activate(device_ptr_t self, enum devact act) -{ - struct udsbr_softc *sc = (struct udsbr_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - break; - - case DVACT_DEACTIVATE: - sc->sc_dying = 1; - if (sc->sc_child != NULL) - rv = config_deactivate(sc->sc_child); - break; - } - return (rv); -} - -int -udsbr_req(struct udsbr_softc *sc, int ureq, int value, int index) -{ - usb_device_request_t req; - usbd_status err; - u_char data; - - DPRINTFN(1,("udsbr_req: ureq=0x%02x value=0x%04x index=0x%04x\n", - ureq, value, index)); - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = ureq; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_udev, &req, &data); - if (err) { - printf("%s: request failed err=%d\n", USBDEVNAME(sc->sc_dev), - err); - } - return !(data & 1); -} - -void -udsbr_start(struct udsbr_softc *sc) -{ - (void)udsbr_req(sc, 0x00, 0x0000, 0x00c7); - (void)udsbr_req(sc, 0x02, 0x0001, 0x0000); -} - -void -udsbr_stop(struct udsbr_softc *sc) -{ - (void)udsbr_req(sc, 0x00, 0x0016, 0x001c); - (void)udsbr_req(sc, 0x02, 0x0000, 0x0000); -} - -void -udsbr_setfreq(struct udsbr_softc *sc, int freq) -{ - DPRINTF(("udsbr_setfreq: setfreq=%d\n", freq)); - /* - * Freq now is in Hz. We need to convert it to the frequency - * that the radio wants. This frequency is 10.7MHz above - * the actual frequency. We then need to convert to - * units of 12.5kHz. We add one to the IFM to make rounding - * easier. - */ - freq = (freq * 1000 + 10700001) / 12500; - (void)udsbr_req(sc, 0x01, (freq >> 8) & 0xff, freq & 0xff); - (void)udsbr_req(sc, 0x00, 0x0096, 0x00b7); - usbd_delay_ms(sc->sc_udev, 240); /* wait for signal to settle */ -} - -int -udsbr_status(struct udsbr_softc *sc) -{ - return (udsbr_req(sc, 0x00, 0x0000, 0x0024)); -} - - -int -udsbr_get_info(void *v, struct radio_info *ri) -{ - struct udsbr_softc *sc = v; - - ri->mute = sc->sc_mute; - ri->volume = sc->sc_vol ? 255 : 0; - ri->caps = RADIO_CAPS_DETECT_STEREO; - ri->rfreq = 0; - ri->lock = 0; - ri->freq = sc->sc_freq; - ri->info = udsbr_status(sc) ? RADIO_INFO_STEREO : 0; - - return (0); -} - -int -udsbr_set_info(void *v, struct radio_info *ri) -{ - struct udsbr_softc *sc = v; - - sc->sc_mute = ri->mute != 0; - sc->sc_vol = ri->volume != 0; - sc->sc_freq = ri->freq; - udsbr_setfreq(sc, sc->sc_freq); - - if (sc->sc_mute || sc->sc_vol == 0) - udsbr_stop(sc); - else - udsbr_start(sc); - - return (0); -} diff --git a/sys/dev/usb/uftdi.c b/sys/dev/usb/uftdi.c index a86b3785fc4..f24ac10e7ea 100644 --- a/sys/dev/usb/uftdi.c +++ b/sys/dev/usb/uftdi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uftdi.c,v 1.4 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uftdi.c,v 1.9 2001/12/17 14:34:37 ichiro Exp $ */ +/* $OpenBSD: uftdi.c,v 1.5 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uftdi.c,v 1.6 2001/01/23 21:56:17 augustss Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -95,19 +95,15 @@ struct uftdi_softc { device_ptr_t sc_subdev; u_char sc_dying; - - u_int last_lcr; }; Static void uftdi_get_status(void *, int portno, u_char *lsr, u_char *msr); Static void uftdi_set(void *, int, int, int); Static int uftdi_param(void *, int, struct termios *); Static int uftdi_open(void *sc, int portno); -Static void uftdi_read(void *sc, int portno, u_char **ptr, - u_int32_t *count); +Static void uftdi_read(void *sc, int portno, u_char **ptr,u_int32_t *count); Static void uftdi_write(void *sc, int portno, u_char *to, u_char *from, u_int32_t *count); -Static void uftdi_break(void *sc, int portno, int onoff); struct ucom_methods uftdi_methods = { uftdi_get_status, @@ -380,7 +376,7 @@ uftdi_set(void *vsc, int portno, int reg, int onoff) ctl = onoff ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; break; case UCOM_SET_BREAK: - uftdi_break(sc, portno, onoff); + /* XXX how do we set break? */ return; default: return; @@ -460,8 +456,6 @@ uftdi_param(void *vsc, int portno, struct termios *t) data |= FTDI_SIO_SET_DATA_BITS(8); break; } - sc->last_lcr = data; - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = FTDI_SIO_SET_DATA; USETW(req.wValue, data); @@ -490,27 +484,3 @@ uftdi_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) if (lsr != NULL) *lsr = sc->sc_lsr; } - -void -uftdi_break(void *vsc, int portno, int onoff) -{ - struct uftdi_softc *sc = vsc; - usb_device_request_t req; - int data; - - DPRINTF(("uftdi_break: sc=%p, port=%d onoff=%d\n", vsc, portno, - onoff)); - - if (onoff) { - data = sc->last_lcr | FTDI_SIO_SET_BREAK; - } else { - data = sc->last_lcr; - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_DATA; - USETW(req.wValue, data); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - (void)usbd_do_request(sc->sc_udev, &req, NULL); -} diff --git a/sys/dev/usb/uftdireg.h b/sys/dev/usb/uftdireg.h index ce2dfb2ea78..03a953ce474 100644 --- a/sys/dev/usb/uftdireg.h +++ b/sys/dev/usb/uftdireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uftdireg.h,v 1.4 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uftdireg.h,v 1.4 2001/12/17 14:31:02 ichiro Exp $ */ +/* $OpenBSD: uftdireg.h,v 1.5 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uftdireg.h,v 1.3 2001/06/12 14:59:28 wiz Exp $ */ /* * Definitions for the FTDI USB Single Port Serial Converter - @@ -121,7 +121,6 @@ enum { #define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) #define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) #define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) /* diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index 6ba08f1ab6e..ab1996330d9 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ugen.c,v 1.19 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ugen.c,v 1.58 2002/02/20 20:30:12 christos Exp $ */ +/* $OpenBSD: ugen.c,v 1.20 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ugen.c,v 1.49 2001/10/24 22:31:04 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -20,8 +20,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -150,16 +150,16 @@ Static struct cdevsw ugen_cdevsw = { }; #endif -Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, +Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status); Static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status); Static int ugen_do_read(struct ugen_softc *, int, struct uio *, int); Static int ugen_do_write(struct ugen_softc *, int, struct uio *, int); -Static int ugen_do_ioctl(struct ugen_softc *, int, u_long, - caddr_t, int, usb_proc_ptr); +Static int ugen_do_ioctl(struct ugen_softc *, int, u_long, + caddr_t, int, struct proc *); Static int ugen_set_config(struct ugen_softc *sc, int configno); -Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc, +Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp); Static usbd_status ugen_set_interface(struct ugen_softc *, int, int); Static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx); @@ -201,7 +201,7 @@ USB_ATTACH(ugen) /* First set configuration index 0, the default one for ugen. */ err = usbd_set_config_index(udev, 0, 0); if (err) { - printf("%s: setting configuration index 0 failed\n", + printf("%s: setting configuration index 0 failed\n", USBDEVNAME(sc->sc_dev)); sc->sc_dying = 1; USB_ATTACH_ERROR_RETURN; @@ -211,7 +211,7 @@ USB_ATTACH(ugen) /* Set up all the local state for this configuration. */ err = ugen_set_config(sc, conf); if (err) { - printf("%s: setting configuration %d failed\n", + printf("%s: setting configuration %d failed\n", USBDEVNAME(sc->sc_dev), conf); sc->sc_dying = 1; USB_ATTACH_ERROR_RETURN; @@ -247,19 +247,6 @@ ugen_set_config(struct ugen_softc *sc, int configno) DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", USBDEVNAME(sc->sc_dev), configno, sc)); - - /* - * We start at 1, not 0, because we don't care whether the - * control endpoint is open or not. It is always present. - */ - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) - if (sc->sc_is_open[endptno]) { - DPRINTFN(1, - ("ugen_set_config: %s - endpoint %d is open\n", - USBDEVNAME(sc->sc_dev), endptno)); - return (USBD_IN_USE); - } - /* Avoid setting the current value. */ if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { err = usbd_set_config_no(dev, configno, 1); @@ -285,7 +272,7 @@ ugen_set_config(struct ugen_softc *sc, int configno) 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", + "(%d,%d), sce=%p\n", endptno, endpt, UE_GET_ADDR(endpt), UE_GET_DIR(endpt), sce)); sce->sc = sc; @@ -297,7 +284,7 @@ ugen_set_config(struct ugen_softc *sc, int configno) } int -ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) +ugenopen(dev_t dev, int flag, int mode, struct proc *p) { struct ugen_softc *sc; int unit = UGENUNIT(dev); @@ -312,7 +299,7 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) USB_GET_SC_OPEN(ugen, unit, sc); - DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", + DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", flag, mode, unit, endpt)); if (sc == NULL || sc->sc_dying) @@ -343,7 +330,7 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) sce = &sc->sc_endpoints[endpt][dir]; sce->state = 0; sce->timeout = USBD_NO_TIMEOUT; - DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", + DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", sc, endpt, dir, sce)); edesc = sce->edesc; switch (edesc->bmAttributes & UE_XFERTYPE) { @@ -352,14 +339,14 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) if (isize == 0) /* shouldn't happen */ return (EINVAL); sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK); - DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", + DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", endpt, isize)); - if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) - return (ENOMEM); - err = usbd_open_pipe_intr(sce->iface, - edesc->bEndpointAddress, - USBD_SHORT_XFER_OK, &sce->pipeh, sce, - sce->ibuf, isize, ugenintr, + if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) + return (ENOMEM); + err = usbd_open_pipe_intr(sce->iface, + edesc->bEndpointAddress, + USBD_SHORT_XFER_OK, &sce->pipeh, sce, + sce->ibuf, isize, ugenintr, USBD_DEFAULT_INTERVAL); if (err) { free(sce->ibuf, M_USBDEV); @@ -369,7 +356,7 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) DPRINTFN(5, ("ugenopen: interrupt open done\n")); break; case UE_BULK: - err = usbd_open_pipe(sce->iface, + err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); if (err) return (EIO); @@ -384,7 +371,7 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) M_USBDEV, M_WAITOK); sce->cur = sce->fill = sce->ibuf; sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES; - DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n", + DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n", endpt, isize)); err = usbd_open_pipe(sce->iface, edesc->bEndpointAddress, 0, &sce->pipeh); @@ -421,7 +408,6 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) usbd_free_xfer(sce->isoreqs[i].xfer); return (ENOMEM); case UE_CONTROL: - sce->timeout = USBD_DEFAULT_TIMEOUT; return (EINVAL); } } @@ -430,7 +416,7 @@ ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p) } int -ugenclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +ugenclose(dev_t dev, int flag, int mode, struct proc *p) { int endpt = UGENENDPOINT(dev); struct ugen_softc *sc; @@ -462,30 +448,31 @@ ugenclose(dev_t dev, int flag, int mode, usb_proc_ptr p) sce = &sc->sc_endpoints[endpt][dir]; if (sce == NULL || sce->pipeh == NULL) continue; - DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", + DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", endpt, dir, sce)); usbd_abort_pipe(sce->pipeh); usbd_close_pipe(sce->pipeh); sce->pipeh = NULL; - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - ndflush(&sce->q, sce->q.c_cc); - clfree(&sce->q); - break; - case UE_ISOCHRONOUS: - for (i = 0; i < UGEN_NISOREQS; ++i) - usbd_free_xfer(sce->isoreqs[i].xfer); - - default: - break; + switch (sce->edesc->bmAttributes & UE_XFERTYPE) { + case UE_INTERRUPT: + ndflush(&sce->q, sce->q.c_cc); + clfree(&sce->q); + break; + case UE_ISOCHRONOUS: + for (i = 0; i < UGEN_NISOREQS; ++i) + usbd_free_xfer(sce->isoreqs[i].xfer); + + default: + break; } if (sce->ibuf != NULL) { free(sce->ibuf, M_USBDEV); sce->ibuf = NULL; clfree(&sce->q); + } } sc->sc_is_open[endpt] = 0; @@ -571,8 +558,8 @@ ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) tn = n; err = usbd_bulk_transfer( xfer, sce->pipeh, - sce->state & UGEN_SHORT_OK ? - USBD_SHORT_XFER_OK : 0, + sce->state & UGEN_SHORT_OK ? + USBD_SHORT_XFER_OK : 0, sce->timeout, buf, &tn, "ugenrb"); if (err) { if (err == USBD_INTERRUPTED) @@ -690,7 +677,7 @@ ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) if (error) break; DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sce->pipeh, 0, + err = usbd_bulk_transfer(xfer, sce->pipeh, 0, sce->timeout, buf, &n,"ugenwb"); if (err) { if (err == USBD_INTERRUPTED) @@ -811,15 +798,14 @@ ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) if (status != USBD_NORMAL_COMPLETION) { DPRINTF(("ugenintr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sce->pipeh); + usbd_clear_endpoint_stall_async(sce->pipeh); return; } usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); ibuf = sce->ibuf; - DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", + DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", xfer, status, count)); DPRINTFN(5, (" data = %02x %02x %02x\n", ibuf[0], ibuf[1], ibuf[2])); @@ -835,7 +821,7 @@ ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) } Static void -ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, +ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) { struct isoreq *req = addr; @@ -973,8 +959,7 @@ ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp) if (lenp) *lenp = len; cdesc = malloc(len, M_TEMP, M_WAITOK); - err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, - len); + err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,len); if (err) { free(cdesc, M_TEMP); return (0); @@ -997,7 +982,7 @@ ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx) Static int ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, - caddr_t addr, int flag, usb_proc_ptr p) + caddr_t addr, int flag, struct proc *p) { struct ugen_endpoint *sce; usbd_status err; @@ -1021,12 +1006,18 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, /* All handled in the upper FS layer. */ return (0); case USB_SET_SHORT_XFER: + /* This flag only affects read */ if (endpt == USB_CONTROL_ENDPOINT) return (EINVAL); - /* This flag only affects read */ sce = &sc->sc_endpoints[endpt][IN]; - if (sce == NULL || sce->pipeh == NULL) + if (sce == NULL) return (EINVAL); +#ifdef DIAGNOSTIC + if (sce->pipeh == NULL) { + printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); + return (EIO); + } +#endif if (*(int *)addr) sce->state |= UGEN_SHORT_OK; else @@ -1034,12 +1025,14 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, return (0); case USB_SET_TIMEOUT: sce = &sc->sc_endpoints[endpt][IN]; - if (sce == NULL - /* XXX this shouldn't happen, but the distinction between - input and output pipes isn't clear enough. - || sce->pipeh == NULL */ - ) + if (sce == NULL) return (EINVAL); +#ifdef DIAGNOSTIC + if (sce->pipeh == NULL) { + printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n"); + return (EIO); + } +#endif sce->timeout = *(int *)addr; return (0); default: @@ -1065,19 +1058,13 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, if (!(flag & FWRITE)) return (EPERM); err = ugen_set_config(sc, *(int *)addr); - switch (err) { - case USBD_NORMAL_COMPLETION: - break; - case USBD_IN_USE: - return (EBUSY); - default: + if (err) return (EIO); - } break; case USB_GET_ALTINTERFACE: ai = (struct usb_alt_interface *)addr; - err = usbd_device2interface_handle(sc->sc_udev, - ai->uai_interface_index, &iface); + err = usbd_device2interface_handle(sc->sc_udev, + ai->uai_interface_index, &iface); if (err) return (EINVAL); idesc = usbd_get_interface_descriptor(iface); @@ -1089,12 +1076,11 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, if (!(flag & FWRITE)) return (EPERM); ai = (struct usb_alt_interface *)addr; - err = usbd_device2interface_handle(sc->sc_udev, - ai->uai_interface_index, &iface); + err = usbd_device2interface_handle(sc->sc_udev, + ai->uai_interface_index, &iface); if (err) return (EINVAL); - err = ugen_set_interface(sc, ai->uai_interface_index, - ai->uai_alt_no); + err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no); if (err) return (EINVAL); break; @@ -1108,8 +1094,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, free(cdesc, M_TEMP); return (EINVAL); } - ai->uai_alt_no = usbd_get_no_alts(cdesc, - idesc->bInterfaceNumber); + ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); free(cdesc, M_TEMP); break; case USB_GET_DEVICE_DESC: @@ -1152,7 +1137,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, alt = ugen_get_alt_index(sc, ed->ued_interface_index); else alt = ed->ued_alt_index; - edesc = usbd_find_edesc(cdesc, ed->ued_interface_index, + edesc = usbd_find_edesc(cdesc, ed->ued_interface_index, alt, ed->ued_endpoint_index); if (edesc == NULL) { free(cdesc, M_TEMP); @@ -1187,7 +1172,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, } case USB_GET_STRING_DESC: si = (struct usb_string_desc *)addr; - err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index, + err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index, si->usd_language_id, &si->usd_desc); if (err) return (EINVAL); @@ -1224,7 +1209,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? + ur->ucr_request.bmRequestType & UT_READ ? UIO_READ : UIO_WRITE; uio.uio_procp = p; ptr = malloc(len, M_TEMP, M_WAITOK); @@ -1234,9 +1219,8 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, goto ret; } } - sce = &sc->sc_endpoints[endpt][IN]; - err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request, - ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout); + err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request, + ptr, ur->ucr_flags, &ur->ucr_actlen); if (err) { error = EIO; goto ret; @@ -1264,7 +1248,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, } int -ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) +ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int endpt = UGENENDPOINT(dev); struct ugen_softc *sc; @@ -1280,7 +1264,7 @@ ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) } int -ugenpoll(dev_t dev, int events, usb_proc_ptr p) +ugenpoll(dev_t dev, int events, struct proc *p) { struct ugen_softc *sc; struct ugen_endpoint *sce; @@ -1325,12 +1309,12 @@ ugenpoll(dev_t dev, int events, usb_proc_ptr p) } break; case UE_BULK: - /* + /* * We have no easy way of determining if a read will * yield any data or a write will happen. * Pretend they will. */ - revents |= events & + revents |= events & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM); break; default: diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 090f26f99f8..a233ff1b502 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhci.c,v 1.24 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhci.c,v 1.158 2002/03/17 18:02:53 augustss Exp $ */ +/* $OpenBSD: uhci.c,v 1.25 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uhci.c,v 1.142 2001/10/25 02:08:13 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -174,10 +174,10 @@ Static void uhci_enter_ctl_q(uhci_softc_t *, uhci_soft_qh_t *, Static void uhci_exit_ctl_q(uhci_softc_t *, uhci_soft_qh_t *); #endif -Static void uhci_free_std_chain(uhci_softc_t *, +Static void uhci_free_std_chain(uhci_softc_t *, uhci_soft_td_t *, uhci_soft_td_t *); Static usbd_status uhci_alloc_std_chain(struct uhci_pipe *, - uhci_softc_t *, int, int, u_int16_t, usb_dma_t *, + uhci_softc_t *, int, int, u_int16_t, usb_dma_t *, uhci_soft_td_t **, uhci_soft_td_t **); Static void uhci_poll_hub(void *); Static void uhci_waitintr(uhci_softc_t *, usbd_xfer_handle); @@ -187,7 +187,6 @@ Static void uhci_idone(uhci_intr_info_t *); Static void uhci_abort_xfer(usbd_xfer_handle, usbd_status status); Static void uhci_timeout(void *); -Static void uhci_timeout_task(void *); Static void uhci_add_ls_ctrl(uhci_softc_t *, uhci_soft_qh_t *); Static void uhci_add_hs_ctrl(uhci_softc_t *, uhci_soft_qh_t *); Static void uhci_add_bulk(uhci_softc_t *, uhci_soft_qh_t *); @@ -250,8 +249,8 @@ Static void uhci_softintr(void *); Static usbd_status uhci_device_request(usbd_xfer_handle xfer); Static void uhci_add_intr(uhci_softc_t *, uhci_soft_qh_t *); -Static void uhci_remove_intr(uhci_softc_t *, uhci_soft_qh_t *); -Static usbd_status uhci_device_setintr(uhci_softc_t *sc, +Static void uhci_remove_intr(uhci_softc_t*, uhci_soft_qh_t*); +Static usbd_status uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *pipe, int ival); Static void uhci_device_clear_toggle(usbd_pipe_handle pipe); @@ -302,7 +301,7 @@ struct usbd_bus_methods uhci_bus_methods = { uhci_freex, }; -struct usbd_pipe_methods uhci_root_ctrl_methods = { +struct usbd_pipe_methods uhci_root_ctrl_methods = { uhci_root_ctrl_transfer, uhci_root_ctrl_start, uhci_root_ctrl_abort, @@ -311,7 +310,7 @@ struct usbd_pipe_methods uhci_root_ctrl_methods = { uhci_root_ctrl_done, }; -struct usbd_pipe_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, @@ -367,7 +366,7 @@ uhci_find_prev_qh(uhci_soft_qh_t *pqh, uhci_soft_qh_t *sqh) DPRINTFN(15,("uhci_find_prev_qh: pqh=%p sqh=%p\n", pqh, sqh)); for (; pqh->hlink != sqh; pqh = pqh->hlink) { -#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG) +#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG) if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) { printf("uhci_find_prev_qh: QH not found\n"); return (NULL); @@ -402,12 +401,13 @@ uhci_init(uhci_softc_t *sc) uhci_dumpregs(sc); #endif + uhci_run(sc, 0); /* stop the controller */ UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ uhci_globalreset(sc); /* reset the controller */ uhci_reset(sc); /* Allocate and initialize real frame array. */ - err = usb_allocmem(&sc->sc_bus, + err = usb_allocmem(&sc->sc_bus, UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), UHCI_FRAMELIST_ALIGN, &sc->sc_dma); if (err) @@ -416,7 +416,7 @@ uhci_init(uhci_softc_t *sc) UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/ - /* + /* * Allocate a TD, inactive, that hangs from the last QH. * This is to avoid a bug in the PIIX that makes it run berserk * otherwise. @@ -470,7 +470,7 @@ uhci_init(uhci_softc_t *sc) clsqh->qh.qh_elink = htole32(UHCI_PTR_T); sc->sc_lctl_start = sc->sc_lctl_end = clsqh; - /* + /* * Make all (virtual) frame list pointers point to the interrupt * queue heads and the interrupt queue heads at the control * queue head and point the physical frame list to the virtual. @@ -493,8 +493,8 @@ uhci_init(uhci_softc_t *sc) sc->sc_vframes[i].etd = std; sc->sc_vframes[i].hqh = sqh; sc->sc_vframes[i].eqh = sqh; - for (j = i; - j < UHCI_FRAMELIST_COUNT; + for (j = i; + j < UHCI_FRAMELIST_COUNT; j += UHCI_VFRAMELIST_COUNT) sc->sc_pframes[j] = htole32(std->physaddr); } @@ -516,7 +516,7 @@ uhci_init(uhci_softc_t *sc) #endif DPRINTFN(1,("uhci_init: enabling\n")); - UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | + UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */ UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */ @@ -552,7 +552,7 @@ uhci_detach(struct uhci_softc *sc, int flags) if (sc->sc_child != NULL) rv = config_detach(sc->sc_child, flags); - + if (rv != 0) return (rv); @@ -568,7 +568,7 @@ uhci_detach(struct uhci_softc *sc, int flags) break; SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next); free(xfer, M_USB); - } + } /* XXX free other data structures XXX */ @@ -582,10 +582,10 @@ uhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) struct uhci_softc *sc = (struct uhci_softc *)bus; u_int32_t n; - /* + /* * XXX * Since we are allocating a buffer we can assume that we will - * need TDs for it. Since we don't want to allocate those from + * need TDs for it. Since we don't want to alolocate those from * an interrupt context, we allocate them here and free them again. * This is no guarantee that we'll get the TDs next time... */ @@ -594,8 +594,7 @@ uhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) u_int32_t i; uhci_soft_td_t **stds; DPRINTF(("uhci_allocm: get %d TDs\n", n)); - stds = malloc(sizeof(uhci_soft_td_t *) * n, M_TEMP, - M_NOWAIT); + stds = malloc(sizeof(uhci_soft_td_t *) * n, M_TEMP, M_NOWAIT); if (stds == NULL) panic("uhci_allocm"); memset(stds, 0, sizeof(uhci_soft_td_t *) * n); @@ -694,7 +693,7 @@ uhci_power(int why, void *v) s = splhardusb(); cmd = UREAD2(sc, UHCI_CMD); - DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n", + DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n", sc, why, sc->sc_suspend, cmd)); switch (why) { @@ -740,7 +739,7 @@ uhci_power(int why, void *v) UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ - UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | + UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ uhci_run(sc, 1); /* and start traffic again */ usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); @@ -793,9 +792,9 @@ uhci_dump_td(uhci_soft_td_t *p) (long)le32toh(p->td.td_token), (long)le32toh(p->td.td_buffer))); - bitmask_snprintf((u_int32_t)le32toh(p->td.td_link), "\20\1T\2Q\3VF", + bitmask_snprintf((int)le32toh(p->td.td_link), "\20\1T\2Q\3VF", sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)le32toh(p->td.td_status), + bitmask_snprintf((int)le32toh(p->td.td_status), "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD", sbuf2, sizeof(sbuf2)); @@ -892,7 +891,7 @@ uhci_dump_ii(uhci_intr_info_t *ii) usbd_pipe_handle pipe; usb_endpoint_descriptor_t *ed; usbd_device_handle dev; - + #ifdef DIAGNOSTIC #define DONE ii->isdone #else @@ -925,8 +924,8 @@ uhci_dump_ii(uhci_intr_info_t *ii) } ed = pipe->endpoint->edesc; dev = pipe->device; - printf("ii %p: done=%d xfer=%p dev=%p vid=0x%04x pid=0x%04x addr=%d pipe=%p ep=0x%02x attr=0x%02x\n", - ii, DONE, ii->xfer, dev, + printf("ii %p: done=%d xfer=%p dev=%p vid=0x%04x pid=0x%04x addr=%d pipe=%p ep=0x%02x attr=0x%02x\n", + ii, DONE, ii->xfer, dev, UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct), dev->address, pipe, @@ -1011,7 +1010,7 @@ uhci_add_loop(uhci_softc_t *sc) { if (++sc->sc_loops == 1) { DPRINTFN(5,("uhci_start_loop: add\n")); /* Note, we don't loop back the soft pointer. */ - sc->sc_last_qh->qh.qh_hlink = + sc->sc_last_qh->qh.qh_hlink = htole32(sc->sc_hctl_start->physaddr | UHCI_PTR_QH); } } @@ -1074,7 +1073,7 @@ uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) } pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh); - pqh->hlink = sqh->hlink; + pqh->hlink = sqh->hlink; pqh->qh.qh_hlink = sqh->qh.qh_hlink; delay(UHCI_QH_REMOVE_DELAY); if (sc->sc_hctl_end == sqh) @@ -1091,9 +1090,9 @@ uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh)); eqh = sc->sc_lctl_end; - sqh->hlink = eqh->hlink; + sqh->hlink = eqh->hlink; sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; + eqh->hlink = sqh; eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); sc->sc_lctl_end = sqh; } @@ -1113,7 +1112,7 @@ uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) delay(UHCI_QH_REMOVE_DELAY); } pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh); - pqh->hlink = sqh->hlink; + pqh->hlink = sqh->hlink; pqh->qh.qh_hlink = sqh->qh.qh_hlink; delay(UHCI_QH_REMOVE_DELAY); if (sc->sc_lctl_end == sqh) @@ -1130,9 +1129,9 @@ uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); eqh = sc->sc_bulk_end; - sqh->hlink = eqh->hlink; + sqh->hlink = eqh->hlink; sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; + eqh->hlink = sqh; eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); sc->sc_bulk_end = sqh; uhci_add_loop(sc); @@ -1168,9 +1167,6 @@ uhci_intr(void *arg) { uhci_softc_t *sc = arg; - if (sc->sc_dying) - return (0); - DPRINTFN(15,("uhci_intr: real interrupt\n")); if (sc->sc_bus.use_polling) { #ifdef DIAGNOSTIC @@ -1194,10 +1190,15 @@ uhci_intr1(uhci_softc_t *sc) } #endif - status = UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS; + status = UREAD2(sc, UHCI_STS); if (status == 0) /* The interrupt was not for us. */ return (0); +#if defined(DIAGNOSTIC) && defined(__NetBSD__) + if (sc->sc_suspend != PWR_RESUME) + printf("uhci_intr: suspended sts=0x%x\n", status); +#endif + if (sc->sc_suspend != PWR_RESUME) { printf("%s: interrupt while not operating ignored\n", USBDEVNAME(sc->sc_bus.bdev)); @@ -1222,13 +1223,13 @@ uhci_intr1(uhci_softc_t *sc) } if (status & UHCI_STS_HCPE) { ack |= UHCI_STS_HCPE; - printf("%s: host controller process error\n", + printf("%s: host controller process error\n", USBDEVNAME(sc->sc_bus.bdev)); } if (status & UHCI_STS_HCH) { /* no acknowledge needed */ if (!sc->sc_dying) { - printf("%s: host controller halted\n", + printf("%s: host controller halted\n", USBDEVNAME(sc->sc_bus.bdev)); #ifdef UHCI_DEBUG uhci_dump_all(sc); @@ -1274,11 +1275,6 @@ uhci_softintr(void *v) for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) uhci_check_intr(sc, ii); - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } - sc->sc_bus.intr_context--; } @@ -1296,12 +1292,6 @@ uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) return; } #endif - if (ii->xfer->status == USBD_CANCELLED || - ii->xfer->status == USBD_TIMEOUT) { - DPRINTF(("uhci_check_intr: aborted xfer=%p\n", ii->xfer)); - return; - } - if (ii->stdstart == NULL) return; lstd = ii->stdend; @@ -1311,7 +1301,7 @@ uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) return; } #endif - /* + /* * If the last TD is still active we need to check whether there * is a an error somewhere in the middle, or whether there was a * short packet (SPD and not ACTIVE). @@ -1328,7 +1318,7 @@ uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) goto done; /* We want short packets, and it is short: it's done */ if ((status & UHCI_TD_SPD) && - UHCI_TD_GET_ACTLEN(status) < + UHCI_TD_GET_ACTLEN(status) < UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) goto done; } @@ -1371,6 +1361,12 @@ uhci_idone(uhci_intr_info_t *ii) } #endif + if (xfer->status == USBD_CANCELLED || + xfer->status == USBD_TIMEOUT) { + DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer)); + return; + } + if (xfer->nframes != 0) { /* Isoc transfer, do things differently. */ uhci_soft_td_t **stds = upipe->u.iso.stds; @@ -1426,15 +1422,14 @@ uhci_idone(uhci_intr_info_t *ii) upipe->nexttoggle = UHCI_TD_GET_DT(le32toh(std->td.td_token)); status &= UHCI_TD_ERROR; - DPRINTFN(10, ("uhci_idone: actlen=%d, status=0x%x\n", + DPRINTFN(10, ("uhci_idone: actlen=%d, status=0x%x\n", actlen, status)); xfer->actlen = actlen; if (status != 0) { #ifdef UHCI_DEBUG char sbuf[128]; - bitmask_snprintf((u_int32_t)status, - "\20\22BITSTUFF\23CRCTO\24NAK\25" + bitmask_snprintf((int)status, "\20\22BITSTUFF\23CRCTO\24NAK\25" "BABBLE\26DBUFFER\27STALLED\30ACTIVE", sbuf, sizeof(sbuf)); @@ -1466,33 +1461,17 @@ void uhci_timeout(void *addr) { uhci_intr_info_t *ii = addr; - struct uhci_xfer *uxfer = UXFER(ii->xfer); - struct uhci_pipe *upipe = (struct uhci_pipe *)uxfer->xfer.pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; - - DPRINTF(("uhci_timeout: uxfer=%p\n", uxfer)); - - if (sc->sc_dying) { - uhci_abort_xfer(&uxfer->xfer, USBD_TIMEOUT); - return; - } - /* Execute the abort in a process context. */ - usb_init_task(&uxfer->abort_task, uhci_timeout_task, ii->xfer); - usb_add_task(uxfer->xfer.pipe->device, &uxfer->abort_task); -} + DPRINTF(("uhci_timeout: ii=%p\n", ii)); -void -uhci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - int s; - - DPRINTF(("uhci_timeout_task: xfer=%p\n", xfer)); +#ifdef UHCI_DEBUG + if (uhcidebug > 10) + uhci_dump_tds(ii->stdstart); +#endif - s = splusb(); - uhci_abort_xfer(xfer, USBD_TIMEOUT); - splx(s); + ii->xfer->device->bus->intr_context++; + uhci_abort_xfer(ii->xfer, USBD_TIMEOUT); + ii->xfer->device->bus->intr_context--; } /* @@ -1523,7 +1502,7 @@ uhci_waitintr(uhci_softc_t *sc, usbd_xfer_handle xfer) /* Timeout */ DPRINTF(("uhci_waitintr: timeout\n")); for (ii = LIST_FIRST(&sc->sc_intrhead); - ii != NULL && ii->xfer != xfer; + ii != NULL && ii->xfer != xfer; ii = LIST_NEXT(ii, list)) ; #ifdef DIAGNOSTIC @@ -1549,11 +1528,11 @@ uhci_reset(uhci_softc_t *sc) UHCICMD(sc, UHCI_CMD_HCRESET); /* The reset bit goes low when the controller is done. */ - for (n = 0; n < UHCI_RESET_TIMEOUT && + for (n = 0; n < UHCI_RESET_TIMEOUT && (UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++) usb_delay_ms(&sc->sc_bus, 1); if (n >= UHCI_RESET_TIMEOUT) - printf("%s: controller did not reset\n", + printf("%s: controller did not reset\n", USBDEVNAME(sc->sc_bus.bdev)); } @@ -1701,9 +1680,9 @@ uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len, int addr = upipe->pipe.device->address; int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d speed=%d " - "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len, - upipe->pipe.device->speed, flags)); + DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d " + "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len, + upipe->pipe.device->lowspeed, flags)); maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize); if (maxp == 0) { printf("uhci_alloc_std_chain: maxp=0\n"); @@ -1726,14 +1705,14 @@ uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len, lastlink = UHCI_PTR_T; ntd--; status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); - if (upipe->pipe.device->speed == USB_SPEED_LOW) + if (upipe->pipe.device->lowspeed) status |= UHCI_TD_LS; if (flags & USBD_SHORT_XFER_OK) status |= UHCI_TD_SPD; for (i = ntd; i >= 0; i--) { p = uhci_alloc_std(sc); if (p == NULL) { - uhci_free_std_chain(sc, lastp, NULL); + uhci_free_std_chain(sc, lastp, 0); return (USBD_NOMEM); } p->link.std = lastp; @@ -1749,14 +1728,14 @@ uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len, *ep = p; } else l = maxp; - p->td.td_token = + p->td.td_token = htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) : UHCI_TD_OUT(l, endpt, addr, tog)); p->td.td_buffer = htole32(DMAADDR(dma) + i * maxp); tog ^= 1; } *sp = lastp; - DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n", + DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n", upipe->nexttoggle)); return (USBD_NORMAL_COMPLETION); } @@ -1783,7 +1762,7 @@ uhci_device_bulk_transfer(usbd_xfer_handle xfer) if (err) return (err); - /* + /* * Pipe isn't running (otherwise err would be USBD_INPROG), * so start it first. */ @@ -1882,68 +1861,44 @@ uhci_device_bulk_abort(usbd_xfer_handle xfer) } /* - * Abort a device request. - * If this routine is called at splusb() it guarantees that the request - * will be removed from the hardware scheduling and that the callback - * for it will be called with USBD_CANCELLED status. - * It's impossible to guarantee that the requested transfer will not - * have happened since the hardware runs concurrently. - * If the transaction has already happened we rely on the ordinary - * interrupt processing to process it. + * XXX This way of aborting is neither safe, nor good. + * But it will have to do until I figure out what to do. + * I apologize for the delay(). */ void uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) { uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; uhci_soft_td_t *std; int s; DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status)); - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - usb_uncallout(xfer->timeout_handle, uhci_timeout, xfer); - usb_transfer_complete(xfer); + s = splusb(); + + /* Transfer is already done. */ + if (xfer->status != USBD_NOT_STARTED && + xfer->status != USBD_IN_PROGRESS) { splx(s); + return; } - if (xfer->device->bus->intr_context || !curproc) - panic("uhci_abort_xfer: not in process context\n"); + /* Make interrupt routine ignore it, */ + xfer->status = status; - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - s = splusb(); - xfer->status = status; /* make software ignore it */ + /* don't timeout, */ usb_uncallout(xfer->timeout_handle, uhci_timeout, ii); - DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii)); + + /* make hardware ignore it, */ for (std = ii->stdstart; std != NULL; std = std->link.std) std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - splx(s); - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. Also make sure the soft interrupt routine - * has run. - */ - usb_delay_ms(upipe->pipe.device->bus, 2); /* Hardware finishes in 1ms */ - s = splusb(); - sc->sc_softwake = 1; - usb_schedsoftintr(&sc->sc_bus); - DPRINTFN(1,("uhci_abort_xfer: tsleep\n")); - tsleep(&sc->sc_softwake, PZERO, "uhciab", 0); - splx(s); - - /* - * Step 3: Execute callback. - */ xfer->hcpriv = ii; - DPRINTFN(1,("uhci_abort_xfer: callback\n")); + splx(s); + + delay(1000); + s = splusb(); #ifdef DIAGNOSTIC ii->isdone = 1; @@ -1973,7 +1928,7 @@ uhci_device_ctrl_transfer(usbd_xfer_handle xfer) if (err) return (err); - /* + /* * Pipe isn't running (otherwise err would be USBD_INPROG), * so start it first. */ @@ -2013,7 +1968,7 @@ uhci_device_intr_transfer(usbd_xfer_handle xfer) if (err) return (err); - /* + /* * Pipe isn't running (otherwise err would be USBD_INPROG), * so start it first. */ @@ -2069,7 +2024,7 @@ uhci_device_intr_start(usbd_xfer_handle xfer) ii->isdone = 0; #endif - DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n", + DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n", upipe->u.intr.qhs[0])); for (i = 0; i < upipe->u.intr.npoll; i++) { sqh = upipe->u.intr.qhs[i]; @@ -2112,7 +2067,7 @@ uhci_device_intr_abort(usbd_xfer_handle xfer) DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer)); if (xfer->pipe->intrxfer == xfer) { DPRINTFN(1,("uhci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; + xfer->pipe->intrxfer = 0; } uhci_abort_xfer(xfer, USBD_CANCELLED); } @@ -2133,7 +2088,7 @@ uhci_device_intr_close(usbd_pipe_handle pipe) uhci_remove_intr(sc, upipe->u.intr.qhs[i]); splx(s); - /* + /* * We now have to wait for any activity on the physical * descriptors to stop. */ @@ -2170,7 +2125,7 @@ uhci_device_request(usbd_xfer_handle xfer) UGETW(req->wIndex), UGETW(req->wLength), addr, endpt)); - ls = dev->speed == USB_SPEED_LOW ? UHCI_TD_LS : 0; + ls = dev->lowspeed ? UHCI_TD_LS : 0; isread = req->bmRequestType & UT_READ; len = UGETW(req->wLength); @@ -2204,9 +2159,9 @@ uhci_device_request(usbd_xfer_handle xfer) stat->link.std = NULL; stat->td.td_link = htole32(UHCI_PTR_T); - stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | + stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE | UHCI_TD_IOC); - stat->td.td_token = + stat->td.td_token = htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) : UHCI_TD_IN (0, endpt, addr, 1)); stat->td.td_buffer = htole32(0); @@ -2233,7 +2188,7 @@ uhci_device_request(usbd_xfer_handle xfer) sqh->qh.qh_elink = htole32(setup->physaddr | UHCI_PTR_TD); s = splusb(); - if (dev->speed == USB_SPEED_LOW) + if (dev->lowspeed) uhci_add_ls_ctrl(sc, sqh); else uhci_add_hs_ctrl(sc, sqh); @@ -2256,7 +2211,7 @@ uhci_device_request(usbd_xfer_handle xfer) uhci_dump_qh(sxqh); for (xqh = sxqh; xqh != NULL; - xqh = (maxqh++ == 5 || xqh->hlink == sxqh || + xqh = (maxqh++ == 5 || xqh->hlink == sxqh || xqh->hlink == xqh ? NULL : xqh->hlink)) { uhci_dump_qh(xqh); } @@ -2308,7 +2263,7 @@ uhci_device_isoc_enter(usbd_xfer_handle xfer) 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; + uhci_soft_td_t *std; u_int32_t buf, len, status; int s, i, next, nframes; @@ -2404,7 +2359,7 @@ uhci_device_isoc_start(usbd_xfer_handle xfer) #endif s = splusb(); - + /* Set up interrupt info. */ ii->xfer = xfer; ii->stdstart = end; @@ -2415,7 +2370,7 @@ uhci_device_isoc_start(usbd_xfer_handle xfer) ii->isdone = 0; #endif uhci_add_intr_info(sc, ii); - + splx(s); return (USBD_IN_PROGRESS); @@ -2432,7 +2387,7 @@ uhci_device_isoc_abort(usbd_xfer_handle xfer) s = splusb(); /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && + if (xfer->status != USBD_NOT_STARTED && xfer->status != USBD_IN_PROGRESS) { splx(s); return; @@ -2616,7 +2571,7 @@ uhci_device_intr_done(usbd_xfer_handle xfer) sqh->elink = NULL; sqh->qh.qh_elink = htole32(UHCI_PTR_T); } - uhci_free_std_chain(sc, ii->stdstart, NULL); + uhci_free_std_chain(sc, ii->stdstart, 0); /* XXX Wasteful. */ if (xfer->pipe->repeat) { @@ -2673,7 +2628,7 @@ uhci_device_ctrl_done(usbd_xfer_handle xfer) uhci_del_intr_info(ii); /* remove from active list */ - if (upipe->pipe.device->speed == USB_SPEED_LOW) + if (upipe->pipe.device->lowspeed) uhci_remove_ls_ctrl(sc, upipe->u.ctl.sqh); else uhci_remove_hs_ctrl(sc, upipe->u.ctl.sqh); @@ -2696,7 +2651,7 @@ uhci_device_bulk_done(usbd_xfer_handle xfer) uhci_remove_bulk(sc, upipe->u.bulk.sqh); - uhci_free_std_chain(sc, ii->stdstart, NULL); + uhci_free_std_chain(sc, ii->stdstart, 0); DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen)); } @@ -2762,10 +2717,10 @@ uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) DPRINTFN(2, ("uhci_setintr: ival=%d npoll=%d\n", ival, npoll)); upipe->u.intr.npoll = npoll; - upipe->u.intr.qhs = + upipe->u.intr.qhs = malloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_WAITOK); - /* + /* * Figure out which offset in the schedule that has most * bandwidth left over. */ @@ -2809,7 +2764,7 @@ uhci_open(usbd_pipe_handle pipe) int ival; DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, pipe->device->address, + pipe, pipe->device->address, ed->bEndpointAddress, sc->sc_addr)); upipe->aborting = 0; @@ -2844,8 +2799,8 @@ uhci_open(usbd_pipe_handle pipe) uhci_free_std(sc, upipe->u.ctl.setup); goto bad; } - err = usb_allocmem(&sc->sc_bus, - sizeof(usb_device_request_t), + err = usb_allocmem(&sc->sc_bus, + sizeof(usb_device_request_t), 0, &upipe->u.ctl.reqdma); if (err) { uhci_free_sqh(sc, upipe->u.ctl.sqh); @@ -2886,7 +2841,7 @@ usb_device_descriptor_t uhci_devd = { {0x00, 0x01}, /* USB version */ UDCLASS_HUB, /* class */ UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ + 0, /* protocol */ 64, /* max packet */ {0},{0},{0x00,0x01}, /* device id */ 1,2,0, /* string indicies */ @@ -2914,7 +2869,7 @@ usb_interface_descriptor_t uhci_ifcd = { 1, UICLASS_HUB, UISUBCLASS_HUB, - UIPROTO_FSHUB, + 0, 0 }; @@ -2967,7 +2922,7 @@ uhci_root_ctrl_transfer(usbd_xfer_handle xfer) if (err) return (err); - /* + /* * Pipe isn't running (otherwise err would be USBD_INPROG), * so start it first. */ @@ -2994,7 +2949,7 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer) #endif req = &xfer->request; - DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", + DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", req->bmRequestType, req->bRequest)); len = UGETW(req->wLength); @@ -3009,7 +2964,7 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer) case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): - /* + /* * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops * for the integrated root hub. */ @@ -3177,7 +3132,7 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer) goto ret; } if (len > 0) { - *(u_int8_t *)buf = + *(u_int8_t *)buf = (UREAD2(sc, port) & UHCI_PORTSC_LS) >> UHCI_PORTSC_LS_SHIFT; totlen = 1; @@ -3217,19 +3172,19 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer) status = change = 0; if (x & UHCI_PORTSC_CCS) status |= UPS_CURRENT_CONNECT_STATUS; - if (x & UHCI_PORTSC_CSC) + if (x & UHCI_PORTSC_CSC) change |= UPS_C_CONNECT_STATUS; - if (x & UHCI_PORTSC_PE) + if (x & UHCI_PORTSC_PE) status |= UPS_PORT_ENABLED; - if (x & UHCI_PORTSC_POEDC) + if (x & UHCI_PORTSC_POEDC) change |= UPS_C_PORT_ENABLED; - if (x & UHCI_PORTSC_OCI) + if (x & UHCI_PORTSC_OCI) status |= UPS_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_OCIC) + if (x & UHCI_PORTSC_OCIC) change |= UPS_C_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_SUSP) + if (x & UHCI_PORTSC_SUSP) status |= UPS_SUSPEND; - if (x & UHCI_PORTSC_LSDA) + if (x & UHCI_PORTSC_LSDA) status |= UPS_LOW_SPEED; status |= UPS_PORT_POWER; if (sc->sc_isreset) @@ -3266,7 +3221,7 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer) case UHF_PORT_RESET: x = URWMASK(UREAD2(sc, port)); UWRITE2(sc, port, x | UHCI_PORTSC_PR); - usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY); + usb_delay_ms(&sc->sc_bus, 50); /*XXX USB v1.1 7.1.7.3 */ UWRITE2(sc, port, x & ~UHCI_PORTSC_PR); delay(100); x = UREAD2(sc, port); diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h index c0d73cedc4c..d51b7492396 100644 --- a/sys/dev/usb/uhcireg.h +++ b/sys/dev/usb/uhcireg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcireg.h,v 1.10 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhcireg.h,v 1.15 2002/02/11 11:41:30 augustss Exp $ */ +/* $OpenBSD: uhcireg.h,v 1.11 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uhcireg.h,v 1.14 2001/08/06 15:15:08 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhcireg.h,v 1.12 1999/11/17 22:33:42 n_hibma Exp $ */ /* @@ -76,7 +76,6 @@ #define UHCI_STS_HSE 0x0008 #define UHCI_STS_HCPE 0x0010 #define UHCI_STS_HCH 0x0020 -#define UHCI_STS_ALLINTRS 0x003f #define UHCI_INTR 0x04 #define UHCI_INTR_TOCRCIE 0x0001 diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index b8fdfeea482..acf3d7cd860 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: uhcivar.h,v 1.12 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhcivar.h,v 1.33 2002/02/11 11:41:30 augustss Exp $ */ +/* $OpenBSD: uhcivar.h,v 1.13 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uhcivar.h,v 1.32 2000/08/13 16:18:09 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.14 1999/11/17 22:33:42 n_hibma Exp $ */ /* @@ -84,7 +84,6 @@ typedef struct uhci_intr_info { struct uhci_xfer { struct usbd_xfer xfer; uhci_intr_info_t iinfo; - struct usb_task abort_task; int curframe; }; @@ -162,7 +161,6 @@ typedef struct uhci_softc { u_int8_t sc_saved_sof; u_int16_t sc_saved_frnum; - char sc_softwake; char sc_isreset; char sc_suspend; char sc_dying; diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index 48fb9f7d21d..968af28c593 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,5 +1,6 @@ -/* $OpenBSD: uhid.c,v 1.17 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhid.c,v 1.51 2002/03/17 18:02:53 augustss Exp $ */ +/* $OpenBSD: uhid.c,v 1.18 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uhid.c,v 1.45 2001/10/26 17:58:21 augustss Exp $ */ +/* $FreeBSD: src/sys/dev/usb/uhid.c,v 1.22 1999/11/17 22:33:43 n_hibma Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -47,8 +48,16 @@ #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/signalvar.h> +#if defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/device.h> #include <sys/ioctl.h> +#elif defined(__FreeBSD__) +#include <sys/ioccom.h> +#include <sys/filio.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/ioccom.h> +#endif #include <sys/conf.h> #include <sys/tty.h> #include <sys/file.h> @@ -66,7 +75,8 @@ #include <dev/usb/hid.h> #include <dev/usb/usb_quirks.h> -#include <dev/usb/uhidev.h> +/* Report descriptor for broken Wacom Graphire */ +#include <dev/usb/ugraphire_rdesc.h> #ifdef UHID_DEBUG #define DPRINTF(x) if (uhiddebug) logprintf x @@ -78,20 +88,33 @@ int uhiddebug = 0; #endif struct uhid_softc { - struct uhidev sc_hdev; + USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; /* interface */ + usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ + int sc_ep_addr; int sc_isize; int sc_osize; int sc_fsize; + u_int8_t sc_iid; + u_int8_t sc_oid; + u_int8_t sc_fid; + u_char *sc_ibuf; u_char *sc_obuf; + void *sc_repdesc; + int sc_repdesc_size; + struct clist sc_q; struct selinfo sc_rsel; - usb_proc_ptr sc_async; /* process that wants SIGIO */ + struct proc *sc_async; /* process that wants SIGIO */ u_char sc_state; /* driver state */ -#define UHID_ASLP 0x01 /* waiting for device data */ -#define UHID_IMMED 0x02 /* return read data immediately */ +#define UHID_OPEN 0x01 /* device is open */ +#define UHID_ASLP 0x02 /* waiting for device data */ +#define UHID_NEEDCLEAR 0x04 /* needs clearing endpoint stall */ +#define UHID_IMMED 0x08 /* return read data immediately */ int sc_refcnt; u_char sc_dying; @@ -101,52 +124,153 @@ struct uhid_softc { #define UHID_CHUNK 128 /* chunk size for read */ #define UHID_BSIZE 1020 /* buffer size */ +#if defined(__NetBSD__) || defined(__OpenBSD__) cdev_decl(uhid); +#elif defined(__FreeBSD__) +d_open_t uhidopen; +d_close_t uhidclose; +d_read_t uhidread; +d_write_t uhidwrite; +d_ioctl_t uhidioctl; +d_poll_t uhidpoll; + +#define UHID_CDEV_MAJOR 122 + +Static struct cdevsw uhid_cdevsw = { + /* open */ uhidopen, + /* close */ uhidclose, + /* read */ uhidread, + /* write */ uhidwrite, + /* ioctl */ uhidioctl, + /* poll */ uhidpoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "uhid", + /* maj */ UHID_CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, + /* bmaj */ -1 +}; +#endif -Static void uhid_intr(struct uhidev *, void *, u_int len); +Static void uhid_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int); Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int); -Static int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int, - usb_proc_ptr); +Static int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int,struct proc*); USB_DECLARE_DRIVER(uhid); USB_MATCH(uhid) { USB_MATCH_START(uhid, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; - - DPRINTF(("uhid_match: report=%d\n", uha->reportid)); - - if (uha->matchlvl) - return (uha->matchlvl); + usb_interface_descriptor_t *id; + + if (uaa->iface == NULL) + return (UMATCH_NONE); + id = usbd_get_interface_descriptor(uaa->iface); + if (id == NULL || id->bInterfaceClass != UICLASS_HID) + return (UMATCH_NONE); + if (uaa->matchlvl) + return (uaa->matchlvl); return (UMATCH_IFACECLASS_GENERIC); } USB_ATTACH(uhid) { USB_ATTACH_START(uhid, sc, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; - int size, repid; + usbd_interface_handle iface = uaa->iface; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + int size; void *desc; + usbd_status err; + char devinfo[1024]; + + sc->sc_udev = uaa->device; + sc->sc_iface = iface; + id = usbd_get_interface_descriptor(iface); + usbd_devinfo(uaa->device, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), + devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + + ed = usbd_interface2endpoint_descriptor(iface, 0); + if (ed == NULL) { + printf("%s: could not read endpoint descriptor\n", + USBDEVNAME(sc->sc_dev)); + sc->sc_dying = 1; + USB_ATTACH_ERROR_RETURN; + } + + DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d " + "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" + " bInterval=%d\n", + ed->bLength, ed->bDescriptorType, + ed->bEndpointAddress & UE_ADDR, + UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", + ed->bmAttributes & UE_XFERTYPE, + UGETW(ed->wMaxPacketSize), ed->bInterval)); + + 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; + USB_ATTACH_ERROR_RETURN; + } + + sc->sc_ep_addr = ed->bEndpointAddress; + + if (uaa->vendor == USB_VENDOR_WACOM && + uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* && + uaa->revision == 0x???? */) { /* XXX should use revision */ + /* The report descriptor for the Wacom Graphire is broken. */ + size = sizeof uhid_graphire_report_descr; + desc = malloc(size, M_USBDEV, M_NOWAIT); + if (desc == NULL) + err = USBD_NOMEM; + else { + err = USBD_NORMAL_COMPLETION; + memcpy(desc, uhid_graphire_report_descr, size); + } + } else { + desc = NULL; + err = usbd_read_report_desc(uaa->iface, &desc, &size,M_USBDEV); + } + if (err) { + printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev)); + sc->sc_dying = 1; + USB_ATTACH_ERROR_RETURN; + } - sc->sc_hdev.sc_intr = uhid_intr; - sc->sc_hdev.sc_parent = uha->parent; - sc->sc_hdev.sc_report_id = uha->reportid; + (void)usbd_set_idle(iface, 0, 0); + + sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); + sc->sc_osize = hid_report_size(desc, size, hid_output, &sc->sc_oid); + sc->sc_fsize = hid_report_size(desc, size, hid_feature, &sc->sc_fid); - uhidev_get_report_desc(uha->parent, &desc, &size); - repid = uha->reportid; - sc->sc_isize = hid_report_size(desc, size, hid_input, repid); - sc->sc_osize = hid_report_size(desc, size, hid_output, repid); - sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid); + sc->sc_repdesc = desc; + sc->sc_repdesc_size = size; - printf(": input=%d, output=%d, feature=%d\n", - sc->sc_isize, sc->sc_osize, sc->sc_fsize); +#ifdef __FreeBSD__ + { + static int global_init_done = 0; + + if (!global_init_done) { + cdevsw_add(&uhid_cdevsw); + global_init_done = 1; + } + } +#endif + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); USB_ATTACH_SUCCESS_RETURN; } +#if defined(__NetBSD__) || defined(__OpenBSD__) int uhid_activate(device_ptr_t self, enum devact act) { @@ -163,28 +287,36 @@ uhid_activate(device_ptr_t self, enum devact act) } return (0); } +#endif USB_DETACH(uhid) { USB_DETACH_START(uhid, sc); int s; +#if defined(__NetBSD__) || defined(__OpenBSD__) int maj, mn; DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); +#else + DPRINTF(("uhid_detach: sc=%p\n", sc)); +#endif sc->sc_dying = 1; + if (sc->sc_intrpipe != NULL) + usbd_abort_pipe(sc->sc_intrpipe); - if (sc->sc_hdev.sc_state & UHIDEV_OPEN) { + if (sc->sc_state & UHID_OPEN) { s = splusb(); if (--sc->sc_refcnt >= 0) { /* Wake everyone */ wakeup(&sc->sc_q); /* Wait for processes to go away. */ - usb_detach_wait(USBDEV(sc->sc_hdev.sc_dev)); + usb_detach_wait(USBDEV(sc->sc_dev)); } splx(s); } +#if defined(__NetBSD__) || defined(__OpenBSD__) /* locate the major number */ for (maj = 0; maj < nchrdev; maj++) if (cdevsw[maj].d_open == uhidopen) @@ -193,33 +325,47 @@ USB_DETACH(uhid) /* Nuke the vnodes for any open instances (calls close). */ mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); - -#if 0 - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, - sc->sc_hdev.sc_parent->sc_udev, - USBDEV(sc->sc_hdev.sc_dev)); +#elif defined(__FreeBSD__) + /* XXX not implemented yet */ #endif + if (sc->sc_repdesc) + free(sc->sc_repdesc, M_USBDEV); + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + return (0); } void -uhid_intr(struct uhidev *addr, void *data, u_int len) +uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) { - struct uhid_softc *sc = (struct uhid_softc *)addr; + struct uhid_softc *sc = addr; #ifdef UHID_DEBUG if (uhiddebug > 5) { - u_int32_t i; + u_int32_t cc, i; + usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); + DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc)); DPRINTF(("uhid_intr: data =")); - for (i = 0; i < len; i++) - DPRINTF((" %02x", ((u_char *)data)[i])); + for (i = 0; i < cc; i++) + DPRINTF((" %02x", sc->sc_ibuf[i])); DPRINTF(("\n")); } #endif - (void)b_to_q(data, len, &sc->sc_q); + if (status == USBD_CANCELLED) + return; + + if (status != USBD_NORMAL_COMPLETION) { + DPRINTF(("uhid_intr: status=%d\n", status)); + sc->sc_state |= UHID_NEEDCLEAR; + return; + } + + (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q); if (sc->sc_state & UHID_ASLP) { sc->sc_state &= ~UHID_ASLP; @@ -234,10 +380,10 @@ uhid_intr(struct uhidev *addr, void *data, u_int len) } int -uhidopen(dev_t dev, int flag, int mode, usb_proc_ptr p) +uhidopen(dev_t dev, int flag, int mode, struct proc *p) { struct uhid_softc *sc; - int error; + usbd_status err; USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc); @@ -246,23 +392,40 @@ uhidopen(dev_t dev, int flag, int mode, usb_proc_ptr p) if (sc->sc_dying) return (ENXIO); - error = uhidev_open(&sc->sc_hdev); - if (error) - return (error); + if (sc->sc_state & UHID_OPEN) + return (EBUSY); + sc->sc_state |= UHID_OPEN; if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) { - uhidev_close(&sc->sc_hdev); + sc->sc_state &= ~UHID_OPEN; return (ENOMEM); } + + sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK); + + /* Set up interrupt pipe. */ + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, + sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL); + if (err) { + DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " + "error=%d\n",err)); + free(sc->sc_ibuf, M_USBDEV); + free(sc->sc_obuf, M_USBDEV); + sc->sc_state &= ~UHID_OPEN; + return (EIO); + } + sc->sc_state &= ~UHID_IMMED; - sc->sc_async = NULL; + + sc->sc_async = 0; return (0); } int -uhidclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +uhidclose(dev_t dev, int flag, int mode, struct proc *p) { struct uhid_softc *sc; @@ -270,10 +433,19 @@ uhidclose(dev_t dev, int flag, int mode, usb_proc_ptr p) DPRINTF(("uhidclose: sc=%p\n", sc)); + /* Disable interrupts. */ + usbd_abort_pipe(sc->sc_intrpipe); + usbd_close_pipe(sc->sc_intrpipe); + sc->sc_intrpipe = 0; + clfree(&sc->sc_q); + + free(sc->sc_ibuf, M_USBDEV); free(sc->sc_obuf, M_USBDEV); - sc->sc_async = NULL; - uhidev_close(&sc->sc_hdev); + + sc->sc_state &= ~UHID_OPEN; + + sc->sc_async = 0; return (0); } @@ -283,7 +455,6 @@ uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) { int s; int error = 0; - int extra; size_t length; u_char buffer[UHID_CHUNK]; usbd_status err; @@ -291,12 +462,12 @@ uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) DPRINTFN(1, ("uhidread\n")); if (sc->sc_state & UHID_IMMED) { DPRINTFN(1, ("uhidread immed\n")); - extra = sc->sc_hdev.sc_report_id != 0; - err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, - buffer, sc->sc_isize + extra); + + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + sc->sc_iid, buffer, sc->sc_isize); if (err) return (EIO); - return (uiomove(buffer+extra, sc->sc_isize, uio)); + return (uiomove(buffer, sc->sc_isize, uio)); } s = splusb(); @@ -315,6 +486,11 @@ uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) sc->sc_state &= ~UHID_ASLP; break; } + if (sc->sc_state & UHID_NEEDCLEAR) { + DPRINTFN(-1,("uhidread: clearing stall\n")); + sc->sc_state &= ~UHID_NEEDCLEAR; + usbd_clear_endpoint_stall(sc->sc_intrpipe); + } } splx(s); @@ -347,7 +523,7 @@ uhidread(dev_t dev, struct uio *uio, int flag) sc->sc_refcnt++; error = uhid_do_read(sc, uio, flag); if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_hdev.sc_dev)); + usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); } @@ -369,8 +545,12 @@ uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) return (EINVAL); error = uiomove(sc->sc_obuf, size, uio); if (!error) { - err = uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, - sc->sc_obuf, size); + if (sc->sc_oid) + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + sc->sc_obuf[0], sc->sc_obuf+1, size-1); + else + err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, + 0, sc->sc_obuf, size); if (err) error = EIO; } @@ -389,20 +569,18 @@ uhidwrite(dev_t dev, struct uio *uio, int flag) sc->sc_refcnt++; error = uhid_do_write(sc, uio, flag); if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_hdev.sc_dev)); + usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); } int uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, - int flag, usb_proc_ptr p) + int flag, struct proc *p) { struct usb_ctl_report_desc *rd; struct usb_ctl_report *re; - u_char buffer[UHID_CHUNK]; - int size, extra; + int size, id; usbd_status err; - void *desc; DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); @@ -433,18 +611,17 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, break; case USB_GET_REPORT_DESC: - uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); rd = (struct usb_ctl_report_desc *)addr; - size = min(size, sizeof rd->ucrd_data); + size = min(sc->sc_repdesc_size, sizeof rd->ucrd_data); rd->ucrd_size = size; - memcpy(rd->ucrd_data, desc, size); + memcpy(rd->ucrd_data, sc->sc_repdesc, size); break; case USB_SET_IMMED: if (*(int *)addr) { - extra = sc->sc_hdev.sc_report_id != 0; - err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, - buffer, sc->sc_isize + extra); + /* XXX should read into ibuf, but does it matter? */ + err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, + sc->sc_iid, sc->sc_ibuf, sc->sc_isize); if (err) return (EOPNOTSUPP); @@ -458,21 +635,21 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, switch (re->ucr_report) { case UHID_INPUT_REPORT: size = sc->sc_isize; + id = sc->sc_iid; break; case UHID_OUTPUT_REPORT: size = sc->sc_osize; + id = sc->sc_oid; break; case UHID_FEATURE_REPORT: size = sc->sc_fsize; + id = sc->sc_fid; break; default: return (EINVAL); } - extra = sc->sc_hdev.sc_report_id != 0; - err = uhidev_get_report(&sc->sc_hdev, re->ucr_report, - re->ucr_data, size + extra); - if (extra) - memcpy(re->ucr_data, re->ucr_data+1, size); + err = usbd_get_report(sc->sc_iface, re->ucr_report, id, + re->ucr_data, size); if (err) return (EIO); break; @@ -482,26 +659,26 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, switch (re->ucr_report) { case UHID_INPUT_REPORT: size = sc->sc_isize; + id = sc->sc_iid; break; case UHID_OUTPUT_REPORT: size = sc->sc_osize; + id = sc->sc_oid; break; case UHID_FEATURE_REPORT: size = sc->sc_fsize; + id = sc->sc_fid; break; default: return (EINVAL); } - err = uhidev_set_report(&sc->sc_hdev, re->ucr_report, - re->ucr_data, size); + err = usbd_set_report(sc->sc_iface, re->ucr_report, id, + re->ucr_data, + size); if (err) return (EIO); break; - case USB_GET_REPORT_ID: - *(int *)addr = sc->sc_hdev.sc_report_id; - break; - default: return (EINVAL); } @@ -509,7 +686,7 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, } int -uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) +uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct uhid_softc *sc; int error; @@ -519,12 +696,12 @@ uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) sc->sc_refcnt++; error = uhid_do_ioctl(sc, cmd, addr, flag, p); if (--sc->sc_refcnt < 0) - usb_detach_wakeup(USBDEV(sc->sc_hdev.sc_dev)); + usb_detach_wakeup(USBDEV(sc->sc_dev)); return (error); } int -uhidpoll(dev_t dev, int events, usb_proc_ptr p) +uhidpoll(dev_t dev, int events, struct proc *p) { struct uhid_softc *sc; int revents = 0; @@ -548,3 +725,7 @@ uhidpoll(dev_t dev, int events, usb_proc_ptr p) splx(s); return (revents); } + +#if defined(__FreeBSD__) +DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0); +#endif diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c deleted file mode 100644 index 263ab111bf1..00000000000 --- a/sys/dev/usb/uhidev.c +++ /dev/null @@ -1,513 +0,0 @@ -/* $OpenBSD: uhidev.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhidev.c,v 1.5 2002/02/27 01:30:50 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/signalvar.h> -#include <sys/device.h> -#include <sys/ioctl.h> -#include <sys/conf.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdevs.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/hid.h> -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/uhidev.h> - -/* Report descriptor for broken Wacom Graphire */ -#include <dev/usb/ugraphire_rdesc.h> - -#ifdef UHIDEV_DEBUG -#define DPRINTF(x) if (uhidevdebug) logprintf x -#define DPRINTFN(n,x) if (uhidevdebug>(n)) logprintf x -int uhidevdebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -Static void uhidev_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -Static int uhidev_maxrepid(void *buf, int len); -Static int uhidevprint(void *aux, const char *pnp); -#if defined(__NetBSD__) -Static int uhidevsubmatch(struct device *parent, struct cfdata *cf, void *aux); -#else -Static int uhidevsubmatch(struct device *parent, void *cf, void *aux); -#endif - -USB_DECLARE_DRIVER(uhidev); - -USB_MATCH(uhidev) -{ - USB_MATCH_START(uhidev, uaa); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL || id->bInterfaceClass != UICLASS_HID) - return (UMATCH_NONE); - if (uaa->matchlvl) - return (uaa->matchlvl); - return (UMATCH_IFACECLASS_GENERIC); -} - -int repproto = 1; - -USB_ATTACH(uhidev) -{ - USB_ATTACH_START(uhidev, sc, uaa); - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - struct uhidev_attach_arg uha; - struct uhidev *dev; - int size, nrepid, repid, repsz; - int repsizes[256]; - void *desc; - usbd_status err; - char devinfo[1024]; - - sc->sc_udev = uaa->device; - sc->sc_iface = iface; - id = usbd_get_interface_descriptor(iface); - usbd_devinfo(uaa->device, 0, devinfo); - USB_ATTACH_SETUP; - printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), - devinfo, id->bInterfaceClass, id->bInterfaceSubClass); - - (void)usbd_set_idle(iface, 0, 0); -#if 0 - - qflags = usbd_get_quirks(sc->sc_udev)->uq_flags; - if ((qflags & UQ_NO_SET_PROTO) == 0 && - id->bInterfaceSubClass != UISUBCLASS_BOOT) - (void)usbd_set_protocol(iface, 1); -#endif - - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == NULL) { - printf("%s: could not read endpoint descriptor\n", - USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d " - "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" - " bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - ed->bEndpointAddress & UE_ADDR, - UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", - ed->bmAttributes & UE_XFERTYPE, - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - 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; - USB_ATTACH_ERROR_RETURN; - } - - sc->sc_ep_addr = ed->bEndpointAddress; - - /* XXX need to extend this */ - if (uaa->vendor == USB_VENDOR_WACOM && - uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* && - uaa->revision == 0x???? */) { /* XXX should use revision */ - /* The report descriptor for the Wacom Graphire is broken. */ - size = sizeof uhid_graphire_report_descr; - desc = malloc(size, M_USBDEV, M_NOWAIT); - if (desc == NULL) - err = USBD_NOMEM; - else { - err = USBD_NORMAL_COMPLETION; - memcpy(desc, uhid_graphire_report_descr, size); - } - } else { - desc = NULL; - err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV); - } - if (err) { - printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - sc->sc_repdesc = desc; - sc->sc_repdesc_size = size; - - uha.uaa = uaa; - nrepid = uhidev_maxrepid(desc, size); - if (nrepid < 0) - USB_ATTACH_SUCCESS_RETURN; - if (nrepid > 0) - printf("%s: %d report ids\n", USBDEVNAME(sc->sc_dev), nrepid); - nrepid++; - sc->sc_subdevs = malloc(nrepid * sizeof(device_ptr_t), - M_USBDEV, M_NOWAIT); - bzero(sc->sc_subdevs, nrepid * sizeof(device_ptr_t)); - if (sc->sc_subdevs == NULL) { - printf("%s: no memory\n", USBDEVNAME(sc->sc_dev)); - USB_ATTACH_ERROR_RETURN; - } - sc->sc_nrepid = nrepid; - sc->sc_isize = 0; - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - for (repid = 0; repid < nrepid; repid++) { - repsz = hid_report_size(desc, size, hid_input, repid); - DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); - repsizes[repid] = repsz; - if (repsz > 0) { - if (repsz > sc->sc_isize) - sc->sc_isize = repsz; - } - } - sc->sc_isize += nrepid != 1; /* space for report ID */ - DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); - - uha.parent = sc; - for (repid = 0; repid < nrepid; repid++) { - DPRINTF(("uhidev_match: try repid=%d\n", repid)); - if (hid_report_size(desc, size, hid_input, repid) == 0 && - hid_report_size(desc, size, hid_output, repid) == 0 && - hid_report_size(desc, size, hid_feature, repid) == 0) { - ; /* already NULL in sc->sc_subdevs[repid] */ - } else { - uha.reportid = repid; - dev = (struct uhidev *)config_found_sm(self, &uha, - uhidevprint, uhidevsubmatch); - sc->sc_subdevs[repid] = dev; - if (dev != NULL) { - dev->sc_in_rep_size = repsizes[repid]; -#ifdef DIAGNOSTIC - DPRINTF(("uhidev_match: repid=%d dev=%p\n", - repid, dev)); - if (dev->sc_intr == NULL) { - printf("%s: sc_intr == NULL\n", - USBDEVNAME(sc->sc_dev)); - USB_ATTACH_ERROR_RETURN; - } -#endif - } - } - } - - USB_ATTACH_SUCCESS_RETURN; -} - -int -uhidev_maxrepid(void *buf, int len) -{ - struct hid_data *d; - struct hid_item h; - int maxid; - - maxid = -1; - h.report_ID = 0; - for (d = hid_start_parse(buf, len, hid_none); hid_get_item(d, &h); ) - if (h.report_ID > maxid) - maxid = h.report_ID; - hid_end_parse(d); - return (maxid); -} - -int -uhidevprint(void *aux, const char *pnp) -{ - struct uhidev_attach_arg *uha = aux; - - if (pnp) - printf("uhid at %s", pnp); - if (uha->reportid != 0) - printf(" reportid %d", uha->reportid); - return (UNCONF); -} - -#if defined(__NetBSD__) -Static int uhidevsubmatch(struct device *parent, struct cfdata *cf, void *aux) -#else -Static int uhidevsubmatch(struct device *parent, void *match, void *aux) -#endif -{ - struct uhidev_attach_arg *uha = aux; -#if defined(__OpenBSD__) - struct cfdata *cf = match; -#endif - - if (cf->uhidevcf_reportid != UHIDEV_UNK_REPORTID && - cf->uhidevcf_reportid != uha->reportid) - return (0); - if (cf->uhidevcf_reportid == uha->reportid) - uha->matchlvl = UMATCH_VENDOR_PRODUCT; - else - uha->matchlvl = 0; - return ((*cf->cf_attach->ca_match)(parent, cf, aux)); -} - -int -uhidev_activate(device_ptr_t self, enum devact act) -{ - struct uhidev_softc *sc = (struct uhidev_softc *)self; - int i, rv; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - break; - - case DVACT_DEACTIVATE: - rv = 0; - for (i = 0; i < sc->sc_nrepid; i++) - if (sc->sc_subdevs[i] != NULL) - rv |= config_deactivate( - &sc->sc_subdevs[i]->sc_dev); - sc->sc_dying = 1; - break; - } - return (rv); -} - -USB_DETACH(uhidev) -{ - USB_DETACH_START(uhidev, sc); - int i, rv; - - DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); - - sc->sc_dying = 1; - if (sc->sc_intrpipe != NULL) - usbd_abort_pipe(sc->sc_intrpipe); - - if (sc->sc_repdesc != NULL) - free(sc->sc_repdesc, M_USBDEV); - - rv = 0; - for (i = 0; i < sc->sc_nrepid; i++) { - if (sc->sc_subdevs[i] != NULL) { - rv |= config_detach(&sc->sc_subdevs[i]->sc_dev, flags); - sc->sc_subdevs[i] = NULL; - } - } - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - return (rv); -} - -void -uhidev_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct uhidev_softc *sc = addr; - struct uhidev *scd; - u_char *p; - u_int rep; - u_int32_t cc; - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - -#ifdef UHIDEV_DEBUG - if (uhidevdebug > 5) { - u_int32_t i; - - DPRINTF(("uhidev_intr: status=%d cc=%d\n", status, cc)); - DPRINTF(("uhidev_intr: data =")); - for (i = 0; i < cc; i++) - DPRINTF((" %02x", sc->sc_ibuf[i])); - DPRINTF(("\n")); - } -#endif - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("%s: interrupt status=%d\n", USBDEVNAME(sc->sc_dev), - status)); - usbd_clear_endpoint_stall_async(sc->sc_intrpipe); - return; - } - - p = sc->sc_ibuf; - if (sc->sc_nrepid != 1) - rep = *p++, cc--; - else - rep = 0; - if (rep >= sc->sc_nrepid) { - printf("uhidev_intr: bad repid %d\n", rep); - return; - } - scd = sc->sc_subdevs[rep]; - DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=0x%x\n", - rep, scd, scd ? scd->sc_state : 0)); - if (scd == NULL || !(scd->sc_state & UHIDEV_OPEN)) - return; -#ifdef DIAGNOSTIC - if (scd->sc_in_rep_size != cc) - printf("%s: bad input length %d != %d\n",USBDEVNAME(sc->sc_dev), - scd->sc_in_rep_size, cc); -#endif - scd->sc_intr(scd, p, cc); -} - -void -uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) -{ - *desc = sc->sc_repdesc; - *size = sc->sc_repdesc_size; -} - -int -uhidev_open(struct uhidev *scd) -{ - struct uhidev_softc *sc = scd->sc_parent; - usbd_status err; - - DPRINTF(("uhidev_open: open pipe, state=%d refcnt=%d\n", - scd->sc_state, sc->sc_refcnt)); - - if (scd->sc_state & UHIDEV_OPEN) - return (EBUSY); - scd->sc_state |= UHIDEV_OPEN; - if (sc->sc_refcnt++) - return (0); - - if (sc->sc_isize == 0) - return (0); - - sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); - - /* Set up interrupt pipe. */ - DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize, - sc->sc_ep_addr)); - err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, - USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, - sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL); - if (err) { - DPRINTF(("uhidopen: usbd_open_pipe_intr failed, " - "error=%d\n",err)); - free(sc->sc_ibuf, M_USBDEV); - scd->sc_state &= ~UHIDEV_OPEN; - sc->sc_refcnt = 0; - sc->sc_intrpipe = NULL; - return (EIO); - } - return (0); -} - -void -uhidev_close(struct uhidev *scd) -{ - struct uhidev_softc *sc = scd->sc_parent; - - if (!(scd->sc_state & UHIDEV_OPEN)) - return; - scd->sc_state &= ~UHIDEV_OPEN; - if (--sc->sc_refcnt) - return; - DPRINTF(("uhidev_close: close pipe\n")); - - /* Disable interrupts. */ - if (sc->sc_intrpipe != NULL) { - usbd_abort_pipe(sc->sc_intrpipe); - usbd_close_pipe(sc->sc_intrpipe); - sc->sc_intrpipe = NULL; - } - - if (sc->sc_ibuf != NULL) { - free(sc->sc_ibuf, M_USBDEV); - sc->sc_ibuf = NULL; - } -} - -usbd_status -uhidev_set_report(struct uhidev *scd, int type, void *data, int len) -{ - /* XXX */ - char buf[100]; - if (scd->sc_report_id) { - buf[0] = scd->sc_report_id; - memcpy(buf+1, data, len); - len++; - data = buf; - } - - return usbd_set_report(scd->sc_parent->sc_iface, type, - scd->sc_report_id, data, len); -} - -void -uhidev_set_report_async(struct uhidev *scd, int type, void *data, int len) -{ - /* XXX */ - char buf[100]; - if (scd->sc_report_id) { - buf[0] = scd->sc_report_id; - memcpy(buf+1, data, len); - len++; - data = buf; - } - - usbd_set_report_async(scd->sc_parent->sc_iface, type, - scd->sc_report_id, data, len); -} - -usbd_status -uhidev_get_report(struct uhidev *scd, int type, void *data, int len) -{ - return usbd_get_report(scd->sc_parent->sc_iface, type, - scd->sc_report_id, data, len); -} diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h deleted file mode 100644 index 8d2700132cb..00000000000 --- a/sys/dev/usb/uhidev.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $OpenBSD: uhidev.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhidev.h,v 1.2 2001/12/29 18:56:52 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(__NetBSD__) -#include "locators.h" -#endif - -#define uhidevcf_reportid cf_loc[UHIDBUSCF_REPORTID] -#define UHIDEV_UNK_REPORTID UHIDBUSCF_REPORTID_DEFAULT - -struct uhidev_softc { - USBBASEDEVICE sc_dev; /* base device */ - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; /* interface */ - usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ - int sc_ep_addr; - - u_char *sc_ibuf; - u_int sc_isize; - - void *sc_repdesc; - int sc_repdesc_size; - - u_int sc_nrepid; - struct uhidev **sc_subdevs; - - int sc_refcnt; - u_char sc_dying; -}; - -struct uhidev { - USBBASEDEVICE sc_dev; /* base device */ - struct uhidev_softc *sc_parent; - uByte sc_report_id; - u_int8_t sc_state; - int sc_in_rep_size; -#define UHIDEV_OPEN 0x01 /* device is open */ - void (*sc_intr)(struct uhidev *, void *, u_int); -}; - -struct uhidev_attach_arg { - struct usb_attach_arg *uaa; - struct uhidev_softc *parent; - int reportid; - int reportsize; - int matchlvl; -}; - -void uhidev_get_report_desc(struct uhidev_softc *, void **, int *); -int uhidev_open(struct uhidev *); -void uhidev_close(struct uhidev *); -usbd_status uhidev_set_report(struct uhidev *scd, int type, void *data,int len); -void uhidev_set_report_async(struct uhidev *scd, int type, void *data, int len); -usbd_status uhidev_get_report(struct uhidev *scd, int type, void *data,int len); diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 364de76d3f4..19c6acc0b10 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uhub.c,v 1.15 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uhub.c,v 1.57 2001/11/20 16:08:37 augustss Exp $ */ +/* $OpenBSD: uhub.c,v 1.16 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uhub.c,v 1.52 2001/10/26 17:53:59 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */ /* @@ -268,7 +268,6 @@ USB_ATTACH(uhub) * For all ports * get port status * if device connected - * wait 100 ms * turn on reset * wait * clear C_PORT_RESET @@ -324,7 +323,6 @@ uhub_explore(usbd_device_handle dev) struct uhub_softc *sc = dev->hub->hubsoftc; struct usbd_port *up; usbd_status err; - int speed; int port; int change, status; @@ -425,38 +423,15 @@ uhub_explore(usbd_device_handle dev) /* Reset port, which implies enabling it. */ if (usbd_reset_port(dev, port, &up->status)) { - printf("%s: port %d reset failed\n", - USBDEVNAME(sc->sc_dev), port); - continue; - } - /* Get port status again, it might have changed during reset */ - err = usbd_get_port_status(dev, port, &up->status); - if (err) { - DPRINTF(("uhub_explore: get port status failed, " - "error=%s\n", usbd_errstr(err))); - continue; - } - status = UGETW(up->status.wPortStatus); - change = UGETW(up->status.wPortChange); - if (!(status & UPS_CURRENT_CONNECT_STATUS)) { - /* Nothing connected, just ignore it. */ -#ifdef DIAGNOSTIC - printf("%s: port %d, device disappeared after reset\n", - USBDEVNAME(sc->sc_dev), port); -#endif + printf("uhub_explore: port=%d reset failed\n", + port); continue; } - /* Figure out device speed */ - if (status & UPS_HIGH_SPEED) - speed = USB_SPEED_HIGH; - else if (status & UPS_LOW_SPEED) - speed = USB_SPEED_LOW; - else - speed = USB_SPEED_FULL; /* Get device info and set its address. */ err = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, - dev->depth + 1, speed, port, up); + dev->depth + 1, status & UPS_LOW_SPEED, + port, up); /* XXX retry a few times? */ if (err) { DPRINTFN(-1,("uhub_explore: usb_new_device failed, " diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c index b57d0f4e37b..0843bd9392d 100644 --- a/sys/dev/usb/ukbd.c +++ b/sys/dev/usb/ukbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ukbd.c,v 1.12 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ukbd.c,v 1.79 2001/12/30 19:37:43 augustss Exp $ */ +/* $OpenBSD: ukbd.c,v 1.13 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ukbd.c,v 1.69 2001/10/24 21:02:18 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -66,7 +66,6 @@ #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdevs.h> #include <dev/usb/usb_quirks.h> -#include <dev/usb/uhidev.h> #include <dev/usb/hid.h> #include <dev/usb/ukbdvar.h> @@ -89,96 +88,119 @@ int ukbddebug = 0; #define DPRINTFN(n,x) #endif -#define MAXKEYCODE 6 -#define MAXMOD 8 /* max 32 */ +#define NKEYCODE 6 + +#define NUM_LOCK 0x01 +#define CAPS_LOCK 0x02 +#define SCROLL_LOCK 0x04 struct ukbd_data { - u_int32_t modifiers; - u_int8_t keycode[MAXKEYCODE]; + u_int8_t modifiers; +#define MOD_CONTROL_L 0x01 +#define MOD_CONTROL_R 0x10 +#define MOD_SHIFT_L 0x02 +#define MOD_SHIFT_R 0x20 +#define MOD_ALT_L 0x04 +#define MOD_ALT_R 0x40 +#define MOD_WIN_L 0x08 +#define MOD_WIN_R 0x80 + u_int8_t reserved; + u_int8_t keycode[NKEYCODE]; }; #define PRESS 0x000 #define RELEASE 0x100 #define CODEMASK 0x0ff +/* Translate USB bitmap to USB keycode. */ +#define NMOD 8 +Static const struct { + int mask, key; +} ukbd_mods[NMOD] = { + { MOD_CONTROL_L, 224 }, + { MOD_CONTROL_R, 228 }, + { MOD_SHIFT_L, 225 }, + { MOD_SHIFT_R, 229 }, + { MOD_ALT_L, 226 }, + { MOD_ALT_R, 230 }, + { MOD_WIN_L, 227 }, + { MOD_WIN_R, 231 }, +}; + #if defined(WSDISPLAY_COMPAT_RAWKBD) #define NN 0 /* no translation */ /* * Translate USB keycodes to US keyboard XT scancodes. - * Scancodes >= 0x80 represent EXTENDED keycodes. - * - * See http://www.microsoft.com/HWDEV/TECH/input/Scancode.asp + * Scancodes >= 128 represent EXTENDED keycodes. */ Static const u_int8_t ukbd_trtab[256] = { - NN, NN, NN, NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */ - 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */ - 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */ - 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */ - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */ - 0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */ - 0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */ - 0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */ - 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */ - 0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */ - 0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */ - 0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */ - 0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, NN, 0x59, /* 60 - 67 */ - 0x5d, 0x5e, 0x5f, NN, NN, NN, NN, NN, /* 68 - 6f */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7f */ - NN, NN, NN, NN, NN, 0x7e, NN, 0x73, /* 80 - 87 */ - 0x70, 0x7d, 0x79, 0x7b, 0x5c, NN, NN, NN, /* 88 - 8f */ - NN, NN, 0x78, 0x77, 0x76, NN, NN, NN, /* 90 - 97 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9f */ - NN, NN, NN, NN, NN, NN, NN, NN, /* a0 - a7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* a8 - af */ - NN, NN, NN, NN, NN, NN, NN, NN, /* b0 - b7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* b8 - bf */ - NN, NN, NN, NN, NN, NN, NN, NN, /* c0 - c7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* c8 - cf */ - NN, NN, NN, NN, NN, NN, NN, NN, /* d0 - d7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* d8 - df */ - 0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* e8 - ef */ - NN, NN, NN, NN, NN, NN, NN, NN, /* f0 - f7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* f8 - ff */ + NN, NN, NN, NN, 30, 48, 46, 32, /* 00 - 07 */ + 18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */ + 50, 49, 24, 25, 16, 19, 31, 20, /* 10 - 17 */ + 22, 47, 17, 45, 21, 44, 2, 3, /* 18 - 1F */ + 4, 5, 6, 7, 8, 9, 10, 11, /* 20 - 27 */ + 28, 1, 14, 15, 57, 12, 13, 26, /* 28 - 2F */ + 27, 43, 43, 39, 40, 41, 51, 52, /* 30 - 37 */ + 53, 58, 59, 60, 61, 62, 63, 64, /* 38 - 3F */ + 65, 66, 67, 68, 87, 88, 170, 70, /* 40 - 47 */ + 127, 210, 199, 201, 211, 207, 209, 205, /* 48 - 4F */ + 203, 208, 200, 69, 181, 55, 74, 78, /* 50 - 57 */ + 156, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ + 72, 73, 82, 83, 86, 221, NN, NN, /* 60 - 67 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 70 - 77 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 78 - 7F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 80 - 87 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 88 - 8F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* 98 - 9F */ + NN, NN, NN, NN, NN, NN, NN, NN, /* A0 - A7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* A8 - AF */ + NN, NN, NN, NN, NN, NN, NN, NN, /* B0 - B7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* B8 - BF */ + NN, NN, NN, NN, NN, NN, NN, NN, /* C0 - C7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* C8 - CF */ + NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ + 29, 42, 56, 219, 157, 54, 184,220, /* E0 - E7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ + NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ + NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ }; #endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */ #define KEY_ERROR 0x01 -#define MAXKEYS (MAXMOD+2*MAXKEYCODE) +#define MAXKEYS (NMOD+2*NKEYCODE) struct ukbd_softc { - struct uhidev sc_hdev; + USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; /* interface */ + usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ + int sc_ep_addr; struct ukbd_data sc_ndata; struct ukbd_data sc_odata; - struct hid_location sc_modloc[MAXMOD]; - u_int sc_nmod; - struct { - u_int32_t mask; - u_int8_t key; - } sc_mods[MAXMOD]; - - struct hid_location sc_keycodeloc; - u_int sc_nkeycode; char sc_enabled; int sc_console_keyboard; /* we are the console keyboard */ char sc_debounce; /* for quirk handling */ - usb_callout_t sc_delay; /* for quirk handling */ struct ukbd_data sc_data; /* for quirk handling */ - struct hid_location sc_numloc; - struct hid_location sc_capsloc; - struct hid_location sc_scroloc; int sc_leds; - usb_callout_t sc_rawrepeat_ch; +#if defined(__OpenBSD__) + struct timeout sc_delay; /* for quirk handling */ + struct timeout sc_rawrepeat_ch; +#else + struct callout sc_delay; /* for quirk handling */ + struct callout sc_rawrepeat_ch; +#endif +#if defined(__NetBSD__) || defined(__OpenBSD__) struct device *sc_wskbddev; #if defined(WSDISPLAY_COMPAT_RAWKBD) #define REP_DELAY1 400 @@ -191,6 +213,7 @@ struct ukbd_softc { int sc_polling; int sc_npollchar; u_int16_t sc_pollchars[MAXKEYS]; +#endif u_char sc_dying; }; @@ -231,21 +254,22 @@ Static int ukbd_is_console; Static void ukbd_cngetc(void *, u_int *, int *); Static void ukbd_cnpollc(void *, int); +#if defined(__NetBSD__) || defined(__OpenBSD__) const struct wskbd_consops ukbd_consops = { ukbd_cngetc, ukbd_cnpollc, }; +#endif -Static const char *ukbd_parse_desc(struct ukbd_softc *sc); - -Static void ukbd_intr(struct uhidev *addr, void *ibuf, u_int len); +Static void ukbd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); Static void ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud); Static void ukbd_delayed_decode(void *addr); Static int ukbd_enable(void *, int); Static void ukbd_set_leds(void *, int); -Static int ukbd_ioctl(void *, u_long, caddr_t, int, usb_proc_ptr ); +#if defined(__NetBSD__) || defined(__OpenBSD__) +Static int ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *); #ifdef WSDISPLAY_COMPAT_RAWKBD Static void ukbd_rawrepeat(void *v); #endif @@ -266,53 +290,90 @@ const struct wskbd_mapdata ukbd_keymapdata = { KB_US, #endif }; +#endif USB_DECLARE_DRIVER(ukbd); USB_MATCH(ukbd) { USB_MATCH_START(ukbd, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; - int size; - void *desc; + usb_interface_descriptor_t *id; - uhidev_get_report_desc(uha->parent, &desc, &size); - if (!hid_is_collection(desc, size, uha->reportid, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) + /* Check that this is a keyboard that speaks the boot protocol. */ + if (uaa->iface == NULL) return (UMATCH_NONE); - - return (UMATCH_IFACECLASS); + id = usbd_get_interface_descriptor(uaa->iface); + if (id == NULL || + id->bInterfaceClass != UICLASS_HID || + id->bInterfaceSubClass != UISUBCLASS_BOOT || + id->bInterfaceProtocol != UIPROTO_BOOT_KEYBOARD) + return (UMATCH_NONE); + return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); } USB_ATTACH(ukbd) { USB_ATTACH_START(ukbd, sc, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; + usbd_interface_handle iface = uaa->iface; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + usbd_status err; u_int32_t qflags; - const char *parseerr; + char devinfo[1024]; +#if defined(__NetBSD__) || defined(__OpenBSD__) struct wskbddev_attach_args a; +#else + int i; +#endif - sc->sc_hdev.sc_intr = ukbd_intr; - sc->sc_hdev.sc_parent = uha->parent; - sc->sc_hdev.sc_report_id = uha->reportid; - - parseerr = ukbd_parse_desc(sc); - if (parseerr != NULL) { - printf("\n%s: attach failed, %s\n", - sc->sc_hdev.sc_dev.dv_xname, parseerr); + sc->sc_udev = uaa->device; + sc->sc_iface = iface; + id = usbd_get_interface_descriptor(iface); + usbd_devinfo(uaa->device, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), + devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + + ed = usbd_interface2endpoint_descriptor(iface, 0); + if (ed == NULL) { + printf("%s: could not read endpoint descriptor\n", + USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } - -#ifdef DIAGNOSTIC - printf(": %d modifier keys, %d key codes", sc->sc_nmod, - sc->sc_nkeycode); -#endif - printf("\n"); + DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d " + "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" + " bInterval=%d\n", + ed->bLength, ed->bDescriptorType, + ed->bEndpointAddress & UE_ADDR, + UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", + ed->bmAttributes & UE_XFERTYPE, + UGETW(ed->wMaxPacketSize), ed->bInterval)); + + if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || + (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { + printf("%s: unexpected endpoint\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } - qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags; + qflags = usbd_get_quirks(uaa->device)->uq_flags; + if ((qflags & UQ_NO_SET_PROTO) == 0) { + err = usbd_set_protocol(iface, 0); + DPRINTFN(5, ("ukbd_attach: protocol set\n")); + if (err) { + printf("%s: set protocol failed\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } + } sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0; + /* Ignore if SETIDLE fails since it is not crucial. */ + (void)usbd_set_idle(iface, 0, 0); + + sc->sc_ep_addr = ed->bEndpointAddress; + /* * Remember if we're the console keyboard. * @@ -337,14 +398,26 @@ USB_ATTACH(ukbd) a.accessops = &ukbd_accessops; a.accesscookie = sc; - usb_callout_init(sc->sc_rawrepeat_ch); - usb_callout_init(sc->sc_delay); +#if defined(__OpenBSD__) +#ifdef WSDISPLAY_COMPAT_RAWKBD + timeout_set(&sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); +#endif + timeout_set(&sc->sc_delay, ukbd_delayed_decode, sc); +#endif + +#if defined(__NetBSD__) + callout_init(&sc->sc_rawrepeat_ch); + callout_init(&sc->sc_delay); +#endif /* Flash the leds; no real purpose, just shows we're alive. */ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); - usbd_delay_ms(uha->parent->sc_udev, 400); + usbd_delay_ms(uaa->device, 400); ukbd_set_leds(sc, 0); + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + sc->sc_wskbddev = config_found(self, &a, wskbddevprint); USB_ATTACH_SUCCESS_RETURN; @@ -354,27 +427,38 @@ int ukbd_enable(void *v, int on) { struct ukbd_softc *sc = v; + usbd_status err; if (on && sc->sc_dying) return (EIO); /* Should only be called to change state */ if (sc->sc_enabled == on) { -#ifdef DIAGNOSTIC +#ifdef UKBD_DEBUG printf("ukbd_enable: %s: bad call on=%d\n", - USBDEVNAME(sc->sc_hdev.sc_dev), on); + USBDEVNAME(sc->sc_dev), on); #endif return (EBUSY); } DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on)); - sc->sc_enabled = on; if (on) { - return (uhidev_open(&sc->sc_hdev)); + /* Set up interrupt pipe. */ + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, + &sc->sc_ndata, sizeof(sc->sc_ndata), ukbd_intr, + USBD_DEFAULT_INTERVAL); + if (err) + return (EIO); } else { - uhidev_close(&sc->sc_hdev); - return (0); + /* Disable interrupts. */ + usbd_abort_pipe(sc->sc_intrpipe); + usbd_close_pipe(sc->sc_intrpipe); + sc->sc_intrpipe = NULL; } + sc->sc_enabled = on; + + return (0); } int @@ -423,8 +507,7 @@ USB_DETACH(ukbd) * XXX Should notify some other keyboard that it can be * XXX console, if there are any other keyboards. */ - printf("%s: was console keyboard\n", - USBDEVNAME(sc->sc_hdev.sc_dev)); + printf("%s: was console keyboard\n", USBDEVNAME(sc->sc_dev)); wskbd_cndetach(); ukbd_is_console = 1; #endif @@ -434,34 +517,37 @@ USB_DETACH(ukbd) rv = config_detach(sc->sc_wskbddev, flags); /* The console keyboard does not get a disable call, so check pipe. */ - if (sc->sc_hdev.sc_state & UHIDEV_OPEN) - uhidev_close(&sc->sc_hdev); + if (sc->sc_intrpipe != NULL) { + usbd_abort_pipe(sc->sc_intrpipe); + usbd_close_pipe(sc->sc_intrpipe); + sc->sc_intrpipe = NULL; + } + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); return (rv); } void -ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) +ukbd_intr(xfer, addr, status) + usbd_xfer_handle xfer; + usbd_private_handle addr; + usbd_status status; { - struct ukbd_softc *sc = (struct ukbd_softc *)addr; + struct ukbd_softc *sc = addr; struct ukbd_data *ud = &sc->sc_ndata; - int i; -#ifdef UKBD_DEBUG - if (ukbddebug > 5) { - printf("ukbd_intr: data"); - for (i = 0; i < len; i++) - printf(" 0x%02x", ((u_char *)ibuf)[i]); - printf("\n"); - } -#endif + DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); + if (status == USBD_CANCELLED) + return; - ud->modifiers = 0; - for (i = 0; i < sc->sc_nmod; i++) - if (hid_get_data(ibuf, &sc->sc_modloc[i])) - ud->modifiers |= sc->sc_mods[i].mask; - memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8, - sc->sc_nkeycode); + if (status) { + DPRINTF(("ukbd_intr: status=%d\n", status)); + if (status == USBD_STALLED) + usbd_clear_endpoint_stall_async(sc->sc_intrpipe); + return; + } if (sc->sc_debounce && !sc->sc_polling) { /* @@ -471,8 +557,12 @@ ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) * We avoid this bug by holding off decoding for 20 ms. */ sc->sc_data = *ud; - usb_callout(sc->sc_delay, hz / 50, ukbd_delayed_decode, sc); -#ifdef DDB +#if defined(__OpenBSD__) + timeout_add(&sc->sc_delay, hz / 50); +#else + callout_reset(&sc->sc_delay, hz / 50, ukbd_delayed_decode, sc); +#endif +#if DDB } else if (sc->sc_console_keyboard && !sc->sc_polling) { /* * For the console keyboard we can't deliver CTL-ALT-ESC @@ -481,7 +571,11 @@ ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) * loses bigtime. */ sc->sc_data = *ud; - usb_callout(sc->sc_delay, 1, ukbd_delayed_decode, sc); +#if defined(__OpenBSD__) + timeout_add(&sc->sc_delay, 1); /* NOT an immediate timeout */ +#else + callout_reset(&sc->sc_delay, 0, ukbd_delayed_decode, sc); +#endif #endif } else { ukbd_decode(sc, ud); @@ -513,7 +607,7 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) */ if (ukbdtrace) { struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex]; - p->unit = sc->sc_hdev.sc_dev.dv_unit; + p->unit = sc->sc_dev.dv_unit; microtime(&p->tv); p->ud = *ud; if (++ukbdtraceindex >= UKBDTRACESIZE) @@ -538,19 +632,19 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) mod = ud->modifiers; omod = sc->sc_odata.modifiers; if (mod != omod) - for (i = 0; i < sc->sc_nmod; i++) - if (( mod & sc->sc_mods[i].mask) != - (omod & sc->sc_mods[i].mask)) - ADDKEY(sc->sc_mods[i].key | - (mod & sc->sc_mods[i].mask + for (i = 0; i < NMOD; i++) + if (( mod & ukbd_mods[i].mask) != + (omod & ukbd_mods[i].mask)) + ADDKEY(ukbd_mods[i].key | + (mod & ukbd_mods[i].mask ? PRESS : RELEASE)); - if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) { + if (memcmp(ud->keycode, sc->sc_odata.keycode, NKEYCODE) != 0) { /* Check for released keys. */ - for (i = 0; i < sc->sc_nkeycode; i++) { + for (i = 0; i < NKEYCODE; i++) { key = sc->sc_odata.keycode[i]; if (key == 0) continue; - for (j = 0; j < sc->sc_nkeycode; j++) + for (j = 0; j < NKEYCODE; j++) if (key == ud->keycode[j]) goto rfound; DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key)); @@ -560,11 +654,11 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) } /* Check for pressed keys. */ - for (i = 0; i < sc->sc_nkeycode; i++) { + for (i = 0; i < NKEYCODE; i++) { key = ud->keycode[i]; if (key == 0) continue; - for (j = 0; j < sc->sc_nkeycode; j++) + for (j = 0; j < NKEYCODE; j++) if (key == sc->sc_odata.keycode[j]) goto pfound; DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key)); @@ -586,7 +680,7 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) } #ifdef WSDISPLAY_COMPAT_RAWKBD if (sc->sc_rawkbd) { - u_char cbuf[MAXKEYS * 2]; + char cbuf[MAXKEYS * 2]; int c; int npress; @@ -614,11 +708,19 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud) s = spltty(); wskbd_rawinput(sc->sc_wskbddev, cbuf, j); splx(s); - usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); +#if defined(__OpenBSD__) + timeout_del(&sc->sc_rawrepeat_ch); +#else + callout_stop(&sc->sc_rawrepeat_ch); +#endif if (npress != 0) { sc->sc_nrep = npress; - usb_callout(sc->sc_rawrepeat_ch, +#if defined(__OpenBSD__) + timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAY1/1000); +#else + callout_reset(&sc->sc_rawrepeat_ch, hz * REP_DELAY1 / 1000, ukbd_rawrepeat, sc); +#endif } return; } @@ -640,24 +742,21 @@ ukbd_set_leds(void *v, int leds) struct ukbd_softc *sc = v; u_int8_t res; - DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n", - sc, leds, sc->sc_leds)); + DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds)); if (sc->sc_dying) return; - if (sc->sc_leds == leds) - return; sc->sc_leds = leds; res = 0; - /* XXX not really right */ - if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1) - res |= 1 << sc->sc_scroloc.pos; - if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1) - res |= 1 << sc->sc_numloc.pos; - if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1) - res |= 1 << sc->sc_capsloc.pos; - uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1); + if (leds & WSKBD_LED_SCROLL) + res |= SCROLL_LOCK; + if (leds & WSKBD_LED_NUM) + res |= NUM_LOCK; + if (leds & WSKBD_LED_CAPS) + res |= CAPS_LOCK; + res |= leds & 0xf8; + usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1); } #ifdef WSDISPLAY_COMPAT_RAWKBD @@ -670,13 +769,17 @@ ukbd_rawrepeat(void *v) s = spltty(); wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep); splx(s); - usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, +#if defined(__OpenBSD__) + timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000); +#else + callout_reset(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000, ukbd_rawrepeat, sc); +#endif } #endif int -ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) +ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { struct ukbd_softc *sc = v; @@ -694,19 +797,17 @@ ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) case WSKBDIO_SETMODE: DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data)); sc->sc_rawkbd = *(int *)data == WSKBD_RAW; - usb_uncallout(sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc); +#if defined(__OpenBSD__) + timeout_del(&sc->sc_rawrepeat_ch); +#else + callout_stop(&sc->sc_rawrepeat_ch); +#endif return (0); #endif } return (-1); } -/* - * This is a hack to work around some broken ports that don't call - * cnpollc() before cngetc(). - */ -static int pollenter, warned; - /* Console interface. */ void ukbd_cngetc(void *v, u_int *type, int *data) @@ -714,25 +815,12 @@ ukbd_cngetc(void *v, u_int *type, int *data) struct ukbd_softc *sc = v; int s; int c; - int broken; - - if (pollenter == 0) { - if (!warned) { - printf("\n" -"This port is broken, it does not call cnpollc() before calling cngetc().\n" -"This should be fixed, but it will work anyway (for now).\n"); - warned = 1; - } - broken = 1; - ukbd_cnpollc(v, 1); - } else - broken = 0; DPRINTFN(0,("ukbd_cngetc: enter\n")); s = splusb(); sc->sc_polling = 1; while(sc->sc_npollchar <= 0) - usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface); + usbd_dopoll(sc->sc_iface); sc->sc_polling = 0; c = sc->sc_pollchars[0]; sc->sc_npollchar--; @@ -742,8 +830,6 @@ ukbd_cngetc(void *v, u_int *type, int *data) *data = c & CODEMASK; splx(s); DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c)); - if (broken) - ukbd_cnpollc(v, 0); } void @@ -754,8 +840,7 @@ ukbd_cnpollc(void *v, int on) DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on)); - usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev); - if (on) pollenter++; else pollenter--; + (void)usbd_interface2device_handle(sc->sc_iface,&dev); usbd_set_polling(dev, on); } @@ -771,64 +856,3 @@ ukbd_cnattach(void) ukbd_is_console = 1; return (0); } - -const char * -ukbd_parse_desc(struct ukbd_softc *sc) -{ - struct hid_data *d; - struct hid_item h; - int size; - void *desc; - int imod; - - uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); - imod = 0; - sc->sc_nkeycode = 0; - d = hid_start_parse(desc, size, hid_input); - while (hid_get_item(d, &h)) { - /*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n", - h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/ - if (h.kind != hid_input || (h.flags & HIO_CONST) || - HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD || - h.report_ID != sc->sc_hdev.sc_report_id) - continue; - DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d " - "cnt=%d\n", imod, - h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count)); - if (h.flags & HIO_VARIABLE) { - if (h.loc.size != 1) - return ("bad modifier size"); - /* Single item */ - if (imod < MAXMOD) { - sc->sc_modloc[imod] = h.loc; - sc->sc_mods[imod].mask = 1 << imod; - sc->sc_mods[imod].key = HID_GET_USAGE(h.usage); - imod++; - } else - return ("too many modifier keys"); - } else { - /* Array */ - if (h.loc.size != 8) - return ("key code size != 8"); - if (h.loc.count > MAXKEYCODE) - return ("too many key codes"); - if (h.loc.pos % 8 != 0) - return ("key codes not on byte boundary"); - if (sc->sc_nkeycode != 0) - return ("multiple key code arrays\n"); - sc->sc_keycodeloc = h.loc; - sc->sc_nkeycode = h.loc.count; - } - } - sc->sc_nmod = imod; - hid_end_parse(d); - - hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK), - sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL); - hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK), - sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL); - hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK), - sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL); - - return (NULL); -} diff --git a/sys/dev/usb/ukbdmap.c b/sys/dev/usb/ukbdmap.c index 9d0ad9f25d8..b5f4bb01d69 100644 --- a/sys/dev/usb/ukbdmap.c +++ b/sys/dev/usb/ukbdmap.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ukbdmap.c,v 1.10 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ukbdmap.c,v 1.10 2002/03/17 18:01:07 augustss Exp $ */ +/* $OpenBSD: ukbdmap.c,v 1.11 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ukbdmap.c,v 1.6 2001/04/04 05:31:57 toshii Exp $ */ /* - * Copyright (c) 1999,2001 The NetBSD Foundation, Inc. + * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -94,7 +94,7 @@ Static const keysym_t ukbd_keydesc_us[] = { KC(47), KS_bracketleft, KS_braceleft, KC(48), KS_bracketright,KS_braceright, KC(49), KS_backslash, KS_bar, - KC(50), KS_backslash, KS_bar, + KC(50), KS_numbersign, KS_asciitilde, KC(51), KS_semicolon, KS_colon, KC(52), KS_apostrophe, KS_quotedbl, KC(53), KS_grave, KS_asciitilde, @@ -256,7 +256,6 @@ Static const keysym_t ukbd_keydesc_sv[] = { /* pos normal shifted altgr shift-altgr */ KC(45), KS_plus, KS_question, KS_backslash, KC(48), KS_dead_diaeresis, KS_dead_circumflex, KS_dead_tilde, - KC(50), KS_comma, KS_asterisk, KC(51), KS_odiaeresis, KC(52), KS_adiaeresis, KC(53), KS_paragraph, KS_onehalf, @@ -274,7 +273,6 @@ Static const keysym_t ukbd_keydesc_no[] = { /* pos normal shifted altgr shift-altgr */ KC(46), KS_backslash, KS_dead_grave, KS_dead_acute, KC(48), KS_dead_diaeresis, KS_dead_circumflex, KS_dead_tilde, - KC(50), KS_comma, KS_asterisk, KC(51), KS_oslash, KC(52), KS_ae, KC(53), KS_bar, KS_paragraph, @@ -360,7 +358,6 @@ Static const keysym_t ukbd_keydesc_uk[] = { KC(45), KS_minus, KS_underscore, KS_hyphen, KS_ssharp, KC(46), KS_equal, KS_plus, KS_onehalf, KS_guillemotleft, KC(49), KS_numbersign, KS_asciitilde, KS_sterling, KS_thorn, - KC(50), KS_numbersign, KS_asciitilde, KC(52), KS_apostrophe, KS_at, KS_section, KS_Agrave, KC(53), KS_grave, KS_grave, KS_agrave, KS_agrave, KC(100), KS_backslash, KS_bar, KS_Udiaeresis, diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c index a47e31a0d27..b1a38c934f8 100644 --- a/sys/dev/usb/umass.c +++ b/sys/dev/usb/umass.c @@ -1,5 +1,5 @@ -/* $OpenBSD: umass.c,v 1.15 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umass.c,v 1.87 2002/03/17 18:02:53 augustss Exp $ */ +/* $OpenBSD: umass.c,v 1.16 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: umass.c,v 1.49 2001/01/21 18:56:38 augustss Exp $ */ /*- * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, * Nick Hibma <n_hibma@freebsd.org> @@ -30,7 +30,7 @@ */ /* - * Universal Serial Bus Mass Storage Class specs: + * Universal Serial Bus Mass Storage Class Bulk-Only Transport * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf * http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf @@ -51,14 +51,13 @@ * * Over these wire protocols it handles the following command protocols * - SCSI - * - 8070 (ATA/ATAPI for rewritable removable media) - * - UFI (USB Floppy Interface) + * - UFI (floppy command set) + * - 8070 (ATA/ATAPI) * - * 8070i is a transformed version of the SCSI command set. UFI is a transformed - * version of the 8070i command set. The sc->transform method is used to - * convert the commands into the appropriate format (if at all necessary). - * For example, ATAPI requires all commands to be 12 bytes in length amongst - * other things. + * UFI and 8070i are transformed versions of the SCSI command set. The + * sc->transform method is used to convert the commands into the appropriate + * format (if at all necessary). For example, UFI requires all commands to be + * 12 bytes in length amongst other things. * * The source code below is marked and can be split into a number of pieces * (in this order): @@ -94,15 +93,15 @@ * umass_cam_cb again to complete the CAM command. */ -#if defined(__NetBSD__) +/* XXX Should we split the driver into a number of files? umass.c, + * umass_scsi.c, umass_8070.c, umass_ufi.c, umass_bbb.c, umass_cbi.c or + * something similar? + */ + +#if !defined(__OpenBSD__) #include "atapibus.h" -#include "scsibus.h" -#elif defined(__OpenBSD__) -#include "atapiscsi.h" #endif -#include "wd.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -125,15 +124,396 @@ #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdevs.h> -#include <dev/usb/umassvar.h> -#include <dev/usb/umass_quirks.h> -#include <dev/usb/umass_scsipi.h> -#include <dev/usb/umass_isdata.h> +#if defined(__FreeBSD__) +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/scsi/scsi_all.h> +#include <cam/scsi/scsi_da.h> + +#ifdef UMASS_DO_CAM_RESCAN +#include <sys/devicestat.h> +#include <cam/cam_periph.h> +#endif +#elif defined(__NetBSD__) +#include <sys/scsiio.h> +#include <dev/scsipi/scsi_all.h> +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsiconf.h> + +#include <dev/scsipi/atapiconf.h> + +#include <dev/scsipi/scsipi_disk.h> +#include <dev/scsipi/scsi_disk.h> +#include <dev/scsipi/scsi_changer.h> + +#include <dev/ata/atavar.h> /* XXX */ + +#define SCSI_LINK_TARGET(sc) ((sc)->scsipi_scsi.target) +#define SCSI_LINK_LUN(sc) ((sc)->scsipi_scsi.lun) +#elif defined(__OpenBSD__) +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#include <scsi/scsi_disk.h> +#include <machine/bus.h> + +#define SCSI_LINK_TARGET(sc) ((sc)->target) +#define SCSI_LINK_LUN(sc) ((sc)->lun) +#define scsipi_generic scsi_generic + +#endif + +#define SHORT_INQUIRY_LENGTH 36 /* XXX */ #ifdef UMASS_DEBUG +#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0) +#define DPRINTF(m, x) if (umassdebug & (m)) logprintf x +#define UDMASS_UPPER 0x00008000 /* upper layer */ +#define UDMASS_GEN 0x00010000 /* general */ +#define UDMASS_SCSI 0x00020000 /* scsi */ +#define UDMASS_UFI 0x00040000 /* ufi command set */ +#define UDMASS_8070 0x00080000 /* 8070i command set */ +#define UDMASS_USB 0x00100000 /* USB general */ +#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ +#define UDMASS_CBI 0x00400000 /* CBI transfers */ +#define UDMASS_ALL 0xffff0000 /* all of the above */ + +#define UDMASS_XFER 0x40000000 /* all transfers */ +#define UDMASS_CMD 0x80000000 + int umassdebug = 0; +#else +#define DIF(m, x) /* nop */ +#define DPRINTF(m, x) /* nop */ +#endif + + +/* Generic definitions */ + +#define UFI_COMMAND_LENGTH 12 +#define ATAPI_COMMAND_LENGTH 12 +/* Direction for umass_*_transfer */ +#define DIR_NONE 0 +#define DIR_IN 1 +#define DIR_OUT 2 + +/* The transfer speed determines the timeout value */ +#define UMASS_DEFAULT_TRANSFER_SPEED 150 /* in kb/s, conservative est. */ +#define UMASS_FLOPPY_TRANSFER_SPEED 20 +#define UMASS_ZIP100_TRANSFER_SPEED 650 + +#define UMASS_SPINUP_TIME 10000 /* ms */ + +#ifdef __FreeBSD__ +/* device name */ +#define DEVNAME "umass" +#define DEVNAME_SIM "umass-" + +#define UMASS_MAX_TRANSFER_SIZE 65536 + +/* CAM specific definitions */ + +/* The bus id, whatever that is */ +#define UMASS_SCSI_BUS 0 + +/* All USB drives are 'connected' to one SIM (SCSI controller). umass3 + * ends up being target 3 on that SIM. When a request for target 3 + * comes in we fetch the softc with devclass_get_softc(target_id). + * + * The SIM is the highest target number. This makes sure that umass0 corresponds + * to target 0 on the USB SCSI bus. + */ +#ifndef UMASS_DEBUG +#define UMASS_SCSIID_MAX 32 /* maximum number of drives expected */ +#else +/* while debugging avoid unnecessary clutter in the output at umass_cam_rescan + * (XPT_PATH_INQ) + */ +#define UMASS_SCSIID_MAX 3 /* maximum number of drives expected */ +#endif +#define UMASS_SCSIID_HOST UMASS_SCSIID_MAX +#endif + +#define MS_TO_TICKS(ms) ((ms) * hz / 1000) + + +/* Bulk-Only features */ + +#define UR_BBB_RESET 0xff /* Bulk-Only reset */ +#define UR_BBB_GET_MAX_LUN 0xfe + +/* Command Block Wrapper */ +typedef struct { + uDWord dCBWSignature; +# define CBWSIGNATURE 0x43425355 + uDWord dCBWTag; + uDWord dCBWDataTransferLength; + uByte bCBWFlags; +# define CBWFLAGS_OUT 0x00 +# define CBWFLAGS_IN 0x80 + uByte bCBWLUN; + uByte bCDBLength; +# define CBWCDBLENGTH 16 + uByte CBWCDB[CBWCDBLENGTH]; +} umass_bbb_cbw_t; +#define UMASS_BBB_CBW_SIZE 31 + +/* Command Status Wrapper */ +typedef struct { + uDWord dCSWSignature; +# define CSWSIGNATURE 0x53425355 + uDWord dCSWTag; + uDWord dCSWDataResidue; + uByte bCSWStatus; +# define CSWSTATUS_GOOD 0x0 +# define CSWSTATUS_FAILED 0x1 +# define CSWSTATUS_PHASE 0x2 +} umass_bbb_csw_t; +#define UMASS_BBB_CSW_SIZE 13 + +/* CBI features */ + +#define UR_CBI_ADSC 0x00 + +typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */ + +typedef union { + struct { + unsigned char type; + #define IDB_TYPE_CCI 0x00 + unsigned char value; + #define IDB_VALUE_PASS 0x00 + #define IDB_VALUE_FAIL 0x01 + #define IDB_VALUE_PHASE 0x02 + #define IDB_VALUE_PERSISTENT 0x03 + #define IDB_VALUE_STATUS_MASK 0x03 + } common; + + struct { + unsigned char asc; + unsigned char ascq; + } ufi; +} umass_cbi_sbl_t; + + + +struct umass_softc; /* see below */ + +typedef void (*transfer_cb_f)(struct umass_softc *sc, void *priv, + int residue, int status); +#define STATUS_CMD_OK 0 /* everything ok */ +#define STATUS_CMD_UNKNOWN 1 /* will have to fetch sense */ +#define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ +#define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ + +typedef void (*wire_reset_f)(struct umass_softc *sc, int status); +typedef void (*wire_transfer_f)(struct umass_softc *sc, int lun, + void *cmd, int cmdlen, void *data, int datalen, + int dir, transfer_cb_f cb, void *priv); +typedef void (*wire_state_f)(usbd_xfer_handle xfer, + usbd_private_handle priv, usbd_status err); + +#if defined(__FreeBSD__) +typedef int (*command_transform_f)(struct umass_softc *sc, + unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen); +#endif + + +/* the per device structure */ +struct umass_softc { + USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; /* device */ + + unsigned char drive; +# define DRIVE_GENERIC 0 /* use defaults for this one */ +# define ZIP_100 1 /* to be used for quirks */ +# define ZIP_250 2 +# define SHUTTLE_EUSB 3 +# define INSYSTEM_USBCABLE 4 + unsigned char quirks; + /* The drive does not support Test Unit Ready. Convert to + * Start Unit. + * Y-E Data + * ZIP 100 + */ +# define NO_TEST_UNIT_READY 0x01 + /* The drive does not reset the Unit Attention state after + * REQUEST SENSE has been sent. The INQUIRY command does not reset + * the UA either, and so CAM runs in circles trying to retrieve the + * initial INQUIRY data. + * Y-E Data + */ +# define RS_NO_CLEAR_UA 0x02 /* no REQUEST SENSE on INQUIRY*/ + /* The drive does not support START_STOP. + * Shuttle E-USB + */ +# define NO_START_STOP 0x04 + /* Don't ask for full inquiry data (255 bytes). + * Yano ATAPI-USB + */ +# define FORCE_SHORT_INQUIRY 0x08 + + unsigned int proto; +# define PROTO_UNKNOWN 0x0000 /* unknown protocol */ +# define PROTO_BBB 0x0001 /* USB wire protocol */ +# define PROTO_CBI 0x0002 +# define PROTO_CBI_I 0x0004 +# define PROTO_WIRE 0x00ff /* USB wire protocol mask */ +# define PROTO_SCSI 0x0100 /* command protocol */ +# define PROTO_ATAPI 0x0200 +# define PROTO_UFI 0x0400 +# define PROTO_RBC 0x0800 +# define PROTO_COMMAND 0xff00 /* command protocol mask */ + + u_char subclass; /* interface subclass */ + u_char protocol; /* interface protocol */ + + usbd_interface_handle iface; /* Mass Storage interface */ + int ifaceno; /* MS iface number */ + + u_int8_t bulkin; /* bulk-in Endpoint Address */ + u_int8_t bulkout; /* bulk-out Endpoint Address */ + u_int8_t intrin; /* intr-in Endp. (CBI) */ + usbd_pipe_handle bulkin_pipe; + usbd_pipe_handle bulkout_pipe; + usbd_pipe_handle intrin_pipe; + + /* Reset the device in a wire protocol specific way */ + wire_reset_f reset; + + /* The start of a wire transfer. It prepares the whole transfer (cmd, + * data, and status stage) and initiates it. It is up to the state + * machine (below) to handle the various stages and errors in these + */ + wire_transfer_f transfer; + + /* The state machine, handling the various states during a transfer */ + wire_state_f state; + +#if defined(__FreeBSD__) + /* The command transform function is used to conver the SCSI commands + * into their derivatives, like UFI, ATAPI, and friends. + */ + command_transform_f transform; /* command transform */ +#endif + + /* Bulk specific variables for transfers in progress */ + umass_bbb_cbw_t cbw; /* command block wrapper */ + umass_bbb_csw_t csw; /* command status wrapper*/ + /* CBI specific variables for transfers in progress */ + umass_cbi_cbl_t cbl; /* command block */ + umass_cbi_sbl_t sbl; /* status block */ + + /* generic variables for transfers in progress */ + /* ctrl transfer requests */ + usb_device_request_t request; + + /* xfer handles + * Most of our operations are initiated from interrupt context, so + * we need to avoid using the one that is in use. We want to avoid + * allocating them in the interrupt context as well. + */ + /* indices into array below */ +# define XFER_BBB_CBW 0 /* Bulk-Only */ +# define XFER_BBB_DATA 1 +# define XFER_BBB_DCLEAR 2 +# define XFER_BBB_CSW1 3 +# define XFER_BBB_CSW2 4 +# define XFER_BBB_SCLEAR 5 +# define XFER_BBB_RESET1 6 +# define XFER_BBB_RESET2 7 +# define XFER_BBB_RESET3 8 + +# define XFER_CBI_CB 0 /* CBI */ +# define XFER_CBI_DATA 1 +# define XFER_CBI_STATUS 2 +# define XFER_CBI_DCLEAR 3 +# define XFER_CBI_SCLEAR 4 +# define XFER_CBI_RESET1 5 +# define XFER_CBI_RESET2 6 +# define XFER_CBI_RESET3 7 + +# define XFER_NR 9 /* maximum number */ + + usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */ + + void *data_buffer; + + int transfer_dir; /* data direction */ + void *transfer_data; /* data buffer */ + int transfer_datalen; /* (maximum) length */ + int transfer_actlen; /* actual length */ + transfer_cb_f transfer_cb; /* callback */ + void *transfer_priv; /* for callback */ + int transfer_status; + + int transfer_state; +# define TSTATE_IDLE 0 +# define TSTATE_BBB_COMMAND 1 /* CBW transfer */ +# define TSTATE_BBB_DATA 2 /* Data transfer */ +# define TSTATE_BBB_DCLEAR 3 /* clear endpt stall */ +# define TSTATE_BBB_STATUS1 4 /* clear endpt stall */ +# define TSTATE_BBB_SCLEAR 5 /* clear endpt stall */ +# define TSTATE_BBB_STATUS2 6 /* CSW transfer */ +# define TSTATE_BBB_RESET1 7 /* reset command */ +# define TSTATE_BBB_RESET2 8 /* in clear stall */ +# define TSTATE_BBB_RESET3 9 /* out clear stall */ +# define TSTATE_CBI_COMMAND 10 /* command transfer */ +# define TSTATE_CBI_DATA 11 /* data transfer */ +# define TSTATE_CBI_STATUS 12 /* status transfer */ +# define TSTATE_CBI_DCLEAR 13 /* clear ep stall */ +# define TSTATE_CBI_SCLEAR 14 /* clear ep stall */ +# define TSTATE_CBI_RESET1 15 /* reset command */ +# define TSTATE_CBI_RESET2 16 /* in clear stall */ +# define TSTATE_CBI_RESET3 17 /* out clear stall */ +# define TSTATE_STATES 18 /* # of states above */ + + + int transfer_speed; /* in kb/s */ + int timeout; /* in msecs */ + + u_int8_t maxlun; /* max lun supported */ + +#ifdef UMASS_DEBUG + struct timeval tv; +#endif + +#if defined(__FreeBSD__) + /* SCSI/CAM specific variables */ + struct scsi_sense cam_scsi_sense; + +#elif defined(__NetBSD__) || defined(__OpenBSD__) + union { + struct scsipi_link sc_link; +#if defined(__NetBSD__) + struct { + struct ata_atapi_attach sc_aa; + struct ata_drive_datas sc_aa_drive; + } aa; +#endif + } u; +#if defined(__NetBSD__) + struct atapi_adapter sc_atapi_adapter; +#define sc_adapter sc_atapi_adapter._generic +#else + struct scsi_adapter sc_atapi_adapter; +#define sc_adapter sc_atapi_adapter +#endif + int sc_xfer_flags; + usbd_status sc_sync_status; + struct scsipi_sense sc_sense_cmd; + + device_ptr_t sc_child; /* child device, for detach */ + char sc_dying; + +#endif +}; + +#ifdef UMASS_DEBUG char *states[TSTATE_STATES+1] = { /* should be kept in sync with the list at transfer_state */ "Idle", @@ -158,9 +538,17 @@ char *states[TSTATE_STATES+1] = { }; #endif +struct cam_sim *umass_sim; /* SCSI Interface Module */ +struct cam_path *umass_path; /* and its path */ + + /* USB device probe/attach/detach functions */ USB_DECLARE_DRIVER(umass); Static void umass_disco(struct umass_softc *sc); +Static int umass_match_proto(struct umass_softc *sc, + usbd_interface_handle iface, + usbd_device_handle dev); +Static void umass_init_shuttle(struct umass_softc *sc); /* generic transfer functions */ Static usbd_status umass_setup_transfer(struct umass_softc *sc, @@ -168,43 +556,114 @@ Static usbd_status umass_setup_transfer(struct umass_softc *sc, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); Static usbd_status umass_setup_ctrl_transfer(struct umass_softc *sc, + usbd_device_handle dev, usb_device_request_t *req, void *buffer, int buflen, int flags, usbd_xfer_handle xfer); -Static void umass_clear_endpoint_stall(struct umass_softc *sc, int endpt, - usbd_xfer_handle xfer); +Static void umass_clear_endpoint_stall(struct umass_softc *sc, + u_int8_t endpt, usbd_pipe_handle pipe, + int state, usbd_xfer_handle xfer); #if 0 -Static void umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv); +Static void umass_reset(struct umass_softc *sc, + transfer_cb_f cb, void *priv); #endif /* Bulk-Only related functions */ -Static void umass_bbb_transfer(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); -Static void umass_bbb_reset(struct umass_softc *, int); -Static void umass_bbb_state(usbd_xfer_handle, usbd_private_handle, usbd_status); +Static void umass_bbb_reset(struct umass_softc *sc, int status); +Static void umass_bbb_transfer(struct umass_softc *sc, int lun, + void *cmd, int cmdlen, + void *data, int datalen, int dir, + transfer_cb_f cb, void *priv); +Static void umass_bbb_state(usbd_xfer_handle xfer, + usbd_private_handle priv, + usbd_status err); +usbd_status umass_bbb_get_max_lun(struct umass_softc *sc, + u_int8_t *maxlun); -usbd_status umass_bbb_get_max_lun(struct umass_softc *, u_int8_t *); /* CBI related functions */ -Static void umass_cbi_transfer(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); -Static void umass_cbi_reset(struct umass_softc *, int); -Static void umass_cbi_state(usbd_xfer_handle, usbd_private_handle, usbd_status); +Static int umass_cbi_adsc(struct umass_softc *sc, char *buffer,int buflen, + usbd_xfer_handle xfer); +Static void umass_cbi_reset(struct umass_softc *sc, int status); +Static void umass_cbi_transfer(struct umass_softc *sc, int lun, + void *cmd, int cmdlen, + void *data, int datalen, int dir, + transfer_cb_f cb, void *priv); +Static void umass_cbi_state(usbd_xfer_handle xfer, + usbd_private_handle priv, usbd_status err); + +#if defined(__FreeBSD__) +/* CAM related functions */ +Static void umass_cam_action(struct cam_sim *sim, union ccb *ccb); +Static void umass_cam_poll(struct cam_sim *sim); + +Static void umass_cam_cb(struct umass_softc *sc, void *priv, + int residue, int status); +Static void umass_cam_sense_cb(struct umass_softc *sc, void *priv, + int residue, int status); + +#ifdef UMASS_DO_CAM_RESCAN +Static void umass_cam_rescan(struct umass_softc *sc); +#endif -Static int umass_cbi_adsc(struct umass_softc *, char *, int, usbd_xfer_handle); +Static int umass_cam_attach_sim(void); +Static int umass_cam_attach(struct umass_softc *sc); +Static int umass_cam_detach_sim(void); +Static int umass_cam_detach(struct umass_softc *sc); -const struct umass_wire_methods umass_bbb_methods = { - umass_bbb_transfer, - umass_bbb_reset, - umass_bbb_state -}; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + +#define UMASS_SCSIID_HOST 0x00 +#define UMASS_SCSIID_DEVICE 0x01 -const struct umass_wire_methods umass_cbi_methods = { - umass_cbi_transfer, - umass_cbi_reset, - umass_cbi_state +#define UMASS_ATAPI_DRIVE 0 + +#define UMASS_MAX_TRANSFER_SIZE MAXBSIZE + +struct scsipi_device umass_dev = +{ + NULL, /* Use default error handler */ + NULL, /* have a queue, served by this */ + NULL, /* have no async handler */ + NULL, /* Use default 'done' routine */ }; +Static int umass_scsipi_cmd(struct scsipi_xfer *xs); +Static void umass_scsipi_minphys(struct buf *bp); +Static int umass_scsipi_ioctl(struct scsipi_link *, u_long, + caddr_t, int, struct proc *); +Static void umass_scsipi_cb(struct umass_softc *sc, void *priv, + int residue, int status); +Static void umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, + int residue, int status); + +Static int scsipiprint(void *aux, const char *pnp); +Static int umass_ufi_transform(struct umass_softc *sc, + struct scsipi_generic *cmd, int cmdlen, + struct scsipi_generic *rcmd, int *rcmdlen); + +#if NATAPIBUS > 0 +Static void umass_atapi_probedev(struct atapibus_softc *, int); +#endif +#endif + +#if defined(__FreeBSD__) +/* SCSI specific functions */ +Static int umass_scsi_transform(struct umass_softc *sc, + unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen); + +/* UFI specific functions */ +Static int umass_ufi_transform(struct umass_softc *sc, + unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen); + +/* 8070 specific functions */ +Static int umass_8070_transform(struct umass_softc *sc, + unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen); +#endif + #ifdef UMASS_DEBUG /* General debugging functions */ Static void umass_bbb_dump_cbw(struct umass_softc *sc, @@ -216,180 +675,292 @@ Static void umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, #endif +void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */ + /* * USB device probe/attach/detach */ -USB_MATCH(umass) +/* + * Match the device we are seeing with the devices supported. Fill in the + * proto and drive fields in the softc accordingly. + * This function is called from both probe and attach. + */ + +Static int +umass_match_proto(sc, iface, dev) + struct umass_softc *sc; + usbd_interface_handle iface; + usbd_device_handle dev; { - USB_MATCH_START(umass, uaa); - const struct umass_quirk *quirk; + usb_device_descriptor_t *dd; usb_interface_descriptor_t *id; + u_int vendor, product; - if (uaa->iface == NULL) - return (UMATCH_NONE); + /* + * Fill in sc->drive and sc->proto and return a match + * value if both are determined and 0 otherwise. + */ - quirk = umass_lookup(uaa->vendor, uaa->product); - if (quirk != NULL) - return (quirk->uq_match); + sc->drive = DRIVE_GENERIC; + sc->proto = PROTO_UNKNOWN; + sc->transfer_speed = UMASS_DEFAULT_TRANSFER_SPEED; - id = usbd_get_interface_descriptor(uaa->iface); + sc->sc_udev = dev; + dd = usbd_get_device_descriptor(dev); + vendor = UGETW(dd->idVendor); + product = UGETW(dd->idProduct); + + if (vendor == USB_VENDOR_SHUTTLE && + product == USB_PRODUCT_SHUTTLE_EUSB) { + sc->drive = SHUTTLE_EUSB; +#if CBI_I + sc->proto = PROTO_ATAPI | PROTO_CBI_I; +#else + sc->proto = PROTO_ATAPI | PROTO_CBI; +#endif + sc->subclass = UISUBCLASS_SFF8020I; + sc->protocol = UIPROTO_MASS_CBI; + sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP; + return (UMATCH_VENDOR_PRODUCT); + } + + if (vendor == USB_VENDOR_YANO && + product == USB_PRODUCT_YANO_U640MO) { + sc->proto = PROTO_ATAPI | PROTO_CBI_I; + sc->quirks |= FORCE_SHORT_INQUIRY; + return (UMATCH_VENDOR_PRODUCT); + } + + if (vendor == USB_VENDOR_SONY && + product == USB_PRODUCT_SONY_MSC) { + printf ("XXX Sony MSC\n"); + sc->quirks |= FORCE_SHORT_INQUIRY; + } + + if (vendor == USB_VENDOR_YEDATA && + product == USB_PRODUCT_YEDATA_FLASHBUSTERU) { + + /* Revisions < 1.28 do not handle the interrupt endpoint + * very well. + */ + if (UGETW(dd->bcdDevice) < 0x128) + sc->proto = PROTO_UFI | PROTO_CBI; + else +#if CBI_I + sc->proto = PROTO_UFI | PROTO_CBI_I; +#else + sc->proto = PROTO_UFI | PROTO_CBI; +#endif + /* + * Revisions < 1.28 do not have the TEST UNIT READY command + * Revisions == 1.28 have a broken TEST UNIT READY + */ + if (UGETW(dd->bcdDevice) <= 0x128) + sc->quirks |= NO_TEST_UNIT_READY; + + sc->subclass = UISUBCLASS_UFI; + sc->protocol = UIPROTO_MASS_CBI; + + sc->quirks |= RS_NO_CLEAR_UA; + sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED; + return (UMATCH_VENDOR_PRODUCT_REV); + } + + if (vendor == USB_VENDOR_INSYSTEM && + product == USB_PRODUCT_INSYSTEM_USBCABLE) { + sc->drive = INSYSTEM_USBCABLE; + sc->proto = PROTO_ATAPI | PROTO_CBI; + sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP; + return (UMATCH_VENDOR_PRODUCT); + } + + id = usbd_get_interface_descriptor(iface); if (id == NULL || id->bInterfaceClass != UICLASS_MASS) return (UMATCH_NONE); - switch (id->bInterfaceSubClass) { - case UISUBCLASS_RBC: - case UISUBCLASS_SFF8020I: - case UISUBCLASS_QIC157: + if (vendor == USB_VENDOR_SONY && id->bInterfaceSubClass == 0xff) { + /* + * Sony DSC devices set the sub class to 0xff + * instead of 1 (RBC). Fix that here. + */ + id->bInterfaceSubClass = UISUBCLASS_RBC; + /* They also should be able to do higher speed. */ + sc->transfer_speed = 500; + } + + if (vendor == USB_VENDOR_FUJIPHOTO && + product == USB_PRODUCT_FUJIPHOTO_MASS0100) + sc->quirks |= NO_TEST_UNIT_READY | NO_START_STOP; + + sc->subclass = id->bInterfaceSubClass; + sc->protocol = id->bInterfaceProtocol; + + switch (sc->subclass) { + case UISUBCLASS_SCSI: + sc->proto |= PROTO_SCSI; + break; case UISUBCLASS_UFI: + sc->transfer_speed = UMASS_FLOPPY_TRANSFER_SPEED; + sc->proto |= PROTO_UFI; + break; + case UISUBCLASS_SFF8020I: case UISUBCLASS_SFF8070I: - case UISUBCLASS_SCSI: + case UISUBCLASS_QIC157: + sc->proto |= PROTO_ATAPI; + break; + case UISUBCLASS_RBC: + sc->proto |= PROTO_RBC; break; default: - return (UMATCH_IFACECLASS); + /* Assume that unsupported devices are ATAPI */ + DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n", + USBDEVNAME(sc->sc_dev), id->bInterfaceSubClass)); + + sc->proto |= PROTO_ATAPI; + break; } - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_CBI_I: + switch (sc->protocol) { case UIPROTO_MASS_CBI: - case UIPROTO_MASS_BBB_OLD: + sc->proto |= PROTO_CBI; + break; + case UIPROTO_MASS_CBI_I: +#if CBI_I + sc->proto |= PROTO_CBI_I; +#else + sc->proto |= PROTO_CBI; +#endif + break; case UIPROTO_MASS_BBB: + sc->proto |= PROTO_BBB; + break; + case UIPROTO_MASS_BBB_P: + sc->drive = ZIP_100; + sc->proto |= PROTO_BBB; + sc->transfer_speed = UMASS_ZIP100_TRANSFER_SPEED; + sc->quirks |= NO_TEST_UNIT_READY; break; default: - return (UMATCH_IFACECLASS_IFACESUBCLASS); + DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n", + USBDEVNAME(sc->sc_dev), id->bInterfaceProtocol)); + return (UMATCH_NONE); } - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); + return (UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO); } +USB_MATCH(umass) +{ + USB_MATCH_START(umass, uaa); +#if defined(__FreeBSD__) + struct umass_softc *sc = device_get_softc(self); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + struct umass_softc scs, *sc = &scs; + memset(sc, 0, sizeof *sc); + strcpy(sc->sc_dev.dv_xname, "umass"); +#endif + + if (uaa->iface == NULL) + return(UMATCH_NONE); + + return (umass_match_proto(sc, uaa->iface, uaa->device)); +} + +void umass_delayed_attach(struct umass_softc *sc); + USB_ATTACH(umass) { USB_ATTACH_START(umass, sc, uaa); - const struct umass_quirk *quirk; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; - const char *sWire, *sCommand; + const char *sSubclass, *sProto; char devinfo[1024]; - usbd_status err; - int i, bno, error; + int i, bno; + int err; + + /* + * the softc struct is bzero-ed in device_set_driver. We can safely + * call umass_detach without specifically initialising the struct. + */ usbd_devinfo(uaa->device, 0, devinfo); USB_ATTACH_SETUP; - sc->sc_udev = uaa->device; - sc->sc_iface = uaa->iface; - sc->sc_ifaceno = uaa->ifaceno; - - quirk = umass_lookup(uaa->vendor, uaa->product); - if (quirk != NULL) { - sc->sc_wire = quirk->uq_wire; - sc->sc_cmd = quirk->uq_cmd; - sc->sc_quirks = quirk->uq_flags; - sc->sc_busquirks = quirk->uq_busquirks; - - if (quirk->uq_fixup != NULL) - (*quirk->uq_fixup)(sc); - } else { - sc->sc_wire = UMASS_WPROTO_UNSPEC; - sc->sc_cmd = UMASS_CPROTO_UNSPEC; - sc->sc_quirks = 0; - sc->sc_busquirks = 0; - } + sc->iface = uaa->iface; + sc->ifaceno = uaa->ifaceno; - id = usbd_get_interface_descriptor(sc->sc_iface); - if (id == NULL) + /* initialise the proto and drive values in the umass_softc (again) */ + if (umass_match_proto(sc, sc->iface, uaa->device) == 0) { + printf("%s: match failed\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; - - if (sc->sc_wire == UMASS_WPROTO_UNSPEC) { - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_CBI: - sc->sc_wire = UMASS_WPROTO_CBI; - break; - case UIPROTO_MASS_CBI_I: - sc->sc_wire = UMASS_WPROTO_CBI_I; - break; - case UIPROTO_MASS_BBB: - case UIPROTO_MASS_BBB_OLD: - sc->sc_wire = UMASS_WPROTO_BBB; - break; - default: - DPRINTF(UDMASS_GEN, - ("%s: Unsupported wire protocol %u\n", - USBDEVNAME(sc->sc_dev), - id->bInterfaceProtocol)); - USB_ATTACH_ERROR_RETURN; - } } - /* XXX - Now unsupported CBI with CCI */ - if (sc->sc_wire == UMASS_WPROTO_CBI_I) - sc->sc_wire = UMASS_WPROTO_CBI; - - if (sc->sc_cmd == UMASS_CPROTO_UNSPEC) { - switch (id->bInterfaceSubClass) { - case UISUBCLASS_SCSI: - sc->sc_cmd = UMASS_CPROTO_SCSI; - break; - case UISUBCLASS_UFI: - sc->sc_cmd = UMASS_CPROTO_UFI; - break; - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - case UISUBCLASS_QIC157: - sc->sc_cmd = UMASS_CPROTO_ATAPI; - break; - case UISUBCLASS_RBC: - sc->sc_cmd = UMASS_CPROTO_RBC; - break; - default: - DPRINTF(UDMASS_GEN, - ("%s: Unsupported command protocol %u\n", - USBDEVNAME(sc->sc_dev), - id->bInterfaceSubClass)); - USB_ATTACH_ERROR_RETURN; - } - } + /* + * The timeout is based on the maximum expected transfer size + * divided by the expected transfer speed. + * We multiply by 4 to make sure a busy system doesn't make things + * fail. + */ + sc->timeout = 4 * UMASS_MAX_TRANSFER_SIZE / sc->transfer_speed; + sc->timeout += UMASS_SPINUP_TIME; /* allow for spinning up */ + id = usbd_get_interface_descriptor(sc->iface); printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - switch (sc->sc_wire) { - case UMASS_WPROTO_CBI: - sWire = "CBI"; + switch (sc->subclass) { + case UISUBCLASS_RBC: + sSubclass = "RBC"; + break; + case UISUBCLASS_SCSI: + sSubclass = "SCSI"; + break; + case UISUBCLASS_UFI: + sSubclass = "UFI"; break; - case UMASS_WPROTO_CBI_I: - sWire = "CBI with CCI"; + case UISUBCLASS_SFF8020I: + sSubclass = "SFF8020i"; break; - case UMASS_WPROTO_BBB: - sWire = "Bulk-Only"; + case UISUBCLASS_SFF8070I: + sSubclass = "SFF8070i"; + break; + case UISUBCLASS_QIC157: + sSubclass = "QIC157"; break; default: - sWire = "unknown"; + sSubclass = "unknown"; break; } - - switch (sc->sc_cmd) { - case UMASS_CPROTO_RBC: - sCommand = "RBC"; - break; - case UMASS_CPROTO_SCSI: - sCommand = "SCSI"; + switch (sc->protocol) { + case UIPROTO_MASS_CBI: + sProto = "CBI"; break; - case UMASS_CPROTO_UFI: - sCommand = "UFI"; + case UIPROTO_MASS_CBI_I: + sProto = "CBI-I"; break; - case UMASS_CPROTO_ATAPI: - sCommand = "ATAPI"; + case UIPROTO_MASS_BBB: + sProto = "BBB"; break; - case UMASS_CPROTO_ISD_ATA: - sCommand = "ISD-ATA"; + case UIPROTO_MASS_BBB_P: + sProto = "BBB-P"; break; default: - sCommand = "unknown"; + sProto = "unknown"; break; } + printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sSubclass, + sProto); - printf("%s: using %s over %s\n", USBDEVNAME(sc->sc_dev), sCommand, - sWire); + if (sc->drive == INSYSTEM_USBCABLE) { + err = usbd_set_interface(0, 1); + if (err) { + DPRINTF(UDMASS_USB, ("%s: could not switch to " + "Alt Interface %d\n", + USBDEVNAME(sc->sc_dev), 1)); + umass_disco(sc); + USB_ATTACH_ERROR_RETURN; + } + } /* * In addition to the Control endpoint the following endpoints @@ -403,22 +974,22 @@ USB_ATTACH(umass) * from the device descriptors of the current interface. */ for (i = 0 ; i < id->bNumEndpoints ; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { + ed = usbd_interface2endpoint_descriptor(sc->iface, i); + if (!ed) { printf("%s: could not read endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->sc_epaddr[UMASS_BULKIN] = ed->bEndpointAddress; + sc->bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->sc_epaddr[UMASS_BULKOUT] = ed->bEndpointAddress; - } else if (sc->sc_wire == UMASS_WPROTO_CBI_I + sc->bulkout = ed->bEndpointAddress; + } else if (sc->proto & PROTO_CBI_I && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - sc->sc_epaddr[UMASS_INTRIN] = ed->bEndpointAddress; + sc->intrin = ed->bEndpointAddress; #ifdef UMASS_DEBUG if (UGETW(ed->wMaxPacketSize) > 2) { DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n", @@ -430,21 +1001,19 @@ USB_ATTACH(umass) } /* check whether we found all the endpoints we need */ - if (!sc->sc_epaddr[UMASS_BULKIN] || !sc->sc_epaddr[UMASS_BULKOUT] || - (sc->sc_wire == UMASS_WPROTO_CBI_I && - !sc->sc_epaddr[UMASS_INTRIN])) { - DPRINTF(UDMASS_USB, ("%s: endpoint not found %u/%u/%u\n", - USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN], - sc->sc_epaddr[UMASS_BULKOUT], - sc->sc_epaddr[UMASS_INTRIN])); + if (!sc->bulkin || !sc->bulkout + || (sc->proto & PROTO_CBI_I && !sc->intrin) ) { + DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n", + USBDEVNAME(sc->sc_dev), + sc->bulkin, sc->bulkout, sc->intrin)); + umass_disco(sc); USB_ATTACH_ERROR_RETURN; } /* * Get the maximum LUN supported by the device. */ - if (sc->sc_wire == UMASS_WPROTO_BBB && - !(sc->sc_quirks & UMASS_QUIRK_NO_MAX_LUN)) { + if ((sc->proto & PROTO_WIRE) == PROTO_BBB) { err = umass_bbb_get_max_lun(sc, &sc->maxlun); if (err) { printf("%s: unable to get Max Lun: %s\n", @@ -456,20 +1025,19 @@ USB_ATTACH(umass) } /* Open the bulk-in and -out pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKOUT], - USBD_EXCLUSIVE_USE, - &sc->sc_pipe[UMASS_BULKOUT]); + err = usbd_open_pipe(sc->iface, sc->bulkout, + USBD_EXCLUSIVE_USE, &sc->bulkout_pipe); if (err) { - DPRINTF(UDMASS_USB, ("%s: cannot open %u-out pipe (bulk)\n", - USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKOUT])); + DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n", + USBDEVNAME(sc->sc_dev), sc->bulkout)); umass_disco(sc); USB_ATTACH_ERROR_RETURN; } - err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_BULKIN], - USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_BULKIN]); + err = usbd_open_pipe(sc->iface, sc->bulkin, + USBD_EXCLUSIVE_USE, &sc->bulkin_pipe); if (err) { - DPRINTF(UDMASS_USB, ("%s: could not open %u-in pipe (bulk)\n", - USBDEVNAME(sc->sc_dev), sc->sc_epaddr[UMASS_BULKIN])); + DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n", + USBDEVNAME(sc->sc_dev), sc->bulkin)); umass_disco(sc); USB_ATTACH_ERROR_RETURN; } @@ -485,13 +1053,12 @@ USB_ATTACH(umass) * code for handling the data on that endpoint simpler. No data * arriving concurrently. */ - if (sc->sc_wire == UMASS_WPROTO_CBI_I) { - err = usbd_open_pipe(sc->sc_iface, sc->sc_epaddr[UMASS_INTRIN], - USBD_EXCLUSIVE_USE, &sc->sc_pipe[UMASS_INTRIN]); + if (sc->proto & PROTO_CBI_I) { + err = usbd_open_pipe(sc->iface, sc->intrin, + USBD_EXCLUSIVE_USE, &sc->intrin_pipe); if (err) { - DPRINTF(UDMASS_USB, ("%s: couldn't open %u-in (intr)\n", - USBDEVNAME(sc->sc_dev), - sc->sc_epaddr[UMASS_INTRIN])); + DPRINTF(UDMASS_USB, ("%s: couldn't open %d-in (intr)\n", + USBDEVNAME(sc->sc_dev), sc->intrin)); umass_disco(sc); USB_ATTACH_ERROR_RETURN; } @@ -511,14 +1078,14 @@ USB_ATTACH(umass) } } /* Allocate buffer for data transfer (it's huge). */ - switch (sc->sc_wire) { - case UMASS_WPROTO_BBB: + switch (sc->proto & PROTO_WIRE) { + case PROTO_BBB: bno = XFER_BBB_DATA; goto dalloc; - case UMASS_WPROTO_CBI: + case PROTO_CBI: bno = XFER_CBI_DATA; goto dalloc; - case UMASS_WPROTO_CBI_I: + case PROTO_CBI_I: bno = XFER_CBI_DATA; dalloc: sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno], @@ -533,89 +1100,123 @@ USB_ATTACH(umass) } /* Initialise the wire protocol specific methods */ - switch (sc->sc_wire) { - case UMASS_WPROTO_BBB: - sc->sc_methods = &umass_bbb_methods; - break; - case UMASS_WPROTO_CBI: - case UMASS_WPROTO_CBI_I: - sc->sc_methods = &umass_cbi_methods; - break; - default: - umass_disco(sc); - USB_ATTACH_ERROR_RETURN; - } - - if (quirk != NULL && quirk->uq_init != NULL) { - err = (*quirk->uq_init)(sc); - if (err) { - umass_disco(sc); - USB_ATTACH_ERROR_RETURN; - } + if (sc->proto & PROTO_BBB) { + sc->reset = umass_bbb_reset; + sc->transfer = umass_bbb_transfer; + sc->state = umass_bbb_state; + } else if ((sc->proto & PROTO_CBI) || (sc->proto & PROTO_CBI_I)) { + sc->reset = umass_cbi_reset; + sc->transfer = umass_cbi_transfer; + sc->state = umass_cbi_state; +#ifdef UMASS_DEBUG + } else { + panic("%s:%d: Unknown proto 0x%02x\n", + __FILE__, __LINE__, sc->proto); +#endif } - error = 0; - switch (sc->sc_cmd) { - case UMASS_CPROTO_RBC: - case UMASS_CPROTO_SCSI: -#if defined(__OpenBSD__) || NSCSIBUS > 0 - error = umass_scsi_attach(sc); -#else - printf("%s: scsibus not configured\n", USBDEVNAME(sc->sc_dev)); -#endif - break; + if (sc->drive == SHUTTLE_EUSB) + umass_init_shuttle(sc); - case UMASS_CPROTO_UFI: - case UMASS_CPROTO_ATAPI: -#if (NATAPIBUS > 0) || (NATAPISCSI > 0) - error = umass_atapi_attach(sc); -#else - printf("%s: "UMASS_ATAPISTR" not configured\n", - USBDEVNAME(sc->sc_dev)); -#endif + /* + * Fill in the adapter. + */ + sc->sc_adapter.scsipi_cmd = umass_scsipi_cmd; + sc->sc_adapter.scsipi_minphys = umass_scsipi_minphys; + + /* + * fill in the prototype scsipi_link. + */ + switch (sc->proto & PROTO_COMMAND) { + case PROTO_SCSI: + case PROTO_UFI: + case PROTO_ATAPI: + case PROTO_RBC: + if ((sc->proto & PROTO_COMMAND) != PROTO_SCSI) + sc->u.sc_link.flags |= SDEV_ATAPI; + else + sc->u.sc_link.flags &= ~SDEV_ATAPI; + + sc->u.sc_link.adapter_buswidth = 2; + sc->u.sc_link.adapter_target = UMASS_SCSIID_HOST; + sc->u.sc_link.luns = sc->maxlun + 1; + + sc->u.sc_link.adapter_softc = sc; + sc->u.sc_link.adapter = &sc->sc_adapter; + sc->u.sc_link.device = &umass_dev; + sc->u.sc_link.openings = 1; + + if(sc->quirks & NO_TEST_UNIT_READY) + sc->u.sc_link.quirks |= ADEV_NOTUR; break; - case UMASS_CPROTO_ISD_ATA: -#if defined (__NetBSD__) && NWD > 0 - error = umass_isdata_attach(sc); -#else - printf("%s: isdata not configured\n", USBDEVNAME(sc->sc_dev)); -#endif - break; default: - printf("%s: command protocol=0x%x not supported\n", - USBDEVNAME(sc->sc_dev), sc->sc_cmd); + printf("%s: proto=0x%x not supported yet\n", + USBDEVNAME(sc->sc_dev), sc->proto); umass_disco(sc); USB_ATTACH_ERROR_RETURN; } - if (error) { - printf("%s: bus attach failed\n", USBDEVNAME(sc->sc_dev)); + + if (cold) { + startuphook_establish((void (*)(void *))umass_delayed_attach, + sc); + } else { + /* hot plug, do it now */ + umass_delayed_attach(sc); + } + + DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev))); + + USB_ATTACH_SUCCESS_RETURN; +} + +void +umass_delayed_attach(struct umass_softc *sc) +{ + sc->sc_child = config_found(&sc->sc_dev, &sc->u, scsipiprint); + if (sc->sc_child == NULL) { umass_disco(sc); - USB_ATTACH_ERROR_RETURN; + /* Not an error, just not a complete success. */ + USB_ATTACH_SUCCESS_RETURN; } usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, USBDEV(sc->sc_dev)); +} - DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev))); - - USB_ATTACH_SUCCESS_RETURN; +Static int +scsipiprint(aux, pnp) + void *aux; + const char *pnp; +{ +#if !defined(__OpenBSD__) + extern int atapi_print(void *aux, const char *pnp); + struct scsipi_link *l = aux; + + if (l->type == BUS_SCSI) + return (scsiprint(aux, pnp)); + else + return (atapi_print(aux, pnp)); +#else + return (scsiprint(aux, pnp)); +#endif } USB_DETACH(umass) { USB_DETACH_START(umass, sc); - struct umassbus_softc *scbus = sc->bus; - int rv = 0, i; + int rv = 0; DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev))); /* Abort the pipes to wake up any waiting processes. */ - for (i = 0 ; i < UMASS_NEP ; i++) { - if (sc->sc_pipe[i] != NULL) - usbd_abort_pipe(sc->sc_pipe[i]); - } + if (sc->bulkout_pipe != NULL) + usbd_abort_pipe(sc->bulkout_pipe); + if (sc->bulkin_pipe != NULL) + usbd_abort_pipe(sc->bulkin_pipe); + if (sc->intrin_pipe != NULL) + usbd_abort_pipe(sc->intrin_pipe); #if 0 /* Do we really need reference counting? Perhaps in ioctl() */ @@ -627,13 +1228,16 @@ USB_DETACH(umass) splx(s); #endif - if (scbus != NULL) { - if (scbus->sc_child != NULL) - rv = config_detach(scbus->sc_child, flags); - free(scbus, M_DEVBUF); - sc->bus = NULL; - } - +#if defined(__FreeBSD__) + if ((sc->proto & PROTO_SCSI) || + (sc->proto & PROTO_ATAPI) || + (sc->proto & PROTO_UFI)) + /* detach the device from the SCSI host controller (SIM) */ + rv = umass_cam_detach(sc); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + if (sc->sc_child != NULL) + rv = config_detach(sc->sc_child, flags); +#endif if (rv != 0) return (rv); @@ -642,14 +1246,16 @@ USB_DETACH(umass) usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, USBDEV(sc->sc_dev)); - return (rv); + return (0); } +#if defined(__NetBSD__) || defined(__OpenBSD__) int -umass_activate(struct device *dev, enum devact act) +umass_activate(self, act) + struct device *self; + enum devact act; { - struct umass_softc *sc = (struct umass_softc *)dev; - struct umassbus_softc *scbus = sc->bus; + struct umass_softc *sc = (struct umass_softc *) self; int rv = 0; DPRINTF(UDMASS_USB, ("%s: umass_activate: %d\n", @@ -661,19 +1267,22 @@ umass_activate(struct device *dev, enum devact act) break; case DVACT_DEACTIVATE: - sc->sc_dying = 1; - if (scbus == NULL || scbus->sc_child == NULL) + if (sc->sc_child == NULL) break; - rv = config_deactivate(scbus->sc_child); + rv = config_deactivate(sc->sc_child); DPRINTF(UDMASS_USB, ("%s: umass_activate: child " "returned %d\n", USBDEVNAME(sc->sc_dev), rv)); + if (rv == 0) + sc->sc_dying = 1; break; } return (rv); } +#endif Static void -umass_disco(struct umass_softc *sc) +umass_disco(sc) + struct umass_softc *sc; { int i; @@ -687,10 +1296,27 @@ umass_disco(struct umass_softc *sc) } /* Remove all the pipes. */ - for (i = 0 ; i < UMASS_NEP ; i++) { - if (sc->sc_pipe[i] != NULL) - usbd_close_pipe(sc->sc_pipe[i]); - } + if (sc->bulkout_pipe != NULL) + usbd_close_pipe(sc->bulkout_pipe); + if (sc->bulkin_pipe != NULL) + usbd_close_pipe(sc->bulkin_pipe); + if (sc->intrin_pipe != NULL) + usbd_close_pipe(sc->intrin_pipe); +} + +Static void +umass_init_shuttle(struct umass_softc *sc) +{ + usb_device_request_t req; + u_char status[2]; + + /* The Linux driver does this */ + req.bmRequestType = UT_READ_VENDOR_DEVICE; + req.bRequest = 1; + USETW(req.wValue, 0); + USETW(req.wIndex, sc->ifaceno); + USETW(req.wLength, sizeof status); + (void)usbd_do_request(sc->sc_udev, &req, &status); } /* @@ -710,7 +1336,7 @@ umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, /* Initialiase a USB transfer and then schedule it */ usbd_setup_xfer(xfer, pipe, (void *)sc, buffer, buflen, - flags | sc->sc_xfer_flags, sc->timeout, sc->sc_methods->wire_state); + flags | sc->sc_xfer_flags, sc->timeout, sc->state); err = usbd_transfer(xfer); DPRINTF(UDMASS_XFER,("%s: start xfer buffer=%p buflen=%d flags=0x%x " @@ -727,8 +1353,10 @@ umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, Static usbd_status -umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req, - void *buffer, int buflen, int flags, usbd_xfer_handle xfer) +umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle dev, + usb_device_request_t *req, + void *buffer, int buflen, int flags, + usbd_xfer_handle xfer) { usbd_status err; @@ -737,8 +1365,8 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req, /* Initialiase a USB control transfer and then schedule it */ - usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc, sc->timeout, - req, buffer, buflen, flags, sc->sc_methods->wire_state); + usbd_setup_default_xfer(xfer, dev, (void *) sc, + sc->timeout, req, buffer, buflen, flags, sc->state); err = usbd_transfer(xfer); if (err && err != USBD_IN_PROGRESS) { @@ -753,23 +1381,30 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, usb_device_request_t *req, } Static void -umass_clear_endpoint_stall(struct umass_softc *sc, int endpt, - usbd_xfer_handle xfer) +umass_clear_endpoint_stall(struct umass_softc *sc, + u_int8_t endpt, usbd_pipe_handle pipe, + int state, usbd_xfer_handle xfer) { + usbd_device_handle dev; + if (sc->sc_dying) return; DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n", - USBDEVNAME(sc->sc_dev), sc->sc_epaddr[endpt])); + USBDEVNAME(sc->sc_dev), endpt)); + + usbd_interface2device_handle(sc->iface, &dev); - usbd_clear_endpoint_toggle(sc->sc_pipe[endpt]); + sc->transfer_state = state; - sc->sc_req.bmRequestType = UT_WRITE_ENDPOINT; - sc->sc_req.bRequest = UR_CLEAR_FEATURE; - USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT); - USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]); - USETW(sc->sc_req.wLength, 0); - umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer); + usbd_clear_endpoint_toggle(pipe); + + sc->request.bmRequestType = UT_WRITE_ENDPOINT; + sc->request.bRequest = UR_CLEAR_FEATURE; + USETW(sc->request.wValue, UF_ENDPOINT_HALT); + USETW(sc->request.wIndex, endpt); + USETW(sc->request.wLength, 0); + umass_setup_ctrl_transfer(sc, dev, &sc->request, NULL, 0, 0, xfer); } #if 0 @@ -791,9 +1426,10 @@ umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv) Static void umass_bbb_reset(struct umass_softc *sc, int status) { - KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, - ("sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n", - sc->sc_wire)); + usbd_device_handle dev; + + KASSERT(sc->proto & PROTO_BBB, + ("sc->proto == 0x%02x wrong for umass_bbb_reset\n", sc->proto)); if (sc->sc_dying) return; @@ -820,32 +1456,31 @@ umass_bbb_reset(struct umass_softc *sc, int status) sc->transfer_state = TSTATE_BBB_RESET1; sc->transfer_status = status; + usbd_interface2device_handle(sc->iface, &dev); + /* reset is a class specific interface write */ - sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - sc->sc_req.bRequest = UR_BBB_RESET; - USETW(sc->sc_req.wValue, 0); - USETW(sc->sc_req.wIndex, sc->sc_ifaceno); - USETW(sc->sc_req.wLength, 0); - umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, + sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; + sc->request.bRequest = UR_BBB_RESET; + USETW(sc->request.wValue, 0); + USETW(sc->request.wIndex, sc->ifaceno); + USETW(sc->request.wLength, 0); + umass_setup_ctrl_transfer(sc, dev, &sc->request, NULL, 0, 0, sc->transfer_xfer[XFER_BBB_RESET1]); } Static void umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, - void *data, int datalen, int dir, u_int timeout, - umass_callback cb, void *priv) + void *data, int datalen, int dir, + transfer_cb_f cb, void *priv) { static int dCBWtag = 42; /* unique for CBW of transfer */ DPRINTF(UDMASS_BBB,("%s: umass_bbb_transfer cmd=0x%02x\n", USBDEVNAME(sc->sc_dev), *(u_char *)cmd)); - KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, - ("sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n", - sc->sc_wire)); - - /* Be a little generous. */ - sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; + KASSERT(sc->proto & PROTO_BBB, + ("sc->proto == 0x%02x wrong for umass_bbb_transfer\n", + sc->proto)); /* * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly @@ -917,7 +1552,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT); sc->cbw.bCBWLUN = lun; sc->cbw.bCDBLength = cmdlen; - memcpy(sc->cbw.CBWCDB, cmd, cmdlen); + bcopy(cmd, sc->cbw.CBWCDB, cmdlen); DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); @@ -934,7 +1569,7 @@ umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen, sc->transfer_state = TSTATE_BBB_COMMAND; /* Send the CBW from host to device via bulk-out endpoint. */ - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], + if (umass_setup_transfer(sc, sc->bulkout_pipe, &sc->cbw, UMASS_BBB_CBW_SIZE, 0, sc->transfer_xfer[XFER_BBB_CBW])) { umass_bbb_reset(sc, STATUS_WIRE_FAILED); @@ -949,9 +1584,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, struct umass_softc *sc = (struct umass_softc *) priv; usbd_xfer_handle next_xfer; - KASSERT(sc->sc_wire & UMASS_WPROTO_BBB, - ("sc->sc_wire == 0x%02x wrong for umass_bbb_state\n", - sc->sc_wire)); + KASSERT(sc->proto & PROTO_BBB, + ("sc->proto == 0x%02x wrong for umass_bbb_state\n",sc->proto)); if (sc->sc_dying) return; @@ -990,7 +1624,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, /* Data transport phase, setup transfer */ sc->transfer_state = TSTATE_BBB_DATA; if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], + if (umass_setup_transfer(sc, sc->bulkin_pipe, sc->data_buffer, sc->transfer_datalen, USBD_SHORT_XFER_OK | USBD_NO_COPY, sc->transfer_xfer[XFER_BBB_DATA])) @@ -1000,7 +1634,7 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, } else if (sc->transfer_dir == DIR_OUT) { memcpy(sc->data_buffer, sc->transfer_data, sc->transfer_datalen); - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], + if (umass_setup_transfer(sc, sc->bulkout_pipe, sc->data_buffer, sc->transfer_datalen, USBD_NO_COPY,/* fixed length transfer */ sc->transfer_xfer[XFER_BBB_DATA])) @@ -1022,16 +1656,18 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, &sc->transfer_actlen, NULL); if (err) { - DPRINTF(UDMASS_BBB, ("%s: Data-%s %d failed, " + DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, " "%s\n", USBDEVNAME(sc->sc_dev), (sc->transfer_dir == DIR_IN?"in":"out"), sc->transfer_datalen,usbd_errstr(err))); if (err == USBD_STALLED) { - sc->transfer_state = TSTATE_BBB_DCLEAR; umass_clear_endpoint_stall(sc, (sc->transfer_dir == DIR_IN? - UMASS_BULKIN:UMASS_BULKOUT), + sc->bulkin:sc->bulkout), + (sc->transfer_dir == DIR_IN? + sc->bulkin_pipe:sc->bulkout_pipe), + TSTATE_BBB_DCLEAR, sc->transfer_xfer[XFER_BBB_DCLEAR]); return; } else { @@ -1087,8 +1723,9 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, } /* Read the Command Status Wrapper via bulk-in endpoint. */ - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], - &sc->csw, UMASS_BBB_CSW_SIZE, 0, next_xfer)) { + if (umass_setup_transfer(sc, sc->bulkin_pipe, + &sc->csw, UMASS_BBB_CSW_SIZE, 0, + next_xfer)) { umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; } @@ -1107,9 +1744,10 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, * retry it, otherwise fail. */ if (sc->transfer_state == TSTATE_BBB_STATUS1) { - sc->transfer_state = TSTATE_BBB_SCLEAR; - umass_clear_endpoint_stall(sc, UMASS_BULKIN, - sc->transfer_xfer[XFER_BBB_SCLEAR]); + umass_clear_endpoint_stall(sc, + sc->bulkin, sc->bulkin_pipe, + TSTATE_BBB_SCLEAR, + sc->transfer_xfer[XFER_BBB_SCLEAR]); return; } else { umass_bbb_reset(sc, STATUS_WIRE_FAILED); @@ -1119,11 +1757,6 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); - /* Translate weird command-status signatures. */ - if ((sc->sc_quirks & UMASS_QUIRK_WRONG_CSWSIG) && - UGETDW(sc->csw.dCSWSignature) == CSWSIGNATURE_OLYMPUS_C1) - USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); - /* Check CSW and handle any error */ if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { /* Invalid CSW: Wrong signature or wrong tag might @@ -1168,8 +1801,9 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, panic("%s: transferred %d bytes instead of %d bytes\n", USBDEVNAME(sc->sc_dev), sc->transfer_actlen, sc->transfer_datalen); + } #if 0 - } else if (sc->transfer_datalen - sc->transfer_actlen + else if (sc->transfer_datalen - sc->transfer_actlen != UGETDW(sc->csw.dCSWDataResidue)) { DPRINTF(UDMASS_BBB, ("%s: actlen=%d != residue=%d\n", USBDEVNAME(sc->sc_dev), @@ -1178,8 +1812,10 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, umass_bbb_reset(sc, STATUS_WIRE_FAILED); return; + + } #endif - } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { + else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n", USBDEVNAME(sc->sc_dev), UGETDW(sc->csw.dCSWDataResidue))); @@ -1207,8 +1843,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, printf("%s: BBB reset failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - sc->transfer_state = TSTATE_BBB_RESET2; - umass_clear_endpoint_stall(sc, UMASS_BULKIN, + umass_clear_endpoint_stall(sc, + sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2, sc->transfer_xfer[XFER_BBB_RESET2]); return; @@ -1218,8 +1854,8 @@ umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ - sc->transfer_state = TSTATE_BBB_RESET3; - umass_clear_endpoint_stall(sc, UMASS_BULKOUT, + umass_clear_endpoint_stall(sc, + sc->bulkout, sc->bulkout_pipe, TSTATE_BBB_RESET3, sc->transfer_xfer[XFER_BBB_RESET3]); return; @@ -1253,16 +1889,19 @@ Static int umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, usbd_xfer_handle xfer) { - KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), - ("sc->sc_wire == 0x%02x wrong for umass_cbi_adsc\n", - sc->sc_wire)); - - sc->sc_req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - sc->sc_req.bRequest = UR_CBI_ADSC; - USETW(sc->sc_req.wValue, 0); - USETW(sc->sc_req.wIndex, sc->sc_ifaceno); - USETW(sc->sc_req.wLength, buflen); - return umass_setup_ctrl_transfer(sc, &sc->sc_req, buffer, + usbd_device_handle dev; + + KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), + ("sc->proto == 0x%02x wrong for umass_cbi_adsc\n",sc->proto)); + + usbd_interface2device_handle(sc->iface, &dev); + + sc->request.bmRequestType = UT_WRITE_CLASS_INTERFACE; + sc->request.bRequest = UR_CBI_ADSC; + USETW(sc->request.wValue, 0); + USETW(sc->request.wIndex, sc->ifaceno); + USETW(sc->request.wLength, buflen); + return umass_setup_ctrl_transfer(sc, dev, &sc->request, buffer, buflen, 0, xfer); } @@ -1273,9 +1912,8 @@ umass_cbi_reset(struct umass_softc *sc, int status) int i; # define SEND_DIAGNOSTIC_CMDLEN 12 - KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), - ("sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n", - sc->sc_wire)); + KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), + ("sc->proto == 0x%02x wrong for umass_cbi_reset\n",sc->proto)); if (sc->sc_dying) return; @@ -1321,22 +1959,19 @@ umass_cbi_reset(struct umass_softc *sc, int status) Static void umass_cbi_transfer(struct umass_softc *sc, int lun, - void *cmd, int cmdlen, void *data, int datalen, int dir, - u_int timeout, umass_callback cb, void *priv) + void *cmd, int cmdlen, void *data, int datalen, int dir, + transfer_cb_f cb, void *priv) { DPRINTF(UDMASS_CBI,("%s: umass_cbi_transfer cmd=0x%02x, len=%d\n", USBDEVNAME(sc->sc_dev), *(u_char *)cmd, datalen)); - KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), - ("sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n", - sc->sc_wire)); + KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), + ("sc->proto == 0x%02x wrong for umass_cbi_transfer\n", + sc->proto)); if (sc->sc_dying) return; - /* Be a little generous. */ - sc->timeout = timeout + USBD_DEFAULT_TIMEOUT; - /* * Do a CBI transfer with cmdlen bytes from cmd, possibly * a data phase of datalen bytes from/to the device and finally a @@ -1384,9 +2019,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, { struct umass_softc *sc = (struct umass_softc *) priv; - KASSERT(sc->sc_wire & (UMASS_WPROTO_CBI|UMASS_WPROTO_CBI_I), - ("sc->sc_wire == 0x%02x wrong for umass_cbi_state\n", - sc->sc_wire)); + KASSERT(sc->proto & (PROTO_CBI|PROTO_CBI_I), + ("sc->proto == 0x%02x wrong for umass_cbi_state\n", sc->proto)); if (sc->sc_dying) return; @@ -1409,10 +2043,10 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, /* Status transport by control pipe (section 2.3.2.1). * The command contained in the command block failed. * - * The control pipe has already been unstalled by the - * USB stack. - * Section 2.4.3.1.1 states that the bulk in endpoints - * should not stalled at this point. + * The control pipe has already been unstalled by the + * USB stack. + * Section 2.4.3.1.1 states that the bulk in endpoints + * should not stalled at this point. */ sc->transfer_state = TSTATE_IDLE; @@ -1431,7 +2065,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, sc->transfer_state = TSTATE_CBI_DATA; if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKIN], + if (umass_setup_transfer(sc, sc->bulkin_pipe, sc->transfer_data, sc->transfer_datalen, USBD_SHORT_XFER_OK | USBD_NO_COPY, sc->transfer_xfer[XFER_CBI_DATA])) @@ -1440,17 +2074,17 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, } else if (sc->transfer_dir == DIR_OUT) { memcpy(sc->data_buffer, sc->transfer_data, sc->transfer_datalen); - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_BULKOUT], + if (umass_setup_transfer(sc, sc->bulkout_pipe, sc->transfer_data, sc->transfer_datalen, USBD_NO_COPY,/* fixed length transfer */ sc->transfer_xfer[XFER_CBI_DATA])) umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } else if (sc->sc_wire == UMASS_WPROTO_CBI_I) { + } else if (sc->proto & PROTO_CBI_I) { DPRINTF(UDMASS_CBI, ("%s: no data phase\n", USBDEVNAME(sc->sc_dev))); sc->transfer_state = TSTATE_CBI_STATUS; - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN], + if (umass_setup_transfer(sc, sc->intrin_pipe, &sc->sbl, sizeof(sc->sbl), 0, /* fixed length transfer */ sc->transfer_xfer[XFER_CBI_STATUS])){ @@ -1476,14 +2110,15 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, USBDEVNAME(sc->sc_dev), sc->transfer_actlen)); if (err) { - DPRINTF(UDMASS_CBI, ("%s: Data-%s %d failed, " + DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, " "%s\n", USBDEVNAME(sc->sc_dev), (sc->transfer_dir == DIR_IN?"in":"out"), sc->transfer_datalen,usbd_errstr(err))); if (err == USBD_STALLED) { - sc->transfer_state = TSTATE_CBI_DCLEAR; - umass_clear_endpoint_stall(sc, UMASS_BULKIN, + umass_clear_endpoint_stall(sc, + sc->bulkin, sc->bulkin_pipe, + TSTATE_CBI_DCLEAR, sc->transfer_xfer[XFER_CBI_DCLEAR]); } else { umass_cbi_reset(sc, STATUS_WIRE_FAILED); @@ -1499,10 +2134,10 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, umass_dump_buffer(sc, sc->transfer_data, sc->transfer_actlen, 48)); - if (sc->sc_wire == UMASS_WPROTO_CBI_I) { + if (sc->proto & PROTO_CBI_I) { sc->transfer_state = TSTATE_CBI_STATUS; memset(&sc->sbl, 0, sizeof(sc->sbl)); - if (umass_setup_transfer(sc, sc->sc_pipe[UMASS_INTRIN], + if (umass_setup_transfer(sc, sc->intrin_pipe, &sc->sbl, sizeof(sc->sbl), 0, /* fixed length transfer */ sc->transfer_xfer[XFER_CBI_STATUS])){ @@ -1527,8 +2162,9 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, */ if (err == USBD_STALLED) { - sc->transfer_state = TSTATE_CBI_SCLEAR; - umass_clear_endpoint_stall(sc, UMASS_INTRIN, + umass_clear_endpoint_stall(sc, + sc->intrin, sc->intrin_pipe, + TSTATE_CBI_SCLEAR, sc->transfer_xfer[XFER_CBI_SCLEAR]); } else { umass_cbi_reset(sc, STATUS_WIRE_FAILED); @@ -1538,7 +2174,7 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, /* Dissect the information in the buffer */ - if (sc->sc_cmd == UMASS_CPROTO_UFI) { + if (sc->proto & PROTO_UFI) { int status; /* Section 3.4.3.1.3 specifies that the UFI command @@ -1614,8 +2250,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, printf("%s: CBI reset failed, %s\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - sc->transfer_state = TSTATE_CBI_RESET2; - umass_clear_endpoint_stall(sc, UMASS_BULKIN, + umass_clear_endpoint_stall(sc, + sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2, sc->transfer_xfer[XFER_CBI_RESET2]); return; @@ -1625,8 +2261,8 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, USBDEVNAME(sc->sc_dev), usbd_errstr(err)); /* no error recovery, otherwise we end up in a loop */ - sc->transfer_state = TSTATE_CBI_RESET3; - umass_clear_endpoint_stall(sc, UMASS_BULKOUT, + umass_clear_endpoint_stall(sc, + sc->bulkout, sc->bulkout_pipe, TSTATE_CBI_RESET3, sc->transfer_xfer[XFER_CBI_RESET3]); return; @@ -1656,21 +2292,26 @@ umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun) { + usbd_device_handle dev; usb_device_request_t req; usbd_status err; + usb_interface_descriptor_t *id; *maxlun = 0; /* Default to 0. */ DPRINTF(UDMASS_BBB, ("%s: Get Max Lun\n", USBDEVNAME(sc->sc_dev))); + usbd_interface2device_handle(sc->iface, &dev); + id = usbd_get_interface_descriptor(sc->iface); + /* The Get Max Lun command is a class-specific request. */ req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_BBB_GET_MAX_LUN; USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); + USETW(req.wIndex, id->bInterfaceNumber); USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_udev, &req, maxlun); + err = usbd_do_request(dev, &req, maxlun); switch (err) { case USBD_NORMAL_COMPLETION: DPRINTF(UDMASS_BBB, ("%s: Max Lun %d\n", @@ -1707,6 +2348,706 @@ umass_bbb_get_max_lun(struct umass_softc *sc, u_int8_t *maxlun) +#if defined(__FreeBSD__) +/* + * CAM specific functions (used by SCSI, UFI, 8070) + */ + +Static int +umass_cam_attach_sim() +{ + struct cam_devq *devq; /* Per device Queue */ + + /* A HBA is attached to the CAM layer. + * + * The CAM layer will then after a while start probing for + * devices on the bus. The number of devices is limitted to one. + */ + + /* SCSI transparent command set */ + + devq = cam_simq_alloc(1 /*maximum openings*/); + if (devq == NULL) + return(ENOMEM); + + umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, DEVNAME, + NULL /*priv*/, 0 /*unit number*/, + 1 /*maximum device openings*/, + 0 /*maximum tagged device openings*/, + devq); + if (umass_sim == NULL) { + cam_simq_free(devq); + return(ENOMEM); + } + + if(xpt_bus_register(umass_sim, 0) != CAM_SUCCESS) + return(ENOMEM); + + if (xpt_create_path(&umass_path, NULL, cam_sim_path(umass_sim), + UMASS_SCSIID_HOST, 0) + != CAM_REQ_CMP) + return(ENOMEM); + + return(0); +} + +#ifdef UMASS_DO_CAM_RESCAN +/* this function is only used from umass_cam_rescan, so mention + * prototype down here. + */ +Static void umass_cam_rescan_callback(struct cam_periph *periph,union ccb *ccb); + +Static void +umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) +{ +#ifdef UMASS_DEBUG + struct umass_softc *sc = devclass_get_softc(umass_devclass, + ccb->ccb_h.target_id); + + if (ccb->ccb_h.status != CAM_REQ_CMP) { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan failed, 0x%04x\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccb->ccb_h.status)); + } else { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: Rescan succeeded, freeing resources.\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + } +#endif + + xpt_free_path(ccb->ccb_h.path); + free(ccb, M_USBDEV); +} + +Static void +umass_cam_rescan(struct umass_softc *sc) +{ + struct cam_path *path; + union ccb *ccb = malloc(sizeof(union ccb), M_USBDEV, M_WAITOK); + + memset(ccb, 0, sizeof(union ccb)); + + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d: scanning bus for new device %d\n", + USBDEVNAME(sc->sc_dev), cam_sim_path(umass_sim), + device_get_unit(sc->sc_dev), 0, + device_get_unit(sc->sc_dev))); + + if (xpt_create_path(&path, xpt_periph, cam_sim_path(umass_sim), + device_get_unit(sc->sc_dev), 0) + != CAM_REQ_CMP) + return; + + xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); + ccb->ccb_h.func_code = XPT_SCAN_BUS; + ccb->ccb_h.cbfcnp = umass_cam_rescan_callback; + ccb->crcn.flags = CAM_FLAG_NONE; + xpt_action(ccb); + + /* The scan is in progress now. */ +} +#endif + +Static int +umass_cam_attach(struct umass_softc *sc) +{ + /* SIM already attached at module load. The device is a target on the + * one SIM we registered: target device_get_unit(self). + */ + + /* The artificial limit UMASS_SCSIID_MAX is there because CAM expects + * a limit to the number of targets that are present on a SIM. + */ + if (device_get_unit(sc->sc_dev) > UMASS_SCSIID_MAX) { + printf("%s: Increase UMASS_SCSIID_MAX (currently %d) in %s " + "and try again.\n", USBDEVNAME(sc->sc_dev), + UMASS_SCSIID_MAX, __FILE__); + return(1); + } + +#ifdef UMASS_DO_CAM_RESCAN + if (!cold) { + /* Notify CAM of the new device. Any failure is benign, as the + * user can still do it by hand (camcontrol rescan <busno>). + * Only do this if we are not booting, because CAM does a scan + * after booting has completed, when interrupts have been + * enabled. + */ + umass_cam_rescan(sc); + } +#endif + + return(0); /* always succesful */ +} + +/* umass_cam_detach + * detach from the CAM layer + */ + +Static int +umass_cam_detach_sim() +{ + if (umass_sim) + return(EBUSY); /* XXX CAM can't handle disappearing SIMs yet */ + + if (umass_path) { + /* XXX do we need to send an asynchroneous event for the SIM? + xpt_async(AC_LOST_DEVICE, umass_path, NULL); + */ + xpt_free_path(umass_path); + umass_path = NULL; + } + + if (umass_sim) { + if (xpt_bus_deregister(cam_sim_path(umass_sim))) + cam_sim_free(umass_sim, /*free_devq*/TRUE); + else + return(EBUSY); + + umass_sim = NULL; + } + + return(0); +} + +Static int +umass_cam_detach(struct umass_softc *sc) +{ + struct cam_path *path; + + /* detach of sim not done until module unload */ + DPRINTF(UDMASS_SCSI, ("%s: losing CAM device entry\n", + USBDEVNAME(sc->sc_dev))); + + if (xpt_create_path(&path, NULL, cam_sim_path(umass_sim), + device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD) + != CAM_REQ_CMP) + return(ENOMEM); + xpt_async(AC_LOST_DEVICE, path, NULL); + xpt_free_path(path); + + return(0); +} + + + +/* umass_cam_action + * CAM requests for action come through here + */ + +Static void +umass_cam_action(struct cam_sim *sim, union ccb *ccb) +{ + struct umass_softc *sc = devclass_get_softc(umass_devclass, + ccb->ccb_h.target_id); + + /* The softc is still there, but marked as going away. umass_cam_detach + * has not yet notified CAM of the lost device however. + */ + if (sc && sc->sc_dying) { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " + "Invalid target (gone)\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccb->ccb_h.func_code)); + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } + + /* Verify, depending on the operation to perform, that we either got a + * valid sc, because an existing target was referenced, or otherwise + * the SIM is addressed. + * + * This avoids bombing out at a printf and does give the CAM layer some + * sensible feedback on errors. + */ + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + case XPT_RESET_DEV: + case XPT_GET_TRAN_SETTINGS: + case XPT_SET_TRAN_SETTINGS: + case XPT_CALC_GEOMETRY: + /* the opcodes requiring a target. These should never occur. */ + if (sc == NULL) { + printf("%s:%d:%d:%d:func_code 0x%04x: " + "Invalid target\n", + DEVNAME_SIM, UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccb->ccb_h.func_code); + + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } + break; + case XPT_PATH_INQ: + case XPT_NOOP: + /* The opcodes sometimes aimed at a target (sc is valid), + * sometimes aimed at the SIM (sc is invalid and target is + * CAM_TARGET_WILDCARD) + */ + if (sc == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " + "Invalid target\n", + DEVNAME_SIM, UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccb->ccb_h.func_code)); + + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } + break; + default: + /* XXX Hm, we should check the input parameters */ + } + + /* Perform the requested action */ + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + { + struct ccb_scsiio *csio = &ccb->csio; /* deref union */ + int dir; + unsigned char *cmd; + int cmdlen; + + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " + "cmd: 0x%02x, flags: 0x%02x, " + "%db cmd/%db data/%db sense\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + csio->cdb_io.cdb_bytes[0], + ccb->ccb_h.flags & CAM_DIR_MASK, + csio->cdb_len, csio->dxfer_len, + csio->sense_len)); + + /* clear the end of the buffer to make sure we don't send out + * garbage. + */ + DIF(UDMASS_SCSI, if ((ccb->ccb_h.flags & CAM_DIR_MASK) + == CAM_DIR_OUT) + umass_dump_buffer(sc, csio->data_ptr, + csio->dxfer_len, 48)); + + if (sc->transfer_state != TSTATE_IDLE) { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " + "I/O requested while busy (state %d, %s)\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + sc->transfer_state,states[sc->transfer_state])); + ccb->ccb_h.status = CAM_SCSI_BUSY; + xpt_done(ccb); + return; + } + + switch(ccb->ccb_h.flags&CAM_DIR_MASK) { + case CAM_DIR_IN: + dir = DIR_IN; + break; + case CAM_DIR_OUT: + dir = DIR_OUT; + break; + default: + dir = DIR_NONE; + } + + ccb->ccb_h.status = CAM_REQ_INPROG | CAM_SIM_QUEUED; + if (sc->transform(sc, csio->cdb_io.cdb_bytes, csio->cdb_len, + &cmd, &cmdlen)) { + sc->transfer(sc, ccb->ccb_h.target_lun, cmd, cmdlen, + csio->data_ptr, + csio->dxfer_len, dir, + umass_cam_cb, (void *) ccb); + } else { + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + } + + break; + } + case XPT_PATH_INQ: + { + struct ccb_pathinq *cpi = &ccb->cpi; + + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n", + (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), + UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + + /* host specific information */ + cpi->version_num = 1; + cpi->hba_inquiry = 0; + cpi->target_sprt = 0; + cpi->hba_misc = 0; + cpi->hba_eng_cnt = 0; + cpi->max_target = UMASS_SCSIID_MAX; /* one target */ + cpi->max_lun = 0; /* no LUN's supported */ + cpi->initiator_id = UMASS_SCSIID_HOST; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->bus_id = UMASS_SCSI_BUS; + if (sc) { + cpi->base_transfer_speed = sc->transfer_speed; + cpi->max_lun = sc->maxlun; + } + + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + case XPT_RESET_DEV: + { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + + ccb->ccb_h.status = CAM_REQ_INPROG; + umass_reset(sc, umass_cam_cb, (void *) ccb); + break; + } + case XPT_GET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + + cts->valid = 0; + cts->flags = 0; /* no disconnection, tagging */ + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + case XPT_SET_TRAN_SETTINGS: + { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + break; + } + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg = &ccb->ccg; + + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_CALC_GEOMETRY: " + "Volume size = %d\n", + USBDEVNAME(sc->sc_dev), UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccg->volume_size)); + + /* XXX We should probably ask the drive for the details + * instead of cluching them up ourselves + */ + if (sc->drive == ZIP_100) { + ccg->heads = 64; + ccg->secs_per_track = 32; + ccg->cylinders = ccg->volume_size / ccg->heads + / ccg->secs_per_track; + ccb->ccb_h.status = CAM_REQ_CMP; + break; + } else if (sc->proto & PROTO_UFI) { + ccg->heads = 2; + if (ccg->volume_size == 2880) + ccg->secs_per_track = 18; + else + ccg->secs_per_track = 9; + ccg->cylinders = 80; + break; + } else { + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + } + + xpt_done(ccb); + break; + } + case XPT_NOOP: + { + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n", + (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), + UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun)); + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + default: + DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " + "Not implemented\n", + (sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)), + UMASS_SCSI_BUS, + ccb->ccb_h.target_id, ccb->ccb_h.target_lun, + ccb->ccb_h.func_code)); + + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + break; + } +} + +/* umass_cam_poll + * all requests are handled through umass_cam_action, requests + * are never pending. So, nothing to do here. + */ +Static void +umass_cam_poll(struct cam_sim *sim) +{ +#ifdef UMASS_DEBUG + struct umass_softc *sc = (struct umass_softc *) sim->softc; + + DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n", + USBDEVNAME(sc->sc_dev))); +#endif + + /* nop */ +} + + +/* umass_cam_cb + * finalise a completed CAM command + */ + +Static void +umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status) +{ + union ccb *ccb = (union ccb *) priv; + struct ccb_scsiio *csio = &ccb->csio; /* deref union */ + + csio->resid = residue; + + switch (status) { + case STATUS_CMD_OK: + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + + case STATUS_CMD_UNKNOWN: + case STATUS_CMD_FAILED: + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + { + unsigned char *cmd; + int cmdlen; + + /* fetch sense data */ + DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n", + USBDEVNAME(sc->sc_dev), + sc->cam_scsi_sense.length)); + + sc->cam_scsi_sense.length = csio->sense_len; + + if (sc->transform(sc, (char *) &sc->cam_scsi_sense, + sizeof(sc->cam_scsi_sense), + &cmd, &cmdlen)) { + sc->transfer(sc, ccb->ccb_h.target_lun, + cmd, cmdlen, + &csio->sense_data, + csio->sense_len, DIR_IN, + umass_cam_sense_cb, (void *) ccb); + } else { +#ifdef UMASS_DEBUG + panic("transform(REQUEST_SENSE) failed\n"); +#else + csio->resid = sc->transfer_datalen; + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); +#endif + } + break; + } + case XPT_RESET_DEV: /* Reset failed */ + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); + break; + default: + panic("umass_cam_cb called for func_code %d\n", + ccb->ccb_h.func_code); + } + break; + + case STATUS_WIRE_FAILED: + /* the wire protocol failed and will have recovered + * (hopefully). We return an error to CAM and let CAM retry + * the command if necessary. + */ + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); + break; + + default: + panic("%s: Unknown status %d in umass_cam_cb\n", + USBDEVNAME(sc->sc_dev), status); + } +} + +/* Finalise a completed autosense operation + */ +Static void +umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status) +{ + union ccb *ccb = (union ccb *) priv; + struct ccb_scsiio *csio = &ccb->csio; /* deref union */ + + switch (status) { + case STATUS_CMD_OK: + case STATUS_CMD_UNKNOWN: + /* Getting sense data succeeded. The length of the sense data + * is not returned in any way. The sense data itself contains + * the length of the sense data that is valid. + */ + if (sc->quirks & RS_NO_CLEAR_UA + && csio->cdb_io.cdb_bytes[0] == INQUIRY + && (csio->sense_data.flags & SSD_KEY) + == SSD_KEY_UNIT_ATTENTION) { + /* Ignore unit attention errors in the case where + * the Unit Attention state is not cleared on + * REQUEST SENSE. They will appear again at the next + * command. + */ + ccb->ccb_h.status = CAM_REQ_CMP; + } else if ((csio->sense_data.flags & SSD_KEY) + == SSD_KEY_NO_SENSE) { + /* No problem after all (in the case of CBI without + * CCI) + */ + ccb->ccb_h.status = CAM_REQ_CMP; + } else { + ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR + | CAM_AUTOSNS_VALID; + csio->scsi_status = SCSI_STATUS_CHECK_COND; + } + xpt_done(ccb); + break; + + default: + DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", + USBDEVNAME(sc->sc_dev), status)); + ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + xpt_done(ccb); + } +} + + +Static int +umass_driver_load(module_t mod, int what, void *arg) +{ + int err; + + switch (what) { + case MOD_UNLOAD: + err = umass_cam_detach_sim(); + if (err) + return(err); + return(usbd_driver_load(mod, what, arg)); + case MOD_LOAD: + /* We don't attach to CAM at this point, because it will try + * and malloc memory for it. This is not possible when the + * boot loader loads umass as a module before the kernel + * has been bootstrapped. + */ + default: + return(usbd_driver_load(mod, what, arg)); + } +} + + + +/* (even the comment is missing) */ + +DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, umass_driver_load, 0); + + +/* + * SCSI specific functions + */ + +Static int +umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen) +{ + *rcmd = cmd; /* trivial copy */ + *rcmdlen = cmdlen; + + switch (cmd[0]) { + case TEST_UNIT_READY: + if (sc->quirks & NO_TEST_UNIT_READY) { + DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " + "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); + cmd[0] = START_STOP_UNIT; + cmd[4] = SSS_START; + } + break; + } + + return 1; /* success */ +} + +/* + * UFI specific functions + */ + +Static int +umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen) +{ + *rcmd = cmd; + /* A UFI command is always 12 bytes in length */ + /* XXX cmd[(cmdlen+1)..12] contains garbage */ + *rcmdlen = 12; + + switch (cmd[0]) { + case TEST_UNIT_READY: + if (sc->quirks & NO_TEST_UNIT_READY) { + DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY " + "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); + cmd[0] = START_STOP_UNIT; + cmd[4] = SSS_START; + } + return 1; + case INQUIRY: + case START_STOP_UNIT: + case MODE_SENSE: + case PREVENT_ALLOW: + case READ_10: + case READ_12: + case READ_CAPACITY: + case REQUEST_SENSE: + case REZERO_UNIT: + case POSITION_TO_ELEMENT: /* SEEK_10 */ + case SEND_DIAGNOSTIC: + case WRITE_10: + case WRITE_12: + /* FORMAT_UNIT */ + /* MODE_SELECT */ + /* READ_FORMAT_CAPACITY */ + /* VERIFY */ + /* WRITE_AND_VERIFY */ + return 1; /* success */ + default: + return 0; /* success */ + } +} + +/* + * 8070 specific functions + */ +Static int +umass_8070_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, + unsigned char **rcmd, int *rcmdlen) +{ + return 0; /* failure */ +} + +#endif /* __FreeBSD__ */ + #ifdef UMASS_DEBUG Static void @@ -1718,13 +3059,11 @@ umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) int tag = UGETDW(cbw->dCBWTag); int flags = cbw->bCBWFlags; - DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmdlen=%d " - "(0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%s), " + DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db " + "(0x%02x%02x%02x%02x%02x%02x%s), " "data = %d bytes, dir = %s\n", USBDEVNAME(sc->sc_dev), tag, clen, - c[0], c[1], c[2], c[3], c[4], c[5], - c[6], c[7], c[8], c[9], - (clen > 10? "...":""), + c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""), dlen, (flags == CBWFLAGS_IN? "in": (flags == CBWFLAGS_OUT? "out":"<invalid>")))); } @@ -1774,3 +3113,482 @@ umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen, USBDEVNAME(sc->sc_dev), s1, s2, s3)); } #endif + + + + + + + + +#if defined(__NetBSD__) || defined(__OpenBSD__) +Static int +umass_scsipi_cmd(xs) + struct scsipi_xfer *xs; +{ + struct scsipi_link *sc_link = xs->sc_link; + struct umass_softc *sc = sc_link->adapter_softc; + struct scsipi_generic *cmd, trcmd; + int cmdlen; + int dir; +#ifdef UMASS_DEBUG + microtime(&sc->tv); +#endif + + memset(&trcmd, 0, sizeof(trcmd)); + +#if defined(__NetBSD__) + DIF(UDMASS_UPPER, sc_link->flags |= DEBUGLEVEL); +#endif +#if defined(__OpenBSD__) + DIF(UDMASS_UPPER, sc_link->flags |= SCSIDEBUG_LEVEL); +#endif + +#if defined(__NetBSD__) || defined(__OpenBSD__) + DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: %d:%d xs=%p cmd=0x%02x " + "(quirks=0x%x, poll=%d)\n", USBDEVNAME(sc->sc_dev), + SCSI_LINK_TARGET(sc_link), SCSI_LINK_LUN(sc_link), + xs, xs->cmd->opcode, sc_link->quirks, + xs->xs_control & XS_CTL_POLL)); +#endif + +#if defined(USB_DEBUG) && defined(SCSIDEBUG) + if (umassdebug & UDMASS_SCSI) + show_scsipi_xs(xs); + else if (umassdebug & ~UDMASS_CMD) + show_scsipi_cmd(xs); +#endif + + if (sc->sc_dying) { + xs->error = XS_DRIVER_STUFFUP; + goto done; + } + +#ifdef UMASS_DEBUG +#if defined(__NetBSD__) + if ((sc_link->type == BUS_ATAPI ? + sc_link->scsipi_atapi.drive : SCSI_LINK_TARGET(sc_link)) + != UMASS_SCSIID_DEVICE) { + DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n", + USBDEVNAME(sc->sc_dev), + SCSI_LINK_TARGET(sc_link))); + xs->error = XS_DRIVER_STUFFUP; + goto done; + } +#endif +#if defined(__OpenBSD__) + if (sc_link->target != UMASS_SCSIID_DEVICE) { + DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n", + USBDEVNAME(sc->sc_dev), + sc_link->target)); + xs->error = XS_DRIVER_STUFFUP; + goto done; + } +#endif +#endif + + cmd = xs->cmd; + + if (xs->cmd->opcode == SCSI_MODE_SENSE && + (sc_link->quirks & SDEV_NOMODESENSE)) { + /*printf("%s: SCSI_MODE_SENSE\n", USBDEVNAME(sc->sc_dev));*/ + xs->error = XS_TIMEOUT; + goto done; + } + + if (xs->cmd->opcode == START_STOP && + (sc->quirks & NO_START_STOP)) { + /*printf("%s: START_STOP\n", USBDEVNAME(sc->sc_dev));*/ + xs->error = XS_NOERROR; + goto done; + } + + if (xs->cmd->opcode == INQUIRY && + (sc->quirks & FORCE_SHORT_INQUIRY)) { + memcpy(&trcmd, cmd, sizeof trcmd); + trcmd.bytes[4] = SHORT_INQUIRY_LENGTH; + cmd = &trcmd; + } + + dir = DIR_NONE; + if (xs->datalen) { + switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) { + case XS_CTL_DATA_IN: + dir = DIR_IN; + break; + case XS_CTL_DATA_OUT: + dir = DIR_OUT; + break; + } + } + + if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) { + printf("umass_cmd: large datalen, %d\n", xs->datalen); + xs->error = XS_DRIVER_STUFFUP; + goto done; + } + + cmdlen = xs->cmdlen; + if (sc->proto & PROTO_UFI) { + if (!umass_ufi_transform(sc, cmd, cmdlen, &trcmd, &cmdlen)) { + xs->error = XS_DRIVER_STUFFUP; + goto done; + } + cmd= &trcmd; + } + + if (sc->proto & PROTO_ATAPI) { + bcopy(cmd, &trcmd, cmdlen); + cmd = &trcmd; + cmdlen = ATAPI_COMMAND_LENGTH; + } + + if (xs->xs_control & XS_CTL_POLL) { + /* Use sync transfer. XXX Broken! */ + DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir)); + sc->sc_xfer_flags = USBD_SYNCHRONOUS; + sc->sc_sync_status = USBD_INVAL; + sc->transfer(sc, SCSI_LINK_LUN(sc_link), cmd, cmdlen, + xs->data, xs->datalen, dir, 0, xs); + sc->sc_xfer_flags = 0; + DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n", + sc->sc_sync_status)); + switch (sc->sc_sync_status) { + case USBD_NORMAL_COMPLETION: + xs->error = XS_NOERROR; + break; + case USBD_TIMEOUT: + xs->error = XS_TIMEOUT; + break; + default: + xs->error = XS_DRIVER_STUFFUP; + break; + } + goto done; + } else { + DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: async dir=%d, cmdlen=%d" + " datalen=%d\n", + dir, cmdlen, xs->datalen)); + sc->transfer(sc, SCSI_LINK_LUN(sc_link), cmd, cmdlen, + xs->data, xs->datalen, dir, umass_scsipi_cb, xs); + return (SUCCESSFULLY_QUEUED); + } + + /* Return if command finishes early. */ + done: +#if defined(__NetBSD__) + xs->xs_status |= XS_STS_DONE; +#endif +#if defined(__OpenBSD__) + xs->flags |= ITSDONE; +#endif + + scsipi_done(xs); + if (xs->xs_control & XS_CTL_POLL) + return (COMPLETE); + else + return (SUCCESSFULLY_QUEUED); +} + +Static void +umass_scsipi_minphys(bp) + struct buf *bp; +{ + if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE) + bp->b_bcount = UMASS_MAX_TRANSFER_SIZE; + minphys(bp); +} + +int +umass_scsipi_ioctl(link, cmd, arg, flag, p) + struct scsipi_link *link; + u_long cmd; + caddr_t arg; + int flag; + struct proc *p; +{ + /*struct umass_softc *sc = link->adapter_softc;*/ + + switch (cmd) { +#if 0 + case SCBUSIORESET: + ccb->ccb_h.status = CAM_REQ_INPROG; + umass_reset(sc, umass_cam_cb, (void *) ccb); + return (0); +#endif + default: + return (ENOTTY); + } +} + +Static void +umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status) +{ + struct scsipi_xfer *xs = priv; + struct scsipi_link *sc_link = xs->sc_link; + int cmdlen; + int s; +#ifdef UMASS_DEBUG + struct timeval tv; + u_int delta; + microtime(&tv); + delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + tv.tv_usec - sc->tv.tv_usec; +#endif + + DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d" + " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue, status)); + xs->resid = residue; + + switch (status) { + case STATUS_CMD_OK: + xs->error = XS_NOERROR; + break; + + case STATUS_CMD_UNKNOWN: + case STATUS_CMD_FAILED: + /* fetch sense data */ + memset(&sc->sc_sense_cmd, 0, sizeof(sc->sc_sense_cmd)); + sc->sc_sense_cmd.opcode = REQUEST_SENSE; + sc->sc_sense_cmd.byte2 = SCSI_LINK_LUN(sc_link) << + SCSI_CMD_LUN_SHIFT; + sc->sc_sense_cmd.length = sizeof(xs->sense); + + cmdlen = sizeof(sc->sc_sense_cmd); + if (sc->proto & PROTO_UFI) + cmdlen = UFI_COMMAND_LENGTH; + else if (sc->proto & PROTO_ATAPI) + cmdlen = ATAPI_COMMAND_LENGTH; + + sc->transfer(sc, SCSI_LINK_LUN(sc_link), + &sc->sc_sense_cmd, cmdlen, + &xs->sense, sizeof(xs->sense), DIR_IN, + umass_scsipi_sense_cb, xs); + return; + + case STATUS_WIRE_FAILED: + xs->error = XS_RESET; + break; + + default: + panic("%s: Unknown status %d in umass_scsipi_cb\n", + USBDEVNAME(sc->sc_dev), status); + } + +#if defined(__NetBSD__) + xs->xs_status |= XS_STS_DONE; +#endif +#if defined(__OpenBSD__) + xs->flags |= ITSDONE; +#endif + + DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu: return xs->error=" + "%d, xs->xs_status=0x%x xs->resid=%d\n", + tv.tv_sec, tv.tv_usec, + xs->error, xs->xs_status, xs->resid)); + + s = splbio(); + scsipi_done(xs); + splx(s); +} + +/* + * Finalise a completed autosense operation + */ +Static void +umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue, + int status) +{ + struct scsipi_xfer *xs = priv; + int s; + int bytes_received; + + DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: xs=%p residue=%d " + "status=%d\n", xs, residue, status)); + + switch (status) { + case STATUS_CMD_OK: + case STATUS_CMD_UNKNOWN: + /* getting sense data succeeded */ + if ((xs->cmd->opcode == INQUIRY) + && (xs->resid < xs->datalen)) { + /* Some drivers return SENSE errors even after INQUIRY + * The upper layer doesn't like that. + */ + xs->error = XS_NOERROR; + break; + } + + bytes_received = sizeof(xs->sense) - residue; + + if (bytes_received < 8 || + (bytes_received < xs->sense.extra_len + 8)) + xs->error = XS_SHORTSENSE; + else + xs->error = XS_SENSE; + +#if defined(__OpenBSD__) + /* Note that this test may need to be revised + with QIC-157a/SCSI tape drives that return + ILI, EOM in the high bits of flags. + */ + if ((xs->sense.error_code & SSD_ERRCODE) == 0x70 && + (xs->sense.flags == 0)) + xs->error = XS_NOERROR; +#endif + + break; + default: + DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", + USBDEVNAME(sc->sc_dev), status)); + xs->error = XS_DRIVER_STUFFUP; + break; + } + +#if defined(__NetBSD__) + xs->xs_status |= XS_STS_DONE; +#endif +#if defined(__OpenBSD__) + xs->flags |= ITSDONE; +#endif + + DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: return xs->error=%d, " + "xs->xs_status=0x%x xs->resid=%d\n", xs->error, xs->xs_status, + xs->resid)); + + s = splbio(); + scsipi_done(xs); + splx(s); +} + +/* + * UFI specific functions + */ + +Static int +umass_ufi_transform(struct umass_softc *sc, struct scsipi_generic *cmd, + int cmdlen, struct scsipi_generic *rcmd, int *rcmdlen) +{ + *rcmdlen = UFI_COMMAND_LENGTH; + memset(rcmd, 0, sizeof *rcmd); + + /* Handle any quirks */ + if (cmd->opcode == TEST_UNIT_READY + && (sc->quirks & NO_TEST_UNIT_READY)) { + /* + * Some devices do not support this command. + * Start Stop Unit should give the same results + */ + DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY " + "to START_UNIT\n", USBDEVNAME(sc->sc_dev))); + rcmd->opcode = START_STOP; + rcmd->bytes[3] = SSS_START; + return 1; + } + + switch (cmd->opcode) { + /* Commands of which the format has been verified. They should work. */ + case TEST_UNIT_READY: + case SCSI_REZERO_UNIT: + case REQUEST_SENSE: + case INQUIRY: + case START_STOP: + /*case SEND_DIAGNOSTIC: ??*/ + case PREVENT_ALLOW: + case READ_CAPACITY: + case READ_BIG: + case WRITE_BIG: + case POSITION_TO_ELEMENT: /* SEEK_10 */ + case SCSI_MODE_SELECT_BIG: + case SCSI_MODE_SENSE_BIG: + default: + /* Copy the command into the (zeroed out) destination buffer */ + memcpy(rcmd, cmd, cmdlen); + return (1); /* success */ + + /* + * Other UFI commands: FORMAT_UNIT, MODE_SELECT, READ_FORMAT_CAPACITY, + * VERIFY, WRITE_AND_VERIFY. + * These should be checked whether they somehow can be made to fit. + */ + + /* These commands are known _not_ to work. They should be converted. */ + case SCSI_READ_COMMAND: + case SCSI_WRITE_COMMAND: + case SCSI_MODE_SENSE: + case SCSI_MODE_SELECT: + printf("%s: Unsupported UFI command 0x%02x", + USBDEVNAME(sc->sc_dev), cmd->opcode); + if (cmdlen == 6) + printf(", 6 byte command should have been converted"); + printf("\n"); + return (0); /* failure */ + } +} + + +#if NATAPIBUS > 0 +Static void +umass_atapi_probedev(atapi, target) + struct atapibus_softc *atapi; + int target; +{ + struct scsipi_link *sc_link; + struct scsipibus_attach_args sa; + struct ata_drive_datas *drvp = &atapi->sc_drvs[target]; + char vendor[33], product[65], revision[17]; + struct scsipi_inquiry_data inqbuf; + + DPRINTF(UDMASS_SCSI,("umass_atapi_probedev: atapi=%p target=%d\n", + atapi, target)); + + if (atapi->sc_link[target]) + return; + + sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT); + if (sc_link == NULL) { + printf("%s: can't allocate link for drive %d\n", + atapi->sc_dev.dv_xname, target); + return; + } + *sc_link = *atapi->adapter_link; + + DIF(UDMASS_UPPER, sc_link->flags |= DEBUGLEVEL); + + /* Fill generic parts of the link. */ + sc_link->active = 0; + sc_link->scsipi_atapi.drive = target; + sc_link->device = &umass_dev; + TAILQ_INIT(&sc_link->pending_xfers); + + DPRINTF(UDMASS_SCSI, ("umass_atapi_probedev: doing inquiry\n")); + /* Now go ask the device all about itself. */ + memset(&inqbuf, 0, sizeof(inqbuf)); + if (scsipi_inquire(sc_link, &inqbuf, XS_CTL_DISCOVERY) != 0) + goto bad; + + scsipi_strvis(vendor, 33, inqbuf.vendor, 8); + scsipi_strvis(product, 65, inqbuf.product, 16); + scsipi_strvis(revision, 17, inqbuf.revision, 4); + + sa.sa_sc_link = sc_link; + sa.sa_inqbuf.type = inqbuf.device; + sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ? + T_REMOV : T_FIXED; + if (sa.sa_inqbuf.removable) + sc_link->flags |= SDEV_REMOVABLE; + /* XXX how? sc_link->scsipi_atapi.cap |= ACAP_LEN;*/ + sa.sa_inqbuf.vendor = vendor; + sa.sa_inqbuf.product = product; + sa.sa_inqbuf.revision = revision; + sa.sa_inqptr = NULL; + + drvp->drv_softc = atapi_probedev(atapi, target, sc_link, &sa); + /* atapi_probedev() frees the scsipi_link when there is no device. */ + return; + +bad: + free(sc_link, M_DEVBUF); + return; +} +#endif +#endif diff --git a/sys/dev/usb/umass_isdata.c b/sys/dev/usb/umass_isdata.c deleted file mode 100644 index bd5a73562dd..00000000000 --- a/sys/dev/usb/umass_isdata.c +++ /dev/null @@ -1,589 +0,0 @@ -/* $NetBSD: umass_isdata.c,v 1.1 2001/12/24 13:43:25 augustss Exp $ */ - -/* - * TODO: - * get ATA registers on any kind of error - * implement more commands (what is needed) - */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umass_isdata.c,v 1.1 2001/12/24 13:43:25 augustss Exp $"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/buf.h> -#include <sys/device.h> -#include <sys/proc.h> -#include <sys/disklabel.h> -#include <sys/malloc.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include <dev/usb/umassvar.h> -#include <dev/usb/umass_isdata.h> - -int umass_wd_attach(struct umass_softc *); - -#include <dev/ata/atareg.h> -#include <dev/ata/atavar.h> -#include <dev/ata/wdvar.h> -#include <dev/ic/wdcreg.h> - -/* XXX move this */ -struct isd200_config { - uByte EventNotification; - uByte ExternalClock; - uByte ATAInitTimeout; - uByte ATAMisc1; -#define ATATiming 0x0f -#define ATAPIReset 0x10 -#define MasterSlaveSelection 0x20 -#define ATAPICommandBlockSize 0xc0 - uByte ATAMajorCommand; - uByte ATAMinorCommand; - uByte ATAMisc2; -#define LastLUNIdentifier 0x07 -#define DescriptOverride 0x08 -#define ATA3StateSuspend 0x10 -#define SkipDeviceBoot 0x20 -#define ConfigDescriptor2 0x40 -#define InitStatus 0x80 - uByte ATAMisc3; -#define SRSTEnable 0x01 -}; - -struct uisdata_softc { - struct umassbus_softc base; - - struct ata_drive_datas sc_drv_data; - struct isd200_config sc_isd_config; - void *sc_ata_bio; - u_long sc_skip; -}; - -#undef DPRINTF -#undef DPRINTFN -#ifdef UISDATA_DEBUG -#define DPRINTF(x) if (uisdatadebug) logprintf x -#define DPRINTFN(n,x) if (uisdatadebug>(n)) logprintf x -int uisdatadebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -int uisdata_bio(struct ata_drive_datas *, struct ata_bio *); -int uisdata_bio1(struct ata_drive_datas *, struct ata_bio *); -void uisdata_reset_channel(struct ata_drive_datas *); -int uisdata_exec_command(struct ata_drive_datas *, struct wdc_command *); -int uisdata_get_params(struct ata_drive_datas *, u_int8_t, struct ataparams *); -int uisdata_addref(struct ata_drive_datas *); -void uisdata_delref(struct ata_drive_datas *); -void uisdata_kill_pending(struct ata_drive_datas *); - -void uisdata_bio_cb(struct umass_softc *, void *, int, int); -void uisdata_exec_cb(struct umass_softc *, void *, int, int); -int uwdprint(void *, const char *); - -const struct ata_bustype uisdata_bustype = { - SCSIPI_BUSTYPE_ATA, - uisdata_bio, - uisdata_reset_channel, - uisdata_exec_command, - uisdata_get_params, - uisdata_addref, - uisdata_delref, - uisdata_kill_pending, -}; - -struct ata_cmd { - u_int8_t ac_signature0; - u_int8_t ac_signature1; - - u_int8_t ac_action_select; -#define AC_ReadRegisterAccess 0x01 -#define AC_NoDeviceSelectionBit 0x02 -#define AC_NoBSYPollBit 0x04 -#define AC_IgnorePhaseErrorBit 0x08 -#define AC_IgnoreDeviceErrorBit 0x10 - - u_int8_t ac_register_select; -#define AC_SelectAlternateStatus 0x01 /* R */ -#define AC_SelectDeviceControl 0x01 /* W */ -#define AC_SelectError 0x02 /* R */ -#define AC_SelectFeatures 0x02 /* W */ -#define AC_SelectSectorCount 0x04 /* RW */ -#define AC_SelectSectorNumber 0x08 /* RW */ -#define AC_SelectCylinderLow 0x10 /* RW */ -#define AC_SelectCylinderHigh 0x20 /* RW */ -#define AC_SelectDeviceHead 0x40 /* RW */ -#define AC_SelectStatus 0x80 /* R */ -#define AC_SelectCommand 0x80 /* W */ - - u_int8_t ac_transfer_blocksize; - - u_int8_t ac_alternate_status; -#define ac_device_control ac_alternate_status - u_int8_t ac_error; -#define ac_features ac_error - - u_int8_t ac_sector_count; - u_int8_t ac_sector_number; - u_int8_t ac_cylinder_low; - u_int8_t ac_cylinder_high; - u_int8_t ac_device_head; - - u_int8_t ac_status; -#define ac_command ac_status - - u_int8_t ac_reserved[3]; -}; - -#define ATA_DELAY 10000 /* 10s for a drive I/O */ - -int -umass_isdata_attach(struct umass_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - struct ata_device adev; - struct uisdata_softc *scbus; - struct isd200_config *cf; - - scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO); - sc->bus = &scbus->base; - cf = &scbus->sc_isd_config; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = 0x02; - USETW(req.wValue, 0); - USETW(req.wIndex, 2); - USETW(req.wLength, sizeof *cf); - - err = usbd_do_request(sc->sc_udev, &req, cf); - if (err) - return (EIO); - DPRINTF(("umass_wd_attach info:\n EventNotification=0x%02x " - "ExternalClock=0x%02x ATAInitTimeout=0x%02x\n" - " ATAMisc1=0x%02x ATAMajorCommand=0x%02x " - "ATAMinorCommand=0x%02x\n" - " ATAMisc2=0x%02x ATAMisc3=0x%02x\n", - cf->EventNotification, cf->ExternalClock, cf->ATAInitTimeout, - cf->ATAMisc1, cf->ATAMajorCommand, cf->ATAMinorCommand, - cf->ATAMisc2, cf->ATAMisc3)); - - memset(&adev, 0, sizeof(struct ata_device)); - adev.adev_bustype = &uisdata_bustype; - adev.adev_channel = 1; /* XXX */ - adev.adev_openings = 1; - adev.adev_drv_data = &scbus->sc_drv_data; - scbus->sc_drv_data.drive_flags = DRIVE_ATA; - scbus->sc_drv_data.chnl_softc = sc; - scbus->base.sc_child = config_found(&sc->sc_dev, &adev, uwdprint); - - return (0); -} - - -void -uisdata_bio_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; - struct ata_bio *ata_bio = priv; - int s; - - DPRINTF(("%s: residue=%d status=%d\n", __FUNCTION__, residue, status)); - - s = splbio(); - scbus->sc_ata_bio = NULL; - if (status != STATUS_CMD_OK) - ata_bio->error = ERR_DF; /* ??? */ - else - ata_bio->error = NOERROR; - ata_bio->flags |= ATA_ITSDONE; - - ata_bio->blkdone += ata_bio->nblks; - ata_bio->blkno += ata_bio->nblks; - ata_bio->bcount -= ata_bio->nbytes; - scbus->sc_skip += ata_bio->nbytes; - if (residue != 0) { - ata_bio->bcount += residue; - } else if (ata_bio->bcount > 0) { - DPRINTF(("%s: continue\n", __FUNCTION__)); - (void)uisdata_bio1(&scbus->sc_drv_data, ata_bio); /*XXX save drv*/ - splx(s); - return; - } - - if (ata_bio->flags & ATA_POLL) { - DPRINTF(("%s: wakeup %p\n", __FUNCTION__, ata_bio)); - wakeup(ata_bio); - } else { - wddone(scbus->sc_drv_data.drv_softc); - } - splx(s); -} - -int -uisdata_bio(struct ata_drive_datas *drv, struct ata_bio *ata_bio) -{ - struct umass_softc *sc = drv->chnl_softc; - struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; - - scbus->sc_skip = 0; - return (uisdata_bio1(drv, ata_bio)); -} - -int -uisdata_bio1(struct ata_drive_datas *drv, struct ata_bio *ata_bio) -{ - struct umass_softc *sc = drv->chnl_softc; - struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; - struct isd200_config *cf = &scbus->sc_isd_config; - struct ata_cmd ata; - u_int16_t cyl; - u_int8_t head, sect; - int dir; - long nbytes; - u_int nblks; - - DPRINTF(("%s\n", __FUNCTION__)); - /* XXX */ - - if (ata_bio->flags & ATA_NOSLEEP) { - printf("%s: ATA_NOSLEEP not supported\n", __FUNCTION__); - ata_bio->error = TIMEOUT; - ata_bio->flags |= ATA_ITSDONE; - return (WDC_COMPLETE); - } - - if (scbus->sc_ata_bio != NULL) { - printf("%s: multiple uisdata_bio\n", __FUNCTION__); - return (WDC_TRY_AGAIN); - } else - scbus->sc_ata_bio = ata_bio; - - if (ata_bio->flags & ATA_LBA) { - sect = (ata_bio->blkno >> 0) & 0xff; - cyl = (ata_bio->blkno >> 8) & 0xffff; - head = (ata_bio->blkno >> 24) & 0x0f; - head |= WDSD_LBA; - } else { - int blkno = ata_bio->blkno; - sect = blkno % ata_bio->lp->d_nsectors; - sect++; /* Sectors begin with 1, not 0. */ - blkno /= ata_bio->lp->d_nsectors; - head = blkno % ata_bio->lp->d_ntracks; - blkno /= ata_bio->lp->d_ntracks; - cyl = blkno; - head |= WDSD_CHS; - } - - nbytes = ata_bio->bcount; - if (ata_bio->flags & ATA_SINGLE) - nblks = 1; - else - nblks = min(ata_bio->multi, nbytes / ata_bio->lp->d_secsize); - nbytes = nblks * ata_bio->lp->d_secsize; - ata_bio->nblks = nblks; - ata_bio->nbytes = nbytes; - - memset(&ata, 0, sizeof ata); - ata.ac_signature0 = cf->ATAMajorCommand; - ata.ac_signature1 = cf->ATAMinorCommand; - ata.ac_transfer_blocksize = 1; - ata.ac_sector_count = nblks; - ata.ac_sector_number = sect; - ata.ac_cylinder_high = cyl >> 8; - ata.ac_cylinder_low = cyl; - ata.ac_device_head = head; - ata.ac_register_select = AC_SelectSectorCount | AC_SelectSectorNumber | - AC_SelectCylinderLow | AC_SelectCylinderHigh | AC_SelectDeviceHead | - AC_SelectCommand; - - dir = DIR_NONE; - if (ata_bio->bcount != 0) { - if (ata_bio->flags & ATA_READ) - dir = DIR_IN; - else - dir = DIR_OUT; - } - - if (ata_bio->flags & ATA_READ) { - ata.ac_command = WDCC_READ; - } else { - ata.ac_command = WDCC_WRITE; - } - DPRINTF(("%s: bno=%d LBA=%d cyl=%d head=%d sect=%d count=%d multi=%d\n", - __FUNCTION__, ata_bio->blkno, - (ata_bio->flags & ATA_LBA) != 0, cyl, head, sect, - ata.ac_sector_count, ata_bio->multi)); - DPRINTF((" data=%p bcount=%ld, drive=%d\n", ata_bio->databuf, - ata_bio->bcount, drv->drive)); - sc->sc_methods->wire_xfer(sc, drv->drive, &ata, sizeof ata, - ata_bio->databuf + scbus->sc_skip, nbytes, - dir, ATA_DELAY, uisdata_bio_cb, ata_bio); - - while (ata_bio->flags & ATA_POLL) { - DPRINTF(("%s: tsleep %p\n", __FUNCTION__, ata_bio)); - if (tsleep(ata_bio, PZERO, "uisdatabl", 0)) { - ata_bio->error = TIMEOUT; - ata_bio->flags |= ATA_ITSDONE; - return (WDC_COMPLETE); - } - } - - return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED; -} - -void -uisdata_reset_channel(struct ata_drive_datas *drv) -{ - DPRINTFN(-1,("%s\n", __FUNCTION__)); - /* XXX what? */ -} - -void -uisdata_exec_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - struct wdc_command *cmd = priv; - - DPRINTF(("%s: status=%d\n", __FUNCTION__, status)); - if (status != STATUS_CMD_OK) - cmd->flags |= AT_DF; /* XXX */ - cmd->flags |= AT_DONE; - if (cmd->flags & (AT_POLL | AT_WAIT)) { - DPRINTF(("%s: wakeup %p\n", __FUNCTION__, cmd)); - wakeup(cmd); - } -} - -int -uisdata_exec_command(struct ata_drive_datas *drv, struct wdc_command *cmd) -{ - struct umass_softc *sc = drv->chnl_softc; - struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; - struct isd200_config *cf = &scbus->sc_isd_config; - int dir; - struct ata_cmd ata; - - DPRINTF(("%s\n", __FUNCTION__)); - DPRINTF((" r_command=0x%02x timeout=%d flags=0x%x bcount=%d\n", - cmd->r_command, cmd->timeout, cmd->flags, cmd->bcount)); - - dir = DIR_NONE; - if (cmd->bcount != 0) { - if (cmd->flags & AT_READ) - dir = DIR_IN; - else - dir = DIR_OUT; - } - - if (cmd->bcount > UMASS_MAX_TRANSFER_SIZE) { - printf("uisdata_exec_command: large datalen %d\n", cmd->bcount); - cmd->flags |= AT_ERROR; - goto done; - } - - memset(&ata, 0, sizeof ata); - ata.ac_signature0 = cf->ATAMajorCommand; - ata.ac_signature1 = cf->ATAMinorCommand; - ata.ac_transfer_blocksize = 1; - - switch (cmd->r_command) { - case WDCC_IDENTIFY: - ata.ac_register_select |= AC_SelectCommand; - ata.ac_command = WDCC_IDENTIFY; - break; - default: - printf("uisdata_exec_command: bad command 0x%02x\n", - cmd->r_command); - cmd->flags |= AT_ERROR; - goto done; - } - - DPRINTF(("%s: execute ATA command 0x%02x, drive=%d\n", __FUNCTION__, - ata.ac_command, drv->drive)); - sc->sc_methods->wire_xfer(sc, drv->drive, &ata, - sizeof ata, cmd->data, cmd->bcount, dir, - cmd->timeout, uisdata_exec_cb, cmd); - if (cmd->flags & (AT_POLL | AT_WAIT)) { -#if 0 - if (cmd->flags & AT_POLL) - printf("%s: AT_POLL not supported\n", __FUNCTION__); -#endif - DPRINTF(("%s: tsleep %p\n", __FUNCTION__, cmd)); - if (tsleep(cmd, PZERO, "uisdataex", 0)) { - cmd->flags |= AT_ERROR; - goto done; - } - } - -done: - return (WDC_COMPLETE); -} - -int -uisdata_addref(struct ata_drive_datas *drv) -{ - DPRINTF(("%s\n", __FUNCTION__)); - /* Nothing to do */ - return (0); -} - -void -uisdata_delref(struct ata_drive_datas *drv) -{ - DPRINTF(("%s\n", __FUNCTION__)); - /* Nothing to do */ -} - -void -uisdata_kill_pending(struct ata_drive_datas *drv) -{ - struct umass_softc *sc = drv->chnl_softc; - struct uisdata_softc *scbus = (struct uisdata_softc *)sc->bus; - struct ata_bio *ata_bio = scbus->sc_ata_bio; - - DPRINTFN(-1,("%s\n", __FUNCTION__)); - - if (ata_bio == NULL) - return; - scbus->sc_ata_bio = NULL; - ata_bio->flags |= ATA_ITSDONE; - ata_bio->error = ERR_NODEV; - ata_bio->r_error = WDCE_ABRT; - wddone(scbus->sc_drv_data.drv_softc); -} - -int -uisdata_get_params(struct ata_drive_datas *drvp, u_int8_t flags, - struct ataparams *prms) -{ - char tb[DEV_BSIZE]; - struct wdc_command wdc_c; - -#if BYTE_ORDER == LITTLE_ENDIAN - int i; - u_int16_t *p; -#endif - - DPRINTF(("%s\n", __FUNCTION__)); - - memset(tb, 0, DEV_BSIZE); - memset(prms, 0, sizeof(struct ataparams)); - memset(&wdc_c, 0, sizeof(struct wdc_command)); - - wdc_c.r_command = WDCC_IDENTIFY; - wdc_c.timeout = 1000; /* 1s */ - wdc_c.flags = AT_READ | flags; - wdc_c.data = tb; - wdc_c.bcount = DEV_BSIZE; - if (uisdata_exec_command(drvp, &wdc_c) != WDC_COMPLETE) { - DPRINTF(("uisdata_get_parms: wdc_exec_command failed\n")); - return (CMD_AGAIN); - } - if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { - DPRINTF(("uisdata_get_parms: wdc_c.flags=0x%x\n", - wdc_c.flags)); - return (CMD_ERR); - } else { - /* Read in parameter block. */ - memcpy(prms, tb, sizeof(struct ataparams)); -#if BYTE_ORDER == LITTLE_ENDIAN - /* XXX copied from ata.c */ - /* - * Shuffle string byte order. - * ATAPI Mitsumi and NEC drives don't need this. - */ - if ((prms->atap_config & WDC_CFG_ATAPI_MASK) == - WDC_CFG_ATAPI && - ((prms->atap_model[0] == 'N' && - prms->atap_model[1] == 'E') || - (prms->atap_model[0] == 'F' && - prms->atap_model[1] == 'X'))) - return 0; - for (i = 0; i < sizeof(prms->atap_model); i += 2) { - p = (u_short *)(prms->atap_model + i); - *p = ntohs(*p); - } - for (i = 0; i < sizeof(prms->atap_serial); i += 2) { - p = (u_short *)(prms->atap_serial + i); - *p = ntohs(*p); - } - for (i = 0; i < sizeof(prms->atap_revision); i += 2) { - p = (u_short *)(prms->atap_revision + i); - *p = ntohs(*p); - } -#endif - return CMD_OK; - } -} - - -/* XXX join with wdc.c routine? */ -int -uwdprint(void *aux, const char *pnp) -{ - //struct ata_device *adev = aux; - if (pnp) - printf("wd at %s", pnp); -#if 0 - printf(" channel %d drive %d", adev->adev_channel, - adev->adev_drv_data->drive); -#endif - return (UNCONF); -} - - -#if 0 - -int umass_wd_attach(struct umass_softc *); - -#if NWD > 0 - case UMASS_CPROTO_ISD_ATA: - return (umass_wd_attach(sc)); -#endif - -#endif diff --git a/sys/dev/usb/umass_isdata.h b/sys/dev/usb/umass_isdata.h deleted file mode 100644 index 665922192a4..00000000000 --- a/sys/dev/usb/umass_isdata.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $NetBSD: umass_isdata.h,v 1.1 2001/12/24 13:43:25 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -int umass_isdata_attach(struct umass_softc *sc); diff --git a/sys/dev/usb/umass_quirks.c b/sys/dev/usb/umass_quirks.c deleted file mode 100644 index 5cf42653814..00000000000 --- a/sys/dev/usb/umass_quirks.c +++ /dev/null @@ -1,333 +0,0 @@ -/* $OpenBSD: umass_quirks.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umass_quirks.c,v 1.13 2002/04/22 12:48:40 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by MAEKAWA Masahide (gehenna@NetBSD.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/buf.h> - -#if defined(__NetBSD__) -#include <dev/scsipi/scsipi_all.h> /* for scsiconf.h below */ -#include <dev/scsipi/scsiconf.h> /* for quirks defines */ -#endif - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdevs.h> - -#include <dev/usb/umassvar.h> -#include <dev/usb/umass_quirks.h> - -Static usbd_status umass_init_insystem(struct umass_softc *); -Static usbd_status umass_init_shuttle(struct umass_softc *); - -Static void umass_fixup_sony(struct umass_softc *); -Static void umass_fixup_yedata(struct umass_softc *); - -Static const struct umass_quirk umass_quirks[] = { - { { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_NO_START_STOP, - PQUIRK_NOTUR | PQUIRK_NOSENSE, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE }, - UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI, - UMASS_QUIRK_NO_START_STOP, - PQUIRK_NOTUR, - UMATCH_VENDOR_PRODUCT, - umass_init_insystem, NULL - }, - - { { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - 0, - PQUIRK_NOTUR, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP250 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - 0, - PQUIRK_NOTUR, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM }, - UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - - { { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - 0, - PQUIRK_NOMODESENSE | PQUIRK_NODOORLOCK | PQUIRK_NOBIGMODESENSE, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_WRONG_CSWSIG, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MD2 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - 0, - PQUIRK_NOMODESENSE, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MD1II }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP, - PQUIRK_NOMODESENSE, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - - { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB }, - UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI, - UMASS_QUIRK_NO_START_STOP, - PQUIRK_NOTUR, - UMATCH_VENDOR_PRODUCT, - umass_init_shuttle, NULL - }, - - { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC }, - UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI, - UMASS_QUIRK_NO_START_STOP, - PQUIRK_NOTUR, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - - { { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_FORCE_SHORT_INQUIRY, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, umass_fixup_sony - }, - - { { USB_VENDOR_SONY, USB_PRODUCT_ANY }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_RBC, - 0, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, umass_fixup_sony - }, - - { { USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - 0, - PQUIRK_NOMODESENSE, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO }, - UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI, - UMASS_QUIRK_FORCE_SHORT_INQUIRY, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - - { { USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UFI, - UMASS_QUIRK_RS_NO_CLEAR_UA, - PQUIRK_NOMODESENSE, - UMATCH_VENDOR_PRODUCT_REV, - NULL, umass_fixup_yedata - }, - - { { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_S304 }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_X }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - { { USB_VENDOR_PEN, USB_PRODUCT_PEN_USBDISK }, - UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, - UMASS_QUIRK_NO_MAX_LUN | UMASS_QUIRK_NO_START_STOP, - 0, - UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, - NULL, NULL - }, - - /* InSystem Design ATA over USB devices */ - { { USB_VENDOR_ATI, USB_PRODUCT_ATI2_205 }, - UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI }, - UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_DRIVEV2_5 }, - UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ADAPTERV2 }, - UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, - { { USB_VENDOR_SONY, USB_PRODUCT_SONY_DRIVEV2 }, - UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, - 0, - 0, - UMATCH_VENDOR_PRODUCT, - NULL, NULL - }, -}; - -const struct umass_quirk * -umass_lookup(u_int16_t vendor, u_int16_t product) -{ - return ((const struct umass_quirk *) - usb_lookup(umass_quirks, vendor, product)); -} - -Static usbd_status -umass_init_insystem(struct umass_softc *sc) -{ - usbd_status err; - - err = usbd_set_interface(sc->sc_iface, 1); - if (err) { - DPRINTF(UDMASS_USB, - ("%s: could not switch to Alt Interface 1\n", - USBDEVNAME(sc->sc_dev))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -Static usbd_status -umass_init_shuttle(struct umass_softc *sc) -{ - usb_device_request_t req; - u_int8_t status[2]; - - /* The Linux driver does this */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = 1; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, sizeof(status)); - - return (usbd_do_request(sc->sc_udev, &req, &status)); -} - -Static void -umass_fixup_sony(struct umass_softc *sc) -{ - usb_interface_descriptor_t *id; - - id = usbd_get_interface_descriptor(sc->sc_iface); - if (id->bInterfaceSubClass == 0xff) { - sc->sc_cmd = UMASS_CPROTO_RBC; - } -} - -Static void -umass_fixup_yedata(struct umass_softc *sc) -{ - usb_device_descriptor_t *dd; - - dd = usbd_get_device_descriptor(sc->sc_udev); - - /* - * Revisions < 1.28 do not handle the interrupt endpoint very well. - */ - if (UGETW(dd->bcdDevice) < 0x128) - sc->sc_wire = UMASS_WPROTO_CBI; - else - sc->sc_wire = UMASS_WPROTO_CBI_I; - - /* - * Revisions < 1.28 do not have the TEST UNIT READY command - * Revisions == 1.28 have a broken TEST UNIT READY - */ - if (UGETW(dd->bcdDevice) <= 0x128) - sc->sc_busquirks |= PQUIRK_NOTUR; -} diff --git a/sys/dev/usb/umass_quirks.h b/sys/dev/usb/umass_quirks.h deleted file mode 100644 index 5348583ba34..00000000000 --- a/sys/dev/usb/umass_quirks.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $OpenBSD: umass_quirks.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umass_quirks.h,v 1.3 2001/12/29 13:46:23 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by MAEKAWA Masahide (gehenna@NetBSD.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _DEV_USB_UMASS_QUIRKS_H_ -#define _DEV_USB_UMASS_QUIRKS_H_ - -typedef usbd_status (*umass_init_quirk)(struct umass_softc *); -typedef void (*umass_fixup_quirk)(struct umass_softc *); - -struct umass_quirk { - struct usb_devno uq_dev; - - u_int8_t uq_wire; - u_int8_t uq_cmd; - u_int32_t uq_flags; - u_int32_t uq_busquirks; - int uq_match; - - umass_init_quirk uq_init; - umass_fixup_quirk uq_fixup; -}; - -const struct umass_quirk *umass_lookup(u_int16_t, u_int16_t); - -#endif /* _DEV_USB_UMASS_QUIRKS_H_ */ diff --git a/sys/dev/usb/umass_scsi.c b/sys/dev/usb/umass_scsi.c deleted file mode 100644 index 2c1f1c2ba50..00000000000 --- a/sys/dev/usb/umass_scsi.c +++ /dev/null @@ -1,488 +0,0 @@ -/* $OpenBSD: umass_scsi.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* - * Copyright (c) 2001 Nathan L. Binkert - * All rights reserved. - * - * Permission to redistribute, use, copy, and modify this software - * without fee is hereby granted, provided that the following - * conditions are met: - * - * 1. This entire notice is included in all source code copies of any - * software which is or includes a copy or modification of this - * software. - * 2. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "atapiscsi.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/buf.h> -#include <sys/device.h> -#include <sys/ioctl.h> -#include <sys/malloc.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdevs.h> - -#include <dev/usb/umassvar.h> -#include <dev/usb/umass_scsi.h> - -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> -#include <scsi/scsi_disk.h> -#include <machine/bus.h> - -struct umass_scsi_softc { - struct umassbus_softc base; - struct scsi_link sc_link; - struct scsi_adapter sc_adapter; - - usbd_status sc_sync_status; - struct scsi_sense sc_sense_cmd; -}; - - -#define SHORT_INQUIRY_LENGTH 36 /* XXX */ - -#define UMASS_SCSIID_HOST 0x00 -#define UMASS_SCSIID_DEVICE 0x01 - -#define UMASS_ATAPI_DRIVE 0 - -int umass_scsi_cmd(struct scsi_xfer *); -void umass_scsi_minphys(struct buf *); -int umass_scsi_ioctl(struct scsi_link *, u_long cmd, caddr_t addrp, int flag, - struct proc *p); - -void umass_scsi_cb(struct umass_softc *sc, void *priv, int residue, - int status); -void umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue, - int status); -struct umass_scsi_softc *umass_scsi_setup(struct umass_softc *); - -struct scsi_device umass_scsi_dev = { NULL, NULL, NULL, NULL, }; - -int -umass_scsi_attach(struct umass_softc *sc) -{ - struct umass_scsi_softc *scbus; - - scbus = umass_scsi_setup(sc); - scbus->sc_link.adapter_target = UMASS_SCSIID_HOST; - scbus->sc_link.luns = sc->maxlun + 1; - - scbus->sc_adapter.scsi_cmd = umass_scsi_cmd; - scbus->sc_adapter.scsi_minphys = umass_scsi_minphys; - scbus->sc_adapter.ioctl = umass_scsi_ioctl; - - DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n" - "sc = 0x%x, scbus = 0x%x\n", - USBDEVNAME(sc->sc_dev), sc, scbus)); - - scbus->base.sc_child = - config_found((struct device *)sc, &scbus->sc_link, scsiprint); - - return (0); -} - -#if NATAPISCSI > 0 -int -umass_atapi_attach(struct umass_softc *sc) -{ - struct umass_scsi_softc *scbus; - - scbus = umass_scsi_setup(sc); - scbus->sc_link.adapter_target = UMASS_SCSIID_HOST; - scbus->sc_link.luns = 1; - - scbus->sc_adapter.scsi_cmd = umass_scsi_cmd; - scbus->sc_adapter.scsi_minphys = umass_scsi_minphys; - scbus->sc_adapter.ioctl = umass_scsi_ioctl; - - DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n" - "sc = 0x%x, scbus = 0x%x\n", - USBDEVNAME(sc->sc_dev), sc, scbus)); - - scbus->base.sc_child = - config_found((struct device *)sc, &scbus->sc_link, scsiprint); - - return (0); -} -#endif - -struct umass_scsi_softc * -umass_scsi_setup(struct umass_softc *sc) -{ - struct umass_scsi_softc *scbus; - - scbus = malloc(sizeof(struct umass_scsi_softc), M_DEVBUF, M_WAITOK); - memset(&scbus->sc_link, 0, sizeof(struct scsi_link)); - memset(&scbus->sc_adapter, 0, sizeof(struct scsi_adapter)); - - sc->bus = (struct umassbus_softc *)scbus; - - scbus->sc_link.adapter_buswidth = 2; - scbus->sc_link.openings = 1; - scbus->sc_link.flags &= ~SDEV_ATAPI; - scbus->sc_link.device = &umass_scsi_dev; - scbus->sc_link.adapter = &scbus->sc_adapter; - scbus->sc_link.adapter_softc = sc; - scbus->sc_link.openings = 1; - - return (scbus); -} - -int -umass_scsi_cmd(struct scsi_xfer *xs) -{ - struct scsi_link *sc_link = xs->sc_link; - struct umass_softc *sc = sc_link->adapter_softc; - struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus; - - struct scsi_generic *cmd, trcmd; - int cmdlen, dir; - -#ifdef UMASS_DEBUG - microtime(&sc->tv); -#endif - - memset(&trcmd, 0, sizeof(trcmd)); - - DIF(UDMASS_UPPER, sc_link->flags |= SCSIDEBUG_LEVEL); - - DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: at %lu.%06lu: %d:%d " - "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n", - USBDEVNAME(sc->sc_dev), sc->tv.tv_sec, sc->tv.tv_usec, - sc_link->target, sc_link->lun, xs, xs->cmd->opcode, - xs->datalen, sc_link->quirks, xs->flags & SCSI_POLL)); - -#if defined(USB_DEBUG) && defined(SCSIDEBUG) - if (umassdebug & UDMASS_SCSI) - show_scsi_xs(xs); - else if (umassdebug & ~UDMASS_CMD) - show_scsi_cmd(xs); -#endif - - if (sc->sc_dying) { - xs->error = XS_DRIVER_STUFFUP; - goto done; - } - -#if defined(UMASS_DEBUG) - if (sc_link->target != UMASS_SCSIID_DEVICE) { - DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n", - USBDEVNAME(sc->sc_dev), sc_link->target)); - xs->error = XS_DRIVER_STUFFUP; - goto done; - } -#endif - - cmd = xs->cmd; - cmdlen = xs->cmdlen; - - if (cmd->opcode == MODE_SENSE && - (sc_link->quirks & SDEV_NOMODESENSE)) { - xs->error = XS_TIMEOUT; - goto done; - } - - if (cmd->opcode == START_STOP && - (sc->sc_quirks & UMASS_QUIRK_NO_START_STOP)) { - xs->error = XS_NOERROR; - goto done; - } - - if (cmd->opcode == INQUIRY && - (sc->sc_quirks & UMASS_QUIRK_FORCE_SHORT_INQUIRY)) { - memcpy(&trcmd, cmd, sizeof(trcmd)); - trcmd.bytes[4] = SHORT_INQUIRY_LENGTH; - cmd = &trcmd; - } - - dir = DIR_NONE; - if (xs->datalen) { - switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { - case SCSI_DATA_IN: - dir = DIR_IN; - break; - case SCSI_DATA_OUT: - dir = DIR_OUT; - break; - } - } - - if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) { - printf("umass_cmd: large datalen, %d\n", xs->datalen); - xs->error = XS_DRIVER_STUFFUP; - goto done; - } - - if (xs->flags & SCSI_POLL) { - /* Use sync transfer. XXX Broken! */ - DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir)); - sc->sc_xfer_flags = USBD_SYNCHRONOUS; - scbus->sc_sync_status = USBD_INVAL; - sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen, - xs->data, xs->datalen, dir, - xs->timeout, 0, xs); - sc->sc_xfer_flags = 0; - DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n", - scbus->sc_sync_status)); - switch (scbus->sc_sync_status) { - case USBD_NORMAL_COMPLETION: - xs->error = XS_NOERROR; - break; - case USBD_TIMEOUT: - xs->error = XS_TIMEOUT; - break; - default: - xs->error = XS_DRIVER_STUFFUP; - break; - } - goto done; - } else { - DPRINTF(UDMASS_SCSI, - ("umass_scsi_cmd: async dir=%d, cmdlen=%d" - " datalen=%d\n", - dir, cmdlen, xs->datalen)); - sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen, - xs->data, xs->datalen, dir, - xs->timeout, umass_scsi_cb, xs); - return (SUCCESSFULLY_QUEUED); - } - - /* Return if command finishes early. */ - done: - xs->flags |= ITSDONE; - - scsi_done(xs); - if (xs->flags & SCSI_POLL) - return (COMPLETE); - else - return (SUCCESSFULLY_QUEUED); -} - -void -umass_scsi_minphys(struct buf *bp) -{ - if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE) - bp->b_bcount = UMASS_MAX_TRANSFER_SIZE; - - minphys(bp); -} - -int -umass_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t arg, int flag, - struct proc *p) -{ -#if 0 - struct umass_softc *sc = link->adapter_softc; -#endif - - switch (cmd) { -#if 0 - case SCBUSIORESET: - ccb->ccb_h.status = CAM_REQ_INPROG; - umass_reset(sc, umass_cam_cb, (void *) ccb); - return (0); -#endif - default: - return (ENOTTY); - } -} - -void -umass_scsi_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus; - struct scsi_xfer *xs = priv; - struct scsi_link *link = xs->sc_link; - int cmdlen; - int s; -#ifdef UMASS_DEBUG - struct timeval tv; - u_int delta; - microtime(&tv); - delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + - tv.tv_usec - sc->tv.tv_usec; -#endif - - DPRINTF(UDMASS_CMD, - ("umass_scsi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d" - " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue, - status)); - - xs->resid = residue; - - switch (status) { - case STATUS_CMD_OK: - xs->error = XS_NOERROR; - break; - - case STATUS_CMD_UNKNOWN: - /* we can't issue REQUEST SENSE */ - if (xs->sc_link->quirks & PQUIRK_NOSENSE) { - /* - * If no residue and no other USB error, - * command succeeded. - */ - if (residue == 0) { - xs->error = XS_NOERROR; - break; - } - - /* - * Some devices return a short INQUIRY - * response, omitting response data from the - * "vendor specific data" on... - */ - if (xs->cmd->opcode == INQUIRY && - residue < xs->datalen) { - xs->error = XS_NOERROR; - break; - } - - xs->error = XS_DRIVER_STUFFUP; - break; - } - /* FALLTHROUGH */ - case STATUS_CMD_FAILED: - /* fetch sense data */ - memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd)); - scbus->sc_sense_cmd.opcode = REQUEST_SENSE; - scbus->sc_sense_cmd.byte2 = link->lun << SCSI_CMD_LUN_SHIFT; - scbus->sc_sense_cmd.length = sizeof(xs->sense); - - cmdlen = sizeof(scbus->sc_sense_cmd); - if (sc->sc_cmd == UMASS_CPROTO_UFI) /* XXX */ - cmdlen = UFI_COMMAND_LENGTH; - sc->sc_methods->wire_xfer(sc, link->lun, - &scbus->sc_sense_cmd, cmdlen, - &xs->sense, sizeof(xs->sense), - DIR_IN, xs->timeout, - umass_scsi_sense_cb, xs); - return; - - case STATUS_WIRE_FAILED: - xs->error = XS_RESET; - break; - - default: - panic("%s: Unknown status %d in umass_scsi_cb\n", - USBDEVNAME(sc->sc_dev), status); - } - - DPRINTF(UDMASS_CMD,("umass_scsi_cb: at %lu.%06lu: return error=%d, " - "status=0x%x resid=%d\n", - tv.tv_sec, tv.tv_usec, - xs->error, xs->status, xs->resid)); - - s = splbio(); - scsi_done(xs); - splx(s); -} - -/* - * Finalise a completed autosense operation - */ -void -umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue, - int status) -{ - struct scsi_xfer *xs = priv; - int s; - - DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: xs=%p residue=%d " - "status=%d\n", xs, residue, status)); - - switch (status) { - case STATUS_CMD_OK: - case STATUS_CMD_UNKNOWN: - /* getting sense data succeeded */ - if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen || - (sc->sc_quirks & UMASS_QUIRK_RS_NO_CLEAR_UA /* XXX */))) { - /* - * Some drivers return SENSE errors even after INQUIRY. - * The upper layer doesn't like that. - */ - xs->error = XS_NOERROR; - break; - } - /* XXX look at residue */ - if (residue == 0 || residue == 14)/* XXX */ - xs->error = XS_SENSE; - else - xs->error = XS_SHORTSENSE; - break; - default: - DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", - USBDEVNAME(sc->sc_dev), status)); - xs->error = XS_DRIVER_STUFFUP; - break; - } - - xs->status |= ITSDONE; - - DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: return xs->error=%d, " - "xs->status=0x%x xs->resid=%d\n", xs->error, xs->status, - xs->resid)); - - s = splbio(); - scsi_done(xs); - splx(s); -} diff --git a/sys/dev/usb/umass_scsi.h b/sys/dev/usb/umass_scsi.h deleted file mode 100644 index 9237f5d364c..00000000000 --- a/sys/dev/usb/umass_scsi.h +++ /dev/null @@ -1,31 +0,0 @@ -/* $OpenBSD: umass_scsi.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* - * Copyright (c) 2001 Nathan L. Binkert - * All rights reserved. - * - * Permission to redistribute, use, copy, and modify this software - * without fee is hereby granted, provided that the following - * conditions are met: - * - * 1. This entire notice is included in all source code copies of any - * software which is or includes a copy or modification of this - * software. - * 2. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int umass_scsi_attach(struct umass_softc *sc); -int umass_atapi_attach(struct umass_softc *sc); diff --git a/sys/dev/usb/umass_scsipi.c b/sys/dev/usb/umass_scsipi.c deleted file mode 100644 index a37fb3cb425..00000000000 --- a/sys/dev/usb/umass_scsipi.c +++ /dev/null @@ -1,636 +0,0 @@ -/* $NetBSD: umass_scsipi.c,v 1.4 2001/12/31 12:15:21 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: umass_scsipi.c,v 1.4 2001/12/31 12:15:21 augustss Exp $"); - -#include "atapibus.h" -#include "scsibus.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/buf.h> -#include <sys/device.h> -#include <sys/ioctl.h> -#include <sys/malloc.h> - -/* SCSI & ATAPI */ -#include <sys/scsiio.h> -#include <dev/scsipi/scsi_all.h> -#include <dev/scsipi/scsipi_all.h> -#include <dev/scsipi/scsiconf.h> - -#include <dev/scsipi/atapiconf.h> - -#include <dev/scsipi/scsipi_disk.h> -#include <dev/scsipi/scsi_disk.h> -#include <dev/scsipi/scsi_changer.h> - -#include <dev/scsipi/atapi_disk.h> - -#include <sys/disk.h> /* XXX */ -#include <dev/scsipi/sdvar.h> /* XXX */ - -/* USB */ -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdevs.h> - -#include <dev/usb/umassvar.h> -#include <dev/usb/umass_scsipi.h> - -struct umass_scsipi_softc { - struct umassbus_softc base; - - struct atapi_adapter sc_atapi_adapter; -#define sc_adapter sc_atapi_adapter._generic - struct scsipi_channel sc_channel; - usbd_status sc_sync_status; - struct scsipi_sense sc_sense_cmd; -}; - - -#define SHORT_INQUIRY_LENGTH 36 /* XXX */ - -#define UMASS_SCSIID_HOST 0x00 -#define UMASS_SCSIID_DEVICE 0x01 - -#define UMASS_ATAPI_DRIVE 0 - -Static void umass_scsipi_request(struct scsipi_channel *, - scsipi_adapter_req_t, void *); -Static void umass_scsipi_minphys(struct buf *bp); -Static int umass_scsipi_ioctl(struct scsipi_channel *, u_long, - caddr_t, int, usb_proc_ptr); -Static int umass_scsipi_getgeom(struct scsipi_periph *periph, - struct disk_parms *, u_long sectors); - -Static void umass_scsipi_cb(struct umass_softc *sc, void *priv, - int residue, int status); -Static void umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, - int residue, int status); - -Static struct umass_scsipi_softc *umass_scsipi_setup(struct umass_softc *sc); - -Static int scsipiprint(void *aux, const char *pnp); - -#if NATAPIBUS > 0 -Static void umass_atapi_probe_device(struct atapibus_softc *, int); - -const struct scsipi_bustype umass_atapi_bustype = { - SCSIPI_BUSTYPE_ATAPI, - atapi_scsipi_cmd, - atapi_interpret_sense, - atapi_print_addr, - scsi_kill_pending, -}; -#endif - - -#if NSCSIBUS > 0 -int -umass_scsi_attach(struct umass_softc *sc) -{ - struct umass_scsipi_softc *scbus; - - scbus = umass_scsipi_setup(sc); - - scbus->sc_channel.chan_bustype = &scsi_bustype; - scbus->sc_channel.chan_ntargets = UMASS_SCSIID_DEVICE + 1; - scbus->sc_channel.chan_nluns = sc->maxlun + 1; - scbus->sc_channel.chan_id = UMASS_SCSIID_HOST; - DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n", - USBDEVNAME(sc->sc_dev))); - scbus->base.sc_child = - config_found(&sc->sc_dev, &scbus->sc_channel, scsipiprint); - - return (0); -} -#endif - -#if NATAPIBUS > 0 -int -umass_atapi_attach(struct umass_softc *sc) -{ - struct umass_scsipi_softc *scbus; - - scbus = umass_scsipi_setup(sc); - scbus->sc_atapi_adapter.atapi_probe_device = umass_atapi_probe_device; - - scbus->sc_channel.chan_bustype = &umass_atapi_bustype; - scbus->sc_channel.chan_ntargets = 2; - scbus->sc_channel.chan_nluns = 1; - - scbus->sc_channel.chan_defquirks |= sc->sc_busquirks; - DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n", - USBDEVNAME(sc->sc_dev))); - scbus->base.sc_child = - config_found(&sc->sc_dev, &scbus->sc_channel, scsipiprint); - - return (0); -} -#endif - -Static struct umass_scsipi_softc * -umass_scsipi_setup(struct umass_softc *sc) -{ - struct umass_scsipi_softc *scbus; - - scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO); - sc->bus = &scbus->base; - - /* Only use big commands for USB SCSI devices. */ - sc->sc_busquirks |= PQUIRK_ONLYBIG; - - /* Fill in the adapter. */ - memset(&scbus->sc_adapter, 0, sizeof(scbus->sc_adapter)); - scbus->sc_adapter.adapt_dev = &sc->sc_dev; - scbus->sc_adapter.adapt_nchannels = 1; - scbus->sc_adapter.adapt_request = umass_scsipi_request; - scbus->sc_adapter.adapt_minphys = umass_scsipi_minphys; - scbus->sc_adapter.adapt_ioctl = umass_scsipi_ioctl; - scbus->sc_adapter.adapt_getgeom = umass_scsipi_getgeom; - - /* Fill in the channel. */ - memset(&scbus->sc_channel, 0, sizeof(scbus->sc_channel)); - scbus->sc_channel.chan_adapter = &scbus->sc_adapter; - scbus->sc_channel.chan_channel = 0; - scbus->sc_channel.chan_flags = SCSIPI_CHAN_OPENINGS; - scbus->sc_channel.chan_openings = 1; - scbus->sc_channel.chan_max_periph = 1; - scbus->sc_channel.chan_defquirks |= sc->sc_busquirks; - - return (scbus); -} - -Static int -scsipiprint(void *aux, const char *pnp) -{ - struct scsipi_channel *chan = aux; - - if (chan->chan_bustype->bustype_type == SCSIPI_BUSTYPE_SCSI) { -#if NSCSIBUS > 0 - return (scsiprint(aux, pnp)); -#else - if (pnp) - printf("scsibus at %s", pnp); - return (UNCONF); -#endif - } else { -#if NATAPIBUS > 0 - return (atapiprint(aux, pnp)); -#else - if (pnp) - printf("atapibus at %s", pnp); - return (UNCONF); -#endif - } -} - -Static void -umass_scsipi_request(struct scsipi_channel *chan, - scsipi_adapter_req_t req, void *arg) -{ - struct scsipi_adapter *adapt = chan->chan_adapter; - struct scsipi_periph *periph; - struct scsipi_xfer *xs; - struct umass_softc *sc = (void *)adapt->adapt_dev; - struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus; - struct scsipi_generic *cmd, trcmd; - int cmdlen; - int dir; -#ifdef UMASS_DEBUG - microtime(&sc->tv); -#endif - switch(req) { - case ADAPTER_REQ_RUN_XFER: - xs = arg; - periph = xs->xs_periph; - DIF(UDMASS_UPPER, periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS); - - DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: at %lu.%06lu: %d:%d " - "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n", - USBDEVNAME(sc->sc_dev), sc->tv.tv_sec, sc->tv.tv_usec, - periph->periph_target, periph->periph_lun, - xs, xs->cmd->opcode, xs->datalen, - periph->periph_quirks, xs->xs_control & XS_CTL_POLL)); -#if defined(USB_DEBUG) && defined(SCSIPI_DEBUG) - if (umassdebug & UDMASS_SCSI) - show_scsipi_xs(xs); - else if (umassdebug & ~UDMASS_CMD) - show_scsipi_cmd(xs); -#endif - - if (sc->sc_dying) { - xs->error = XS_DRIVER_STUFFUP; - goto done; - } - -#ifdef UMASS_DEBUG - if (chan->chan_bustype->bustype_type == SCSIPI_BUSTYPE_ATAPI ? - periph->periph_target != UMASS_ATAPI_DRIVE : - periph->periph_target != UMASS_SCSIID_DEVICE) { - DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n", - USBDEVNAME(sc->sc_dev), - periph->periph_target)); - xs->error = XS_DRIVER_STUFFUP; - goto done; - } -#endif - - cmd = xs->cmd; - cmdlen = xs->cmdlen; - - /* XXX should use transform */ - - if (cmd->opcode == START_STOP && - (sc->sc_quirks & UMASS_QUIRK_NO_START_STOP)) { - /*printf("%s: START_STOP\n", USBDEVNAME(sc->sc_dev));*/ - xs->error = XS_NOERROR; - goto done; - } - - if (cmd->opcode == INQUIRY && - (sc->sc_quirks & UMASS_QUIRK_FORCE_SHORT_INQUIRY)) { - /* - * some drives wedge when asked for full inquiry - * information. - */ - memcpy(&trcmd, cmd, sizeof trcmd); - trcmd.bytes[4] = SHORT_INQUIRY_LENGTH; - cmd = &trcmd; - } - - dir = DIR_NONE; - if (xs->datalen) { - switch (xs->xs_control & - (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) { - case XS_CTL_DATA_IN: - dir = DIR_IN; - break; - case XS_CTL_DATA_OUT: - dir = DIR_OUT; - break; - } - } - - if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) { - printf("umass_cmd: large datalen, %d\n", xs->datalen); - xs->error = XS_DRIVER_STUFFUP; - goto done; - } - - if (xs->xs_control & XS_CTL_POLL) { - /* Use sync transfer. XXX Broken! */ - DPRINTF(UDMASS_SCSI, - ("umass_scsi_cmd: sync dir=%d\n", dir)); - sc->sc_xfer_flags = USBD_SYNCHRONOUS; - scbus->sc_sync_status = USBD_INVAL; - sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd, - cmdlen, xs->data, - xs->datalen, dir, - xs->timeout, 0, xs); - sc->sc_xfer_flags = 0; - DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n", - scbus->sc_sync_status)); - switch (scbus->sc_sync_status) { - case USBD_NORMAL_COMPLETION: - xs->error = XS_NOERROR; - break; - case USBD_TIMEOUT: - xs->error = XS_TIMEOUT; - break; - default: - xs->error = XS_DRIVER_STUFFUP; - break; - } - goto done; - } else { - DPRINTF(UDMASS_SCSI, - ("umass_scsi_cmd: async dir=%d, cmdlen=%d" - " datalen=%d\n", - dir, cmdlen, xs->datalen)); - sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd, - cmdlen, xs->data, - xs->datalen, dir, - xs->timeout, - umass_scsipi_cb, xs); - return; - } - - /* Return if command finishes early. */ - done: - scsipi_done(xs); - return; - default: - /* Not supported, nothing to do. */ - ; - } -} - -Static void -umass_scsipi_minphys(struct buf *bp) -{ -#ifdef DIAGNOSTIC - if (bp->b_bcount <= 0) { - printf("umass_scsipi_minphys count(%ld) <= 0\n", - bp->b_bcount); - bp->b_bcount = UMASS_MAX_TRANSFER_SIZE; - } -#endif - if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE) - bp->b_bcount = UMASS_MAX_TRANSFER_SIZE; - minphys(bp); -} - -int -umass_scsipi_ioctl(struct scsipi_channel *chan, u_long cmd, caddr_t arg, - int flag, usb_proc_ptr p) -{ - /*struct umass_softc *sc = link->adapter_softc;*/ - /*struct umass_scsipi_softc *scbus = sc->bus;*/ - - switch (cmd) { -#if 0 - case SCBUSIORESET: - ccb->ccb_h.status = CAM_REQ_INPROG; - umass_reset(sc, umass_cam_cb, (void *) ccb); - return (0); -#endif - default: - return (ENOTTY); - } -} - -Static int -umass_scsipi_getgeom(struct scsipi_periph *periph, struct disk_parms *dp, - u_long sectors) -{ - struct umass_softc *sc = - (void *)periph->periph_channel->chan_adapter->adapt_dev; - - /* If it's not a floppy, we don't know what to do. */ - if (sc->sc_cmd != UMASS_CPROTO_UFI) - return (0); - - switch (sectors) { - case 1440: - /* Most likely a single density 3.5" floppy. */ - dp->heads = 2; - dp->sectors = 9; - dp->cyls = 80; - return (1); - case 2880: - /* Most likely a double density 3.5" floppy. */ - dp->heads = 2; - dp->sectors = 18; - dp->cyls = 80; - return (1); - default: - return (0); - } -} - -Static void -umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus; - struct scsipi_xfer *xs = priv; - struct scsipi_periph *periph = xs->xs_periph; - int cmdlen; - int s; -#ifdef UMASS_DEBUG - struct timeval tv; - u_int delta; - microtime(&tv); - delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + tv.tv_usec - sc->tv.tv_usec; -#endif - - DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d" - " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue, status)); - - xs->resid = residue; - - switch (status) { - case STATUS_CMD_OK: - xs->error = XS_NOERROR; - break; - - case STATUS_CMD_UNKNOWN: - /* we can't issue REQUEST SENSE */ - if (xs->xs_periph->periph_quirks & PQUIRK_NOSENSE) { - /* - * If no residue and no other USB error, - * command succeeded. - */ - if (residue == 0) { - xs->error = XS_NOERROR; - break; - } - - /* - * Some devices return a short INQUIRY - * response, omitting response data from the - * "vendor specific data" on... - */ - if (xs->cmd->opcode == INQUIRY && - residue < xs->datalen) { - xs->error = XS_NOERROR; - break; - } - - xs->error = XS_DRIVER_STUFFUP; - break; - } - /* FALLTHROUGH */ - case STATUS_CMD_FAILED: - /* fetch sense data */ - memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd)); - scbus->sc_sense_cmd.opcode = REQUEST_SENSE; - scbus->sc_sense_cmd.byte2 = periph->periph_lun << - SCSI_CMD_LUN_SHIFT; - scbus->sc_sense_cmd.length = sizeof(xs->sense); - - cmdlen = sizeof(scbus->sc_sense_cmd); - if (sc->sc_cmd == UMASS_CPROTO_UFI) /* XXX */ - cmdlen = UFI_COMMAND_LENGTH; - sc->sc_methods->wire_xfer(sc, periph->periph_lun, - &scbus->sc_sense_cmd, cmdlen, - &xs->sense, sizeof(xs->sense), - DIR_IN, xs->timeout, - umass_scsipi_sense_cb, xs); - return; - - case STATUS_WIRE_FAILED: - xs->error = XS_RESET; - break; - - default: - panic("%s: Unknown status %d in umass_scsipi_cb\n", - USBDEVNAME(sc->sc_dev), status); - } - - DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu: return xs->error=" - "%d, xs->xs_status=0x%x xs->resid=%d\n", - tv.tv_sec, tv.tv_usec, - xs->error, xs->xs_status, xs->resid)); - - s = splbio(); - scsipi_done(xs); - splx(s); -} - -/* - * Finalise a completed autosense operation - */ -Static void -umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue, - int status) -{ - struct scsipi_xfer *xs = priv; - int s; - - DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: xs=%p residue=%d " - "status=%d\n", xs, residue, status)); - - switch (status) { - case STATUS_CMD_OK: - case STATUS_CMD_UNKNOWN: - /* getting sense data succeeded */ - if (xs->cmd->opcode == INQUIRY && (xs->resid < xs->datalen || - (sc->sc_quirks & UMASS_QUIRK_RS_NO_CLEAR_UA /* XXX */))) { - /* - * Some drivers return SENSE errors even after INQUIRY. - * The upper layer doesn't like that. - */ - xs->error = XS_NOERROR; - break; - } - /* XXX look at residue */ - if (residue == 0 || residue == 14)/* XXX */ - xs->error = XS_SENSE; - else - xs->error = XS_SHORTSENSE; - break; - default: - DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n", - USBDEVNAME(sc->sc_dev), status)); - xs->error = XS_DRIVER_STUFFUP; - break; - } - - xs->xs_status |= XS_STS_DONE; - - DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: return xs->error=%d, " - "xs->xs_status=0x%x xs->resid=%d\n", xs->error, xs->xs_status, - xs->resid)); - - s = splbio(); - scsipi_done(xs); - splx(s); -} - -#if NATAPIBUS > 0 -Static void -umass_atapi_probe_device(struct atapibus_softc *atapi, int target) -{ - struct scsipi_channel *chan = atapi->sc_channel; - struct scsipi_periph *periph; - struct scsipibus_attach_args sa; - char vendor[33], product[65], revision[17]; - struct scsipi_inquiry_data inqbuf; - - DPRINTF(UDMASS_SCSI,("umass_atapi_probe_device: atapi=%p target=%d\n", - atapi, target)); - - if (target != UMASS_ATAPI_DRIVE) /* only probe drive 0 */ - return; - - /* skip if already attached */ - if (scsipi_lookup_periph(chan, target, 0) != NULL) - return; - - periph = scsipi_alloc_periph(M_NOWAIT); - if (periph == NULL) { - printf("%s: can't allocate link for drive %d\n", - atapi->sc_dev.dv_xname, target); - return; - } - - DIF(UDMASS_UPPER, periph->periph_dbflags |= 1); /* XXX 1 */ - periph->periph_channel = chan; - periph->periph_switch = &atapi_probe_periphsw; - periph->periph_target = target; - periph->periph_quirks = chan->chan_defquirks; - - DPRINTF(UDMASS_SCSI, ("umass_atapi_probe_device: doing inquiry\n")); - /* Now go ask the device all about itself. */ - memset(&inqbuf, 0, sizeof(inqbuf)); - if (scsipi_inquire(periph, &inqbuf, - XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK) != 0) { - DPRINTF(UDMASS_SCSI, ("umass_atapi_probe_device: " - "scsipi_inquire failed\n")); - free(periph, M_DEVBUF); - return; - } - - scsipi_strvis(vendor, 33, inqbuf.vendor, 8); - scsipi_strvis(product, 65, inqbuf.product, 16); - scsipi_strvis(revision, 17, inqbuf.revision, 4); - - sa.sa_periph = periph; - sa.sa_inqbuf.type = inqbuf.device; - sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ? - T_REMOV : T_FIXED; - if (sa.sa_inqbuf.removable) - periph->periph_flags |= PERIPH_REMOVABLE; - sa.sa_inqbuf.vendor = vendor; - sa.sa_inqbuf.product = product; - sa.sa_inqbuf.revision = revision; - sa.sa_inqptr = NULL; - - DPRINTF(UDMASS_SCSI, ("umass_atapi_probedev: doing atapi_probedev on " - "'%s' '%s' '%s'\n", vendor, product, revision)); - atapi_probe_device(atapi, target, periph, &sa); - /* atapi_probe_device() frees the periph when there is no device.*/ -} -#endif diff --git a/sys/dev/usb/umass_scsipi.h b/sys/dev/usb/umass_scsipi.h deleted file mode 100644 index 182b50f294b..00000000000 --- a/sys/dev/usb/umass_scsipi.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $NetBSD: umass_scsipi.h,v 1.1 2001/12/24 13:25:53 augustss Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -int umass_scsi_attach(struct umass_softc *sc); -int umass_atapi_attach(struct umass_softc *sc); diff --git a/sys/dev/usb/umassvar.h b/sys/dev/usb/umassvar.h deleted file mode 100644 index 29e6b4a80cb..00000000000 --- a/sys/dev/usb/umassvar.h +++ /dev/null @@ -1,271 +0,0 @@ -/* $NetBSD: umassvar.h,v 1.15 2002/02/07 13:52:55 augustss Exp $ */ -/*- - * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>, - * Nick Hibma <n_hibma@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/usb/umass.c,v 1.13 2000/03/26 01:39:12 n_hibma Exp $ - */ - -#ifdef UMASS_DEBUG -#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0) -#define DPRINTF(m, x) if (umassdebug & (m)) logprintf x -#define UDMASS_UPPER 0x00008000 /* upper layer */ -#define UDMASS_GEN 0x00010000 /* general */ -#define UDMASS_SCSI 0x00020000 /* scsi */ -#define UDMASS_UFI 0x00040000 /* ufi command set */ -#define UDMASS_8070 0x00080000 /* 8070i command set */ -#define UDMASS_USB 0x00100000 /* USB general */ -#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ -#define UDMASS_CBI 0x00400000 /* CBI transfers */ -#define UDMASS_ALL 0xffff0000 /* all of the above */ - -#define UDMASS_XFER 0x40000000 /* all transfers */ -#define UDMASS_CMD 0x80000000 - -extern int umassdebug; -#else -#define DIF(m, x) /* nop */ -#define DPRINTF(m, x) /* nop */ -#endif - -/* Generic definitions */ - -#define UFI_COMMAND_LENGTH 12 - -/* Direction for umass_*_transfer */ -#define DIR_NONE 0 -#define DIR_IN 1 -#define DIR_OUT 2 - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -/* Endpoints for umass */ -#define UMASS_BULKIN 0 -#define UMASS_BULKOUT 1 -#define UMASS_INTRIN 2 -#define UMASS_NEP 3 - -/* Bulk-Only features */ - -#define UR_BBB_RESET 0xff /* Bulk-Only reset */ -#define UR_BBB_GET_MAX_LUN 0xfe - -/* Command Block Wrapper */ -typedef struct { - uDWord dCBWSignature; -#define CBWSIGNATURE 0x43425355 - uDWord dCBWTag; - uDWord dCBWDataTransferLength; - uByte bCBWFlags; -#define CBWFLAGS_OUT 0x00 -#define CBWFLAGS_IN 0x80 - uByte bCBWLUN; - uByte bCDBLength; -#define CBWCDBLENGTH 16 - uByte CBWCDB[CBWCDBLENGTH]; -} umass_bbb_cbw_t; -#define UMASS_BBB_CBW_SIZE 31 - -/* Command Status Wrapper */ -typedef struct { - uDWord dCSWSignature; -#define CSWSIGNATURE 0x53425355 -#define CSWSIGNATURE_OLYMPUS_C1 0x55425355 - uDWord dCSWTag; - uDWord dCSWDataResidue; - uByte bCSWStatus; -#define CSWSTATUS_GOOD 0x0 -#define CSWSTATUS_FAILED 0x1 -#define CSWSTATUS_PHASE 0x2 -} umass_bbb_csw_t; -#define UMASS_BBB_CSW_SIZE 13 - -/* CBI features */ - -#define UR_CBI_ADSC 0x00 - -typedef unsigned char umass_cbi_cbl_t[16]; /* Command block */ - -typedef union { - struct { - uByte type; -#define IDB_TYPE_CCI 0x00 - uByte value; -#define IDB_VALUE_PASS 0x00 -#define IDB_VALUE_FAIL 0x01 -#define IDB_VALUE_PHASE 0x02 -#define IDB_VALUE_PERSISTENT 0x03 -#define IDB_VALUE_STATUS_MASK 0x03 - } common; - - struct { - uByte asc; - uByte ascq; - } ufi; -} umass_cbi_sbl_t; - -struct umass_softc; /* see below */ - -typedef void (*umass_callback)(struct umass_softc *, void *, int, int); -#define STATUS_CMD_OK 0 /* everything ok */ -#define STATUS_CMD_UNKNOWN 1 /* will have to fetch sense */ -#define STATUS_CMD_FAILED 2 /* transfer was ok, command failed */ -#define STATUS_WIRE_FAILED 3 /* couldn't even get command across */ - -typedef void (*umass_wire_xfer)(struct umass_softc *, int, void *, int, void *, - int, int, u_int, umass_callback, void *); -typedef void (*umass_wire_reset)(struct umass_softc *, int); -typedef void (*umass_wire_state)(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -struct umass_wire_methods { - umass_wire_xfer wire_xfer; - umass_wire_reset wire_reset; - umass_wire_state wire_state; -}; - -struct umassbus_softc { - device_ptr_t sc_child; /* child device, for detach */ -}; - -/* the per device structure */ -struct umass_softc { - USBBASEDEVICE sc_dev; /* base device */ - usbd_device_handle sc_udev; /* device */ - usbd_interface_handle sc_iface; /* interface */ - int sc_ifaceno; /* interface number */ - - u_int8_t sc_epaddr[UMASS_NEP]; - usbd_pipe_handle sc_pipe[UMASS_NEP]; - usb_device_request_t sc_req; - - const struct umass_wire_methods *sc_methods; - - u_int8_t sc_wire; /* wire protocol */ -#define UMASS_WPROTO_UNSPEC 0 -#define UMASS_WPROTO_BBB 1 -#define UMASS_WPROTO_CBI 2 -#define UMASS_WPROTO_CBI_I 3 - - u_int8_t sc_cmd; /* command protocol */ -#define UMASS_CPROTO_UNSPEC 0 -#define UMASS_CPROTO_SCSI 1 -#define UMASS_CPROTO_ATAPI 2 -#define UMASS_CPROTO_UFI 3 -#define UMASS_CPROTO_RBC 4 -#define UMASS_CPROTO_ISD_ATA 5 - - u_int32_t sc_quirks; -#define UMASS_QUIRK_RS_NO_CLEAR_UA 0x00000002 -#define UMASS_QUIRK_NO_START_STOP 0x00000004 -#define UMASS_QUIRK_FORCE_SHORT_INQUIRY 0x00000008 -#define UMASS_QUIRK_WRONG_CSWSIG 0x00000010 -#define UMASS_QUIRK_NO_MAX_LUN 0x00000020 - - u_int32_t sc_busquirks; - - /* Bulk specific variables for transfers in progress */ - umass_bbb_cbw_t cbw; /* command block wrapper */ - umass_bbb_csw_t csw; /* command status wrapper*/ - /* CBI specific variables for transfers in progress */ - umass_cbi_cbl_t cbl; /* command block */ - umass_cbi_sbl_t sbl; /* status block */ - - /* xfer handles - * Most of our operations are initiated from interrupt context, so - * we need to avoid using the one that is in use. We want to avoid - * allocating them in the interrupt context as well. - */ - /* indices into array below */ -#define XFER_BBB_CBW 0 /* Bulk-Only */ -#define XFER_BBB_DATA 1 -#define XFER_BBB_DCLEAR 2 -#define XFER_BBB_CSW1 3 -#define XFER_BBB_CSW2 4 -#define XFER_BBB_SCLEAR 5 -#define XFER_BBB_RESET1 6 -#define XFER_BBB_RESET2 7 -#define XFER_BBB_RESET3 8 - -#define XFER_CBI_CB 0 /* CBI */ -#define XFER_CBI_DATA 1 -#define XFER_CBI_STATUS 2 -#define XFER_CBI_DCLEAR 3 -#define XFER_CBI_SCLEAR 4 -#define XFER_CBI_RESET1 5 -#define XFER_CBI_RESET2 6 -#define XFER_CBI_RESET3 7 - -#define XFER_NR 9 /* maximum number */ - - usbd_xfer_handle transfer_xfer[XFER_NR]; /* for ctrl xfers */ - - void *data_buffer; - - int transfer_dir; /* data direction */ - void *transfer_data; /* data buffer */ - int transfer_datalen; /* (maximum) length */ - int transfer_actlen; /* actual length */ - umass_callback transfer_cb; /* callback */ - void *transfer_priv; /* for callback */ - int transfer_status; - - int transfer_state; -#define TSTATE_IDLE 0 -#define TSTATE_BBB_COMMAND 1 /* CBW transfer */ -#define TSTATE_BBB_DATA 2 /* Data transfer */ -#define TSTATE_BBB_DCLEAR 3 /* clear endpt stall */ -#define TSTATE_BBB_STATUS1 4 /* clear endpt stall */ -#define TSTATE_BBB_SCLEAR 5 /* clear endpt stall */ -#define TSTATE_BBB_STATUS2 6 /* CSW transfer */ -#define TSTATE_BBB_RESET1 7 /* reset command */ -#define TSTATE_BBB_RESET2 8 /* in clear stall */ -#define TSTATE_BBB_RESET3 9 /* out clear stall */ -#define TSTATE_CBI_COMMAND 10 /* command transfer */ -#define TSTATE_CBI_DATA 11 /* data transfer */ -#define TSTATE_CBI_STATUS 12 /* status transfer */ -#define TSTATE_CBI_DCLEAR 13 /* clear ep stall */ -#define TSTATE_CBI_SCLEAR 14 /* clear ep stall */ -#define TSTATE_CBI_RESET1 15 /* reset command */ -#define TSTATE_CBI_RESET2 16 /* in clear stall */ -#define TSTATE_CBI_RESET3 17 /* out clear stall */ -#define TSTATE_STATES 18 /* # of states above */ - - - int timeout; /* in msecs */ - - u_int8_t maxlun; /* max lun supported */ - -#ifdef UMASS_DEBUG - struct timeval tv; -#endif - - int sc_xfer_flags; - char sc_dying; - - struct umassbus_softc *bus; /* bus dependent data */ -}; - -#define UMASS_MAX_TRANSFER_SIZE MAXBSIZE diff --git a/sys/dev/usb/umct.c b/sys/dev/usb/umct.c deleted file mode 100644 index 954ce542c67..00000000000 --- a/sys/dev/usb/umct.c +++ /dev/null @@ -1,631 +0,0 @@ -/* $OpenBSD: umct.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umct.c,v 1.7 2001/12/17 14:19:39 ichiro Exp $ */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Ichiro FUKUHARA (ichiro@ichiro.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MCT USB-RS232 Interface Controller - * http://www.mct.com.tw/p_u232.html - * http://www.dlink.com/products/usb/dsbs25 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/ioctl.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/device.h> -#include <sys/poll.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdevs.h> -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/usbdevs.h> -#include <dev/usb/ucomvar.h> - -#include <dev/usb/umct.h> - -#ifdef UMCT_DEBUG -#define DPRINTFN(n, x) if (umctdebug > (n)) logprintf x -int umctdebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UMCT_CONFIG_INDEX 0 -#define UMCT_IFACE_INDEX 0 - -struct umct_softc { - USBBASEDEVICE sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - usbd_interface_handle sc_iface; /* interface */ - int sc_iface_number; /* interface number */ - u_int16_t sc_product; - - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - usb_cdc_line_state_t sc_line_state; /* current line state */ - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - u_char sc_break; /* set break */ - - u_char sc_status; - - device_ptr_t sc_subdev; /* ucom device */ - - u_char sc_dying; /* disconnecting */ - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* umct status register */ - - u_int last_lcr; /* keep lcr register */ -}; - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UMCTIBUFSIZE 256 -#define UMCTOBUFSIZE 256 - -Static void umct_init(struct umct_softc *); -Static void umct_set_baudrate(struct umct_softc *, u_int); -Static void umct_set_lcr(struct umct_softc *, u_int); -Static void umct_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -Static void umct_set(void *, int, int, int); -Static void umct_dtr(struct umct_softc *, int); -Static void umct_rts(struct umct_softc *, int); -Static void umct_break(struct umct_softc *, int); -Static void umct_set_line_state(struct umct_softc *); -Static void umct_get_status(void *, int portno, u_char *lsr, u_char *msr); -Static int umct_param(void *, int, struct termios *); -Static int umct_open(void *, int); -Static void umct_close(void *, int); - -struct ucom_methods umct_methods = { - umct_get_status, - umct_set, - umct_param, - NULL, - umct_open, - umct_close, - NULL, - NULL, -}; - -static const struct usb_devno umct_devs[] = { - /* MCT USB-232 Interface Products */ - { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232 }, - /* Sitecom USB-232 Products */ - { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232 }, - /* D-Link DU-H3SP USB BAY Hub Products */ - { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232 }, -}; -#define umct_lookup(v, p) usb_lookup(umct_devs, v, p) - -USB_DECLARE_DRIVER(umct); - -USB_MATCH(umct) -{ - USB_MATCH_START(umct, uaa); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (umct_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -USB_ATTACH(umct) -{ - USB_ATTACH_START(umct, sc, uaa); - usbd_device_handle dev = uaa->device; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - - char devinfo[1024]; - char *devname = USBDEVNAME(sc->sc_dev); - usbd_status err; - int i, found; - struct ucom_attach_args uca; - - usbd_devinfo(dev, 0, devinfo); - USB_ATTACH_SETUP; - printf("%s: %s\n", devname, devinfo); - - sc->sc_udev = dev; - sc->sc_product = uaa->product; - - DPRINTF(("\n\numct attach: sc=%p\n", sc)); - - /* initialize endpoints */ - uca.bulkin = uca.bulkout = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1); - if (err) { - printf("\n%s: failed to set configuration, err=%s\n", - devname, usbd_errstr(err)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(sc->sc_udev); - - if (cdesc == NULL) { - printf("%s: failed to get configuration descriptor\n", - USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - /* get the interface */ - err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX, - &sc->sc_iface); - if (err) { - printf("\n%s: failed to get interface, err=%s\n", - devname, usbd_errstr(err)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - /* Find the bulk{in,out} and interrupt endpoints */ - - id = usbd_get_interface_descriptor(sc->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - found = 0; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - printf("%s: no endpoint descriptor for %d\n", - USBDEVNAME(sc->sc_dev), i); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT && - found == 0) { - uca.bulkin = ed->bEndpointAddress; - found = 1; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - uca.bulkout = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } - } - - if (uca.bulkin == -1) { - printf("%s: Could not find data bulk in\n", - USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - if (uca.bulkout == -1) { - printf("%s: Could not find data bulk out\n", - USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - if (sc->sc_intr_number== -1) { - printf("%s: Could not find interrupt in\n", - USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } - - sc->sc_dtr = sc->sc_rts = 0; - uca.portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - uca.ibufsize = UMCTIBUFSIZE; - if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232) - uca.obufsize = 16; /* device is broken */ - else - uca.obufsize = UMCTOBUFSIZE; - uca.ibufsizepad = UMCTIBUFSIZE; - uca.opkthdrlen = 0; - uca.device = dev; - uca.iface = sc->sc_iface; - uca.methods = &umct_methods; - uca.arg = sc; - uca.info = NULL; - - umct_init(sc); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - DPRINTF(("umct: in=0x%x out=0x%x intr=0x%x\n", - uca.bulkin, uca.bulkout, sc->sc_intr_number )); - sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); - - USB_ATTACH_SUCCESS_RETURN; -} - -USB_DETACH(umct) -{ - USB_DETACH_START(umct, sc); - int rv = 0; - - DPRINTF(("umct_detach: sc=%p flags=%d\n", sc, flags)); - - if (sc->sc_intr_pipe != NULL) { - usbd_abort_pipe(sc->sc_intr_pipe); - usbd_close_pipe(sc->sc_intr_pipe); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } - - sc->sc_dying = 1; - if (sc->sc_subdev != NULL) { - rv = config_detach(sc->sc_subdev, flags); - sc->sc_subdev = NULL; - } - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - return (rv); -} - -int -umct_activate(device_ptr_t self, enum devact act) -{ - struct umct_softc *sc = (struct umct_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - break; - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_dying = 1; - break; - } - return (rv); -} - -void -umct_set_line_state(struct umct_softc *sc) -{ - usb_device_request_t req; - uByte ls; - - ls = (sc->sc_dtr ? MCR_DTR : 0) | - (sc->sc_rts ? MCR_RTS : 0); - - DPRINTF(("umct_set_line_state: DTR=%d,RTS=%d,ls=%02x\n", - sc->sc_dtr, sc->sc_rts, ls)); - - req.bmRequestType = UMCT_SET_REQUEST; - req.bRequest = REQ_SET_MCR; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, LENGTH_SET_MCR); - - (void)usbd_do_request(sc->sc_udev, &req, &ls); -} - -void -umct_set(void *addr, int portno, int reg, int onoff) -{ - struct umct_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - umct_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - umct_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - umct_break(sc, onoff); - break; - default: - break; - } -} - -void -umct_dtr(struct umct_softc *sc, int onoff) -{ - - DPRINTF(("umct_dtr: onoff=%d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - umct_set_line_state(sc); -} - -void -umct_rts(struct umct_softc *sc, int onoff) -{ - DPRINTF(("umct_rts: onoff=%d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - umct_set_line_state(sc); -} - -void -umct_break(struct umct_softc *sc, int onoff) -{ - DPRINTF(("umct_break: onoff=%d\n", onoff)); - - umct_set_lcr(sc, onoff ? sc->last_lcr | LCR_SET_BREAK : - sc->last_lcr); -} - -void -umct_set_lcr(struct umct_softc *sc, u_int data) -{ - usb_device_request_t req; - uByte adata; - - adata = data; - req.bmRequestType = UMCT_SET_REQUEST; - req.bRequest = REQ_SET_LCR; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, LENGTH_SET_LCR); - - /* XXX should check */ - (void)usbd_do_request(sc->sc_udev, &req, &adata); -} - -void -umct_set_baudrate(struct umct_softc *sc, u_int rate) -{ - usb_device_request_t req; - uDWord arate; - u_int val; - - if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232) { - switch (rate) { - case 300: val = 0x01; break; - case 600: val = 0x02; break; - case 1200: val = 0x03; break; - case 2400: val = 0x04; break; - case 4800: val = 0x06; break; - case 9600: val = 0x08; break; - case 19200: val = 0x09; break; - case 38400: val = 0x0a; break; - case 57600: val = 0x0b; break; - case 115200: val = 0x0c; break; - default: val = -1; break; - } - } else { - val = UMCT_BAUD_RATE(rate); - } - USETDW(arate, val); - - req.bmRequestType = UMCT_SET_REQUEST; - req.bRequest = REQ_SET_BAUD_RATE; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, LENGTH_BAUD_RATE); - - /* XXX should check */ - (void)usbd_do_request(sc->sc_udev, &req, arate); -} - -void -umct_init(struct umct_softc *sc) -{ - umct_set_baudrate(sc, 9600); - umct_set_lcr(sc, LCR_DATA_BITS_8 | LCR_PARITY_NONE | LCR_STOP_BITS_1); -} - -int -umct_param(void *addr, int portno, struct termios *t) -{ - struct umct_softc *sc = addr; - u_int data = 0; - - DPRINTF(("umct_param: sc=%p\n", sc)); - - DPRINTF(("umct_param: BAUDRATE=%d\n", t->c_ospeed)); - - if (ISSET(t->c_cflag, CSTOPB)) - data |= LCR_STOP_BITS_2; - else - data |= LCR_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= LCR_PARITY_ODD; - else - data |= LCR_PARITY_EVEN; - } else - data |= LCR_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= LCR_DATA_BITS_5; - break; - case CS6: - data |= LCR_DATA_BITS_6; - break; - case CS7: - data |= LCR_DATA_BITS_7; - break; - case CS8: - data |= LCR_DATA_BITS_8; - break; - } - - umct_set_baudrate(sc, t->c_ospeed); - - sc->last_lcr = data; - umct_set_lcr(sc, data); - - return (0); -} - -int -umct_open(void *addr, int portno) -{ - struct umct_softc *sc = addr; - int err, lcr_data; - - if (sc->sc_dying) - return (EIO); - - DPRINTF(("umct_open: sc=%p\n", sc)); - - /* initialize LCR */ - lcr_data = LCR_DATA_BITS_8 | LCR_PARITY_NONE | - LCR_STOP_BITS_1; - umct_set_lcr(sc, lcr_data); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_status = 0; /* clear status bit */ - sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_intr_number, - USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, - sc->sc_intr_buf, sc->sc_isize, - umct_intr, USBD_DEFAULT_INTERVAL); - if (err) { - DPRINTF(("%s: cannot open interrupt pipe (addr %d)\n", - USBDEVNAME(sc->sc_dev), sc->sc_intr_number)); - return (EIO); - } - } - - return (0); -} - -void -umct_close(void *addr, int portno) -{ - struct umct_softc *sc = addr; - int err; - - if (sc->sc_dying) - return; - - DPRINTF(("umct_close: close\n")); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - printf("%s: abort interrupt pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - printf("%s: close interrupt pipe failed: %s\n", - USBDEVNAME(sc->sc_dev), usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -void -umct_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umct_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - u_char mstatus, lstatus; - - if (sc->sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: abnormal status: %s\n", USBDEVNAME(sc->sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - DPRINTF(("%s: umct status = MSR:%02x, LSR:%02x\n", - USBDEVNAME(sc->sc_dev), buf[0],buf[1])); - - sc->sc_lsr = sc->sc_msr = 0; - mstatus = buf[0]; - lstatus = buf[1]; - if (ISSET(mstatus, MSR_DSR)) - sc->sc_msr |= UMSR_DSR; - if (ISSET(mstatus, MSR_DCD)) - sc->sc_msr |= UMSR_DCD; - ucom_status_change((struct ucom_softc *)sc->sc_subdev); -} - -void -umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct umct_softc *sc = addr; - - DPRINTF(("umct_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} diff --git a/sys/dev/usb/umct.h b/sys/dev/usb/umct.h deleted file mode 100644 index e162280d74c..00000000000 --- a/sys/dev/usb/umct.h +++ /dev/null @@ -1,109 +0,0 @@ -/* $OpenBSD: umct.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umct.h,v 1.1 2001/03/28 18:42:13 ichiro Exp $ */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Ichiro FUKUHARA (ichiro@ichiro.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Vendor Request Interface - */ -#define UMCT_SET_REQUEST 0x40 -#define UMCT_GET_REQUEST 0xc0 - -#define REQ_SET_BAUD_RATE 5 /* Set Baud Rate Divisor */ -#define LENGTH_BAUD_RATE 4 - -#define REQ_GET_MSR 2 /* Get Modem Status Register (MSR) */ -#define LENGTH_GET_MSR 1 - -#define REQ_GET_LCR 6 /* Get Line Control Register (LCR) */ -#define LENGTH_GET_LCR 1 - -#define REQ_SET_LCR 7 /* Set Line Control Register (LCR) */ -#define LENGTH_SET_LCR 1 - -#define REQ_SET_MCR 10 /* Set Modem Control Register (MCR) */ -#define LENGTH_SET_MCR 1 - -/* - * Baud rate (divisor) - */ -#define UMCT_BAUD_RATE(b) (115200/b) - -/* - * Line Control Register (LCR) - */ -#define LCR_SET_BREAK 0x40 -#define LCR_PARITY_EVEN 0x18 -#define LCR_PARITY_ODD 0x08 -#define LCR_PARITY_NONE 0x00 -#define LCR_DATA_BITS_5 0x00 -#define LCR_DATA_BITS_6 0x01 -#define LCR_DATA_BITS_7 0x02 -#define LCR_DATA_BITS_8 0x03 -#define LCR_STOP_BITS_2 0x04 -#define LCR_STOP_BITS_1 0x00 - -/* - * Modem Control Register (MCR) - */ -#define MCR_NONE 0x8 -#define MCR_RTS 0xa -#define MCR_DTR 0x9 - -/* - * Modem Status Register (MSR) - */ -#define MSR_CD 0x80 /* Current CD */ -#define MSR_RI 0x40 /* Current RI */ -#define MSR_DSR 0x20 /* Current DSR */ -#define MSR_CTS 0x10 /* Current CTS */ -#define MSR_DCD 0x08 /* Delta CD */ -#define MSR_DRI 0x04 /* Delta RI */ -#define MSR_DDSR 0x02 /* Delta DSR */ -#define MSR_DCTS 0x01 /* Delta CTS */ - -/* - * Line Status Register (LSR) - */ -#define LSR_ERR 0x80 /* OE | PE | FE | BI */ -#define LSR_TEMT 0x40 /* transmit register empty */ -#define LSR_THRE 0x20 /* transmit holding register empty */ -#define LSR_BI 0x10 /* break indicator */ -#define LSR_FE 0x08 /* framing error */ -#define LSR_OE 0x02 /* overrun error */ -#define LSR_PE 0x04 /* parity error */ -#define LSR_OE 0x02 /* overrun error */ -#define LSR_DR 0x01 /* receive data ready */ diff --git a/sys/dev/usb/umidi.c b/sys/dev/usb/umidi.c deleted file mode 100644 index 09b8df082a8..00000000000 --- a/sys/dev/usb/umidi.c +++ /dev/null @@ -1,1374 +0,0 @@ -/* $OpenBSD: umidi.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umidi.c,v 1.14 2002/03/08 17:24:06 kent Exp $ */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/device.h> -#include <sys/ioctl.h> -#include <sys/conf.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/poll.h> -#include <sys/lock.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include <dev/usb/usbdevs.h> -#include <dev/usb/uaudioreg.h> -#include <dev/usb/umidireg.h> -#include <dev/usb/umidivar.h> -#include <dev/usb/umidi_quirks.h> - -#include <dev/midi_if.h> - -#ifdef UMIDI_DEBUG -#define DPRINTF(x) if (umididebug) printf x -#define DPRINTFN(n,x) if (umididebug >= (n)) printf x -int umididebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - - -static int umidi_open(void *, int, - void (*)(void *, int), void (*)(void *), void *); -static void umidi_close(void *); -static int umidi_output(void *, int); -static void umidi_getinfo(void *, struct midi_info *); - -static usbd_status alloc_pipe(struct umidi_endpoint *); -static void free_pipe(struct umidi_endpoint *); - -static usbd_status alloc_all_endpoints(struct umidi_softc *); -static void free_all_endpoints(struct umidi_softc *); - -static usbd_status alloc_all_jacks(struct umidi_softc *); -static void free_all_jacks(struct umidi_softc *); -static usbd_status bind_jacks_to_mididev(struct umidi_softc *, - struct umidi_jack *, - struct umidi_jack *, - struct umidi_mididev *); -static void unbind_jacks_from_mididev(struct umidi_mididev *); -static void unbind_all_jacks(struct umidi_softc *); -static usbd_status assign_all_jacks_automatically(struct umidi_softc *); -static usbd_status open_out_jack(struct umidi_jack *, void *, - void (*)(void *)); -static usbd_status open_in_jack(struct umidi_jack *, void *, - void (*)(void *, int)); -static void close_out_jack(struct umidi_jack *); -static void close_in_jack(struct umidi_jack *); - -static usbd_status attach_mididev(struct umidi_softc *, - struct umidi_mididev *); -static usbd_status detach_mididev(struct umidi_mididev *, int); -static usbd_status deactivate_mididev(struct umidi_mididev *); -static usbd_status alloc_all_mididevs(struct umidi_softc *, int); -static void free_all_mididevs(struct umidi_softc *); -static usbd_status attach_all_mididevs(struct umidi_softc *); -static usbd_status detach_all_mididevs(struct umidi_softc *, int); -static usbd_status deactivate_all_mididevs(struct umidi_softc *); - -#ifdef UMIDI_DEBUG -static void dump_sc(struct umidi_softc *); -static void dump_ep(struct umidi_endpoint *); -static void dump_jack(struct umidi_jack *); -#endif - -static void init_packet(struct umidi_packet *); - -static usbd_status start_input_transfer(struct umidi_endpoint *); -static usbd_status start_output_transfer(struct umidi_endpoint *); -static int out_jack_output(struct umidi_jack *, int); -static void in_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void out_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void out_build_packet(int, struct umidi_packet *, uByte); - - -struct midi_hw_if umidi_hw_if = { - umidi_open, - umidi_close, - umidi_output, - umidi_getinfo, - 0, /* ioctl */ -}; - -USB_DECLARE_DRIVER(umidi); - -USB_MATCH(umidi) -{ - USB_MATCH_START(umidi, uaa); - usb_interface_descriptor_t *id; - - DPRINTFN(1,("umidi_match\n")); - - if (uaa->iface == NULL) - return UMATCH_NONE; - - if (umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno)) - return UMATCH_IFACECLASS_IFACESUBCLASS; - - id = usbd_get_interface_descriptor(uaa->iface); - if (id!=NULL && - id->bInterfaceClass==UICLASS_AUDIO && - id->bInterfaceSubClass==UISUBCLASS_MIDISTREAM) - return UMATCH_IFACECLASS_IFACESUBCLASS; - - return UMATCH_NONE; -} - -USB_ATTACH(umidi) -{ - usbd_status err; - USB_ATTACH_START(umidi, sc, uaa); - char devinfo[1024]; - - DPRINTFN(1,("umidi_attach\n")); - - usbd_devinfo(uaa->device, 0, devinfo); - printf("\n%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - - sc->sc_iface = uaa->iface; - sc->sc_udev = uaa->device; - - sc->sc_quirk = - umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno); - printf("%s: ", USBDEVNAME(sc->sc_dev)); - umidi_print_quirk(sc->sc_quirk); - - - err = alloc_all_endpoints(sc); - if (err!=USBD_NORMAL_COMPLETION) { - printf("%s: alloc_all_endpoints failed. (err=%d)\n", - USBDEVNAME(sc->sc_dev), err); - goto error; - } - err = alloc_all_jacks(sc); - if (err!=USBD_NORMAL_COMPLETION) { - free_all_endpoints(sc); - printf("%s: alloc_all_jacks failed. (err=%d)\n", - USBDEVNAME(sc->sc_dev), err); - goto error; - } - printf("%s: out=%d, in=%d\n", - USBDEVNAME(sc->sc_dev), - sc->sc_out_num_jacks, sc->sc_in_num_jacks); - - err = assign_all_jacks_automatically(sc); - if (err!=USBD_NORMAL_COMPLETION) { - unbind_all_jacks(sc); - free_all_jacks(sc); - free_all_endpoints(sc); - printf("%s: assign_all_jacks_automatically failed. (err=%d)\n", - USBDEVNAME(sc->sc_dev), err); - goto error; - } - err = attach_all_mididevs(sc); - if (err!=USBD_NORMAL_COMPLETION) { - free_all_jacks(sc); - free_all_endpoints(sc); - printf("%s: attach_all_mididevs failed. (err=%d)\n", - USBDEVNAME(sc->sc_dev), err); - } - -#ifdef UMIDI_DEBUG - dump_sc(sc); -#endif - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, - sc->sc_udev, USBDEV(sc->sc_dev)); - - USB_ATTACH_SUCCESS_RETURN; -error: - printf("%s: disabled.\n", USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; -} - -int -umidi_activate(device_ptr_t self, enum devact act) -{ - struct umidi_softc *sc = (struct umidi_softc *)self; - - switch (act) { - case DVACT_ACTIVATE: - DPRINTFN(1,("umidi_activate (activate)\n")); - - return EOPNOTSUPP; - break; - case DVACT_DEACTIVATE: - DPRINTFN(1,("umidi_activate (deactivate)\n")); - sc->sc_dying = 1; - deactivate_all_mididevs(sc); - break; - } - return 0; -} - -USB_DETACH(umidi) -{ - USB_DETACH_START(umidi, sc); - - DPRINTFN(1,("umidi_detach\n")); - - sc->sc_dying = 1; - detach_all_mididevs(sc, flags); - free_all_mididevs(sc); - free_all_jacks(sc); - free_all_endpoints(sc); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, - USBDEV(sc->sc_dev)); - - return 0; -} - - -/* - * midi_if stuffs - */ -int -umidi_open(void *addr, - int flags, - void (*iintr)(void *, int), - void (*ointr)(void *), - void *arg) -{ - struct umidi_mididev *mididev = addr; - struct umidi_softc *sc = mididev->sc; - - DPRINTF(("umidi_open: sc=%p\n", sc)); - - if (!sc) - return ENXIO; - if (mididev->opened) - return EBUSY; - if (sc->sc_dying) - return EIO; - - mididev->opened = 1; - mididev->flags = flags; - if ((mididev->flags & FWRITE) && mididev->out_jack) - open_out_jack(mididev->out_jack, arg, ointr); - if ((mididev->flags & FREAD) && mididev->in_jack) { - open_in_jack(mididev->in_jack, arg, iintr); - } - - return 0; -} - -void -umidi_close(void *addr) -{ - int s; - struct umidi_mididev *mididev = addr; - - s = splusb(); - if ((mididev->flags & FWRITE) && mididev->out_jack) - close_out_jack(mididev->out_jack); - if ((mididev->flags & FREAD) && mididev->in_jack) - close_in_jack(mididev->in_jack); - mididev->opened = 0; - splx(s); -} - -int -umidi_output(void *addr, int d) -{ - struct umidi_mididev *mididev = addr; - - if (!mididev->out_jack || !mididev->opened) - return EIO; - - return out_jack_output(mididev->out_jack, d); -} - -void -umidi_getinfo(void *addr, struct midi_info *mi) -{ - struct umidi_mididev *mididev = addr; -/* struct umidi_softc *sc = mididev->sc; */ - - mi->name = "USB MIDI I/F"; /* XXX: model name */ - mi->props = MIDI_PROP_OUT_INTR; - if (mididev->in_jack) - mi->props |= MIDI_PROP_CAN_INPUT; -} - - -/* - * each endpoint stuffs - */ - -/* alloc/free pipe */ -static usbd_status -alloc_pipe(struct umidi_endpoint *ep) -{ - struct umidi_softc *sc = ep->sc; - usbd_status err; - - DPRINTF(("%s: alloc_pipe %p\n", USBDEVNAME(sc->sc_dev), ep)); - LIST_INIT(&ep->queue_head); - ep->xfer = usbd_alloc_xfer(sc->sc_udev); - if (ep->xfer == NULL) { - err = USBD_NOMEM; - goto quit; - } - ep->buffer = usbd_alloc_buffer(ep->xfer, UMIDI_PACKET_SIZE); - if (ep->buffer == NULL) { - usbd_free_xfer(ep->xfer); - err = USBD_NOMEM; - goto quit; - } - err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe); - if (err) - usbd_free_xfer(ep->xfer); -quit: - return err; -} - -static void -free_pipe(struct umidi_endpoint *ep) -{ - DPRINTF(("%s: free_pipe %p\n", USBDEVNAME(ep->sc->sc_dev), ep)); - usbd_abort_pipe(ep->pipe); - usbd_close_pipe(ep->pipe); - usbd_free_xfer(ep->xfer); -} - - -/* alloc/free the array of endpoint structures */ - -static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *); -static usbd_status alloc_all_endpoints_yamaha(struct umidi_softc *); -static usbd_status alloc_all_endpoints_genuine(struct umidi_softc *); - -static usbd_status -alloc_all_endpoints(struct umidi_softc *sc) -{ - usbd_status err; - struct umidi_endpoint *ep; - int i; - - if (UMQ_ISTYPE(sc, UMQ_TYPE_FIXED_EP)) { - err = alloc_all_endpoints_fixed_ep(sc); - } else if (UMQ_ISTYPE(sc, UMQ_TYPE_YAMAHA)) { - err = alloc_all_endpoints_yamaha(sc); - } else { - err = alloc_all_endpoints_genuine(sc); - } - if (err!=USBD_NORMAL_COMPLETION) - return err; - - ep = sc->sc_endpoints; - for (i=sc->sc_out_num_endpoints+sc->sc_in_num_endpoints; i>0; i--) { - err = alloc_pipe(ep++); - if (err!=USBD_NORMAL_COMPLETION) { - for (; ep!=sc->sc_endpoints; ep--) - free_pipe(ep-1); - free(sc->sc_endpoints, M_USBDEV); - sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL; - break; - } - } - return err; -} - -static void -free_all_endpoints(struct umidi_softc *sc) -{ - int i; - for (i=0; i<sc->sc_in_num_endpoints+sc->sc_out_num_endpoints; i++) - free_pipe(&sc->sc_endpoints[i]); - if (sc->sc_endpoints != NULL) - free(sc->sc_endpoints, M_USBDEV); - sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL; -} - -static usbd_status -alloc_all_endpoints_fixed_ep(struct umidi_softc *sc) -{ - usbd_status err; - struct umq_fixed_ep_desc *fp; - struct umidi_endpoint *ep; - usb_endpoint_descriptor_t *epd; - int i; - - fp = umidi_get_quirk_data_from_type(sc->sc_quirk, - UMQ_TYPE_FIXED_EP); - sc->sc_out_num_jacks = 0; - sc->sc_in_num_jacks = 0; - sc->sc_out_num_endpoints = fp->num_out_ep; - sc->sc_in_num_endpoints = fp->num_in_ep; - sc->sc_endpoints = malloc(sizeof(*sc->sc_out_ep)* - (sc->sc_out_num_endpoints+ - sc->sc_in_num_endpoints), - M_USBDEV, M_WAITOK); - if (!sc->sc_endpoints) { - return USBD_NOMEM; - } - sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; - sc->sc_in_ep = - sc->sc_in_num_endpoints ? - sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; - - ep = &sc->sc_out_ep[0]; - for (i=0; i<sc->sc_out_num_endpoints; i++) { - epd = usbd_interface2endpoint_descriptor( - sc->sc_iface, - fp->out_ep[i].ep); - if (!epd) { - printf("%s: cannot get endpoint descriptor(out:%d)\n", - USBDEVNAME(sc->sc_dev), fp->out_ep[i].ep); - err = USBD_INVAL; - goto error; - } - if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || - UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_OUT) { - printf("%s: illegal endpoint(out:%d)\n", - USBDEVNAME(sc->sc_dev), fp->out_ep[i].ep); - err = USBD_INVAL; - goto error; - } - ep->sc = sc; - ep->addr = epd->bEndpointAddress; - ep->num_jacks = fp->out_ep[i].num_jacks; - sc->sc_out_num_jacks += fp->out_ep[i].num_jacks; - ep->num_open = 0; - memset(ep->jacks, 0, sizeof(ep->jacks)); - LIST_INIT(&ep->queue_head); - ep++; - } - ep = &sc->sc_in_ep[0]; - for (i=0; i<sc->sc_in_num_endpoints; i++) { - epd = usbd_interface2endpoint_descriptor( - sc->sc_iface, - fp->in_ep[i].ep); - if (!epd) { - printf("%s: cannot get endpoint descriptor(in:%d)\n", - USBDEVNAME(sc->sc_dev), fp->in_ep[i].ep); - err = USBD_INVAL; - goto error; - } - if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || - UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_IN) { - printf("%s: illegal endpoint(in:%d)\n", - USBDEVNAME(sc->sc_dev), fp->in_ep[i].ep); - err = USBD_INVAL; - goto error; - } - ep->sc = sc; - ep->addr = epd->bEndpointAddress; - ep->num_jacks = fp->in_ep[i].num_jacks; - sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; - ep->num_open = 0; - memset(ep->jacks, 0, sizeof(ep->jacks)); - ep++; - } - - return USBD_NORMAL_COMPLETION; -error: - free(sc->sc_endpoints, M_USBDEV); - sc->sc_endpoints = NULL; - return err; -} - -static usbd_status -alloc_all_endpoints_yamaha(struct umidi_softc *sc) -{ - /* This driver currently supports max 1in/1out bulk endpoints */ - usb_descriptor_t *desc; - usb_endpoint_descriptor_t *epd; - int out_addr, in_addr, i; - int dir; - size_t remain, descsize; - - sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0; - out_addr = in_addr = 0; - - /* detect endpoints */ - desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface)); - for (i=(int)TO_IFD(desc)->bNumEndpoints-1; i>=0; i--) { - epd = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (UE_GET_XFERTYPE(epd->bmAttributes) == UE_BULK) { - dir = UE_GET_DIR(epd->bEndpointAddress); - if (dir==UE_DIR_OUT && !out_addr) - out_addr = epd->bEndpointAddress; - else if (dir==UE_DIR_IN && !in_addr) - in_addr = epd->bEndpointAddress; - } - } - desc = NEXT_D(desc); - - /* count jacks */ - if (!(desc->bDescriptorType==UDESC_CS_INTERFACE && - desc->bDescriptorSubtype==UMIDI_MS_HEADER)) - return USBD_INVAL; - remain = (size_t)UGETW(TO_CSIFD(desc)->wTotalLength) - - (size_t)desc->bLength; - desc = NEXT_D(desc); - - while (remain>=sizeof(usb_descriptor_t)) { - descsize = desc->bLength; - if (descsize>remain || descsize==0) - break; - if (desc->bDescriptorType==UDESC_CS_INTERFACE && - remain>=UMIDI_JACK_DESCRIPTOR_SIZE) { - if (desc->bDescriptorSubtype==UMIDI_OUT_JACK) - sc->sc_out_num_jacks++; - else if (desc->bDescriptorSubtype==UMIDI_IN_JACK) - sc->sc_in_num_jacks++; - } - desc = NEXT_D(desc); - remain-=descsize; - } - - /* validate some parameters */ - if (sc->sc_out_num_jacks>UMIDI_MAX_EPJACKS) - sc->sc_out_num_jacks = UMIDI_MAX_EPJACKS; - if (sc->sc_in_num_jacks>UMIDI_MAX_EPJACKS) - sc->sc_in_num_jacks = UMIDI_MAX_EPJACKS; - if (sc->sc_out_num_jacks && out_addr) { - sc->sc_out_num_endpoints = 1; - } else { - sc->sc_out_num_endpoints = 0; - sc->sc_out_num_jacks = 0; - } - if (sc->sc_in_num_jacks && in_addr) { - sc->sc_in_num_endpoints = 1; - } else { - sc->sc_in_num_endpoints = 0; - sc->sc_in_num_jacks = 0; - } - sc->sc_endpoints = malloc(sizeof(struct umidi_endpoint)* - (sc->sc_out_num_endpoints+ - sc->sc_in_num_endpoints), - M_USBDEV, M_WAITOK); - if (!sc->sc_endpoints) - return USBD_NOMEM; - if (sc->sc_out_num_endpoints) { - sc->sc_out_ep = sc->sc_endpoints; - sc->sc_out_ep->sc = sc; - sc->sc_out_ep->addr = out_addr; - sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks; - sc->sc_out_ep->num_open = 0; - memset(sc->sc_out_ep->jacks, 0, sizeof(sc->sc_out_ep->jacks)); - } else - sc->sc_out_ep = NULL; - - if (sc->sc_in_num_endpoints) { - sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints; - sc->sc_in_ep->sc = sc; - sc->sc_in_ep->addr = in_addr; - sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks; - sc->sc_in_ep->num_open = 0; - memset(sc->sc_in_ep->jacks, 0, sizeof(sc->sc_in_ep->jacks)); - } else - sc->sc_in_ep = NULL; - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -alloc_all_endpoints_genuine(struct umidi_softc *sc) -{ - usb_descriptor_t *desc; - int num_ep; - size_t remain, descsize; - struct umidi_endpoint *p, *q, *lowest, *endep, tmpep; - int epaddr; - - desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface)); - num_ep = TO_IFD(desc)->bNumEndpoints; - desc = NEXT_D(desc); /* ifd -> csifd */ - remain = ((size_t)UGETW(TO_CSIFD(desc)->wTotalLength) - - (size_t)desc->bLength); - desc = NEXT_D(desc); - - sc->sc_endpoints = p = malloc(sizeof(struct umidi_endpoint)*num_ep, - M_USBDEV, M_WAITOK); - if (!p) - return USBD_NOMEM; - - sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0; - sc->sc_out_num_endpoints = sc->sc_in_num_endpoints = 0; - epaddr = -1; - - /* get the list of endpoints for midi stream */ - while (remain>=sizeof(usb_descriptor_t)) { - descsize = desc->bLength; - if (descsize>remain || descsize==0) - break; - if (desc->bDescriptorType==UDESC_ENDPOINT && - remain>=USB_ENDPOINT_DESCRIPTOR_SIZE && - UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes) == UE_BULK) { - epaddr = TO_EPD(desc)->bEndpointAddress; - } else if (desc->bDescriptorType==UDESC_CS_ENDPOINT && - remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE && - epaddr!=-1) { - if (num_ep>0) { - num_ep--; - p->sc = sc; - p->addr = epaddr; - p->num_jacks = TO_CSEPD(desc)->bNumEmbMIDIJack; - if (UE_GET_DIR(epaddr)==UE_DIR_OUT) { - sc->sc_out_num_endpoints++; - sc->sc_out_num_jacks += p->num_jacks; - } else { - sc->sc_in_num_endpoints++; - sc->sc_in_num_jacks += p->num_jacks; - } - p++; - } - } else - epaddr = -1; - desc = NEXT_D(desc); - remain-=descsize; - } - - /* sort endpoints */ - num_ep = sc->sc_out_num_endpoints + sc->sc_in_num_endpoints; - p = sc->sc_endpoints; - endep = p + num_ep; - while (p<endep) { - lowest = p; - for (q=p+1; q<endep; q++) { - if ((UE_GET_DIR(lowest->addr)==UE_DIR_IN && - UE_GET_DIR(q->addr)==UE_DIR_OUT) || - ((UE_GET_DIR(lowest->addr)== - UE_GET_DIR(q->addr)) && - (UE_GET_ADDR(lowest->addr)> - UE_GET_ADDR(q->addr)))) - lowest = q; - } - if (lowest != p) { - memcpy((void *)&tmpep, (void *)p, sizeof(tmpep)); - memcpy((void *)p, (void *)lowest, sizeof(tmpep)); - memcpy((void *)lowest, (void *)&tmpep, sizeof(tmpep)); - } - p->num_open = 0; - p++; - } - - sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; - sc->sc_in_ep = - sc->sc_in_num_endpoints ? - sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; - - return USBD_NORMAL_COMPLETION; -} - - -/* - * jack stuffs - */ - -static usbd_status -alloc_all_jacks(struct umidi_softc *sc) -{ - int i, j; - struct umidi_endpoint *ep; - struct umidi_jack *jack, **rjack; - - /* allocate/initialize structures */ - sc->sc_jacks = - malloc(sizeof(*sc->sc_out_jacks)*(sc->sc_in_num_jacks+ - sc->sc_out_num_jacks), - M_USBDEV, M_WAITOK); - if (!sc->sc_jacks) - return USBD_NOMEM; - sc->sc_out_jacks = - sc->sc_out_num_jacks ? sc->sc_jacks : NULL; - sc->sc_in_jacks = - sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL; - - jack = &sc->sc_out_jacks[0]; - for (i=0; i<sc->sc_out_num_jacks; i++) { - jack->opened = 0; - jack->binded = 0; - jack->arg = NULL; - jack->u.out.intr = NULL; - jack->cable_number = i; - jack++; - } - jack = &sc->sc_in_jacks[0]; - for (i=0; i<sc->sc_in_num_jacks; i++) { - jack->opened = 0; - jack->binded = 0; - jack->arg = NULL; - jack->u.in.intr = NULL; - jack->cable_number = i; - jack++; - } - - /* assign each jacks to each endpoints */ - jack = &sc->sc_out_jacks[0]; - ep = &sc->sc_out_ep[0]; - for (i=0; i<sc->sc_out_num_endpoints; i++) { - rjack = &ep->jacks[0]; - for (j=0; j<ep->num_jacks; j++) { - *rjack = jack; - jack->endpoint = ep; - jack++; - rjack++; - } - ep++; - } - jack = &sc->sc_in_jacks[0]; - ep = &sc->sc_in_ep[0]; - for (i=0; i<sc->sc_in_num_endpoints; i++) { - rjack = &ep->jacks[0]; - for (j=0; j<ep->num_jacks; j++) { - *rjack = jack; - jack->endpoint = ep; - jack++; - rjack++; - } - ep++; - } - - return USBD_NORMAL_COMPLETION; -} - -static void -free_all_jacks(struct umidi_softc *sc) -{ - int s; - - s = splaudio(); - if (sc->sc_out_jacks) { - free(sc->sc_jacks, M_USBDEV); - sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL; - } - splx(s); -} - -static usbd_status -bind_jacks_to_mididev(struct umidi_softc *sc, - struct umidi_jack *out_jack, - struct umidi_jack *in_jack, - struct umidi_mididev *mididev) -{ - if ((out_jack && out_jack->binded) || (in_jack && in_jack->binded)) - return USBD_IN_USE; - if (mididev->out_jack || mididev->in_jack) - return USBD_IN_USE; - - if (out_jack) - out_jack->binded = 1; - if (in_jack) - in_jack->binded = 1; - mididev->in_jack = in_jack; - mididev->out_jack = out_jack; - - return USBD_NORMAL_COMPLETION; -} - -static void -unbind_jacks_from_mididev(struct umidi_mididev *mididev) -{ - if ((mididev->flags&FWRITE) && mididev->out_jack) - close_out_jack(mididev->out_jack); - if ((mididev->flags&FWRITE) && mididev->in_jack) - close_in_jack(mididev->in_jack); - - if (mididev->out_jack) - mididev->out_jack->binded = 0; - if (mididev->in_jack) - mididev->in_jack->binded = 0; - mididev->out_jack = mididev->in_jack = NULL; -} - -static void -unbind_all_jacks(struct umidi_softc *sc) -{ - int i; - - if (sc->sc_mididevs) - for (i=0; i<sc->sc_num_mididevs; i++) { - unbind_jacks_from_mididev(&sc->sc_mididevs[i]); - } -} - -static usbd_status -assign_all_jacks_automatically(struct umidi_softc *sc) -{ - usbd_status err; - int i; - struct umidi_jack *out, *in; - - err = - alloc_all_mididevs(sc, - max(sc->sc_out_num_jacks, sc->sc_in_num_jacks)); - if (err!=USBD_NORMAL_COMPLETION) - return err; - - for (i=0; i<sc->sc_num_mididevs; i++) { - out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i]:NULL; - in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i]:NULL; - err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]); - if (err!=USBD_NORMAL_COMPLETION) { - free_all_mididevs(sc); - return err; - } - } - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *)) -{ - struct umidi_endpoint *ep = jack->endpoint; - - if (jack->opened) - return USBD_IN_USE; - - jack->arg = arg; - jack->u.out.intr = intr; - init_packet(&jack->packet); - jack->opened = 1; - ep->num_open++; - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int)) -{ - usbd_status err = USBD_NORMAL_COMPLETION; - struct umidi_endpoint *ep = jack->endpoint; - - if (jack->opened) - return USBD_IN_USE; - - jack->arg = arg; - jack->u.in.intr = intr; - jack->opened = 1; - if (ep->num_open++==0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) { - err = start_input_transfer(ep); - if (err!=USBD_NORMAL_COMPLETION) { - ep->num_open--; - } - } - - return err; -} - -static void -close_out_jack(struct umidi_jack *jack) -{ - struct umidi_jack *tail; - int s; - - if (jack->opened) { - s = splusb(); - LIST_REMOVE(jack, u.out.queue_entry); - if (jack==jack->endpoint->queue_tail) { - /* find tail */ - LIST_FOREACH(tail, - &jack->endpoint->queue_head, - u.out.queue_entry) { - if (!LIST_NEXT(tail, u.out.queue_entry)) { - jack->endpoint->queue_tail = tail; - } - } - } - splx(s); - jack->opened = 0; - jack->endpoint->num_open--; - } -} - -static void -close_in_jack(struct umidi_jack *jack) -{ - if (jack->opened) { - jack->opened = 0; - jack->endpoint->num_open--; - } -} - -static usbd_status -attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev) -{ - if (mididev->sc) - return USBD_IN_USE; - - mididev->sc = sc; - - mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, &sc->sc_dev); - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -detach_mididev(struct umidi_mididev *mididev, int flags) -{ - if (!mididev->sc) - return USBD_NO_ADDR; - - if (mididev->opened) { - umidi_close(mididev); - } - unbind_jacks_from_mididev(mididev); - - if (mididev->mdev) - config_detach(mididev->mdev, flags); - - mididev->sc = NULL; - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -deactivate_mididev(struct umidi_mididev *mididev) -{ - if (mididev->out_jack) - mididev->out_jack->binded = 0; - if (mididev->in_jack) - mididev->in_jack->binded = 0; - config_deactivate(mididev->mdev); - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -alloc_all_mididevs(struct umidi_softc *sc, int nmidi) -{ - sc->sc_num_mididevs = nmidi; - sc->sc_mididevs = malloc(sizeof(*sc->sc_mididevs)*nmidi, - M_USBDEV, M_WAITOK|M_ZERO); - if (!sc->sc_mididevs) - return USBD_NOMEM; - - return USBD_NORMAL_COMPLETION; -} - -static void -free_all_mididevs(struct umidi_softc *sc) -{ - sc->sc_num_mididevs = 0; - if (sc->sc_mididevs) - free(sc->sc_mididevs, M_USBDEV); -} - -static usbd_status -attach_all_mididevs(struct umidi_softc *sc) -{ - usbd_status err; - int i; - - if (sc->sc_mididevs) - for (i=0; i<sc->sc_num_mididevs; i++) { - err = attach_mididev(sc, &sc->sc_mididevs[i]); - if (err!=USBD_NORMAL_COMPLETION) - return err; - } - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -detach_all_mididevs(struct umidi_softc *sc, int flags) -{ - usbd_status err; - int i; - - if (sc->sc_mididevs) - for (i=0; i<sc->sc_num_mididevs; i++) { - err = detach_mididev(&sc->sc_mididevs[i], flags); - if (err!=USBD_NORMAL_COMPLETION) - return err; - } - - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -deactivate_all_mididevs(struct umidi_softc *sc) -{ - usbd_status err; - int i; - - if (sc->sc_mididevs) - for (i=0; i<sc->sc_num_mididevs; i++) { - err = deactivate_mididev(&sc->sc_mididevs[i]); - if (err!=USBD_NORMAL_COMPLETION) - return err; - } - - return USBD_NORMAL_COMPLETION; -} - -#ifdef UMIDI_DEBUG -static void -dump_sc(struct umidi_softc *sc) -{ - int i; - - DPRINTFN(10, ("%s: dump_sc\n", USBDEVNAME(sc->sc_dev))); - for (i=0; i<sc->sc_out_num_endpoints; i++) { - DPRINTFN(10, ("\tout_ep(%p):\n", &sc->sc_out_ep[i])); - dump_ep(&sc->sc_out_ep[i]); - } - for (i=0; i<sc->sc_in_num_endpoints; i++) { - DPRINTFN(10, ("\tin_ep(%p):\n", &sc->sc_in_ep[i])); - dump_ep(&sc->sc_in_ep[i]); - } -} - -static void -dump_ep(struct umidi_endpoint *ep) -{ - int i; - for (i=0; i<ep->num_jacks; i++) { - DPRINTFN(10, ("\t\tjack(%p):\n", ep->jacks[i])); - dump_jack(ep->jacks[i]); - } -} -static void -dump_jack(struct umidi_jack *jack) -{ - DPRINTFN(10, ("\t\t\tep=%p, mididev=%p\n", - jack->endpoint, jack->mididev)); -} - -#endif /* UMIDI_DEBUG */ - - - -/* - * MUX MIDI PACKET - */ - -static const int packet_length[16] = { - /*0*/ -1, - /*1*/ -1, - /*2*/ 2, - /*3*/ 3, - /*4*/ 3, - /*5*/ 1, - /*6*/ 2, - /*7*/ 3, - /*8*/ 3, - /*9*/ 3, - /*A*/ 3, - /*B*/ 3, - /*C*/ 2, - /*D*/ 2, - /*E*/ 3, - /*F*/ 1, -}; - -static const struct { - int cin; - packet_state_t next; -} packet_0xFX[16] = { - /*F0: SysEx */ { 0x04, PS_EXCL_1 }, - /*F1: MTC */ { 0x02, PS_NORMAL_1OF2 }, - /*F2: S.POS */ { 0x03, PS_NORMAL_1OF3 }, - /*F3: S.SEL */ { 0x02, PS_NORMAL_1OF2 }, - /*F4: UNDEF */ { 0x00, PS_INITIAL }, - /*F5: UNDEF */ { 0x00, PS_INITIAL }, - /*F6: Tune */ { 0x0F, PS_END }, - /*F7: EofEx */ { 0x00, PS_INITIAL }, - /*F8: Timing */ { 0x0F, PS_END }, - /*F9: UNDEF */ { 0x00, PS_INITIAL }, - /*FA: Start */ { 0x0F, PS_END }, - /*FB: Cont */ { 0x0F, PS_END }, - /*FC: Stop */ { 0x0F, PS_END }, - /*FD: UNDEF */ { 0x00, PS_INITIAL }, - /*FE: ActS */ { 0x0F, PS_END }, - /*FF: Reset */ { 0x0F, PS_END }, -}; - -#define GET_CN(p) (((unsigned char)(p)>>4)&0x0F) -#define GET_CIN(p) ((unsigned char)(p)&0x0F) -#define MIX_CN_CIN(cn, cin) \ - ((unsigned char)((((unsigned char)(cn)&0x0F)<<4)| \ - ((unsigned char)(cin)&0x0F))) - -static void -init_packet(struct umidi_packet *packet) -{ - memset(packet->buffer, 0, UMIDI_PACKET_SIZE); - packet->state = PS_INITIAL; -} - -static usbd_status -start_input_transfer(struct umidi_endpoint *ep) -{ - usbd_setup_xfer(ep->xfer, ep->pipe, - (usbd_private_handle)ep, - ep->buffer, UMIDI_PACKET_SIZE, - USBD_NO_COPY, USBD_NO_TIMEOUT, in_intr); - return usbd_transfer(ep->xfer); -} - -static usbd_status -start_output_transfer(struct umidi_endpoint *ep) -{ - usbd_setup_xfer(ep->xfer, ep->pipe, - (usbd_private_handle)ep, - ep->buffer, UMIDI_PACKET_SIZE, - USBD_NO_COPY, USBD_NO_TIMEOUT, out_intr); - return usbd_transfer(ep->xfer); -} - -#ifdef UMIDI_DEBUG -#define DPR_PACKET(dir, sc, p) \ -if ((unsigned char)(p)->buffer[1]!=0xFE) \ - DPRINTFN(500, \ - ("%s: umidi packet(" #dir "): %02X %02X %02X %02X\n", \ - USBDEVNAME(sc->sc_dev), \ - (unsigned char)(p)->buffer[0], \ - (unsigned char)(p)->buffer[1], \ - (unsigned char)(p)->buffer[2], \ - (unsigned char)(p)->buffer[3])); -#else -#define DPR_PACKET(dir, sc, p) -#endif - -static int -out_jack_output(struct umidi_jack *out_jack, int d) -{ - struct umidi_endpoint *ep = out_jack->endpoint; - struct umidi_softc *sc = ep->sc; - int error; - int s; - - if (sc->sc_dying) - return EIO; - - error = 0; - if (out_jack->opened) { - DPRINTFN(1000, ("umidi_output: ep=%p 0x%02x\n", ep, d)); - out_build_packet(out_jack->cable_number, &out_jack->packet, d); - switch (out_jack->packet.state) { - case PS_EXCL_0: - case PS_END: - DPR_PACKET(out, sc, &out_jack->packet); - s = splusb(); - if (LIST_EMPTY(&ep->queue_head)) { - memcpy(ep->buffer, - out_jack->packet.buffer, - UMIDI_PACKET_SIZE); - start_output_transfer(ep); - } - if (LIST_EMPTY(&ep->queue_head)) - LIST_INSERT_HEAD(&ep->queue_head, - out_jack, u.out.queue_entry); - else - LIST_INSERT_AFTER(ep->queue_tail, - out_jack, u.out.queue_entry); - ep->queue_tail = out_jack; - splx(s); - break; - default: - error = EINPROGRESS; - } - } else - error = ENODEV; - - return error; -} - -static void -in_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - int cn, len, i; - struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; - struct umidi_jack *jack; - - if (ep->sc->sc_dying || !ep->num_open) - return; - - cn = GET_CN(ep->buffer[0]); - len = packet_length[GET_CIN(ep->buffer[0])]; - jack = ep->jacks[cn]; - if (cn>=ep->num_jacks || !jack) { - DPRINTF(("%s: stray umidi packet (in): %02X %02X %02X %02X\n", - USBDEVNAME(ep->sc->sc_dev), - (unsigned)ep->buffer[0], - (unsigned)ep->buffer[1], - (unsigned)ep->buffer[2], - (unsigned)ep->buffer[3])); - return; - } - if (!jack->binded || !jack->opened) - return; - DPR_PACKET(in, ep->sc, &jack->buffer); - if (jack->u.in.intr) { - for (i=0; i<len; i++) { - (*jack->u.in.intr)(jack->arg, ep->buffer[i+1]); - } - } - - (void)start_input_transfer(ep); -} - -static void -out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; - struct umidi_softc *sc = ep->sc; - struct umidi_jack *jack; - - if (sc->sc_dying || !ep->num_open) - return; - - jack = LIST_FIRST(&ep->queue_head); - if (jack && jack->opened) { - LIST_REMOVE(jack, u.out.queue_entry); - if (!LIST_EMPTY(&ep->queue_head)) { - memcpy(ep->buffer, - LIST_FIRST(&ep->queue_head)->packet.buffer, - UMIDI_PACKET_SIZE); - (void)start_output_transfer(ep); - } - if (jack->u.out.intr) { - (*jack->u.out.intr)(jack->arg); - } - } -} - -static void -out_build_packet(int cable_number, struct umidi_packet *packet, uByte in) -{ - int cin; - uByte prev; - -retry: - switch (packet->state) { - case PS_END: - case PS_INITIAL: - prev = packet->buffer[1]; - memset(packet->buffer, 0, UMIDI_PACKET_SIZE); - if (in<0x80) { - if (prev>=0x80 && prev<0xf0) { - /* running status */ - out_build_packet(cable_number, packet, prev); - goto retry; - } - /* ??? */ - break; - } - if (in>=0xf0) { - cin=packet_0xFX[in&0x0F].cin; - packet->state=packet_0xFX[in&0x0F].next; - } else { - cin=(unsigned char)in>>4; - switch (packet_length[cin]) { - case 2: - packet->state = PS_NORMAL_1OF2; - break; - case 3: - packet->state = PS_NORMAL_1OF3; - break; - default: - /* ??? */ - packet->state = PS_INITIAL; - } - } - packet->buffer[0] = MIX_CN_CIN(cable_number, cin); - packet->buffer[1] = in; - break; - case PS_NORMAL_1OF3: - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[2] = in; - packet->state = PS_NORMAL_2OF3; - break; - case PS_NORMAL_2OF3: - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[3] = in; - packet->state = PS_END; - break; - case PS_NORMAL_1OF2: - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[2] = in; - packet->state = PS_END; - break; - case PS_EXCL_0: - memset(packet->buffer, 0, UMIDI_PACKET_SIZE); - if (in==0xF7) { - packet->buffer[0] = MIX_CN_CIN(cable_number, 0x05); - packet->buffer[1] = 0xF7; - packet->state = PS_END; - break; - } - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[1] = in; - packet->state = PS_EXCL_1; - break; - case PS_EXCL_1: - if (in==0xF7) { - packet->buffer[0] = MIX_CN_CIN(cable_number, 0x06); - packet->buffer[2] = 0xF7; - packet->state = PS_END; - break; - } - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[2] = in; - packet->state = PS_EXCL_2; - break; - case PS_EXCL_2: - if (in==0xF7) { - packet->buffer[0] = MIX_CN_CIN(cable_number, 0x07); - packet->buffer[3] = 0xF7; - packet->state = PS_END; - break; - } - if (in>=0x80) { /* ??? */ packet->state = PS_END; break; } - packet->buffer[0] = MIX_CN_CIN(cable_number, 0x04); - packet->buffer[3] = in; - packet->state = PS_EXCL_0; - break; - default: - printf("umidi: ambiguous state.\n"); - packet->state = PS_INITIAL; - goto retry; - } -} - diff --git a/sys/dev/usb/umidi_quirks.c b/sys/dev/usb/umidi_quirks.c deleted file mode 100644 index a7ae1ee27f4..00000000000 --- a/sys/dev/usb/umidi_quirks.c +++ /dev/null @@ -1,215 +0,0 @@ -/* $OpenBSD: umidi_quirks.c,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umidi_quirks.c,v 1.3 2001/11/13 06:24:56 lukem Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/device.h> -#include <sys/ioctl.h> -#include <sys/conf.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/proc.h> -#include <sys/vnode.h> -#include <sys/poll.h> -#include <sys/lock.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include <dev/usb/usbdevs.h> -#include <dev/usb/uaudioreg.h> -#include <dev/usb/umidireg.h> -#include <dev/usb/umidivar.h> -#include <dev/usb/umidi_quirks.h> - -/* - * quirk codes for UMIDI - */ - -#ifdef UMIDIQUIRK_DEBUG -#define DPRINTF(x) if (umidiquirkdebug) printf x -#define DPRINTFN(n,x) if (umidiquirkdebug >= (n)) printf x -int umidiquirkdebug = 1; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - - -/* - * YAMAHA UX-256 - * --- this is a typical yamaha device, but has a broken descriptor :-< - */ - -UMQ_FIXED_EP_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE, 1, 1) = { - /* out */ - { 0, 16 }, - /* in */ - { 1, 8 } -}; - -UMQ_DEF(YAMAHA, YAMAHA_UX256, ANYIFACE) = { - UMQ_FIXED_EP_REG(YAMAHA, YAMAHA_UX256, ANYIFACE), -#if 0 - UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE), -#endif - UMQ_TERMINATOR -}; - - -/* - * YAMAHA generic - */ -UMQ_DEF(YAMAHA, ANYPRODUCT, ANYIFACE) = { - UMQ_YAMAHA_REG(YAMAHA, ANYPRODUCT, ANYIFACE), - UMQ_TERMINATOR -}; - - -/* - * ROLAND UM-1 - */ -UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM1, 2, 1, 1) = { - /* out */ - { 0, 1 }, - /* in */ - { 1, 1 } -}; - -UMQ_DEF(ROLAND, ROLAND_UM1, 2) = { - UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM1, 2), - UMQ_TERMINATOR -}; - - -/* - * ROLAND UM-880 (native mode) - */ -UMQ_FIXED_EP_DEF(ROLAND, ROLAND_UM880N, 0, 1, 1) = { - /* out */ - { 0, 9 }, - /* in */ - { 1, 9 } -}; - -UMQ_DEF(ROLAND, ROLAND_UM880N, 0) = { - UMQ_FIXED_EP_REG(ROLAND, ROLAND_UM880N, 0), - UMQ_TERMINATOR -}; - - - -/* - * quirk list - */ -struct umidi_quirk umidi_quirklist[] = { - UMQ_REG(YAMAHA, YAMAHA_UX256, ANYIFACE), - UMQ_REG(YAMAHA, ANYPRODUCT, ANYIFACE), - UMQ_REG(ROLAND, ROLAND_UM1, 2), - UMQ_REG(ROLAND, ROLAND_UM880N, 0), - UMQ_TERMINATOR -}; - - -/* - * quirk utilities - */ - -struct umidi_quirk * -umidi_search_quirk(int vendor, int product, int ifaceno) -{ - struct umidi_quirk *p; - struct umq_data *q; - - DPRINTF(("umidi_search_quirk: v=%d, p=%d, i=%d\n", - vendor, product, ifaceno)); - - for (p=&umidi_quirklist[0]; p->vendor; p++) { - DPRINTFN(10, ("\tv=%d, p=%d, i=%d", - p->vendor, p->product, p->iface)); - if ((p->vendor==vendor || p->vendor==ANYVENDOR) && - (p->product==product || p->product==ANYPRODUCT) && - (p->iface==ifaceno || p->iface==ANYIFACE)) { - DPRINTFN(10, (" found\n")); - if (!p->type_mask) - /* make quirk mask */ - for (q=p->quirks; q->type; q++) - p->type_mask |= 1<<(q->type-1); - return p; - } - DPRINTFN(10, ("\n")); - } - - return NULL; -} - -static char *quirk_name[] = { - "NULL", - "Fixed Endpoint", - "Yamaha Specific", -}; - -void -umidi_print_quirk(struct umidi_quirk *q) -{ - struct umq_data *qd; - if (q) { - printf("("); - for (qd=q->quirks; qd->type; qd++) - printf("%s%s", quirk_name[qd->type], - (qd+1)->type?", ":")\n"); - } else { - printf("(genuine USB-MIDI)\n"); - } -} - -void * -umidi_get_quirk_data_from_type(struct umidi_quirk *q, u_int32_t type) -{ - struct umq_data *qd; - if (q) { - for (qd=q->quirks; qd->type; qd++) - if (qd->type == type) - return qd->data; - } - return NULL; -} diff --git a/sys/dev/usb/umidi_quirks.h b/sys/dev/usb/umidi_quirks.h deleted file mode 100644 index ea1f503d756..00000000000 --- a/sys/dev/usb/umidi_quirks.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $OpenBSD: umidi_quirks.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umidi_quirks.h,v 1.2 2001/09/29 22:00:47 tshiozak Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * quirk code for UMIDI - */ - -#ifndef _DEV_USB_UMIDI_QUIRKS_H_ -#define _DEV_USB_UMIDI_QUIRKS_H_ - -struct umq_data { - int type; -#define UMQ_TYPE_FIXED_EP 1 -#define UMQ_TYPE_YAMAHA 2 - void *data; -}; - -struct umidi_quirk { - int vendor; - int product; - int iface; - struct umq_data *quirks; - u_int32_t type_mask; -}; -#define UMQ_ISTYPE(q, type) \ - ((q)->sc_quirk && ((q)->sc_quirk->type_mask & (1<<((type)-1)))) - -#define UMQ_TERMINATOR { 0, } -#define UMQ_DEF(v, p, i) \ -static struct umq_data umq_##v##_##p##_##i[] -#define UMQ_REG(v, p, i) \ - { USB_VENDOR_##v, USB_PRODUCT_##p, i, \ - umq_##v##_##p##_##i, 0 } -#define ANYIFACE -1 -#define ANYVENDOR -1 -#define USB_VENDOR_ANYVENDOR ANYVENDOR -#define ANYPRODUCT -1 -#define USB_PRODUCT_ANYPRODUCT ANYPRODUCT - -/* - * quirk - fixed port - */ - -struct umq_fixed_ep_endpoint { - int ep; - int num_jacks; -}; -struct umq_fixed_ep_desc { - int num_out_ep; - int num_in_ep; - struct umq_fixed_ep_endpoint *out_ep; - struct umq_fixed_ep_endpoint *in_ep; -}; - -#define UMQ_FIXED_EP_DEF(v, p, i, noep, niep) \ -static struct umq_fixed_ep_endpoint \ -umq_##v##_##p##_##i##_fixed_ep_endpoints[noep+niep]; \ -static struct umq_fixed_ep_desc \ -umq_##v##_##p##_##i##_fixed_ep_desc = { \ - noep, niep, \ - &umq_##v##_##p##_##i##_fixed_ep_endpoints[0], \ - &umq_##v##_##p##_##i##_fixed_ep_endpoints[noep], \ -}; \ -static struct umq_fixed_ep_endpoint \ -umq_##v##_##p##_##i##_fixed_ep_endpoints[noep+niep] - -#define UMQ_FIXED_EP_REG(v, p, i) \ -{ UMQ_TYPE_FIXED_EP, (void *)&umq_##v##_##p##_##i##_fixed_ep_desc } - - -/* - * quirk - yamaha style midi I/F - */ -#define UMQ_YAMAHA_REG(v, p, i) \ -{ UMQ_TYPE_YAMAHA, NULL } - - -/* extern struct umidi_quirk umidi_quirklist[]; */ -struct umidi_quirk *umidi_search_quirk(int, int, int); -void umidi_print_quirk(struct umidi_quirk *); -void *umidi_get_quirk_data_from_type(struct umidi_quirk *, u_int32_t); - -#endif diff --git a/sys/dev/usb/umidireg.h b/sys/dev/usb/umidireg.h deleted file mode 100644 index f9fd240a1f6..00000000000 --- a/sys/dev/usb/umidireg.h +++ /dev/null @@ -1,80 +0,0 @@ -/* $OpenBSD: umidireg.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umidireg.h,v 1.2 2001/05/28 20:52:06 tshiozak Exp $ */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* Jack Descriptor */ -#define UMIDI_MS_HEADER 0x01 -#define UMIDI_IN_JACK 0x02 -#define UMIDI_OUT_JACK 0x03 - -/* Jack Type */ -#define UMIDI_EMBEDDED 0x01 -#define UMIDI_EXTERNAL 0x02 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uWord bcdMSC; - uWord wTotalLength; -} UPACKED umidi_cs_interface_descriptor_t; -#define UMIDI_CS_INTERFACE_DESCRIPTOR_SIZE 7 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubType; - uByte bNumEmbMIDIJack; -} UPACKED umidi_cs_endpoint_descriptor_t; -#define UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE 4 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bJackType; - uByte bJackID; -} UPACKED umidi_jack_descriptor_t; -#define UMIDI_JACK_DESCRIPTOR_SIZE 5 - - -#define TO_D(p) ((usb_descriptor_t *)(p)) -#define NEXT_D(desc) TO_D((caddr_t)(desc)+(desc)->bLength) -#define TO_IFD(desc) ((usb_interface_descriptor_t *)(desc)) -#define TO_CSIFD(desc) ((umidi_cs_interface_descriptor_t *)(desc)) -#define TO_EPD(desc) ((usb_endpoint_descriptor_t *)(desc)) -#define TO_CSEPD(desc) ((umidi_cs_endpoint_descriptor_t *)(desc)) diff --git a/sys/dev/usb/umidivar.h b/sys/dev/usb/umidivar.h deleted file mode 100644 index d11d69b0303..00000000000 --- a/sys/dev/usb/umidivar.h +++ /dev/null @@ -1,138 +0,0 @@ -/* $OpenBSD: umidivar.h,v 1.1 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umidivar.h,v 1.3 2001/02/03 18:50:32 tshiozak Exp $ */ -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Takuya SHIOZAKI (tshiozak@netbsd.org). - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* pending MUX-MIDI packet */ -typedef enum { - PS_EXCL_0=-2, /* put, and next state is PS_EXCL_0 */ - PS_END=-1, /* put, and next state is PS_INITIAL */ - PS_INITIAL=0, /* 0>= : not put, and state is keeped */ - PS_NORMAL_1OF3=1, - PS_NORMAL_2OF3=2, - PS_NORMAL_1OF2=3, - PS_EXCL_1=4, - PS_EXCL_2=5, -} packet_state_t; - -#define UMIDI_PACKET_SIZE 4 -struct umidi_packet { - char buffer[UMIDI_PACKET_SIZE]; - packet_state_t state; -}; - -/* - * hierarchie - * - * <-- parent child --> - * - * umidi(sc) -> endpoint -> jack <- (dynamically assignable) - mididev - * ^ | ^ | - * +-----+ +-----+ - */ - -/* midi device */ -struct umidi_mididev { - struct umidi_softc *sc; - struct device *mdev; - /* */ - struct umidi_jack *in_jack; - struct umidi_jack *out_jack; - /* */ - int opened; - int flags; -}; - -/* Jack Information */ -struct umidi_jack { - struct umidi_endpoint *endpoint; - /* */ - int cable_number; - struct umidi_packet packet; - void *arg; - int binded; - int opened; - union { - struct { - void (*intr)(void *); - LIST_ENTRY(umidi_jack) queue_entry; - } out; - struct { - void (*intr)(void *, int); - } in; - } u; -}; - -#define UMIDI_MAX_EPJACKS 16 -/* endpoint data */ -struct umidi_endpoint { - struct umidi_softc *sc; - /* */ - int addr; - usbd_pipe_handle pipe; - usbd_xfer_handle xfer; - char *buffer; - int num_open; - int num_jacks; - struct umidi_jack *jacks[UMIDI_MAX_EPJACKS]; - LIST_HEAD(, umidi_jack) queue_head; - struct umidi_jack *queue_tail; -}; - -/* software context */ -struct umidi_softc { - USBBASEDEVICE sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - struct umidi_quirk *sc_quirk; - - int sc_dying; - - int sc_out_num_jacks; - struct umidi_jack *sc_out_jacks; - int sc_in_num_jacks; - struct umidi_jack *sc_in_jacks; - struct umidi_jack *sc_jacks; - - int sc_num_mididevs; - struct umidi_mididev *sc_mididevs; - - int sc_out_num_endpoints; - struct umidi_endpoint *sc_out_ep; - int sc_in_num_endpoints; - struct umidi_endpoint *sc_in_ep; - struct umidi_endpoint *sc_endpoints; -}; diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c index 9dbd15e2166..9a7aec9aa63 100644 --- a/sys/dev/usb/umodem.c +++ b/sys/dev/usb/umodem.c @@ -1,5 +1,5 @@ -/* $OpenBSD: umodem.c,v 1.8 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: umodem.c,v 1.41 2001/11/13 06:24:56 lukem Exp $ */ +/* $OpenBSD: umodem.c,v 1.9 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: umodem.c,v 1.40 2001/03/25 23:02:34 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -137,7 +137,7 @@ Static void umodem_rts(struct umodem_softc *, int); Static void umodem_break(struct umodem_softc *, int); Static void umodem_set_line_state(struct umodem_softc *); Static int umodem_param(void *, int, struct termios *); -Static int umodem_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr); +Static int umodem_ioctl(void *, int, u_long, caddr_t, int, struct proc *); Static int umodem_open(void *, int portno); Static void umodem_close(void *, int portno); Static void umodem_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); @@ -524,7 +524,7 @@ umodem_param(void *addr, int portno, struct termios *t) int umodem_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - usb_proc_ptr p) + struct proc *p) { struct umodem_softc *sc = addr; int error = 0; diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c index d2b058ca11e..8bd88b43c81 100644 --- a/sys/dev/usb/ums.c +++ b/sys/dev/usb/ums.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ums.c,v 1.7 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: ums.c,v 1.55 2001/12/31 12:15:22 augustss Exp $ */ +/* $OpenBSD: ums.c,v 1.8 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: ums.c,v 1.49 2001/10/26 17:58:21 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,6 +42,8 @@ * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf */ +/* XXX complete SPUR_UP change */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -62,7 +64,6 @@ #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdevs.h> #include <dev/usb/usb_quirks.h> -#include <dev/usb/uhidev.h> #include <dev/usb/hid.h> #include <dev/wscons/wsconsio.h> @@ -86,13 +87,18 @@ int umsdebug = 0; #define PS2MBUTMASK x04 #define PS2BUTMASK 0x0f -#define MAX_BUTTONS 7 /* must not exceed size of sc_buttons */ - struct ums_softc { - struct uhidev sc_hdev; - + USBBASEDEVICE sc_dev; /* base device */ + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; /* interface */ + usbd_pipe_handle sc_intrpipe; /* interrupt pipe */ + int sc_ep_addr; + + u_char *sc_ibuf; + u_int8_t sc_iid; + int sc_isize; struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; - struct hid_location sc_loc_btn[MAX_BUTTONS]; + struct hid_location *sc_loc_btn; int sc_enabled; @@ -102,6 +108,7 @@ struct ums_softc { #define UMS_REVZ 0x04 /* Z-axis is reversed */ int nbuttons; +#define MAX_BUTTONS 31 /* chosen because sc_buttons is u_int32_t */ u_int32_t sc_buttons; /* mouse button status */ struct device *sc_wsmousedev; @@ -112,11 +119,11 @@ struct ums_softc { #define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) #define MOUSE_FLAGS (HIO_RELATIVE) -Static void ums_intr(struct uhidev *addr, void *ibuf, u_int len); +Static void ums_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); Static int ums_enable(void *); Static void ums_disable(void *); -Static int ums_ioctl(void *, u_long, caddr_t, int, usb_proc_ptr); +Static int ums_ioctl(void *, u_long, caddr_t, int, struct proc *); const struct wsmouse_accessops ums_accessops = { ums_enable, @@ -129,72 +136,115 @@ USB_DECLARE_DRIVER(ums); USB_MATCH(ums) { USB_MATCH_START(ums, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; - int size; + usb_interface_descriptor_t *id; + int size, ret; void *desc; + usbd_status err; - uhidev_get_report_desc(uha->parent, &desc, &size); - if (!hid_is_collection(desc, size, uha->reportid, - HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) + if (uaa->iface == NULL) + return (UMATCH_NONE); + id = usbd_get_interface_descriptor(uaa->iface); + if (id == NULL || id->bInterfaceClass != UICLASS_HID) return (UMATCH_NONE); - return (UMATCH_IFACECLASS); + err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP); + if (err) + return (UMATCH_NONE); + + if (hid_is_collection(desc, size, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) + ret = UMATCH_IFACECLASS; + else + ret = UMATCH_NONE; + + free(desc, M_TEMP); + return (ret); } USB_ATTACH(ums) { USB_ATTACH_START(ums, sc, uaa); - struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; + usbd_interface_handle iface = uaa->iface; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; struct wsmousedev_attach_args a; int size; void *desc; + usbd_status err; + char devinfo[1024]; u_int32_t flags, quirks; int i, wheel; struct hid_location loc_btn; + + sc->sc_udev = uaa->device; + sc->sc_iface = iface; + id = usbd_get_interface_descriptor(iface); + usbd_devinfo(uaa->device, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), + devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + ed = usbd_interface2endpoint_descriptor(iface, 0); + if (ed == NULL) { + printf("%s: could not read endpoint descriptor\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } - sc->sc_hdev.sc_intr = ums_intr; - sc->sc_hdev.sc_parent = uha->parent; - sc->sc_hdev.sc_report_id = uha->reportid; + DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d " + "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" + " bInterval=%d\n", + ed->bLength, ed->bDescriptorType, + ed->bEndpointAddress & UE_ADDR, + UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", + ed->bmAttributes & UE_XFERTYPE, + UGETW(ed->wMaxPacketSize), ed->bInterval)); + + if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || + (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { + printf("%s: unexpected endpoint\n", + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } - quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags; + quirks = usbd_get_quirks(uaa->device)->uq_flags; if (quirks & UQ_MS_REVZ) sc->flags |= UMS_REVZ; if (quirks & UQ_SPUR_BUT_UP) sc->flags |= UMS_SPUR_BUT_UP; - uhidev_get_report_desc(uha->parent, &desc, &size); + err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP); + if (err) + USB_ATTACH_ERROR_RETURN; if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), - uha->reportid, hid_input, &sc->sc_loc_x, &flags)) { - printf("\n%s: mouse has no X report\n", - USBDEVNAME(sc->sc_hdev.sc_dev)); + hid_input, &sc->sc_loc_x, &flags)) { + printf("%s: mouse has no X report\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("\n%s: X report 0x%04x not supported\n", - USBDEVNAME(sc->sc_hdev.sc_dev), flags); + printf("%s: X report 0x%04x not supported\n", + USBDEVNAME(sc->sc_dev), flags); USB_ATTACH_ERROR_RETURN; } if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), - uha->reportid, hid_input, &sc->sc_loc_y, &flags)) { - printf("\n%s: mouse has no Y report\n", - USBDEVNAME(sc->sc_hdev.sc_dev)); + hid_input, &sc->sc_loc_y, &flags)) { + printf("%s: mouse has no Y report\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("\n%s: Y report 0x%04x not supported\n", - USBDEVNAME(sc->sc_hdev.sc_dev), flags); + printf("%s: Y report 0x%04x not supported\n", + USBDEVNAME(sc->sc_dev), flags); USB_ATTACH_ERROR_RETURN; } /* Try to guess the Z activator: first check Z, then WHEEL. */ wheel = 0; if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), - uha->reportid, hid_input, &sc->sc_loc_z, &flags) || + hid_input, &sc->sc_loc_z, &flags) || (wheel = hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), - uha->reportid, hid_input, &sc->sc_loc_z, &flags))) { + hid_input, &sc->sc_loc_z, &flags))) { if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ } else { @@ -208,18 +258,34 @@ USB_ATTACH(ums) /* figure out the number of buttons */ for (i = 1; i <= MAX_BUTTONS; i++) if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - uha->reportid, hid_input, &loc_btn, 0)) + hid_input, &loc_btn, 0)) break; sc->nbuttons = i - 1; + sc->sc_loc_btn = malloc(sizeof(struct hid_location) * sc->nbuttons, + M_USBDEV, M_NOWAIT); + if (!sc->sc_loc_btn) { + printf("%s: no memory\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } - printf(": %d button%s%s\n", + printf("%s: %d button%s%s\n", USBDEVNAME(sc->sc_dev), sc->nbuttons, sc->nbuttons == 1 ? "" : "s", sc->flags & UMS_Z ? " and Z dir." : ""); for (i = 1; i <= sc->nbuttons; i++) hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - uha->reportid, hid_input, - &sc->sc_loc_btn[i-1], 0); + hid_input, &sc->sc_loc_btn[i-1], 0); + + sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); + sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_NOWAIT); + if (sc->sc_ibuf == NULL) { + printf("%s: no memory\n", USBDEVNAME(sc->sc_dev)); + free(sc->sc_loc_btn, M_USBDEV); + USB_ATTACH_ERROR_RETURN; + } + + sc->sc_ep_addr = ed->bEndpointAddress; + free(desc, M_TEMP); #ifdef USB_DEBUG DPRINTF(("ums_attach: sc=%p\n", sc)); @@ -234,11 +300,15 @@ USB_ATTACH(ums) DPRINTF(("ums_attach: B%d\t%d/%d\n", i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size)); } + DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid)); #endif a.accessops = &ums_accessops; a.accesscookie = sc; + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, + USBDEV(sc->sc_dev)); + sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); USB_ATTACH_SUCCESS_RETURN; @@ -274,21 +344,45 @@ USB_DETACH(ums) /* No need to do reference counting of ums, wsmouse has all the goo. */ if (sc->sc_wsmousedev != NULL) rv = config_detach(sc->sc_wsmousedev, flags); + if (rv == 0) { + free(sc->sc_loc_btn, M_USBDEV); + free(sc->sc_ibuf, M_USBDEV); + } + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, + USBDEV(sc->sc_dev)); return (rv); } void -ums_intr(struct uhidev *addr, void *ibuf, u_int len) +ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) { - struct ums_softc *sc = (struct ums_softc *)addr; + struct ums_softc *sc = addr; + u_char *ibuf; int dx, dy, dz; u_int32_t buttons = 0; int i; int s; - DPRINTFN(5,("ums_intr: len=%d\n", len)); + DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status)); + DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n", + sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2])); + + if (status == USBD_CANCELLED) + return; + + if (status) { + DPRINTF(("ums_intr: status=%d\n", status)); + usbd_clear_endpoint_stall_async(sc->sc_intrpipe); + return; + } + ibuf = sc->sc_ibuf; + if (sc->sc_iid != 0) { + if (*ibuf++ != sc->sc_iid) + return; + } dx = hid_get_data(ibuf, &sc->sc_loc_x); dy = -hid_get_data(ibuf, &sc->sc_loc_y); dz = hid_get_data(ibuf, &sc->sc_loc_z); @@ -316,6 +410,8 @@ ums_enable(void *v) { struct ums_softc *sc = v; + usbd_status err; + DPRINTFN(1,("ums_enable: sc=%p\n", sc)); if (sc->sc_dying) @@ -327,7 +423,17 @@ ums_enable(void *v) sc->sc_enabled = 1; sc->sc_buttons = 0; - return (uhidev_open(&sc->sc_hdev)); + /* Set up interrupt pipe. */ + err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, + USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, + sc->sc_ibuf, sc->sc_isize, ums_intr, USBD_DEFAULT_INTERVAL); + if (err) { + DPRINTF(("ums_enable: usbd_open_pipe_intr failed, error=%d\n", + err)); + sc->sc_enabled = 0; + return (EIO); + } + return (0); } Static void @@ -343,12 +449,15 @@ ums_disable(void *v) } #endif + /* Disable interrupts. */ + usbd_abort_pipe(sc->sc_intrpipe); + usbd_close_pipe(sc->sc_intrpipe); + sc->sc_enabled = 0; - return (uhidev_close(&sc->sc_hdev)); } Static int -ums_ioctl(void *v, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) +ums_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { switch (cmd) { diff --git a/sys/dev/usb/uplcom.c b/sys/dev/usb/uplcom.c index 25d26a8a871..b822f152b01 100644 --- a/sys/dev/usb/uplcom.c +++ b/sys/dev/usb/uplcom.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uplcom.c,v 1.3 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: uplcom.c,v 1.27 2002/03/16 16:10:19 ichiro Exp $ */ +/* $OpenBSD: uplcom.c,v 1.4 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: uplcom.c,v 1.20 2001/07/31 12:33:11 ichiro Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. @@ -131,7 +131,7 @@ Static void uplcom_break(struct uplcom_softc *, int); Static void uplcom_set_line_state(struct uplcom_softc *); Static void uplcom_get_status(void *, int portno, u_char *lsr, u_char *msr); #if TODO -Static int uplcom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr); +Static int uplcom_ioctl(void *, int, u_long, caddr_t, int, struct proc *); #endif Static int uplcom_param(void *, int, struct termios *); Static int uplcom_open(void *, int); @@ -148,7 +148,10 @@ struct ucom_methods uplcom_methods = { NULL, }; -static const struct usb_devno uplcom_devs[] = { +static const struct uplcom_product { + uint16_t vendor; + uint16_t product; +} uplcom_products [] = { /* I/O DATA USB-RSAQ2 */ { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2 }, /* I/O DATA USB-RSAQ */ @@ -157,28 +160,26 @@ static const struct usb_devno uplcom_devs[] = { { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A }, /* IOGEAR/ATEN UC-232A */ { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303 }, - /* ELECOM UC-SGT */ - { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT }, - /* RATOC REX-USB60 */ - { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60 }, - /* TDK USB-PHS Adapter UHA6400 */ - { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400 }, - /* TDK USB-PDC Adapter UPA9664 */ - { USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA9664 }, + { 0, 0 } }; -#define uplcom_lookup(v, p) usb_lookup(uplcom_devs, v, p) USB_DECLARE_DRIVER(uplcom); USB_MATCH(uplcom) { USB_MATCH_START(uplcom, uaa); + int i; if (uaa->iface != NULL) return (UMATCH_NONE); - return (uplcom_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); + for (i = 0; uplcom_products[i].vendor != 0; i++) { + if (uplcom_products[i].vendor == uaa->vendor && + uplcom_products[i].product == uaa->product) { + return (UMATCH_VENDOR_PRODUCT); + } + } + return (UMATCH_NONE); } USB_ATTACH(uplcom) @@ -714,7 +715,7 @@ uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) #if TODO int uplcom_ioctl(void *addr, int portno, u_long cmd, caddr_t data, int flag, - usb_proc_ptr p) + struct proc *p) { struct uplcom_softc *sc = addr; int error = 0; diff --git a/sys/dev/usb/urio.c b/sys/dev/usb/urio.c index 89492aeb019..e01c78442c9 100644 --- a/sys/dev/usb/urio.c +++ b/sys/dev/usb/urio.c @@ -1,5 +1,5 @@ -/* $OpenBSD: urio.c,v 1.7 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: urio.c,v 1.11 2002/02/11 15:11:49 augustss Exp $ */ +/* $OpenBSD: urio.c,v 1.8 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: urio.c,v 1.6 2001/09/25 21:08:44 jdolecek Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -126,13 +126,6 @@ struct urio_softc { #define URIO_RW_TIMEOUT 4000 /* ms */ -static const struct usb_devno urio_devs[] = { - { USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB}, - { USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB}, - { USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB}, -}; -#define urio_lookup(v, p) usb_lookup(urio_devs, v, p) - USB_DECLARE_DRIVER(urio); USB_MATCH(urio) @@ -144,8 +137,15 @@ USB_MATCH(urio) if (uaa->iface != NULL) return (UMATCH_NONE); - return (urio_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); + if ( ( uaa->vendor == USB_VENDOR_DIAMOND && + uaa->product == USB_PRODUCT_DIAMOND_RIO500USB ) || + ( uaa->vendor == USB_VENDOR_DIAMOND2 && + ( uaa->product == USB_PRODUCT_DIAMOND2_RIO600USB || + uaa->product == USB_PRODUCT_DIAMOND2_RIO800USB ) ) + ) + return (UMATCH_VENDOR_PRODUCT); + else + return (UMATCH_NONE); } USB_ATTACH(urio) @@ -293,7 +293,7 @@ urio_activate(device_ptr_t self, enum devact act) #endif int -urioopen(dev_t dev, int flag, int mode, usb_proc_ptr p) +urioopen(dev_t dev, int flag, int mode, struct proc *p) { struct urio_softc *sc; usbd_status err; @@ -326,7 +326,7 @@ urioopen(dev_t dev, int flag, int mode, usb_proc_ptr p) } int -urioclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +urioclose(dev_t dev, int flag, int mode, struct proc *p) { struct urio_softc *sc; USB_GET_SC(urio, URIOUNIT(dev), sc); @@ -379,7 +379,7 @@ urioread(dev_t dev, struct uio *uio, int flag) while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) { DPRINTFN(1, ("urioread: start transfer %d bytes\n", n)); tn = n; - err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY, + err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, 0, URIO_RW_TIMEOUT, bufp, &tn, "uriors"); if (err) { if (err == USBD_INTERRUPTED) @@ -441,7 +441,7 @@ uriowrite(dev_t dev, struct uio *uio, int flag) DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY, + err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, 0, URIO_RW_TIMEOUT, bufp, &n, "uriowr"); DPRINTFN(2, ("uriowrite: err=%d\n", err)); if (err) { @@ -468,7 +468,7 @@ uriowrite(dev_t dev, struct uio *uio, int flag) int -urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) +urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct urio_softc * sc; int unit = URIOUNIT(dev); @@ -544,7 +544,7 @@ urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) sc->sc_refcnt++; err = usbd_do_request_flags(sc->sc_udev, &req, ptr, req_flags, - &req_actlen, USBD_DEFAULT_TIMEOUT); + &req_actlen); if (--sc->sc_refcnt < 0) usb_detach_wakeup(USBDEV(sc->sc_dev)); @@ -563,7 +563,7 @@ ret: } int -uriopoll(dev_t dev, int events, usb_proc_ptr p) +uriopoll(dev_t dev, int events, struct proc *p) { return (0); } diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 3cc61c6bb74..cd8e4d0aa93 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,8 +1,9 @@ -/* $OpenBSD: usb.c,v 1.18 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: usb.c,v 1.69 2002/04/23 06:34:11 augustss Exp $ */ +/* $OpenBSD: usb.c,v 1.19 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: usb.c,v 1.53 2001/01/23 17:04:30 augustss Exp $ */ +/* $FreeBSD: src/sys/dev/usb/usb.c,v 1.20 1999/11/17 22:33:46 n_hibma Exp $ */ /* - * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. + * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -52,7 +53,6 @@ #include <sys/kthread.h> #include <sys/proc.h> #include <sys/conf.h> -#include <sys/fcntl.h> #include <sys/poll.h> #include <sys/select.h> #include <sys/vnode.h> @@ -79,7 +79,7 @@ int uhcidebug; #ifdef OHCI_DEBUG int ohcidebug; #endif -/* +/* * 0 - do usual exploration * 1 - do not use timeout exploration * >1 - do no exploration @@ -95,31 +95,30 @@ struct usb_softc { usbd_bus_handle sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ - usb_proc_ptr sc_event_thread; + TAILQ_HEAD(, usb_task) sc_tasks; + struct proc *sc_event_thread; + + struct usb_task sc_exp_task; char sc_dying; }; -TAILQ_HEAD(, usb_task) usb_all_tasks; - cdev_decl(usb); Static void usb_discover(void *); Static void usb_create_event_thread(void *); Static void usb_event_thread(void *); -Static void usb_task_thread(void *); -Static usb_proc_ptr usb_task_thread_proc = NULL; #define USB_MAX_EVENTS 100 struct usb_event_q { struct usb_event ue; SIMPLEQ_ENTRY(usb_event_q) next; }; -Static SIMPLEQ_HEAD(, usb_event_q) usb_events = +Static SIMPLEQ_HEAD(, usb_event_q) usb_events = SIMPLEQ_HEAD_INITIALIZER(usb_events); Static int usb_nevents = 0; Static struct selinfo usb_selevent; -Static usb_proc_ptr usb_async_proc; /* process that wants USB SIGIO */ +Static struct proc *usb_async_proc; /* process that wants USB SIGIO */ Static int usb_dev_open = 0; Static void usb_add_event(int, struct usb_event *); @@ -141,29 +140,22 @@ USB_ATTACH(usb) usbd_device_handle dev; usbd_status err; int usbrev; - int speed; struct usb_event ue; - + DPRINTF(("usbd_attach\n")); usbd_init(); sc->sc_bus = aux; sc->sc_bus->usbctl = sc; sc->sc_port.power = USB_MAX_POWER; + TAILQ_INIT(&sc->sc_tasks); + + usb_init_task(&sc->sc_exp_task, usb_discover, sc); usbrev = sc->sc_bus->usbrev; printf(": USB revision %s", usbrev_str[usbrev]); - switch (usbrev) { - case USBREV_1_0: - case USBREV_1_1: - speed = USB_SPEED_FULL; - break; - case USBREV_2_0: - speed = USB_SPEED_HIGH; - break; - default: + if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) { printf(", not supported\n"); - sc->sc_dying = 1; USB_ATTACH_ERROR_RETURN; } printf("\n"); @@ -175,34 +167,19 @@ USB_ATTACH(usb) ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); -#ifdef USB_USE_SOFTINTR -#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS - /* XXX we should have our own level */ - sc->sc_bus->soft = softintr_establish(IPL_SOFTNET, - sc->sc_bus->methods->soft_intr, sc->sc_bus); - if (sc->sc_bus->soft == NULL) { - printf("%s: can't register softintr\n", USBDEVNAME(sc->sc_dev)); - sc->sc_dying = 1; - USB_ATTACH_ERROR_RETURN; - } -#else - usb_callout_init(&sc->sc_bus->softi); -#endif -#endif - - err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0, + err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, &sc->sc_port); if (!err) { dev = sc->sc_port.device; if (dev->hub == NULL) { sc->sc_dying = 1; - printf("%s: root device is not a hub\n", + printf("%s: root device is not a hub\n", USBDEVNAME(sc->sc_dev)); USB_ATTACH_ERROR_RETURN; } sc->sc_bus->root_hub = dev; #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. @@ -211,8 +188,8 @@ USB_ATTACH(usb) dev->hub->explore(sc->sc_bus->root_hub); #endif } else { - printf("%s: root hub problem, error=%d\n", - USBDEVNAME(sc->sc_dev), err); + printf("%s: root hub problem, error=%d\n", + USBDEVNAME(sc->sc_dev), err); sc->sc_dying = 1; } if (cold) @@ -229,7 +206,6 @@ void usb_create_event_thread(void *arg) { struct usb_softc *sc = arg; - static int created = 0; if (usb_kthread_create1(usb_event_thread, sc, &sc->sc_event_thread, "%s", sc->sc_dev.dv_xname)) { @@ -237,47 +213,39 @@ usb_create_event_thread(void *arg) sc->sc_dev.dv_xname); panic("usb_create_event_thread"); } - if (!created) { - created = 1; - TAILQ_INIT(&usb_all_tasks); - if (usb_kthread_create1(usb_task_thread, NULL, - &usb_task_thread_proc, "usbtask")) { - printf("unable to create task thread\n"); - panic("usb_create_event_thread task"); - } - } } /* - * Add a task to be performed by the task thread. This function can be + * Add a task to be performed by the event thread. This function can be * called from any context and the task will be executed in a process * context ASAP. */ void usb_add_task(usbd_device_handle dev, struct usb_task *task) { + struct usb_softc *sc = dev->bus->usbctl; int s; s = splusb(); if (!task->onqueue) { - DPRINTFN(2,("usb_add_task: task=%p\n", task)); - TAILQ_INSERT_TAIL(&usb_all_tasks, task, next); + DPRINTFN(2,("usb_add_task: sc=%p task=%p\n", sc, task)); + TAILQ_INSERT_TAIL(&sc->sc_tasks, task, next); task->onqueue = 1; - } else { - DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); - } - wakeup(&usb_all_tasks); + } else + DPRINTFN(3,("usb_add_task: sc=%p task=%p on q\n", sc, task)); + wakeup(&sc->sc_tasks); splx(s); } void usb_rem_task(usbd_device_handle dev, struct usb_task *task) { + struct usb_softc *sc = dev->bus->usbctl; int s; s = splusb(); if (task->onqueue) { - TAILQ_REMOVE(&usb_all_tasks, task, next); + TAILQ_REMOVE(&sc->sc_tasks, task, next); task->onqueue = 0; } splx(s); @@ -287,37 +255,31 @@ void usb_event_thread(void *arg) { struct usb_softc *sc = arg; + struct usb_task *task; + int s; DPRINTF(("usb_event_thread: start\n")); - /* - * In case this controller is a companion controller to an - * EHCI controller we need to wait until the EHCI controller - * has grabbed the port. - * XXX It would be nicer to do this with a tsleep(), but I don't - * know how to synchronize the creation of the threads so it - * will work. - */ - usb_delay_ms(sc->sc_bus, 500); - /* Make sure first discover does something. */ sc->sc_bus->needs_explore = 1; usb_discover(sc); config_pending_decr(); while (!sc->sc_dying) { -#ifdef USB_DEBUG - if (usb_noexplore < 2) -#endif - usb_discover(sc); -#ifdef USB_DEBUG - (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", - usb_noexplore ? 0 : hz * 60); -#else - (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", - hz * 60); -#endif - DPRINTFN(2,("usb_event_thread: woke up\n")); + s = splusb(); + task = TAILQ_FIRST(&sc->sc_tasks); + if (task == NULL) { + tsleep(&sc->sc_tasks, PWAIT, "usbevt", 0); + task = TAILQ_FIRST(&sc->sc_tasks); + } + DPRINTFN(2,("usb_event_thread: woke up task=%p\n", task)); + if (task != NULL && !sc->sc_dying) { + TAILQ_REMOVE(&sc->sc_tasks, task, next); + task->onqueue = 0; + splx(s); + task->fun(task->arg); + } else + splx(s); } sc->sc_event_thread = NULL; @@ -328,32 +290,6 @@ usb_event_thread(void *arg) kthread_exit(0); } -void -usb_task_thread(void *arg) -{ - struct usb_task *task; - int s; - - DPRINTF(("usb_task_thread: start\n")); - - s = splusb(); - for (;;) { - task = TAILQ_FIRST(&usb_all_tasks); - if (task == NULL) { - tsleep(&usb_all_tasks, PWAIT, "usbtsk", 0); - task = TAILQ_FIRST(&usb_all_tasks); - } - DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task)); - if (task != NULL) { - TAILQ_REMOVE(&usb_all_tasks, task, next); - task->onqueue = 0; - splx(s); - task->fun(task->arg); - s = splusb(); - } - } -} - int usbctlprint(void *aux, const char *pnp) { @@ -366,7 +302,7 @@ usbctlprint(void *aux, const char *pnp) #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ int -usbopen(dev_t dev, int flag, int mode, usb_proc_ptr p) +usbopen(dev_t dev, int flag, int mode, struct proc *p) { int unit = minor(dev); struct usb_softc *sc; @@ -421,7 +357,7 @@ usbread(dev_t dev, struct uio *uio, int flag) } int -usbclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +usbclose(dev_t dev, int flag, int mode, struct proc *p) { int unit = minor(dev); @@ -434,7 +370,7 @@ usbclose(dev_t dev, int flag, int mode, usb_proc_ptr p) } int -usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) +usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p) { struct usb_softc *sc; int unit = minor(devt); @@ -444,7 +380,7 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) case FIONBIO: /* All handled in the upper FS layer. */ return (0); - + case FIOASYNC: if (*(int *)data) usb_async_proc = p; @@ -465,8 +401,6 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) switch (cmd) { #ifdef USB_DEBUG case USB_SETDEBUG: - if (!(flag & FWRITE)) - return (EBADF); usbdebug = ((*(int *)data) & 0x000000ff); #ifdef UHCI_DEBUG uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8; @@ -475,7 +409,7 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16; #endif break; -#endif /* USB_DEBUG */ +#endif case USB_REQUEST: { struct usb_ctl_request *ur = (void *)data; @@ -487,13 +421,10 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) usbd_status err; int error = 0; - if (!(flag & FWRITE)) - return (EBADF); - DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); if (len < 0 || len > 32768) return (EINVAL); - if (addr < 0 || addr >= USB_MAX_DEVICES || + if (addr < 0 || addr >= USB_MAX_DEVICES || sc->sc_bus->devices[addr] == 0) return (EINVAL); if (len != 0) { @@ -505,7 +436,7 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? + ur->ucr_request.bmRequestType & UT_READ ? UIO_READ : UIO_WRITE; uio.uio_procp = p; ptr = malloc(len, M_TEMP, M_WAITOK); @@ -516,8 +447,8 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) } } err = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, - USBD_DEFAULT_TIMEOUT); + &ur->ucr_request, ptr, ur->ucr_flags, + &ur->ucr_actlen); if (err) { error = EIO; goto ret; @@ -561,21 +492,21 @@ usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) } int -usbpoll(dev_t dev, int events, usb_proc_ptr p) +usbpoll(dev_t dev, int events, struct proc *p) { int revents, mask, s; if (minor(dev) == USB_DEV_MINOR) { revents = 0; mask = POLLIN | POLLRDNORM; - + s = splusb(); if (events & mask && usb_nevents > 0) revents |= events & mask; if (revents == 0 && events & mask) selrecord(p, &usb_selevent); splx(s); - + return (revents); } else { return (ENXIO); @@ -593,7 +524,7 @@ usb_discover(void *v) if (usb_noexplore > 1) return; #endif - /* + /* * We need mutual exclusion while traversing the device tree, * but this is guaranteed since this function is only called * from the event thread for the controller. @@ -609,7 +540,7 @@ usb_needs_explore(usbd_device_handle dev) { DPRINTFN(2,("usb_needs_explore\n")); dev->bus->needs_explore = 1; - wakeup(&dev->bus->needs_explore); + usb_add_task(dev, &dev->bus->usbctl->sc_exp_task); } /* Called at splusb() */ @@ -621,13 +552,6 @@ usb_get_next_event(struct usb_event *ue) if (usb_nevents <= 0) return (0); ueq = SIMPLEQ_FIRST(&usb_events); -#ifdef DIAGNOSTIC - if (ueq == NULL) { - printf("usb: usb_nevents got out of sync! %d\n", usb_nevents); - usb_nevents = 0; - return (0); - } -#endif *ue = ueq->ue; SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next); free(ueq, M_USBDEV); @@ -650,7 +574,7 @@ usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev) struct usb_event ue; ue.u.ue_driver.ue_cookie = udev->cookie; - strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), + strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), sizeof ue.u.ue_driver.ue_devname); usb_add_event(type, &ue); } @@ -683,26 +607,10 @@ usb_add_event(int type, struct usb_event *uep) psignal(usb_async_proc, SIGIO); splx(s); } - void -usb_schedsoftintr(usbd_bus_handle bus) +usb_schedsoftintr(struct usbd_bus *bus) { - DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling)); -#ifdef USB_USE_SOFTINTR - if (bus->use_polling) { - bus->methods->soft_intr(bus); - } else { -#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS - softintr_schedule(bus->soft); -#else - if (!usb_callout_pending(bus->softi)) - usb_callout(bus->softi, 0, bus->methods->soft_intr, - bus); -#endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */ - } -#else bus->methods->soft_intr(bus); -#endif /* USB_USE_SOFTINTR */ } int @@ -719,8 +627,7 @@ usb_activate(device_ptr_t self, enum devact act) case DVACT_DEACTIVATE: sc->sc_dying = 1; - if (dev != NULL && dev->cdesc != NULL && - dev->subdevs != NULL) { + if (dev && dev->cdesc && dev->subdevs) { for (i = 0; dev->subdevs[i]; i++) rv |= config_deactivate(dev->subdevs[i]); } @@ -740,12 +647,12 @@ usb_detach(device_ptr_t self, int flags) sc->sc_dying = 1; /* Make all devices disconnect. */ - if (sc->sc_port.device != NULL) + if (sc->sc_port.device) usb_disconnect_port(&sc->sc_port, self); /* Kill off event thread. */ - if (sc->sc_event_thread != NULL) { - wakeup(&sc->sc_bus->needs_explore); + if (sc->sc_event_thread) { + wakeup(&sc->sc_tasks); if (tsleep(sc, PWAIT, "usbdet", hz * 60)) printf("%s: event thread didn't die\n", USBDEVNAME(sc->sc_dev)); @@ -754,17 +661,6 @@ usb_detach(device_ptr_t self, int flags) usbd_finish(); -#ifdef USB_USE_SOFTINTR -#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS - if (sc->sc_bus->soft != NULL) { - softintr_disestablish(sc->sc_bus->soft); - sc->sc_bus->soft = NULL; - } -#else - usb_uncallout(sc->sc_bus->softi, bus->methods->soft_intr, bus); -#endif -#endif - ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index c5dc2e8a72a..89121f65dec 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usb.h,v 1.16 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: usb.h,v 1.65 2002/02/26 10:27:49 augustss Exp $ */ +/* $OpenBSD: usb.h,v 1.17 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: usb.h,v 1.52 2001/07/23 15:17:50 nathanw Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */ /* @@ -48,18 +48,23 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/ioctl.h> -#endif -#if defined(__FreeBSD__) -/* These two defines are used by usbd to autoload the usb kld */ -#define USB_KLD "usb" /* name of usb module */ -#define USB_UHUB "usb/uhub" /* root hub */ -#endif #if defined(_KERNEL) #include <dev/usb/usb_port.h> #endif /* _KERNEL */ -#define USB_STACK_VERSION 2 +#elif defined(__FreeBSD__) +#if defined(KERNEL) +#include <sys/malloc.h> + +MALLOC_DECLARE(M_USB); +MALLOC_DECLARE(M_USBDEV); +MALLOC_DECLARE(M_USBHC); + +#include <dev/usb/usb_port.h> +#endif /* KERNEL */ +#endif /* __FreeBSD__ */ + #define USB_MAX_DEVICES 128 #define USB_START_ADDR 0 @@ -154,10 +159,6 @@ typedef struct { #define UDESC_STRING 0x03 #define UDESC_INTERFACE 0x04 #define UDESC_ENDPOINT 0x05 -#define UDESC_DEVICE_QUALIFIER 0x06 -#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 -#define UDESC_INTERFACE_POWER 0x08 -#define UDESC_OTG 0x09 #define UDESC_CS_DEVICE 0x21 /* class specific */ #define UDESC_CS_CONFIG 0x22 #define UDESC_CS_STRING 0x23 @@ -174,13 +175,9 @@ typedef struct { /* Feature numbers */ #define UF_ENDPOINT_HALT 0 #define UF_DEVICE_REMOTE_WAKEUP 1 -#define UF_TEST_MODE 2 #define USB_MAX_IPACKET 8 /* maximum size of the initial packet */ -#define USB_2_MAX_CTRL_PACKET 64 -#define USB_2_MAX_BULK_PACKET 512 - typedef struct { uByte bLength; uByte bDescriptorType; @@ -191,8 +188,6 @@ typedef struct { uByte bLength; uByte bDescriptorType; uWord bcdUSB; -#define UD_USB_2_0 0x0200 -#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) uByte bDeviceClass; uByte bDeviceSubClass; uByte bDeviceProtocol; @@ -274,10 +269,6 @@ typedef struct { /* Hub specific request */ #define UR_GET_BUS_STATE 0x02 -#define UR_CLEAR_TT_BUFFER 0x08 -#define UR_RESET_TT 0x09 -#define UR_GET_TT_STATE 0x0a -#define UR_STOP_TT 0x0b /* Hub features */ #define UHF_C_HUB_LOCAL_POWER 0 @@ -294,29 +285,21 @@ typedef struct { #define UHF_C_PORT_SUSPEND 18 #define UHF_C_PORT_OVER_CURRENT 19 #define UHF_C_PORT_RESET 20 -#define UHF_PORT_TEST 21 -#define UHF_PORT_INDICATOR 22 typedef struct { uByte bDescLength; uByte bDescriptorType; uByte bNbrPorts; uWord wHubCharacteristics; -#define UHD_PWR 0x0003 -#define UHD_PWR_GANGED 0x0000 -#define UHD_PWR_INDIVIDUAL 0x0001 -#define UHD_PWR_NO_SWITCH 0x0002 -#define UHD_COMPOUND 0x0004 -#define UHD_OC 0x0018 -#define UHD_OC_GLOBAL 0x0000 -#define UHD_OC_INDIVIDUAL 0x0008 -#define UHD_OC_NONE 0x0010 -#define UHD_TT_THINK 0x0060 -#define UHD_TT_THINK_8 0x0000 -#define UHD_TT_THINK_16 0x0020 -#define UHD_TT_THINK_24 0x0040 -#define UHD_TT_THINK_32 0x0060 -#define UHD_PORT_IND 0x0080 +#define UHD_PWR 0x03 +#define UHD_PWR_GANGED 0x00 +#define UHD_PWR_INDIVIDUAL 0x01 +#define UHD_PWR_NO_SWITCH 0x02 +#define UHD_COMPOUND 0x04 +#define UHD_OC 0x18 +#define UHD_OC_GLOBAL 0x00 +#define UHD_OC_INDIVIDUAL 0x08 +#define UHD_OC_NONE 0x10 uByte bPwrOn2PwrGood; /* delay in 2 ms units */ #define UHD_PWRON_FACTOR 2 uByte bHubContrCurrent; @@ -328,32 +311,6 @@ typedef struct { #define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord bcdUSB; - uByte bDeviceClass; - uByte bDeviceSubClass; - uByte bDeviceProtocol; - uByte bMaxPacketSize0; - uByte bNumConfigurations; - uByte bReserved; -} UPACKED usb_device_qualifier_t; -#define USB_DEVICE_QUALIFIER_SIZE 10 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bmAttributes; -#define UOTG_SRP 0x01 -#define UOTG_HNP 0x02 -} UPACKED usb_otg_descriptor_t; - -/* OTG feature selectors */ -#define UOTG_B_HNP_ENABLE 3 -#define UOTG_A_HNP_SUPPORT 4 -#define UOTG_A_ALT_HNP_SUPPORT 5 - -typedef struct { uWord wStatus; /* Device status flags */ #define UDS_SELF_POWERED 0x0001 @@ -378,9 +335,6 @@ typedef struct { #define UPS_RESET 0x0010 #define UPS_PORT_POWER 0x0100 #define UPS_LOW_SPEED 0x0200 -#define UPS_HIGH_SPEED 0x0400 -#define UPS_PORT_TEST 0x0800 -#define UPS_PORT_INDICATOR 0x1000 uWord wPortChange; #define UPS_C_CONNECT_STATUS 0x0001 #define UPS_C_PORT_ENABLED 0x0002 @@ -395,9 +349,6 @@ typedef struct { #define UDCLASS_HID 0x00 #define UDCLASS_HUB 0x09 #define UDSUBCLASS_HUB 0 -#define UDPROTO_FSHUB 0 -#define UDPROTO_HSHUBSTT 1 -#define UDPROTO_HSHUBMTT 2 #define UDCLASS_MASS 0x00 /* Interface class codes */ @@ -439,14 +390,11 @@ typedef struct { #define UISUBCLASS_SCSI 6 #define UIPROTO_MASS_CBI_I 0 #define UIPROTO_MASS_CBI 1 -#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ -#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ +#define UIPROTO_MASS_BBB 2 +#define UIPROTO_MASS_BBB_P 80 /* 'P' for the Iomega Zip drive */ #define UICLASS_HUB 0x09 #define UISUBCLASS_HUB 0 -#define UIPROTO_FSHUB 0 -#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ -#define UIPROTO_HSHUBMTT 1 #define UICLASS_CDC_DATA 0x0a #define UISUBCLASS_DATA 0 @@ -467,10 +415,6 @@ typedef struct { #define UICLASS_FIRM_UPD 0x0c #define UICLASS_APPL_SPEC 0xfe -#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 -#define UISUBCLASS_IRDA 2 -#define UIPROTO_IRDA 0 - #define UICLASS_VENDOR 0xff @@ -486,7 +430,6 @@ typedef struct { #if 0 /* These are the values from the spec. */ #define USB_PORT_RESET_DELAY 10 /* ms */ -#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ #define USB_PORT_RESET_SETTLE 10 /* ms */ #define USB_PORT_POWERUP_DELAY 100 /* ms */ #define USB_SET_ADDRESS_SETTLE 2 /* ms */ @@ -497,9 +440,8 @@ typedef struct { #else /* Allow for marginal (i.e. non-conforming) devices. */ #define USB_PORT_RESET_DELAY 50 /* ms */ -#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ #define USB_PORT_RESET_RECOVERY 50 /* ms */ -#define USB_PORT_POWERUP_DELAY 300 /* ms */ +#define USB_PORT_POWERUP_DELAY 200 /* ms */ #define USB_SET_ADDRESS_SETTLE 10 /* ms */ #define USB_RESUME_DELAY (50*5) /* ms */ #define USB_RESUME_WAIT 50 /* ms */ @@ -591,10 +533,7 @@ struct usb_device_info { u_int8_t udi_subclass; u_int8_t udi_protocol; u_int8_t udi_config; - u_int8_t udi_speed; -#define USB_SPEED_LOW 1 -#define USB_SPEED_FULL 2 -#define USB_SPEED_HIGH 3 + u_int8_t udi_lowspeed; int udi_power; /* power consumption in mA, 0 if selfpowered */ int udi_nports; char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; @@ -624,7 +563,6 @@ struct usb_event { #define USB_EVENT_DRIVER_ATTACH 5 #define USB_EVENT_DRIVER_DETACH 6 #define USB_EVENT_IS_ATTACH(n) ((n) == USB_EVENT_CTRLR_ATTACH || (n) == USB_EVENT_DEVICE_ATTACH || (n) == USB_EVENT_DRIVER_ATTACH) -#define USB_EVENT_IS_DETACH(n) ((n) == USB_EVENT_CTRLR_DETACH || (n) == USB_EVENT_DEVICE_DETACH || (n) == USB_EVENT_DRIVER_DETACH) struct timespec ue_time; union { struct { @@ -650,7 +588,6 @@ struct usb_event { #define USB_SET_IMMED _IOW ('U', 22, int) #define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report) #define USB_SET_REPORT _IOW ('U', 24, struct usb_ctl_report) -#define USB_GET_REPORT_ID _IOR ('U', 25, int) /* Generic USB device */ #define USB_GET_CONFIG _IOR ('U', 100, int) diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index 66ceaddaf3f..bb15013ec29 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.36 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: usb_port.h,v 1.54 2002/03/28 21:49:19 ichiro Exp $ */ +/* $OpenBSD: usb_port.h,v 1.37 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: usb_port.h,v 1.44 2001/05/14 20:35:29 bouyer Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -57,7 +57,6 @@ #ifdef USB_DEBUG #define UKBD_DEBUG 1 -#define UHIDEV_DEBUG 1 #define UHID_DEBUG 1 #define OHCI_DEBUG 1 #define UGEN_DEBUG 1 @@ -66,36 +65,26 @@ #define ULPT_DEBUG 1 #define UCOM_DEBUG 1 #define UPLCOM_DEBUG 1 -#define UMCT_DEBUG 1 #define UMODEM_DEBUG 1 #define UAUDIO_DEBUG 1 #define AUE_DEBUG 1 #define CUE_DEBUG 1 #define KUE_DEBUG 1 -#define URL_DEBUG 1 #define UMASS_DEBUG 1 #define UVISOR_DEBUG 1 #define UPL_DEBUG 1 #define UZCOM_DEBUG 1 #define URIO_DEBUG 1 #define UFTDI_DEBUG 1 +#define UMCT_DEBUG 1 #define USCANNER_DEBUG 1 #define USSCANNER_DEBUG 1 -#define EHCI_DEBUG 1 -#define UIRDA_DEBUG 1 -#define USTIR_DEBUG 1 -#define UISDATA_DEBUG 1 -#define UDSBR_DEBUG 1 #define Static #else #define Static static #endif -#define SCSI_MODE_SENSE MODE_SENSE - -#define UMASS_ATAPISTR "atapibus" - -typedef struct proc *usb_proc_ptr; +#define SCSI_MODE_SENSE MODE_SENSE typedef struct device *device_ptr_t; #define USBBASEDEVICE struct device @@ -115,11 +104,8 @@ typedef struct device *device_ptr_t; typedef struct callout usb_callout_t; #define usb_callout_init(h) callout_init(&(h)) #define usb_callout(h, t, f, d) callout_reset(&(h), (t), (f), (d)) -#define usb_callout_pending(h) callout_pending(&(h)) #define usb_uncallout(h, f, d) callout_stop(&(h)) -#define usb_lockmgr(l, f, sl, p) lockmgr((l), (f), (sl)) - #define usb_kthread_create1 kthread_create1 #define usb_kthread_create kthread_create @@ -147,13 +133,21 @@ struct cfattach __CONCAT(dname,_ca) = { \ } #define USB_MATCH(dname) \ -int __CONCAT(dname,_match)(struct device *parent, struct cfdata *match, void *aux) +int \ +__CONCAT(dname,_match)(parent, match, aux) \ + struct device *parent; \ + struct cfdata *match; \ + void *aux; #define USB_MATCH_START(dname, uaa) \ struct usb_attach_arg *uaa = aux #define USB_ATTACH(dname) \ -void __CONCAT(dname,_attach)(struct device *parent, struct device *self, void *aux) +void \ +__CONCAT(dname,_attach)(parent, self, aux) \ + struct device *parent; \ + struct device *self; \ + void *aux; #define USB_ATTACH_START(dname, sc, uaa) \ struct __CONCAT(dname,_softc) *sc = \ @@ -167,7 +161,10 @@ void __CONCAT(dname,_attach)(struct device *parent, struct device *self, void *a #define USB_ATTACH_SETUP printf("\n") #define USB_DETACH(dname) \ -int __CONCAT(dname,_detach)(struct device *self, int flags) +int \ +__CONCAT(dname,_detach)(self, flags) \ + struct device *self; \ + int flags; #define USB_DETACH_START(dname, sc) \ struct __CONCAT(dname,_softc) *sc = \ @@ -187,17 +184,12 @@ int __CONCAT(dname,_detach)(struct device *self, int flags) (config_found_sm(parent, args, print, sub)) #elif defined(__OpenBSD__) +#include <sys/timeout.h> /* * OpenBSD */ -#include <sys/timeout.h> - -#define USB_USE_SOFTINTR - -#define USB_DEBUG #ifdef USB_DEBUG #define UKBD_DEBUG 1 -#define UHIDEV_DEBUG 1 #define UHID_DEBUG 1 #define OHCI_DEBUG 1 #define UGEN_DEBUG 1 @@ -205,8 +197,6 @@ int __CONCAT(dname,_detach)(struct device *self, int flags) #define UHUB_DEBUG 1 #define ULPT_DEBUG 1 #define UCOM_DEBUG 1 -#define UPLCOM_DEBUG 1 -#define UMCT_DEBUG 1 #define UMODEM_DEBUG 1 #define UAUDIO_DEBUG 1 #define AUE_DEBUG 1 @@ -218,49 +208,33 @@ int __CONCAT(dname,_detach)(struct device *self, int flags) #define UZCOM_DEBUG 1 #define URIO_DEBUG 1 #define UFTDI_DEBUG 1 +#define UMCT_DEBUG 1 #define USCANNER_DEBUG 1 #define USSCANNER_DEBUG 1 -#define EHCI_DEBUG 1 -#define UISDATA_DEBUG 1 -#define UDSBR_DEBUG 1 #endif #define Static -#define UMASS_ATAPISTR "atapiscsi" - -/* periph_quirks */ -#define PQUIRK_AUTOSAVE 0x00000001 /* do implicit SAVE POINTERS */ -#define PQUIRK_NOSYNC 0x00000002 /* does not grok SDTR */ -#define PQUIRK_NOWIDE 0x00000004 /* does not grok WDTR */ -#define PQUIRK_NOTAG 0x00000008 /* does not grok tagged cmds */ -#define PQUIRK_NOLUNS 0x00000010 /* DTWT with LUNs */ -#define PQUIRK_FORCELUNS 0x00000020 /* prehistoric device groks - LUNs */ -#define PQUIRK_NOMODESENSE 0x00000040 /* device doesn't do MODE SENSE - properly */ -#define PQUIRK_NOSTARTUNIT 0x00000080 /* do not issue START UNIT */ -#define PQUIRK_NOSYNCCACHE 0x00000100 /* do not issue SYNC CACHE */ -#define PQUIRK_CDROM 0x00000200 /* device is a CD-ROM, no - matter what else it claims */ -#define PQUIRK_LITTLETOC 0x00000400 /* audio TOC is little-endian */ -#define PQUIRK_NOCAPACITY 0x00000800 /* no READ CD CAPACITY */ -#define PQUIRK_NOTUR 0x00001000 /* no TEST UNIT READY */ -#define PQUIRK_NODOORLOCK 0x00002000 /* can't lock door */ -#define PQUIRK_NOSENSE 0x00004000 /* can't REQUEST SENSE */ -#define PQUIRK_ONLYBIG 0x00008000 /* only use SCSI_{R,W}_BIG */ -#define PQUIRK_BYTE5_ZERO 0x00010000 /* byte5 in capacity is wrong */ -#define PQUIRK_NO_FLEX_PAGE 0x00020000 /* does not support flex geom - page */ -#define PQUIRK_NOBIGMODESENSE 0x00040000 /* has no big mode-sense op */ -#define PQUIRK_CAP_SYNC 0x00080000 /* SCSI1 device with sync op */ - -typedef struct proc *usb_proc_ptr; - #define UCOMBUSCF_PORTNO -1 #define UCOMBUSCF_PORTNO_DEFAULT -1 -#define UHIDBUSCF_REPORTID -1 -#define UHIDBUSCF_REPORTID_DEFAULT -1 + +#define SCSI_MODE_SENSE MODE_SENSE +#define XS_STS_DONE ITSDONE +#define XS_CTL_POLL SCSI_POLL +#define XS_CTL_DATA_IN SCSI_DATA_IN +#define XS_CTL_DATA_OUT SCSI_DATA_OUT +#define scsipi_adapter scsi_adapter +#define scsipi_cmd scsi_cmd +#define scsipi_device scsi_device +#define scsipi_done scsi_done +#define scsipi_link scsi_link +#define scsipi_minphys scsi_minphys +#define scsipi_sense scsi_sense +#define scsipi_xfer scsi_xfer +#define show_scsipi_xs show_scsi_xs +#define show_scsipi_cmd show_scsi_cmd +#define xs_control flags +#define xs_status status #define bswap32(x) swap32(x) #define bswap16(x) swap16(x) @@ -327,7 +301,6 @@ typedef struct timeout usb_callout_t; #define usb_callout_init(h) #define usb_callout(h, t, f, d) \ { timeout_set(&(h), (f), (d)); timeout_add(&(h), (t)); } -#define usb_callout_pending(h) timeout_pending(&(h)) #define usb_uncallout(h, f, d) timeout_del(&(h)) #define usb_lockmgr(l, f, sl, p) lockmgr((l), (f), (sl), (p)) @@ -408,15 +381,6 @@ __CONCAT(dname,_detach)(self, flags) \ #include "opt_usb.h" -#if defined(_KERNEL) -#include <sys/malloc.h> - -MALLOC_DECLARE(M_USB); -MALLOC_DECLARE(M_USBDEV); -MALLOC_DECLARE(M_USBHC); - -#endif - #define Static #define USBVERBOSE @@ -431,15 +395,14 @@ MALLOC_DECLARE(M_USBHC); #define DECLARE_USB_DMA_T typedef void * usb_dma_t -typedef struct proc *usb_proc_ptr; - /* XXX Change this when FreeBSD has memset */ #define memcpy(d, s, l) bcopy((s),(d),(l)) #define memset(d, v, l) bzero((d),(l)) #define bswap32(x) swap32(x) -#define kthread_create1(f, s, p, a0, a1) \ - kthread_create((f), (s), (p), RFHIGHPID, (a0), (a1)) +#define usb_kthread_create1(function, sc, priv, string, name) +#define usb_kthread_create(create_function, sc) +#define usb_kthread_exit(err) typedef struct callout_handle usb_callout_t; #define usb_callout_init(h) callout_handle_init(&(h)) @@ -453,8 +416,6 @@ typedef struct callout_handle usb_callout_t; #define powerhook_disestablish(hdl) #define PWR_RESUME 0 -#define config_detach(dev, flag) device_delete_child(device_get_parent(dev), dev) - typedef struct malloc_type *usb_malloc_type; #define USB_DECLARE_DRIVER_INIT(dname, init) \ diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c index 0abf050b1a6..30dde29cafd 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.11 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: usb_quirks.c,v 1.39 2001/11/13 06:24:56 lukem Exp $ */ +/* $OpenBSD: usb_quirks.c,v 1.12 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: usb_quirks.c,v 1.38 2001/04/15 10:26:36 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.13 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -74,6 +74,8 @@ Static const struct usbd_quirk_entry { { USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, { UQ_SPUR_BUT_UP }}, { USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100, 0x102, { UQ_BUS_POWERED }}, { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0x102, { UQ_BUS_POWERED }}, + { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232, 0x102, { UQ_BUS_POWERED }}, + { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232, 0x102, { UQ_BUS_POWERED }}, { USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS, 0x100, { UQ_ASSUME_CM_OVER_DATA | UQ_NO_STRINGS }}, { USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, { UQ_POWER_CLAIM }}, diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 66cb1fd6248..2845b2ddafc 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.20 2002/05/07 18:08:04 nate Exp $ */ -/* $NetBSD: usb_subr.c,v 1.98 2002/02/20 20:30:13 christos Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.21 2002/05/07 18:29:18 nate Exp $ */ +/* $NetBSD: usb_subr.c,v 1.87 2001/08/15 00:04:59 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ /* @@ -352,9 +352,6 @@ usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps) err)); return (err); } - /* If the device disappeared, just give up. */ - if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) - return (USBD_NORMAL_COMPLETION); } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); if (n == 0) return (USBD_TIMEOUT); @@ -478,36 +475,13 @@ usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx) break; } /* passed end, or bad desc */ - printf("usbd_fill_iface_data: bad descriptor(s): %s\n", - ed->bLength == 0 ? "0 length" : - ed->bDescriptorType == UDESC_INTERFACE ? "iface desc": - "out of data"); + DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n", + ed->bLength == 0 ? "0 length" : + ed->bDescriptorType == UDESC_INTERFACE ? "iface desc": + "out of data")); goto bad; found: ifc->endpoints[endpt].edesc = ed; - if (dev->speed == USB_SPEED_HIGH) { - u_int mps; - /* Control and bulk endpoints have max packet - limits. */ - switch (UE_GET_XFERTYPE(ed->bmAttributes)) { - case UE_CONTROL: - mps = USB_2_MAX_CTRL_PACKET; - goto check; - case UE_BULK: - mps = USB_2_MAX_BULK_PACKET; - check: - if (UGETW(ed->wMaxPacketSize) != mps) { - USETW(ed->wMaxPacketSize, mps); -#ifdef DIAGNOSTIC - printf("usbd_fill_iface_data: bad max " - "packet size\n"); -#endif - } - break; - default: - break; - } - } ifc->endpoints[endpt].refcnt = 0; p += ed->bLength; } @@ -751,6 +725,7 @@ usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface, p->repeat = 0; p->interval = ival; SIMPLEQ_INIT(&p->queue); + usb_callout_init(p->abort_handle); err = dev->bus->methods->open_pipe(p); if (err) { DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" @@ -770,7 +745,6 @@ usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface, void usbd_kill_pipe(usbd_pipe_handle pipe) { - usbd_abort_pipe(pipe); pipe->methods->close(pipe); pipe->endpoint->refcnt--; free(pipe, M_USB); @@ -953,17 +927,16 @@ usbd_probe_and_attach(device_ptr_t parent, usbd_device_handle dev, */ usbd_status usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, - int speed, int port, struct usbd_port *up) + int lowspeed, int port, struct usbd_port *up) { usbd_device_handle dev; - struct usbd_device *hub; usb_device_descriptor_t *dd; usbd_status err; int addr; int i; - DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n", - bus, port, depth, speed)); + DPRINTF(("usbd_new_device bus=%p port=%d depth=%d lowspeed=%d\n", + bus, port, depth, lowspeed)); addr = usbd_getnewaddr(bus); if (addr < 0) { printf("%s: No free USB addresses, new device ignored.\n", @@ -974,7 +947,7 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, dev = malloc(sizeof *dev, M_USB, M_NOWAIT); if (dev == NULL) return (USBD_NOMEM); - memset(dev, 0, sizeof *dev); + memset(dev, 0, sizeof(*dev)); dev->bus = bus; @@ -992,15 +965,9 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, dev->quirks = &usbd_no_quirk; dev->address = USB_START_ADDR; dev->ddesc.bMaxPacketSize = 0; + dev->lowspeed = lowspeed != 0; dev->depth = depth; dev->powersrc = up; - dev->myhub = up->parent; - for (hub = up->parent; - hub != NULL && hub->speed != USB_SPEED_HIGH; - hub = hub->myhub) - ; - dev->myhighhub = hub; - dev->speed = speed; dev->langid = USBD_NOLANG; dev->cookie.cookie = ++usb_cookie_no; @@ -1029,22 +996,11 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth, return (err); } - if (speed == USB_SPEED_HIGH) { - /* Max packet size must be 64 (sec 5.5.3). */ - if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) { -#ifdef DIAGNOSTIC - printf("usbd_new_device: addr=%d bad max packet size\n", - addr); -#endif - dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET; - } - } - DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " - "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n", + "subclass=%d, protocol=%d, maxpacket=%d, len=%d, ls=%d\n", addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, - dev->speed)); + dev->lowspeed)); if (dd->bDescriptorType != UDESC_DEVICE) { /* Illegal device descriptor */ @@ -1247,7 +1203,7 @@ usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di, di->udi_protocol = dev->ddesc.bDeviceProtocol; di->udi_config = dev->config; di->udi_power = dev->self_powered ? 0 : dev->power; - di->udi_speed = dev->speed; + di->udi_lowspeed = dev->lowspeed; if (dev->subdevs != NULL) { for (i = 0; dev->subdevs[i] && @@ -1350,7 +1306,13 @@ usb_disconnect_port(struct usbd_port *up, device_ptr_t parent) if (up->portno != 0) printf(" port %d", up->portno); printf(" (addr %d) disconnected\n", dev->address); +#if defined(__NetBSD__) || defined(__OpenBSD__) config_detach(dev->subdevs[i], DETACH_FORCE); +#elif defined(__FreeBSD__) + device_delete_child(device_get_parent(dev->subdevs[i]), + dev->subdevs[i]); +#endif + } } diff --git a/sys/dev/usb/usbdevs.h b/sys/dev/usb/usbdevs.h index 875ba4dfa7a..fef26f39c7b 100644 --- a/sys/dev/usb/usbdevs.h +++ b/sys/dev/usb/usbdevs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdevs.h,v 1.44 2002/05/07 18:08:05 nate Exp $ */ +/* $OpenBSD: usbdevs.h,v 1.45 2002/05/07 18:29:18 nate Exp $ */ /* * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. diff --git a/sys/dev/usb/usbdevs_data.h b/sys/dev/usb/usbdevs_data.h index e7096569e4c..a4715eb8da9 100644 --- a/sys/dev/usb/usbdevs_data.h +++ b/sys/dev/usb/usbdevs_data.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdevs_data.h,v 1.44 2002/05/07 18:08:05 nate Exp $ */ +/* $OpenBSD: usbdevs_data.h,v 1.45 2002/05/07 18:29:18 nate Exp $ */ /* * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 856a20cd905..012409d05d3 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi.c,v 1.17 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbdi.c,v 1.99 2002/02/28 04:49:16 thorpej Exp $ */ +/* $OpenBSD: usbdi.c,v 1.18 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbdi.c,v 1.81 2001/04/17 00:05:33 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ /* @@ -79,10 +79,10 @@ extern int usbdebug; Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe); Static void usbd_do_request_async_cb - (usbd_xfer_handle, usbd_private_handle, usbd_status); +(usbd_xfer_handle, usbd_private_handle, usbd_status); Static void usbd_start_next(usbd_pipe_handle pipe); Static usbd_status usbd_open_pipe_ival - (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int); +(usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int); Static int usbd_nbuses = 0; @@ -109,42 +109,7 @@ usbd_xfer_isread(usbd_xfer_handle xfer) } #ifdef USB_DEBUG -void -usbd_dump_iface(struct usbd_interface *iface) -{ - printf("usbd_dump_iface: iface=%p\n", iface); - if (iface == NULL) - return; - printf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n", - iface->device, iface->idesc, iface->index, iface->altindex, - iface->priv); -} - -void -usbd_dump_device(struct usbd_device *dev) -{ - printf("usbd_dump_device: dev=%p\n", dev); - if (dev == NULL) - return; - printf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe); - printf(" address=%d config=%d depth=%d speed=%d self_powered=%d " - "power=%d langid=%d\n", - dev->address, dev->config, dev->depth, dev->speed, - dev->self_powered, dev->power, dev->langid); -} - -void -usbd_dump_endpoint(struct usbd_endpoint *endp) -{ - printf("usbd_dump_endpoint: endp=%p\n", endp); - if (endp == NULL) - return; - printf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt); - if (endp->edesc) - printf(" bEndpointAddress=0x%02x\n", - endp->edesc->bEndpointAddress); -} - +void usbd_dump_queue(usbd_pipe_handle pipe); void usbd_dump_queue(usbd_pipe_handle pipe) { @@ -157,21 +122,6 @@ usbd_dump_queue(usbd_pipe_handle pipe) printf(" xfer=%p\n", xfer); } } - -void -usbd_dump_pipe(usbd_pipe_handle pipe) -{ - printf("usbd_dump_pipe: pipe=%p\n", pipe); - if (pipe == NULL) - return; - usbd_dump_iface(pipe->iface); - usbd_dump_device(pipe->device); - usbd_dump_endpoint(pipe->endpoint); - printf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n", - pipe->refcnt, pipe->running, pipe->aborting); - printf(" intrxfer=%p, repeat=%d, interval=%d\n", - pipe->intrxfer, pipe->repeat, pipe->interval); -} #endif usbd_status @@ -271,6 +221,12 @@ usbd_close_pipe(usbd_pipe_handle pipe) LIST_REMOVE(pipe, next); pipe->endpoint->refcnt--; pipe->methods->close(pipe); +#if defined(__NetBSD__) && defined(DIAGNOSTIC) + if (callout_pending(&pipe->abort_handle)) { + callout_stop(&pipe->abort_handle); + printf("usbd_close_pipe: abort_handle pending"); + } +#endif if (pipe->intrxfer != NULL) usbd_free_xfer(pipe->intrxfer); free(pipe, M_USB); @@ -359,13 +315,9 @@ usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) struct usbd_bus *bus = xfer->device->bus; usbd_status err; -#ifdef DIAGNOSTIC - if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) - printf("usbd_alloc_buffer: xfer already has a buffer\n"); -#endif err = bus->methods->allocm(bus, &xfer->dmabuf, size); if (err) - return (NULL); + return (0); xfer->rqflags |= URQ_DEV_DMABUF; return (KERNADDR(&xfer->dmabuf)); } @@ -560,7 +512,7 @@ usbd_clear_endpoint_stall(usbd_pipe_handle pipe) DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); /* - * Clearing en endpoint stall resets the endpoint toggle, so + * Clearing en endpoint stall resets the enpoint toggle, so * do the same to the HC toggle. */ pipe->methods->cleartoggle(pipe); @@ -599,6 +551,7 @@ usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe) return (err); } +void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */ void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe) { @@ -627,11 +580,12 @@ usbd_interface_count(usbd_device_handle dev, u_int8_t *count) return (USBD_NORMAL_COMPLETION); } -void +usbd_status usbd_interface2device_handle(usbd_interface_handle iface, usbd_device_handle *dev) { *dev = iface->device; + return (USBD_NORMAL_COMPLETION); } usbd_status @@ -765,13 +719,6 @@ usb_transfer_complete(usbd_xfer_handle xfer) DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_ONQU) { - printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return; - } -#endif #ifdef DIAGNOSTIC if (pipe == NULL) { @@ -811,7 +758,6 @@ usb_transfer_complete(usbd_xfer_handle xfer) if (xfer != SIMPLEQ_FIRST(&pipe->queue)) printf("usb_transfer_complete: bad dequeue %p != %p\n", xfer, SIMPLEQ_FIRST(&pipe->queue)); - xfer->busy_free = XFER_BUSY; #endif SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next); } @@ -865,14 +811,6 @@ usb_insert_transfer(usbd_xfer_handle xfer) DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", pipe, pipe->running, xfer->timeout)); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return (USBD_INVAL); - } - xfer->busy_free = XFER_ONQU; -#endif s = splusb(); SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); if (pipe->running) @@ -923,22 +861,20 @@ usbd_start_next(usbd_pipe_handle pipe) usbd_status usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) { - return (usbd_do_request_flags(dev, req, data, 0, 0, - USBD_DEFAULT_TIMEOUT)); + return (usbd_do_request_flags(dev, req, data, 0, 0)); } usbd_status usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req, - void *data, u_int16_t flags, int *actlen, u_int32_t timo) + void *data, u_int16_t flags, int *actlen) { return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req, - data, flags, actlen, timo)); + data, flags, actlen)); } usbd_status usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe, - usb_device_request_t *req, void *data, u_int16_t flags, int *actlen, - u_int32_t timeout) + usb_device_request_t *req, void *data, u_int16_t flags, int *actlen) { usbd_xfer_handle xfer; usbd_status err; @@ -957,7 +893,7 @@ usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe, xfer = usbd_alloc_xfer(dev); if (xfer == NULL) return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, timeout, req, + usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, UGETW(req->wLength), flags, 0); xfer->pipe = pipe; err = usbd_sync_transfer(xfer); @@ -1088,9 +1024,6 @@ usbd_set_polling(usbd_device_handle dev, int on) dev->bus->use_polling++; else dev->bus->use_polling--; - /* When polling we need to make sure there is nothing pending to do. */ - if (dev->bus->use_polling) - dev->bus->methods->soft_intr(dev->bus); } @@ -1135,7 +1068,7 @@ usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz, if (tbl->ud_vendor == vendor && (tproduct == product || tproduct == USB_PRODUCT_ANY)) return (tbl); - tbl = (const struct usb_devno *)((const char *)tbl + sz); + tbl = (struct usb_devno *)((char *)tbl + sz); } return (NULL); } diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 0a571b0bcee..77c4dd6d425 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdi.h,v 1.15 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbdi.h,v 1.61 2002/02/11 15:20:23 augustss Exp $ */ +/* $OpenBSD: usbdi.h,v 1.16 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbdi.h,v 1.53 2001/08/15 00:04:59 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.18 1999/11/17 22:33:49 n_hibma Exp $ */ /* @@ -48,25 +48,25 @@ typedef void *usbd_private_handle; typedef enum { /* keep in sync with usbd_status_msgs */ USBD_NORMAL_COMPLETION = 0, /* must be 0 */ - USBD_IN_PROGRESS, /* 1 */ + USBD_IN_PROGRESS, /* errors */ - USBD_PENDING_REQUESTS, /* 2 */ - USBD_NOT_STARTED, /* 3 */ - USBD_INVAL, /* 4 */ - USBD_NOMEM, /* 5 */ - USBD_CANCELLED, /* 6 */ - USBD_BAD_ADDRESS, /* 7 */ - USBD_IN_USE, /* 8 */ - USBD_NO_ADDR, /* 9 */ - USBD_SET_ADDR_FAILED, /* 10 */ - USBD_NO_POWER, /* 11 */ - USBD_TOO_DEEP, /* 12 */ - USBD_IOERROR, /* 13 */ - USBD_NOT_CONFIGURED, /* 14 */ - USBD_TIMEOUT, /* 15 */ - USBD_SHORT_XFER, /* 16 */ - USBD_STALLED, /* 17 */ - USBD_INTERRUPTED, /* 18 */ + USBD_PENDING_REQUESTS, + USBD_NOT_STARTED, + USBD_INVAL, + USBD_NOMEM, + USBD_CANCELLED, + USBD_BAD_ADDRESS, + USBD_IN_USE, + USBD_NO_ADDR, + USBD_SET_ADDR_FAILED, + USBD_NO_POWER, + USBD_TOO_DEEP, + USBD_IOERROR, + USBD_NOT_CONFIGURED, + USBD_TIMEOUT, + USBD_SHORT_XFER, + USBD_STALLED, + USBD_INTERRUPTED, USBD_ERROR_MAX /* must be last */ } usbd_status; @@ -117,17 +117,16 @@ usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor usbd_status usbd_abort_pipe(usbd_pipe_handle pipe); usbd_status usbd_clear_endpoint_stall(usbd_pipe_handle pipe); usbd_status usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe); -void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); usbd_status usbd_endpoint_count(usbd_interface_handle dev, u_int8_t *count); usbd_status usbd_interface_count(usbd_device_handle dev, u_int8_t *count); -void usbd_interface2device_handle(usbd_interface_handle iface, - usbd_device_handle *dev); +usbd_status usbd_interface2device_handle(usbd_interface_handle iface, + usbd_device_handle *dev); usbd_status usbd_device2interface_handle(usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface); usbd_device_handle usbd_pipe2device_handle(usbd_pipe_handle); -void *usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size); -void usbd_free_buffer(usbd_xfer_handle xfer); +void *usbd_alloc_buffer(usbd_xfer_handle req, u_int32_t size); +void usbd_free_buffer(usbd_xfer_handle req); void *usbd_get_buffer(usbd_xfer_handle xfer); usbd_status usbd_sync_transfer(usbd_xfer_handle req); usbd_status usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address, @@ -140,11 +139,10 @@ usbd_status usbd_do_request_async(usbd_device_handle pipe, usb_device_request_t *req, void *data); usbd_status usbd_do_request_flags(usbd_device_handle pipe, usb_device_request_t *req, - void *data, u_int16_t flags, int*, u_int32_t); + void *data, u_int16_t flags, int *); usbd_status usbd_do_request_flags_pipe( usbd_device_handle dev, usbd_pipe_handle pipe, - usb_device_request_t *req, void *data, u_int16_t flags, int *actlen, - u_int32_t); + usb_device_request_t *req, void *data, u_int16_t flags, int *actlen); usb_interface_descriptor_t *usbd_get_interface_descriptor (usbd_interface_handle iface); usb_config_descriptor_t *usbd_get_config_descriptor(usbd_device_handle dev); @@ -152,7 +150,7 @@ usb_device_descriptor_t *usbd_get_device_descriptor(usbd_device_handle dev); usbd_status usbd_set_interface(usbd_interface_handle, int); int usbd_get_no_alts(usb_config_descriptor_t *, int); usbd_status usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface); -void usbd_fill_deviceinfo(usbd_device_handle, struct usb_device_info *, int); +void usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di, int); int usbd_get_interface_altindex(usbd_interface_handle iface); usb_interface_descriptor_t *usbd_find_idesc(usb_config_descriptor_t *cd, @@ -269,15 +267,14 @@ struct usb_attach_arg { int usbd_driver_load(module_t mod, int what, void *arg); #endif -/* XXX Perhaps USB should have its own levels? */ -#ifdef USB_USE_SOFTINTR -#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS -#define splusb splsoftnet -#else -#define splusb splsoftclock -#endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */ -#else +/* + * XXX + * splusb MUST be the lowest level interrupt so that within USB callbacks + * the level can be raised the appropriate level. + * XXX Should probably use a softsplusb. + */ +/* XXX */ #define splusb splbio -#endif /* USB_USE_SOFTINTR */ #define splhardusb splbio #define IPL_USB IPL_BIO +/* XXX */ diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index cfe02dfea0f..ae09e7c919e 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.12 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbdi_util.c,v 1.39 2001/12/27 11:24:42 augustss Exp $ */ +/* $OpenBSD: usbdi_util.c,v 1.13 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbdi_util.c,v 1.35 2001/10/26 17:58:21 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.14 1999/11/17 22:33:50 n_hibma Exp $ */ /* @@ -220,25 +220,6 @@ usbd_set_port_feature(usbd_device_handle dev, int port, int sel) return (usbd_do_request(dev, &req, 0)); } -usbd_status -usbd_get_protocol(usbd_interface_handle iface, u_int8_t *report) -{ - usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - DPRINTFN(4, ("usbd_get_protocol: iface=%p, endpt=%d\n", - iface, id->bInterfaceNumber)); - if (id == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_PROTOCOL; - USETW(req.wValue, 0); - USETW(req.wIndex, id->bInterfaceNumber); - USETW(req.wLength, 1); - return (usbd_do_request(dev, &req, report)); -} usbd_status usbd_set_protocol(usbd_interface_handle iface, int report) @@ -246,12 +227,15 @@ usbd_set_protocol(usbd_interface_handle iface, int report) usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; + usbd_status err; DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n", iface, report, id->bInterfaceNumber)); if (id == NULL) return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_PROTOCOL; USETW(req.wValue, report); @@ -267,11 +251,14 @@ usbd_set_report(usbd_interface_handle iface, int type, int id, void *data, usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; + usbd_status err; DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); if (ifd == NULL) return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -281,17 +268,20 @@ usbd_set_report(usbd_interface_handle iface, int type, int id, void *data, } usbd_status -usbd_set_report_async(usbd_interface_handle iface, int type, int id, - void *data, int len) +usbd_set_report_async(usbd_interface_handle iface, int type, int id, void *data, + int len) { usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; + usbd_status err; DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len)); if (ifd == NULL) return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_REPORT; USETW2(req.wValue, type, id); @@ -307,11 +297,14 @@ usbd_get_report(usbd_interface_handle iface, int type, int id, void *data, usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; + usbd_status err; DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); if (ifd == NULL) return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); @@ -326,11 +319,14 @@ usbd_set_idle(usbd_interface_handle iface, int duration, int id) usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; + usbd_status err; DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id)); if (ifd == NULL) return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); + err = usbd_interface2device_handle(iface, &dev); + if (err) + return (err); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_IDLE; USETW2(req.wValue, duration, id); @@ -361,10 +357,13 @@ usbd_get_hid_descriptor(usbd_interface_handle ifc) usb_config_descriptor_t *cdesc; usb_hid_descriptor_t *hd; char *p, *end; + usbd_status err; if (idesc == NULL) return (0); - usbd_interface2device_handle(ifc, &dev); + err = usbd_interface2device_handle(ifc, &dev); + if (err) + return (0); cdesc = usbd_get_config_descriptor(dev); p = (char *)idesc + idesc->bLength; @@ -389,7 +388,9 @@ usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep, usbd_device_handle dev; usbd_status err; - usbd_interface2device_handle(ifc, &dev); + err = usbd_interface2device_handle(ifc, &dev); + if (err) + return (err); id = usbd_get_interface_descriptor(ifc); if (id == NULL) return (USBD_INVAL); @@ -481,21 +482,3 @@ usb_detach_wakeup(device_ptr_t dv) DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv))); wakeup(dv); } - -usb_descriptor_t * -usb_find_desc(usbd_device_handle dev, int type) -{ - usb_descriptor_t *desc; - usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); - uByte *p = (uByte *)cd; - uByte *end = p + UGETW(cd->wTotalLength); - - while (p < end) { - desc = (usb_descriptor_t *)p; - if (desc->bDescriptorType == type) - return (desc); - p += desc->bLength; - } - - return (NULL); -} diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index 6bca3e54e7c..aef2affe9f7 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.9 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbdi_util.h,v 1.27 2002/03/17 18:02:53 augustss Exp $ */ +/* $OpenBSD: usbdi_util.h,v 1.10 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbdi_util.h,v 1.23 2001/10/26 17:58:22 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.9 1999/11/17 22:33:50 n_hibma Exp $ */ /* @@ -53,9 +53,8 @@ usbd_status usbd_set_hub_feature(usbd_device_handle dev, int); usbd_status usbd_clear_hub_feature(usbd_device_handle, int); usbd_status usbd_set_port_feature(usbd_device_handle dev, int, int); usbd_status usbd_clear_port_feature(usbd_device_handle, int, int); -usbd_status usbd_get_device_status(usbd_device_handle, usb_status_t *); +usbd_status usbd_get_device_status(usbd_device_handle,usb_status_t*); usbd_status usbd_get_hub_status(usbd_device_handle, usb_hub_status_t *); -usbd_status usbd_get_protocol(usbd_interface_handle dev, u_int8_t *report); usbd_status usbd_set_protocol(usbd_interface_handle dev, int report); usbd_status usbd_get_report_descriptor(usbd_device_handle dev, int ifcno, int size, void *d); @@ -85,4 +84,3 @@ usbd_status usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, void usb_detach_wait(device_ptr_t); void usb_detach_wakeup(device_ptr_t); -usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type); diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index d5e53c3e0f1..5bf053ed879 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbdivar.h,v 1.15 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbdivar.h,v 1.69 2001/12/27 18:43:46 augustss Exp $ */ +/* $OpenBSD: usbdivar.h,v 1.16 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbdivar.h,v 1.63 2001/01/21 19:00:06 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ /* @@ -80,7 +80,7 @@ struct usbd_port { u_int8_t portno; u_int8_t restartcnt; #define USBD_RESTART_MAX 5 - struct usbd_device *device; /* Connected device */ + struct usbd_device *device; struct usbd_device *parent; /* The ports hub */ }; @@ -117,11 +117,13 @@ struct usbd_bus { #define USBREV_2_0 4 #define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1", "2.0" } +#if 0 #ifdef USB_USE_SOFTINTR #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS void *soft; /* soft interrupt cookie */ #else - usb_callout_t softi; + struct callout softi; +#endif #endif #endif @@ -136,15 +138,13 @@ struct usbd_device { u_int8_t address; /* device addess */ u_int8_t config; /* current configuration # */ u_int8_t depth; /* distance from root hub */ - u_int8_t speed; /* low/full/high speed */ + u_int8_t lowspeed; /* lowspeed flag */ u_int8_t self_powered; /* flag for self powered */ u_int16_t power; /* mA the device uses */ int16_t langid; /* language for strings */ #define USBD_NOLANG (-1) usb_event_cookie_t cookie; /* unique connection id */ struct usbd_port *powersrc; /* upstream hub port, or 0 */ - struct usbd_device *myhub; /* upstream hub */ - struct usbd_device *myhighhub; /* closest high speed hub */ struct usbd_endpoint def_ep; /* for pipe 0 */ usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ struct usbd_interface *ifaces; /* array of all interfaces */ @@ -179,6 +179,8 @@ struct usbd_pipe { char repeat; int interval; + usb_callout_t abort_handle; + /* Filled by HC driver. */ struct usbd_pipe_methods *methods; }; @@ -197,8 +199,7 @@ struct usbd_xfer { #ifdef DIAGNOSTIC u_int32_t busy_free; #define XFER_FREE 0x46524545 -#define XFER_BUSY 0x42555359 -#define XFER_ONQU 0x4f4e5155 +#define XFER_BUSY 0x42555357 #endif /* For control pipe */ @@ -227,14 +228,6 @@ struct usbd_xfer { void usbd_init(void); void usbd_finish(void); -#ifdef USB_DEBUG -void usbd_dump_iface(struct usbd_interface *iface); -void usbd_dump_device(struct usbd_device *dev); -void usbd_dump_endpoint(struct usbd_endpoint *endp); -void usbd_dump_queue(usbd_pipe_handle pipe); -void usbd_dump_pipe(usbd_pipe_handle pipe); -#endif - /* Routines from usb_subr.c */ int usbctlprint(void *, const char *); void usb_delay_ms(usbd_bus_handle, u_int); diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h index cd27fb55643..695c1cdb925 100644 --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -1,5 +1,5 @@ -/* $OpenBSD: usbhid.h,v 1.5 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: usbhid.h,v 1.11 2001/12/28 00:20:24 augustss Exp $ */ +/* $OpenBSD: usbhid.h,v 1.6 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: usbhid.h,v 1.9 2000/09/03 19:09:14 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbhid.h,v 1.7 1999/11/17 22:33:51 n_hibma Exp $ */ /* @@ -165,25 +165,12 @@ typedef struct usb_hid_descriptor { #define HUD_ERASER 0x0045 #define HUD_TABLET_PICK 0x0046 -/* Usages LEDs */ -#define HUD_LED_NUM_LOCK 0x0001 -#define HUD_LED_CAPS_LOCK 0x0002 -#define HUD_LED_SCROLL_LOCK 0x0003 -#define HUD_LED_COMPOSE 0x0004 -#define HUD_LED_KANA 0x0005 - -#define HID_USAGE2(p, u) (((p) << 16) | u) -#define HID_GET_USAGE(u) ((u) & 0xffff) -#define HID_GET_USAGE_PAGE(u) (((u) >> 16) & 0xffff) +#define HID_USAGE2(p,u) (((p) << 16) | u) #define UHID_INPUT_REPORT 0x01 #define UHID_OUTPUT_REPORT 0x02 #define UHID_FEATURE_REPORT 0x03 -#define HCOLL_PHYSICAL 0 -#define HCOLL_APPLICATION 1 -#define HCOLL_LOGICAL 2 - /* Bits in the input/output/feature items */ #define HIO_CONST 0x001 #define HIO_VARIABLE 0x002 diff --git a/sys/dev/usb/uscanner.c b/sys/dev/usb/uscanner.c index dad8296523e..2dc011c215b 100644 --- a/sys/dev/usb/uscanner.c +++ b/sys/dev/usb/uscanner.c @@ -1,5 +1,6 @@ -/* $OpenBSD: uscanner.c,v 1.6 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: uscanner.c,v 1.27 2002/02/11 10:09:14 augustss Exp $ */ +/* $OpenBSD: uscanner.c,v 1.7 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: uscanner.c,v 1.18 2001/10/11 12:05:10 augustss Exp $ */ +/* $FreeBSD$ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -55,11 +56,7 @@ #endif #include <sys/tty.h> #include <sys/file.h> -#if defined(__FreeBSD__) && __FreeBSD_version >= 500014 -#include <sys/selinfo.h> -#else #include <sys/select.h> -#endif #include <sys/proc.h> #include <sys/vnode.h> #include <sys/poll.h> @@ -80,128 +77,104 @@ int uscannerdebug = 0; #define DPRINTFN(n,x) #endif -struct uscan_info { - struct usb_devno devno; - u_int flags; -#define USC_KEEP_OPEN 1 -}; - /* Table of scanners that may work with this driver. */ -static const struct uscan_info uscanner_devs[] = { - /* Acer Peripherals */ - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_C310U }, 0 }, - - /* AGFA */ - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1236U }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U2 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANTOUCH }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE40 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE50 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE20 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE25 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE26 }, 0 }, - {{ USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE52 }, 0 }, - - /* Avision */ - {{ USB_VENDOR_AVISION, USB_PRODUCT_AVISION_1200U }, 0 }, - - /* Canon */ - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_N656U }, 0 }, - - /* Kye */ - {{ USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO }, 0 }, - - /* HP */ - {{ USB_VENDOR_HP, USB_PRODUCT_HP_3300C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_3400CSE }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_4100C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_4200C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_4300C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_S20 }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_5200C }, 0 }, +static const struct scanner_id { + uint16_t vendor; + uint16_t product; +} scanner_ids [] = { + /* Acer Peripherals */ + { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U }, + { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U }, + { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U }, + { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_C310U }, + + /* AGFA */ + { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U }, + { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U2 }, + { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANTOUCH }, + + /* Kye */ + { USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO }, + + /* HP */ + { USB_VENDOR_HP, USB_PRODUCT_HP_3300C }, + { USB_VENDOR_HP, USB_PRODUCT_HP_3400CSE }, + { USB_VENDOR_HP, USB_PRODUCT_HP_4100C }, + { USB_VENDOR_HP, USB_PRODUCT_HP_4200C }, + { USB_VENDOR_HP, USB_PRODUCT_HP_S20 }, + { USB_VENDOR_HP, USB_PRODUCT_HP_5200C }, #if 0 - /* Handled by usscanner */ - {{ USB_VENDOR_HP, USB_PRODUCT_HP_5300C }, 0 }, + { USB_VENDOR_HP, USB_PRODUCT_HP_5300C }, #endif - {{ USB_VENDOR_HP, USB_PRODUCT_HP_6200C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_6300C }, 0 }, + { USB_VENDOR_HP, USB_PRODUCT_HP_6200C }, + { USB_VENDOR_HP, USB_PRODUCT_HP_6300C }, + + /* Avision */ + { USB_VENDOR_AVISION, USB_PRODUCT_AVISION_1200U }, #if 0 - /* XXX Should be handled by usscanner */ - /* Microtek */ - {{ USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_336CX }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_X6U }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX2 }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_C6 }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL2 }, 0 }, - {{ USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6UL }, 0 }, + /* Microtek */ + { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_336CX }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_X6U }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX2 }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_C6 }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL2 }, + { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6UL }, #endif - /* Mustek */ - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200F }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600USB }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600CU }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USB }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200UB }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USBPLUS }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CUPLUS }, 0 }, - - /* National */ - {{ USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW1200 }, 0 }, - {{ USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW2400 }, 0 }, - - /* Primax */ - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E300 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2300 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E3002 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_9600 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_600U }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_19200 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_1200U }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G600 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_636I }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2600 }, 0 }, - {{ USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E600 }, 0 }, - - /* Epson */ - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_636 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_610 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1200 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1240 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1600 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F }, USC_KEEP_OPEN }, - - /* UMAX */ - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1236U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2000U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA3400 }, 0 }, - - /* Visioneer */ - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_5300 }, 0 }, - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_7600 }, 0 }, - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6100 }, 0 }, - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6200 }, 0 }, - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8100 }, 0 }, - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8600 }, 0 }, - - /* Ultima */ - {{ USB_VENDOR_ULTIMA, USB_PRODUCT_ULTIMA_1200UBPLUS }, 0 }, - + /* Mustek */ + { USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU }, + { USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW1200 }, + { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_600CU }, + { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_1200USB }, + { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_1200UB }, + + /* Primax */ + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E300 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2300 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E3002 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_9600 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_600U }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_19200 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_1200U }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G600 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_636I }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2600 }, + { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E600 }, + + /* Epson */ + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_636 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_610 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1200 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1240 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1600 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640 }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U }, + { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650 }, + + /* UMAX */ + { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U }, + { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1236U }, + { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2000U }, + { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U }, + { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA3400 }, + + /* Visioneer */ + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_5300 }, + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_7600 }, + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6100 }, + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6200 }, + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8100 }, + { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8600 }, + + /* Canon */ + { USB_VENDOR_CANON, USB_PRODUCT_CANON_N656U }, + + { 0, 0 } }; -#define uscanner_lookup(v, p) ((const struct uscan_info *)usb_lookup(uscanner_devs, v, p)) #define USCANNER_BUFFERSIZE 1024 @@ -210,8 +183,6 @@ struct uscanner_softc { usbd_device_handle sc_udev; usbd_interface_handle sc_iface; - u_int sc_dev_flags; - usbd_pipe_handle sc_bulkin_pipe; int sc_bulkin; usbd_xfer_handle sc_bulkin_xfer; @@ -258,9 +229,7 @@ Static struct cdevsw uscanner_cdevsw = { /* dump */ nodump, /* psize */ nopsize, /* flags */ 0, -#if !defined(__FreeBSD__) || (__FreeBSD__ < 5) /* bmaj */ -1 -#endif }; #endif @@ -275,12 +244,19 @@ USB_DECLARE_DRIVER(uscanner); USB_MATCH(uscanner) { USB_MATCH_START(uscanner, uaa); + int i; if (uaa->iface != NULL) return UMATCH_NONE; - return (uscanner_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); + for (i = 0; scanner_ids[i].vendor != 0; i++) { + if (scanner_ids[i].vendor == uaa->vendor && + scanner_ids[i].product == uaa->product) { + return (UMATCH_VENDOR_PRODUCT); + } + } + + return (UMATCH_NONE); } USB_ATTACH(uscanner) @@ -296,8 +272,6 @@ USB_ATTACH(uscanner) USB_ATTACH_SETUP; printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); - sc->sc_dev_flags = uscanner_lookup(uaa->vendor, uaa->product)->flags; - sc->sc_udev = uaa->device; err = usbd_set_config_no(uaa->device, 1, 1); /* XXX */ @@ -361,7 +335,11 @@ USB_ATTACH(uscanner) } int -uscanneropen(dev_t dev, int flag, int mode, usb_proc_ptr p) +uscanneropen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; { struct uscanner_softc *sc; int unit = USCANNERUNIT(dev); @@ -388,25 +366,21 @@ uscanneropen(dev_t dev, int flag, int mode, usb_proc_ptr p) sc->sc_bulkout_bufferlen = USCANNER_BUFFERSIZE; /* We have decided on which endpoints to use, now open the pipes */ - if (sc->sc_bulkin_pipe == NULL) { - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin, - USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); - if (err) { - printf("%s: cannot open bulk-in pipe (addr %d)\n", - USBDEVNAME(sc->sc_dev), sc->sc_bulkin); - uscanner_do_close(sc); - return (EIO); - } + err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin, + USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); + if (err) { + printf("%s: cannot open bulk-in pipe (addr %d)\n", + USBDEVNAME(sc->sc_dev), sc->sc_bulkin); + uscanner_do_close(sc); + return (EIO); } - if (sc->sc_bulkout_pipe == NULL) { - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - printf("%s: cannot open bulk-out pipe (addr %d)\n", - USBDEVNAME(sc->sc_dev), sc->sc_bulkout); - uscanner_do_close(sc); - return (EIO); - } + err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout, + USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); + if (err) { + printf("%s: cannot open bulk-out pipe (addr %d)\n", + USBDEVNAME(sc->sc_dev), sc->sc_bulkout); + uscanner_do_close(sc); + return (EIO); } sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev); @@ -424,7 +398,11 @@ uscanneropen(dev_t dev, int flag, int mode, usb_proc_ptr p) } int -uscannerclose(dev_t dev, int flag, int mode, usb_proc_ptr p) +uscannerclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; { struct uscanner_softc *sc; @@ -457,17 +435,15 @@ uscanner_do_close(struct uscanner_softc *sc) sc->sc_bulkout_xfer = NULL; } - if (!(sc->sc_dev_flags & USC_KEEP_OPEN)) { - if (sc->sc_bulkin_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkin_pipe); - usbd_close_pipe(sc->sc_bulkin_pipe); - sc->sc_bulkin_pipe = NULL; - } - if (sc->sc_bulkout_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkout_pipe); - usbd_close_pipe(sc->sc_bulkout_pipe); - sc->sc_bulkout_pipe = NULL; - } + if (sc->sc_bulkin_pipe) { + usbd_abort_pipe(sc->sc_bulkin_pipe); + usbd_close_pipe(sc->sc_bulkin_pipe); + sc->sc_bulkin_pipe = NULL; + } + if (sc->sc_bulkout_pipe) { + usbd_abort_pipe(sc->sc_bulkout_pipe); + usbd_close_pipe(sc->sc_bulkout_pipe); + sc->sc_bulkout_pipe = NULL; } if (sc->sc_bulkin_buffer) { @@ -483,7 +459,10 @@ uscanner_do_close(struct uscanner_softc *sc) } Static int -uscanner_do_read(struct uscanner_softc *sc, struct uio *uio, int flag) +uscanner_do_read(sc, uio, flag) + struct uscanner_softc *sc; + struct uio *uio; + int flag; { u_int32_t n, tn; usbd_status err; @@ -502,7 +481,7 @@ uscanner_do_read(struct uscanner_softc *sc, struct uio *uio, int flag) sc->sc_bulkin_xfer, sc->sc_bulkin_pipe, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, sc->sc_bulkin_buffer, &tn, - "uscnrb"); + "uscannerrb"); if (err) { if (err == USBD_INTERRUPTED) error = EINTR; @@ -522,7 +501,10 @@ uscanner_do_read(struct uscanner_softc *sc, struct uio *uio, int flag) } int -uscannerread(dev_t dev, struct uio *uio, int flag) +uscannerread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; { struct uscanner_softc *sc; int error; @@ -538,7 +520,10 @@ uscannerread(dev_t dev, struct uio *uio, int flag) } Static int -uscanner_do_write(struct uscanner_softc *sc, struct uio *uio, int flag) +uscanner_do_write(sc, uio, flag) + struct uscanner_softc *sc; + struct uio *uio; + int flag; { u_int32_t n; int error = 0; @@ -558,7 +543,7 @@ uscanner_do_write(struct uscanner_softc *sc, struct uio *uio, int flag) sc->sc_bulkout_xfer, sc->sc_bulkout_pipe, 0, USBD_NO_TIMEOUT, sc->sc_bulkout_buffer, &n, - "uscnwb"); + "uscannerwb"); if (err) { if (err == USBD_INTERRUPTED) error = EINTR; @@ -572,7 +557,10 @@ uscanner_do_write(struct uscanner_softc *sc, struct uio *uio, int flag) } int -uscannerwrite(dev_t dev, struct uio *uio, int flag) +uscannerwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; { struct uscanner_softc *sc; int error; @@ -588,7 +576,9 @@ uscannerwrite(dev_t dev, struct uio *uio, int flag) #if defined(__NetBSD__) || defined(__OpenBSD__) int -uscanner_activate(device_ptr_t self, enum devact act) +uscanner_activate(self, act) + device_ptr_t self; + enum devact act; { struct uscanner_softc *sc = (struct uscanner_softc *)self; @@ -623,12 +613,11 @@ USB_DETACH(uscanner) #endif sc->sc_dying = 1; - sc->sc_dev_flags = 0; /* make close really close device */ /* Abort all pipes. Causes processes waiting for transfer to wake. */ - if (sc->sc_bulkin_pipe != NULL) + if (sc->sc_bulkin_pipe) usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) + if (sc->sc_bulkout_pipe) usbd_abort_pipe(sc->sc_bulkout_pipe); s = splusb(); @@ -663,7 +652,10 @@ USB_DETACH(uscanner) } int -uscannerpoll(dev_t dev, int events, usb_proc_ptr p) +uscannerpoll(dev, events, p) + dev_t dev; + int events; + struct proc *p; { struct uscanner_softc *sc; int revents = 0; @@ -685,7 +677,7 @@ uscannerpoll(dev_t dev, int events, usb_proc_ptr p) } int -uscannerioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p) +uscannerioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { return (EINVAL); } diff --git a/sys/dev/usb/usscanner.c b/sys/dev/usb/usscanner.c index 1d7a368d709..c8c7a530c34 100644 --- a/sys/dev/usb/usscanner.c +++ b/sys/dev/usb/usscanner.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usscanner.c,v 1.4 2002/05/07 18:08:05 nate Exp $ */ +/* $OpenBSD: usscanner.c,v 1.5 2002/05/07 18:29:19 nate Exp $ */ /* $NetBSD: usscanner.c,v 1.6 2001/01/23 14:04:14 augustss Exp $ */ /* @@ -89,22 +89,6 @@ int usscannerdebug = 0; #define DPRINTFN(n,x) #endif -#define XS_CTL_DATA_IN SCSI_DATA_IN -#define XS_CTL_DATA_OUT SCSI_DATA_OUT -#define scsipi_adapter scsi_adapter -#define scsipi_cmd scsi_cmd -#define scsipi_device scsi_device -#define scsipi_done scsi_done -#define scsipi_link scsi_link -#define scsipi_minphys scsi_minphys -#define scsipi_sense scsi_sense -#define scsipi_xfer scsi_xfer -#define show_scsipi_xs show_scsi_xs -#define show_scsipi_cmd show_scsi_cmd -#define xs_control flags -#define xs_status status -#define XS_STS_DONE ITSDONE -#define XS_CTL_POLL SCSI_POLL #define USSCANNER_CONFIG_NO 1 #define USSCANNER_IFACE_IDX 0 diff --git a/sys/dev/usb/uvisor.c b/sys/dev/usb/uvisor.c index e44687355f9..53096b1d515 100644 --- a/sys/dev/usb/uvisor.c +++ b/sys/dev/usb/uvisor.c @@ -1,5 +1,5 @@ -/* $OpenBSD: uvisor.c,v 1.4 2002/05/07 18:08:05 nate Exp $ */ -/* $NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $ */ +/* $OpenBSD: uvisor.c,v 1.5 2002/05/07 18:29:19 nate Exp $ */ +/* $NetBSD: uvisor.c,v 1.11 2001/01/23 21:56:17 augustss Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -104,6 +104,7 @@ struct uvisor_connection_info { }; #define UVISOR_CONNECTION_INFO_SIZE 18 + /* struct uvisor_connection_info.connection[x].port_function_id defines: */ #define UVISOR_FUNCTION_GENERIC 0x00 #define UVISOR_FUNCTION_DEBUGGER 0x01 @@ -111,12 +112,6 @@ struct uvisor_connection_info { #define UVISOR_FUNCTION_CONSOLE 0x03 #define UVISOR_FUNCTION_REMOTE_FILE_SYS 0x04 -/* - * Unknown PalmOS stuff. - */ -#define UVISOR_GET_PALM_INFORMATION 0x04 -#define UVISOR_GET_PALM_INFORMATION_LEN 0x14 - #define UVISORIBUFSIZE 1024 #define UVISOROBUFSIZE 1024 @@ -129,8 +124,6 @@ struct uvisor_softc { device_ptr_t sc_subdevs[UVISOR_MAX_CONN]; int sc_numcon; - u_int16_t sc_flags; - u_char sc_dying; }; @@ -151,21 +144,6 @@ struct ucom_methods uvisor_methods = { NULL, }; -struct uvisor_type { - struct usb_devno uv_dev; - u_int16_t uv_flags; -#define PALM4 0x0001 -}; -static const struct uvisor_type uvisor_devs[] = { - {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, 0 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M125 }, PALM4 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, PALM4 }, -/* {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/ -}; -#define uvisor_lookup(v, p) ((struct uvisor_type *)usb_lookup(uvisor_devs, v, p)) - USB_DECLARE_DRIVER(uvisor); USB_MATCH(uvisor) @@ -178,8 +156,11 @@ USB_MATCH(uvisor) DPRINTFN(20,("uvisor: vendor=0x%x, product=0x%x\n", uaa->vendor, uaa->product)); - return (uvisor_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); + if (uaa->vendor == USB_VENDOR_HANDSPRING && + uaa->product == USB_PRODUCT_HANDSPRING_VISOR) + return (UMATCH_VENDOR_PRODUCT); + + return (UMATCH_NONE); } USB_ATTACH(uvisor) @@ -217,8 +198,6 @@ USB_ATTACH(uvisor) USB_ATTACH_SETUP; printf("%s: %s\n", devname, devinfo); - sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags; - id = usbd_get_interface_descriptor(iface); sc->sc_udev = dev; @@ -351,7 +330,6 @@ uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci) usb_device_request_t req; int actlen; uWord avail; - char buffer[256]; DPRINTF(("uvisor_init: getting connection info\n")); req.bmRequestType = UT_READ_VENDOR_ENDPOINT; @@ -360,30 +338,10 @@ uvisor_init(struct uvisor_softc *sc, struct uvisor_connection_info *ci) USETW(req.wIndex, 0); USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); err = usbd_do_request_flags(sc->sc_udev, &req, ci, - USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); + USBD_SHORT_XFER_OK, &actlen); if (err) return (err); - if (sc->sc_flags & PALM4) { - /* Palm OS 4.0 Hack */ - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_PALM_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN); - err = usbd_do_request(sc->sc_udev, &req, buffer); - if (err) - return (err); - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_PALM_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN); - err = usbd_do_request(sc->sc_udev, &req, buffer); - if (err) - return (err); - } - DPRINTF(("uvisor_init: getting available bytes\n")); req.bmRequestType = UT_READ_VENDOR_ENDPOINT; req.bRequest = UVISOR_REQUEST_BYTES_AVAILABLE; @@ -416,5 +374,5 @@ uvisor_close(void *addr, int portno) USETW(req.wIndex, 0); USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); (void)usbd_do_request_flags(sc->sc_udev, &req, &coninfo, - USBD_SHORT_XFER_OK, &actlen, USBD_DEFAULT_TIMEOUT); + USBD_SHORT_XFER_OK, &actlen); } |