diff options
Diffstat (limited to 'sys/dev/usb')
106 files changed, 0 insertions, 82919 deletions
diff --git a/sys/dev/usb/FILES b/sys/dev/usb/FILES deleted file mode 100644 index 5a77cbd..0000000 --- a/sys/dev/usb/FILES +++ /dev/null @@ -1,52 +0,0 @@ -$FreeBSD$ - -A small roadmap of the USB files: - -FILES this file -dsbr100io.h API for ufm.c -ehci.c Host controller driver for EHCI -ehcireg.h Hardware definitions for EHCI -ehcivar.h API for ehci.c -hid.c subroutines to parse and access HID data -hid.h API for hid.c -if_aue.c USB Pegasus Ethernet driver -if_auereg.h and definitions for it -if_axe.c USB ASIX Electronics Ethernet driver -if_axereg.h and definitions for it -if_cue.c USB CATC Ethernet driver -if_cuereg.h and definitions for it -if_kue.c USB Kawasaki Ethernet driver -if_kuereg.h and definitions for it -ohci.c Host controller driver for OHCI -ohcireg.h Hardware definitions for OHCI -ohcivar.h API for ohci.c -ufm.c USB fm radio driver -[Merged] 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 HID class driver -uhub.c USB hub driver -ukbd.c USB keyboard driver -ulpt.c USB printer class driver -umass.c USB mass storage driver -umodem.c USB modem (CDC ACM) driver -ums.c USB mouse driver -urio.c USB Diamond Rio500 driver -usb.c usb (bus) device driver -usb.h general USB defines -usb_mem.c memory allocation for DMAable memory -usb_mem.h API for usb_mem.c -usb_port.h compatibility defines for different OSs -usb_quirks.c table of non-conforming USB devices and their problems -usb_quirks.h API for usb_quirks.c -usb_subr.c various subroutines used by USB code -usbcdc.h USB CDC class definitions -usbdevs data base of known device -usbdi.c implementation of the USBDI API, which all drivers use -usbdi.h API for usbdi.c -usbdi_util.c utilities built on top of usbdi.h -usbdi_util.h API for usbdi_util.c -usbdivar.h internal defines and structures for usbdi.c -uscanner.c minimal USB scanner driver -usbhid.h USB HID class definitions diff --git a/sys/dev/usb/dsbr100io.h b/sys/dev/usb/dsbr100io.h deleted file mode 100644 index f1c8a97..0000000 --- a/sys/dev/usb/dsbr100io.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 2001 M. Warner Losh - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -/* $FreeBSD$ */ - -#include <sys/ioccom.h> - -#define FM_SET_FREQ _IOWR('U', 200, int) -#define FM_GET_FREQ _IOWR('U', 201, int) -#define FM_START _IOWR('U', 202, int) -#define FM_STOP _IOWR('U', 203, int) -#define FM_GET_STAT _IOWR('U', 204, int) diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c deleted file mode 100644 index c159600..0000000 --- a/sys/dev/usb/ehci.c +++ /dev/null @@ -1,3932 +0,0 @@ -/* $NetBSD: ehci.c,v 1.91 2005/02/27 00:27:51 perry Exp $ */ - -/*- - * Copyright (c) 2004 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (lennart@augustsson.net) and by Charles M. Hannum. - * - * 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 1.0 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r10.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/docs/usb_20.zip - * - */ - -/* - * TODO: - * 1) The EHCI driver lacks support for isochronous transfers, so - * devices using them don't work. - * - * 2) Interrupt transfer scheduling does not manage the time available - * in each frame, so it is possible for the transfers to overrun - * the end of the frame. - * - * 3) Command failures are not recovered correctly. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/endian.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/lock.h> -#include <sys/lockmgr.h> -#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) -#include <machine/cpu.h> -#endif -#include <sys/proc.h> -#include <sys/queue.h> -#include <sys/sysctl.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> - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define EHCI_DEBUG USB_DEBUG -#define DPRINTF(x) do { if (ehcidebug) printf x; } while (0) -#define DPRINTFN(n,x) do { if (ehcidebug>(n)) printf x; } while (0) -int ehcidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci"); -SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW, - &ehcidebug, 0, "ehci debug level"); -#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 */ - struct { - u_int length; - } intr; - /* Bulk pipe */ - struct { - u_int length; - } bulk; - /* Iso pipe */ - struct { - u_int next_frame; - u_int cur_xfers; - } isoc; - } u; -}; - -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_check_qh_intr(ehci_softc_t *, struct ehci_xfer *); -static void ehci_check_itd_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 void ehci_intrlist_timeout(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_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 *, - ehci_soft_qtd_t **, ehci_soft_qtd_t **); -static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qh_t *, - ehci_soft_qtd_t *, ehci_soft_qtd_t *); - -static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *); -static void ehci_free_itd(ehci_softc_t *, ehci_soft_itd_t *); -static void ehci_rem_free_itd_chain(ehci_softc_t *, - struct ehci_xfer *); -static void ehci_abort_isoc_xfer(usbd_xfer_handle, usbd_status); - -static usbd_status ehci_device_request(usbd_xfer_handle xfer); - -static usbd_status ehci_device_setintr(ehci_softc_t *, ehci_soft_qh_t *, - int ival); - -static void ehci_add_qh(ehci_softc_t *, 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_activate_qh(ehci_softc_t *sc, 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); - -ehci_softc_t *theehci; - -#define EHCI_NULL(sc) htohc32(sc, 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) \ - do { \ - LIST_REMOVE((ex), inext); \ - (ex)->inext.le_prev = NULL; \ - } while (0) -#define ehci_active_intr_list(ex) ((ex)->inext.le_prev != NULL) - -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_reset(ehci_softc_t *sc) -{ - u_int32_t hcr; - u_int i; - - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; - if (!hcr) { - if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) { - /* - * Force USBMODE as requested. Controllers - * may have multiple operating modes. - */ - uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE); - if (sc->sc_flags & EHCI_SCFLG_SETMODE) { - usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST; - device_printf(sc->sc_bus.bdev, - "set host controller mode\n"); - } - if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) { - usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE; - device_printf(sc->sc_bus.bdev, - "set big-endian mode\n"); - } - EOWRITE4(sc, EHCI_USBMODE, usbmode); - } - return (USBD_NORMAL_COMPLETION); - } - } - printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev)); - return (USBD_IOERROR); -} - -static usbd_status -ehci_hcreset(ehci_softc_t *sc) -{ - u_int32_t hcr; - u_int i; - - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr) - break; - } - if (!hcr) - /* - * Fall through and try reset anyway even though - * Table 2-9 in the EHCI spec says this will result - * in undefined behavior. - */ - device_printf(sc->sc_bus.bdev, "stop timeout\n"); - - return ehci_reset(sc); -} - -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; - u_int ncomp; - int lev; - - DPRINTF(("ehci_init: start\n")); -#ifdef EHCI_DEBUG - theehci = sc; -#endif - - /* NB: must handle byte-order manually before ehci_hcreset */ - - sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); - - version = EREAD2(sc, EHCI_HCIVERSION); - device_printf(sc->sc_bus.bdev, "EHCI version %x.%x\n", - 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); - ncomp = EHCI_HCS_N_CC(sparams); - if (ncomp != sc->sc_ncomp) { - printf("%s: wrong number of companions (%d != %d)\n", - device_get_nameunit(sc->sc_bus.bdev), - ncomp, sc->sc_ncomp); - if (ncomp < sc->sc_ncomp) - sc->sc_ncomp = ncomp; - } - if (sc->sc_ncomp > 0) { - printf("%s: companion controller%s, %d port%s each:", - device_get_nameunit(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", device_get_nameunit(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)); - - if (EHCI_HCC_64BIT(cparams)) { - /* MUST clear segment register if 64 bit capable. */ - EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - } - - sc->sc_bus.usbrev = USBREV_2_0; - - /* Reset the controller */ - DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev))); - err = ehci_hcreset(sc); - if (err != USBD_NORMAL_COMPLETION) - return (err); - - /* 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; break; - case 1: sc->sc_flsize = 512; break; - case 2: sc->sc_flsize = 256; break; - case 3: return (USBD_IOERROR); - } - err = usb_allocmem(&sc->sc_bus, sc->sc_flsize * sizeof(ehci_link_t), - EHCI_FLALIGN_ALIGN, &sc->sc_fldma); - if (err) - return (err); - DPRINTF(("%s: flsize=%d\n", device_get_nameunit(sc->sc_bus.bdev),sc->sc_flsize)); - sc->sc_flist = KERNADDR(&sc->sc_fldma, 0); - - for (i = 0; i < sc->sc_flsize; i++) { - sc->sc_flist[i] = EHCI_NULL(sc); - } - - EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); - - sc->sc_softitds = malloc(sc->sc_flsize * sizeof(ehci_soft_itd_t *), - M_USB, M_NOWAIT | M_ZERO); - if (sc->sc_softitds == NULL) - return (ENOMEM); - LIST_INIT(&sc->sc_freeitds); - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ehci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ehci_pipe); - - sc->sc_eintrs = EHCI_NORMAL_INTRS; - - /* - * Allocate the interrupt dummy QHs. These are arranged to give - * poll intervals that are powers of 2 times 1ms. - */ - for (i = 0; i < EHCI_INTRQHS; i++) { - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) { - err = USBD_NOMEM; - goto bad1; - } - sc->sc_islots[i].sqh = sqh; - } - lev = 0; - for (i = 0; i < EHCI_INTRQHS; i++) { - if (i == EHCI_IQHIDX(lev + 1, 0)) - lev++; - sqh = sc->sc_islots[i].sqh; - if (i == 0) { - /* The last (1ms) QH terminates. */ - sqh->qh.qh_link = EHCI_NULL(sc); - sqh->next = NULL; - } else { - /* Otherwise the next QH has half the poll interval */ - sqh->next = - sc->sc_islots[EHCI_IQHIDX(lev - 1, i + 1)].sqh; - sqh->qh.qh_link = htohc32(sc, sqh->next->physaddr | - EHCI_LINK_QH); - } - sqh->qh.qh_endp = htohc32(sc, EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH)); - sqh->qh.qh_endphub = htohc32(sc, EHCI_QH_SET_MULT(1)); - sqh->qh.qh_curqtd = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_next = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_status = htohc32(sc, EHCI_QTD_HALTED); - } - /* Point the frame list at the last level (128ms). */ - for (i = 0; i < sc->sc_flsize; i++) { - sc->sc_flist[i] = htohc32(sc, EHCI_LINK_QH | - sc->sc_islots[EHCI_IQHIDX(EHCI_IPOLLRATES - 1, i)].sqh->physaddr); - } - - /* 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 = - htohc32(sc, EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL); - sqh->qh.qh_link = - htohc32(sc, sqh->physaddr | EHCI_LINK_QH); - sqh->qh.qh_curqtd = EHCI_NULL(sc); - sqh->prev = sqh; /*It's a circular list.. */ - sqh->next = sqh; - /* Fill the overlay qTD */ - sqh->qh.qh_qtd.qtd_next = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_status = htohc32(sc, 0); -#ifdef EHCI_DEBUG - if (ehcidebug) { - ehci_dump_sqh(sc, sqh); - } -#endif - - /* Point to async list */ - sc->sc_async_head = sqh; - EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH); - - callout_init(&sc->sc_tmo_intrlist, 0); - - 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_2 | /* 2 microframes interrupt delay */ - (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++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (!hcr) - break; - } - if (hcr) { - printf("%s: run timeout\n", device_get_nameunit(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) { - u_int32_t intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - - if (intrs) - EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ -#ifdef DIAGNOSTIC - DPRINTFN(16, ("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_intr1: sc == NULL\n"); -#endif - return (0); - } - - intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)); - if (!intrs) - return (0); - - eintrs = intrs & sc->sc_eintrs; - DPRINTFN(7, ("ehci_intr1: 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); - - EOWRITE4(sc, EHCI_USBSTS, intrs); /* Acknowledge */ - 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)) { - DPRINTFN(5,("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", - device_get_nameunit(sc->sc_bus.bdev)); - /* XXX what else */ - } - if (eintrs & EHCI_STS_PCD) { - ehci_pcd(sc, sc->sc_intrxfer); - 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", - device_get_nameunit(sc->sc_bus.bdev), eintrs); - } - - return (1); -} - -/* - * XXX write back xfer data for architectures with a write-back - * data cache; this is a hack because usb is mis-architected - * in blindly mixing bus_dma w/ PIO. - */ -static __inline void -hacksync(usbd_xfer_handle xfer) -{ - bus_dma_tag_t tag; - struct usb_dma_mapping *dmap; - - if (xfer->length == 0) - return; - tag = xfer->pipe->device->bus->buffer_dmatag; - dmap = &xfer->dmamap; - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); -} - -void -ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe; - u_char *p; - int i, m; - - if (xfer == NULL) { - /* Just ignore the change. */ - return; - } - - pipe = xfer->pipe; - - p = xfer->buffer; - 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; - - hacksync(xfer); /* XXX to compensate for usb_transfer_complete */ - usb_transfer_complete(xfer); -} - -void -ehci_softintr(void *v) -{ - ehci_softc_t *sc = v; - struct ehci_xfer *ex, *nextex; - - DPRINTFN(10,("%s: ehci_softintr (%d)\n", device_get_nameunit(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 = nextex) { - nextex = LIST_NEXT(ex, inext); - ehci_check_intr(sc, ex); - } - - /* Schedule a callout to catch any dropped transactions. */ - if ((sc->sc_flags & EHCI_SCFLG_LOSTINTRBUG) && - !LIST_EMPTY(&sc->sc_intrhead)) - callout_reset(&sc->sc_tmo_intrlist, hz / 5, - ehci_intrlist_timeout, sc); - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; -} - -/* Check for an interrupt. */ -void -ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex) -{ - int attr; - - DPRINTFN(/*15*/2, ("ehci_check_intr: ex=%p\n", ex)); - - attr = ex->xfer.pipe->endpoint->edesc->bmAttributes; - if (UE_GET_XFERTYPE(attr) == UE_ISOCHRONOUS) - ehci_check_itd_intr(sc, ex); - else - ehci_check_qh_intr(sc, ex); -} - -void -ehci_check_qh_intr(ehci_softc_t *sc, struct ehci_xfer *ex) -{ - ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status; - - if (ex->sqtdstart == NULL) { - printf("ehci_check_qh_intr: not valid sqtd\n"); - return; - } - lsqtd = ex->sqtdend; -#ifdef DIAGNOSTIC - if (lsqtd == NULL) { - printf("ehci_check_qh_intr: lsqtd==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 (hc32toh(sc, 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 = hc32toh(sc, 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_GET_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)); - callout_stop(&ex->xfer.timeout_handle); - usb_rem_task(ex->xfer.pipe->device, &ex->abort_task); - ehci_idone(ex); -} - -void -ehci_check_itd_intr(ehci_softc_t *sc, struct ehci_xfer *ex) -{ - ehci_soft_itd_t *itd; - int i; - - if (ex->itdstart == NULL) { - printf("ehci_check_itd_intr: not valid itd\n"); - return; - } - - itd = ex->itdend; -#ifdef DIAGNOSTIC - if (itd == NULL) { - printf("ehci_check_itd_intr: itdend == 0\n"); - return; - } -#endif - - /* - * Step 1, check no active transfers in last itd, meaning we're finished - */ - for (i = 0; i < 8; i++) { - if (hc32toh(sc, itd->itd.itd_ctl[i]) & EHCI_ITD_ACTIVE) - break; - } - - if (i == 8) { - goto done; /* All 8 descriptors inactive, it's done */ - } - - /* - * Step 2, check for errors in status bits, throughout chain... - */ - - DPRINTFN(12, ("ehci_check_itd_intr: active ex=%p\n", ex)); - - for (itd = ex->itdstart; itd != ex->itdend; itd = itd->xfer_next) { - for (i = 0; i < 8; i++) { - if (hc32toh(sc, itd->itd.itd_ctl[i]) & (EHCI_ITD_BUF_ERR | - EHCI_ITD_BABBLE | EHCI_ITD_ERROR)) - break; - } - if (i != 8) { /* Error in one of the itds */ - goto done; - } - } /* itd search loop */ - - DPRINTFN(12, ("ehci_check_itd_intr: ex %p itd %p still active\n", ex, - ex->itdstart)); - return; -done: - DPRINTFN(12, ("ehci_check_itd_intr: ex=%p done\n", ex)); - callout_stop(&ex->xfer.timeout_handle); - usb_rem_task(ex->xfer.pipe->device, &ex->abort_task); - ehci_idone(ex); -} - -void -ehci_idone(struct ehci_xfer *ex) -{ - usbd_xfer_handle xfer = &ex->xfer; - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - ehci_soft_qtd_t *sqtd, *lsqtd; - u_int32_t status = 0, nstatus = 0; - ehci_physaddr_t nextphys, altnextphys; - int actlen, cerr; - - 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(sc, ex->sqtdstart); -#endif - - /* - * Make sure that the QH overlay qTD does not reference any - * of the qTDs we are about to free. This is probably only - * necessary if the transfer is marked as HALTED. - */ - nextphys = EHCI_LINK_ADDR(hc32toh(sc, epipe->sqh->qh.qh_qtd.qtd_next)); - altnextphys = - EHCI_LINK_ADDR(hc32toh(sc, epipe->sqh->qh.qh_qtd.qtd_altnext)); - for (sqtd = ex->sqtdstart; sqtd != ex->sqtdend->nextqtd; - sqtd = sqtd->nextqtd) { - if (sqtd->physaddr == nextphys) { - epipe->sqh->qh.qh_qtd.qtd_next = - htohc32(sc, ex->sqtdend->nextqtd->physaddr); - DPRINTFN(4, ("ehci_idone: updated overlay next ptr\n")); - - } - if (sqtd->physaddr == altnextphys) { - DPRINTFN(4, - ("ehci_idone: updated overlay altnext ptr\n")); - epipe->sqh->qh.qh_qtd.qtd_altnext = - htohc32(sc, ex->sqtdend->nextqtd->physaddr); - } - } - - /* The transfer is done, compute actual length and status. */ - if (UE_GET_XFERTYPE(xfer->pipe->endpoint->edesc->bmAttributes) - == UE_ISOCHRONOUS) { - /* Isoc transfer */ - struct ehci_soft_itd *itd; - int i, nframes, len, uframes; - - nframes = 0; - actlen = 0; - - switch (xfer->pipe->endpoint->edesc->bInterval) { - case 0: - panic("ehci: isoc xfer suddenly has 0 bInterval, " - "invalid\n"); - case 1: - uframes = 1; - break; - case 2: - uframes = 2; - break; - case 3: - uframes = 4; - break; - default: - uframes = 8; - break; - } - - for (itd = ex->itdstart; itd != NULL; itd = itd->xfer_next) { - for (i = 0; i < 8; i += uframes) { - /* XXX - driver didn't fill in the frame full - * of uframes. This leads to scheduling - * inefficiencies, but working around - * this doubles complexity of tracking - * an xfer. - */ - if (nframes >= xfer->nframes) - break; - - status = hc32toh(sc, itd->itd.itd_ctl[i]); - len = EHCI_ITD_GET_LEN(status); - xfer->frlengths[nframes++] = len; - actlen += len; - } - if (nframes >= xfer->nframes) - break; - } - xfer->actlen = actlen; - xfer->status = USBD_NORMAL_COMPLETION; - - goto end; - } - - /* Continue processing xfers using queue heads */ - - lsqtd = ex->sqtdend; - actlen = 0; - for (sqtd = ex->sqtdstart; sqtd != lsqtd->nextqtd; - sqtd =sqtd->nextqtd) { - nstatus = hc32toh(sc, sqtd->qtd.qtd_status); - if (nstatus & EHCI_QTD_ACTIVE) - break; - - status = nstatus; - /* halt is ok if descriptor is last, and complete */ - if (sqtd == lsqtd && EHCI_QTD_GET_BYTES(status) == 0) - status &= ~EHCI_QTD_HALTED; - if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP) - actlen += sqtd->len - EHCI_QTD_GET_BYTES(status); - } - - cerr = EHCI_QTD_GET_CERR(status); - DPRINTFN(/*10*/2, ("ehci_idone: len=%d, actlen=%d, cerr=%d, " - "status=0x%x\n", xfer->length, actlen, cerr, status)); - xfer->actlen = actlen; - if ((status & EHCI_QTD_HALTED) != 0) { - DPRINTFN(2, - ("ehci_idone: error, addr=%d, endpt=0x%02x, status %b\n", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, - status, EHCI_QTD_STATUS_BITS)); - if ((status & EHCI_QTD_BABBLE) == 0 && cerr > 0) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; /* more info XXX */ - } else { - xfer->status = USBD_NORMAL_COMPLETION; - } -#ifdef EHCI_DEBUG - if (ehcidebug > 2) { - ehci_dump_sqh(sc, epipe->sqh); - ehci_dump_sqtds(sc, ex->sqtdstart); - } -#endif -end: - /* XXX transfer_complete memcpys out transfer data (for in endpoints) - * during this call, before methods->done is called: dma sync required - * beforehand? - */ - 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; - - sc->sc_dying = 1; - - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - (void) ehci_hcreset(sc); - callout_stop(&sc->sc_tmo_intrlist); - - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - - usb_freemem(&sc->sc_bus, &sc->sc_fldma); - /* XXX free other data structures XXX */ - - return (rv); -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interrupt context. This is all right since we - * are almost suspended anyway. - */ -void -ehci_power(int why, void *v) -{ - ehci_softc_t *sc = v; - u_int32_t cmd, hcr; - int s, i; - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif - - s = splhardusb(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - sc->sc_bus.use_polling++; - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_PE) == EHCI_PS_PE) - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_SUSP); - } - - sc->sc_cmd = EOREAD4(sc, EHCI_USBCMD); - - cmd = sc->sc_cmd & ~(EHCI_CMD_ASE | EHCI_CMD_PSE); - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & - (EHCI_STS_ASS | EHCI_STS_PSS); - if (hcr == 0) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != 0) { - printf("%s: reset timeout\n", - device_get_nameunit(sc->sc_bus.bdev)); - } - - cmd &= ~EHCI_CMD_RS; - EOWRITE4(sc, EHCI_USBCMD, cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr == EHCI_STS_HCH) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr != EHCI_STS_HCH) { - printf("%s: config timeout\n", - device_get_nameunit(sc->sc_bus.bdev)); - } - - sc->sc_bus.use_polling--; - break; - - case PWR_RESUME: - sc->sc_bus.use_polling++; - - /* restore things in case the bios sucks */ - EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0); - EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0)); - EOWRITE4(sc, EHCI_ASYNCLISTADDR, - sc->sc_async_head->physaddr | EHCI_LINK_QH); - EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs); - - hcr = 0; - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) { - EOWRITE4(sc, EHCI_PORTSC(i), - cmd | EHCI_PS_FPR); - hcr = 1; - } - } - - if (hcr) { - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - - for (i = 1; i <= sc->sc_noport; i++) { - cmd = EOREAD4(sc, EHCI_PORTSC(i)); - if ((cmd & EHCI_PS_PO) == 0 && - (cmd & EHCI_PS_SUSP) == EHCI_PS_SUSP) - EOWRITE4(sc, EHCI_PORTSC(i), - cmd & ~EHCI_PS_FPR); - } - } - - EOWRITE4(sc, EHCI_USBCMD, sc->sc_cmd); - - for (i = 0; i < 100; i++) { - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr != EHCI_STS_HCH) - break; - - usb_delay_ms(&sc->sc_bus, 1); - } - if (hcr == EHCI_STS_HCH) { - printf("%s: config timeout\n", - device_get_nameunit(sc->sc_bus.bdev)); - } - - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - - sc->sc_bus.use_polling--; - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); - -#ifdef EHCI_DEBUG - DPRINTF(("ehci_power: sc=%p\n", sc)); - if (ehcidebug > 0) - ehci_dump_regs(sc); -#endif -} - -/* - * 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")); - (void) ehci_hcreset(sc); -} - -usbd_status -ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - usbd_status err; - - err = usb_allocmem(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) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -ehci_allocx(struct usbd_bus *bus) -{ - struct ehci_softc *sc = (struct ehci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("ehci_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)); - usb_init_task(&EXFER(xfer)->abort_task, ehci_timeout_task, - xfer); - EXFER(xfer)->ehci_xfer_flags = 0; -#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 - STAILQ_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; - ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus; - - 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 - KASSERT((epipe->sqh->qh.qh_qtd.qtd_status & - htohc32(sc, EHCI_QTD_ACTIVE)) == 0, - ("ehci_device_clear_toggle: queue active")); - epipe->sqh->qh.qh_qtd.qtd_status &= htohc32(sc, ~EHCI_QTD_TOGGLE_MASK); -} - -static void -ehci_noop(usbd_pipe_handle pipe) -{ -} - -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 ival, speed, naks; - int hshubaddr, hshubport; - - DPRINTFN(1, ("ehci_open: pipe=%p, xfertype=%d, addr=%d, endpt=%d (%d)\n", - pipe, addr, ed->bEndpointAddress, sc->sc_addr, xfertype)); - - if (dev->myhsport) { - hshubaddr = dev->myhsport->parent->address; - hshubport = dev->myhsport->portno; - } else { - hshubaddr = 0; - hshubport = 0; - } - - 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: - DPRINTF(("ehci_open: bad bEndpointAddress 0x%02x\n", - ed->bEndpointAddress)); - 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", dev->speed); - } - if (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_ISOCHRONOUS) { - printf("%s: *** Error: opening low/full speed isoc device on" - "ehci, this does not work yet. Feel free to implement\n", - device_get_nameunit(sc->sc_bus.bdev)); - DPRINTFN(1,("ehci_open: hshubaddr=%d hshubport=%d\n", - hshubaddr, hshubport)); - return USBD_INVAL; - } - - naks = 8; /* XXX */ - /* Allocate sqh for everything, save isoc xfers */ - if (xfertype != UE_ISOCHRONOUS) { - sqh = ehci_alloc_sqh(sc); - if (sqh == NULL) - goto bad0; - /* qh_link filled when the QH is added */ - sqh->qh.qh_endp = htohc32(sc, - EHCI_QH_SET_ADDR(addr) | - EHCI_QH_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) | - EHCI_QH_SET_EPS(speed) | - (xfertype == UE_CONTROL ? EHCI_QH_DTC : 0) | - 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 = htohc32(sc, - EHCI_QH_SET_MULT(1) | - EHCI_QH_SET_HUBA(hshubaddr) | - EHCI_QH_SET_PORT(hshubport) | - EHCI_QH_SET_CMASK(0x1c) | - EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x01 : 0) - ); - sqh->qh.qh_curqtd = EHCI_NULL(sc); - /* The overlay qTD was already set up by ehci_alloc_sqh(). */ - sqh->qh.qh_qtd.qtd_status = - htohc32(sc, EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle)); - epipe->sqh = sqh; - } else { - sqh = NULL; - } - - 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(sc, sqh, sc->sc_async_head); - splx(s); - break; - case UE_BULK: - pipe->methods = &ehci_device_bulk_methods; - s = splusb(); - ehci_add_qh(sc, sqh, sc->sc_async_head); - splx(s); - break; - case UE_INTERRUPT: - pipe->methods = &ehci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (ehci_device_setintr(sc, sqh, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &ehci_device_isoc_methods; - if (ed->bInterval == 0 || ed->bInterval > 16) { - printf("ehci: opening pipe with invalid bInterval\n"); - err = USBD_INVAL; - goto bad1; - } - if (UGETW(ed->wMaxPacketSize) == 0) { - printf("ehci: zero length endpoint open request\n"); - err = USBD_INVAL; - goto bad1; - } - epipe->u.isoc.next_frame = 0; - epipe->u.isoc.cur_xfers = 0; - break; - default: - DPRINTF(("ehci: bad xfer type %d\n", xfertype)); - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); - - bad1: - if (sqh != NULL) - ehci_free_sqh(sc, sqh); - return (err); - bad0: - return (USBD_NOMEM); -} - -/* - * Add an ED to the schedule. Called at splusb(). - * If in the async schedule, it will always have a next. - * If in the intr schedule it may not. - */ -void -ehci_add_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - SPLUSBCHECK; - - sqh->next = head->next; - sqh->prev = head; - sqh->qh.qh_link = head->qh.qh_link; - head->next = sqh; - if (sqh->next) - sqh->next->prev = sqh; - head->qh.qh_link = htohc32(sc, sqh->physaddr | EHCI_LINK_QH); - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - printf("ehci_add_qh:\n"); - ehci_dump_sqh(sc, sqh); - } -#endif -} - -/* - * Remove an ED from the schedule. Called at splusb(). - * Will always have a 'next' if it's in the async list as it's circular. - */ -void -ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head) -{ - SPLUSBCHECK; - /* XXX */ - sqh->prev->qh.qh_link = sqh->qh.qh_link; - sqh->prev->next = sqh->next; - if (sqh->next) - sqh->next->prev = sqh->prev; - ehci_sync_hc(sc); -} - -/* Restart a QH following the addition of a qTD. */ -void -ehci_activate_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd) -{ - KASSERT((sqtd->qtd.qtd_status & htohc32(sc, EHCI_QTD_ACTIVE)) == 0, - ("ehci_activate_qh: already active")); - - /* - * When a QH is idle, the overlay qTD should be marked as not - * halted and not active. This causes the host controller to - * retrieve the real qTD on each pass (rather than just examinig - * the overlay), so it will notice when we activate the qTD. - */ - if (sqtd == sqh->sqtd) { - /* Check that the hardware is in the state we expect. */ - if (EHCI_LINK_ADDR(hc32toh(sc, sqh->qh.qh_qtd.qtd_next)) != - sqtd->physaddr) { -#ifdef EHCI_DEBUG - printf("ehci_activate_qh: unexpected next ptr\n"); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, sqh->sqtd); -#endif - sqh->qh.qh_qtd.qtd_next = htohc32(sc, sqtd->physaddr); - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL(sc); - } - /* Ensure the flags are correct. */ - sqh->qh.qh_qtd.qtd_status &= htohc32(sc, EHCI_QTD_PINGSTATE | - EHCI_QTD_TOGGLE_MASK); - } - - /* Now activate the qTD. */ - sqtd->qtd.qtd_status |= htohc32(sc, EHCI_QTD_ACTIVE); -} - -/* - * 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 */ - lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE, NULL); - 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 */ - lockmgr(&sc->sc_doorbell_lock, LK_RELEASE, NULL); -#ifdef DIAGNOSTIC - if (error) - printf("ehci_sync_hc: tsleep() = %d\n", error); -#endif - DPRINTFN(2,("ehci_sync_hc: exit\n")); -} - -/*Call at splusb*/ -void -ehci_rem_free_itd_chain(ehci_softc_t *sc, struct ehci_xfer *exfer) -{ - struct ehci_soft_itd *itd, *prev; - - prev = NULL; - - if (exfer->itdstart == NULL || exfer->itdend == NULL) - panic("ehci isoc xfer being freed, but with no itd chain\n"); - - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { - prev = itd->u.frame_list.prev; - /* Unlink itd from hardware chain, or frame array */ - if (prev == NULL) { /* We're at the table head */ - sc->sc_softitds[itd->slot] = itd->u.frame_list.next; - sc->sc_flist[itd->slot] = itd->itd.itd_next; - - if (itd->u.frame_list.next != NULL) - itd->u.frame_list.next->u.frame_list.prev = - NULL; - } else { - /* XXX this part is untested... */ - prev->itd.itd_next = itd->itd.itd_next; - prev->u.frame_list.next = itd->u.frame_list.next; - if (itd->u.frame_list.next != NULL) - itd->u.frame_list.next->u.frame_list.prev = - prev; - } - } - - prev = NULL; - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { - if (prev != NULL) - ehci_free_itd(sc, prev); - prev = itd; - } - if (prev) - ehci_free_itd(sc, prev); - exfer->itdstart = NULL; - exfer->itdend = NULL; -} - -/***********/ - -/* - * 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(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(STAILQ_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_start: 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 = xfer->buffer; - -#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_start: 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 0: /* Language table */ - totlen = ehci_str(buf, len, "\001"); - break; - 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_start: 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_start: clear port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_start: 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; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 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_INDICATOR(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_start: 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_start: port status=0x%04x\n", - v)); - - i = UPS_HIGH_SPEED; - - if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) { - if ((v & 0xc000000) == 0x8000000) - i = UPS_HIGH_SPEED; - else if ((v & 0xc000000) == 0x4000000) - i = UPS_LOW_SPEED; - else - i = 0; - } - - 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_start: reset port %d\n", - index)); - if (EHCI_PS_IS_LOWSPEED(v) && - (sc->sc_flags & EHCI_SCFLG_TT) == 0) { - /* 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. */ - if (sc->sc_flags & EHCI_SCFLG_NORESTERM) - ; - else - 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", - device_get_nameunit(sc->sc_bus.bdev)); - return (USBD_TIMEOUT); - } - if (!(v & EHCI_PS_PE) && - (sc->sc_flags & EHCI_SCFLG_TT) == 0) { - /* 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_start: set port power " - "%d\n", index)); - EOWRITE4(sc, port, v | EHCI_PS_PP); - break; - case UHF_PORT_TEST: - DPRINTFN(2,("ehci_root_ctrl_start: set port test " - "%d\n", index)); - break; - case UHF_PORT_INDICATOR: - DPRINTFN(2,("ehci_root_ctrl_start: 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(); - hacksync(xfer); /* XXX to compensate for usb_transfer_complete */ - 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", - device_get_nameunit(sc->sc_bus.bdev)); - else - printf("%s: handing over %s speed device on " - "port %d to %s\n", - device_get_nameunit(sc->sc_bus.bdev), - lowspeed ? "low" : "full", - index, device_get_nameunit(sc->sc_comps[i]->bdev)); - } else { - printf("%s: npcomp == 0\n", device_get_nameunit(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) -{ -} - -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(STAILQ_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) -{ -} - -/************************/ - -ehci_soft_qh_t * -ehci_alloc_sqh(ehci_softc_t *sc) -{ - ehci_soft_qh_t *sqh; - ehci_soft_qtd_t *sqtd; - 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 = KERNADDR(&dma, offs); - sqh->physaddr = DMAADDR(&dma, offs); - sqh->next = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; - } - } - /* Allocate the initial inactive sqtd. */ - sqtd = ehci_alloc_sqtd(sc); - if (sqtd == NULL) - return (NULL); - sqtd->qtd.qtd_status = htohc32(sc, 0); - sqtd->qtd.qtd_next = EHCI_NULL(sc); - sqtd->qtd.qtd_altnext = EHCI_NULL(sc); - - sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->next; - - /* The overlay QTD should begin zeroed. */ - sqh->qh.qh_qtd.qtd_next = htohc32(sc, sqtd->physaddr); - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_status = 0; - for (i = 0; i < EHCI_QTD_NBUFFERS; i++) { - sqh->qh.qh_qtd.qtd_buffer[i] = 0; - sqh->qh.qh_qtd.qtd_buffer_hi[i] = 0; - } - sqh->next = NULL; - sqh->prev = NULL; - sqh->sqtd = sqtd; - sqh->inactivesqtd = sqtd; - return (sqh); -} - -void -ehci_free_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh) -{ - ehci_free_sqtd(sc, sqh->inactivesqtd); - 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 = 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; - sqtd->qtd.qtd_next = EHCI_NULL(sc); - sqtd->qtd.qtd_altnext = EHCI_NULL(sc); - sqtd->qtd.qtd_status = 0; - for (i = 0; i < EHCI_QTD_NBUFFERS; i++) { - sqtd->qtd.qtd_buffer[i] = 0; - sqtd->qtd.qtd_buffer_hi[i] = 0; - } - 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 *start, - ehci_soft_qtd_t *newinactive, ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) -{ - ehci_soft_qtd_t *next, *cur; - ehci_physaddr_t dataphys, nextphys; - u_int32_t qtdstatus; - int adj, len, curlen, mps, offset, pagelen, seg, segoff; - int i, iscontrol, forceshort; - struct usb_dma_mapping *dma = &xfer->dmamap; - - DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen)); - - offset = 0; - len = alen; - iscontrol = (epipe->pipe.endpoint->edesc->bmAttributes & UE_XFERTYPE) == - UE_CONTROL; - qtdstatus = 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 */ - ; - mps = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize); - forceshort = ((xfer->flags & USBD_FORCE_SHORT_XFER) || len == 0) && - len % mps == 0; - /* - * The control transfer data stage always starts with a toggle of 1. - * For other transfers we let the hardware track the toggle state. - */ - if (iscontrol) - qtdstatus |= EHCI_QTD_SET_TOGGLE(1); - - if (start != NULL) { - /* - * If we are given a starting qTD, assume it is linked into - * an active QH so be careful not to mark it active. - */ - cur = start; - *sp = cur; - qtdstatus &= ~EHCI_QTD_ACTIVE; - } else { - cur = ehci_alloc_sqtd(sc); - *sp = cur; - if (cur == NULL) - goto nomem; - } - seg = 0; - segoff = 0; - for (;;) { - curlen = 0; - - /* The EHCI hardware can handle at most 5 pages. */ - for (i = 0; i < EHCI_QTD_NBUFFERS && curlen < len; i++) { - KASSERT(seg < dma->nsegs, - ("ehci_alloc_sqtd_chain: overrun")); - dataphys = dma->segs[seg].ds_addr + segoff; - pagelen = dma->segs[seg].ds_len - segoff; - if (pagelen > len - curlen) - pagelen = len - curlen; - if (pagelen > EHCI_PAGE_SIZE - - EHCI_PAGE_OFFSET(dataphys)) - pagelen = EHCI_PAGE_SIZE - - EHCI_PAGE_OFFSET(dataphys); - segoff += pagelen; - if (segoff >= dma->segs[seg].ds_len) { - KASSERT(segoff == dma->segs[seg].ds_len, - ("ehci_alloc_sqtd_chain: overlap")); - seg++; - segoff = 0; - } - - cur->qtd.qtd_buffer[i] = htohc32(sc, dataphys); - cur->qtd.qtd_buffer_hi[i] = 0; - curlen += pagelen; - - /* - * Must stop if there is any gap before or after - * the page boundary. - */ - if (EHCI_PAGE_OFFSET(dataphys + pagelen) != 0) - break; - if (seg < dma->nsegs && EHCI_PAGE_OFFSET(segoff + - dma->segs[seg].ds_addr) != 0) - break; - } - /* Adjust down to a multiple of mps if not at the end. */ - if (curlen < len && curlen % mps != 0) { - adj = curlen % mps; - curlen -= adj; - KASSERT(curlen > 0, - ("ehci_alloc_sqtd_chain: need to copy")); - segoff -= adj; - if (segoff < 0) { - seg--; - segoff += dma->segs[seg].ds_len; - } - KASSERT(seg >= 0 && segoff >= 0, - ("ehci_alloc_sqtd_chain: adjust to mps")); - } - - len -= curlen; - - if (len != 0 || forceshort) { - next = ehci_alloc_sqtd(sc); - if (next == NULL) - goto nomem; - nextphys = htohc32(sc, next->physaddr); - } else { - next = NULL; - nextphys = EHCI_NULL(sc); - } - - cur->nextqtd = next; - cur->qtd.qtd_next = nextphys; - /* Make sure to stop after a short transfer. */ - cur->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - cur->qtd.qtd_status = - htohc32(sc, qtdstatus | EHCI_QTD_SET_BYTES(curlen)); - cur->xfer = xfer; - cur->len = curlen; - DPRINTFN(10,("ehci_alloc_sqtd_chain: curlen=%d\n", curlen)); - if (iscontrol) { - /* - * adjust the toggle based on the number of packets - * in this qtd - */ - if ((((curlen + mps - 1) / mps) & 1) || curlen == 0) - qtdstatus ^= EHCI_QTD_TOGGLE_MASK; - } - qtdstatus |= EHCI_QTD_ACTIVE; - if (len == 0) { - if (!forceshort) - break; - forceshort = 0; - } - DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n")); - offset += curlen; - cur = next; - } - cur->qtd.qtd_status |= htohc32(sc, 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); -} - -/* Free the chain starting at sqtd and end at the qTD before sqtdend */ -static void -ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qh_t *sqh, - ehci_soft_qtd_t *sqtd, ehci_soft_qtd_t *sqtdend) -{ - ehci_soft_qtd_t *p, **prevp; - int i; - - DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p sqtdend=%p\n", - sqtd, sqtdend)); - - /* First unlink the chain from the QH's software qTD list. */ - prevp = &sqh->sqtd; - for (p = sqh->sqtd; p != NULL; p = p->nextqtd) { - if (p == sqtd) { - *prevp = sqtdend; - break; - } - prevp = &p->nextqtd; - } - KASSERT(p != NULL, ("ehci_free_sqtd_chain: chain not found")); - for (i = 0; sqtd != sqtdend; sqtd = p, i++) { - p = sqtd->nextqtd; - ehci_free_sqtd(sc, sqtd); - } -} - -ehci_soft_itd_t * -ehci_alloc_itd(ehci_softc_t *sc) -{ - struct ehci_soft_itd *itd, *freeitd; - usbd_status err; - int i, s, offs, frindex, previndex; - usb_dma_t dma; - - s = splusb(); - - /* Find an itd that wasn't freed this frame or last frame. This can - * discard itds that were freed before frindex wrapped around - * XXX - can this lead to thrashing? Could fix by enabling wrap-around - * interrupt and fiddling with list when that happens */ - frindex = (EOREAD4(sc, EHCI_FRINDEX) + 1) >> 3; - previndex = (frindex != 0) ? frindex - 1 : sc->sc_flsize; - - freeitd = NULL; - LIST_FOREACH(itd, &sc->sc_freeitds, u.free_list) { - if (itd == NULL) - break; - if (itd->slot != frindex && itd->slot != previndex) { - freeitd = itd; - break; - } - } - - if (freeitd == NULL) { - DPRINTFN(2, ("ehci_alloc_itd allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, EHCI_ITD_SIZE * EHCI_ITD_CHUNK, - EHCI_PAGE_SIZE, &dma); - - if (err) { - DPRINTF(("ehci_alloc_itd, alloc returned %d\n", err)); - return NULL; - } - - for (i = 0; i < EHCI_ITD_CHUNK; i++) { - offs = i * EHCI_ITD_SIZE; - itd = KERNADDR(&dma, offs); - itd->physaddr = DMAADDR(&dma, offs); - itd->dma = dma; - itd->offs = offs; - LIST_INSERT_HEAD(&sc->sc_freeitds, itd, u.free_list); - } - freeitd = LIST_FIRST(&sc->sc_freeitds); - } - - itd = freeitd; - LIST_REMOVE(itd, u.free_list); - memset(&itd->itd, 0, sizeof(ehci_itd_t)); - itd->u.frame_list.next = NULL; - itd->u.frame_list.prev = NULL; - itd->xfer_next = NULL; - itd->slot = 0; - splx(s); - - return (itd); -} - -void -ehci_free_itd(ehci_softc_t *sc, ehci_soft_itd_t *itd) -{ - int s; - - s = splusb(); - LIST_INSERT_AFTER(LIST_FIRST(&sc->sc_freeitds), itd, u.free_list); - splx(s); -} - -/****************/ - -/* - * 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); - pipe->endpoint->savedtoggle = - EHCI_QTD_GET_TOGGLE(hc32toh(sc, sqh->qh.qh_qtd.qtd_status)); - 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. - */ -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, *snext; - ehci_physaddr_t cur, us, next; - int s; - int hit, i; - /* int count = 0; */ - ehci_soft_qh_t *psqh; - - 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 */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - usb_transfer_complete(xfer); - splx(s); - return; - } - - if (xfer->device->bus->intr_context) - panic("ehci_abort_xfer: not in process context"); - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) { - DPRINTFN(2, ("ehci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n")); - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTWAIT; - while (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) - tsleep(&exfer->ehci_xfer_flags, PZERO, "ehciaw", 0); - return; - } - - /* - * Step 1: Make interrupt routine and timeouts ignore xfer. - */ - s = splusb(); - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - splx(s); - - /* - * Step 2: Wait until we know hardware has finished any possible - * use of the xfer. We do this by removing the entire - * queue from the async schedule and waiting for the doorbell. - * Nothing else should be touching the queue now. - */ - psqh = sqh->prev; - ehci_rem_qh(sc, sqh, psqh); - - /* - * Step 3: make sure the soft interrupt routine - * has run. This should remove any completed items off the queue. - * The hardware has no reference to completed items (TDs). - * It's safe to remove them at any time. - */ - s = splusb(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - tsleep(&sc->sc_softwake, PZERO, "ehciab", 0); -#endif /* USB_USE_SOFTINTR */ - - /* - * Step 4: Remove any vestiges of the xfer from the hardware. - * The complication here is that the hardware may have executed - * into or even 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. - * - * first we need to see if there are any transfers - * on this queue before the xfer we are aborting.. we need - * to update any pointers that point to us to point past - * the aborting xfer. (If there is something past us). - * Hardware and software. - */ - cur = EHCI_LINK_ADDR(hc32toh(sc, sqh->qh.qh_curqtd)); - hit = 0; - - /* If they initially point here. */ - us = exfer->sqtdstart->physaddr; - - /* We will change them to point here */ - snext = exfer->sqtdend->nextqtd; - next = (snext != NULL) ? htohc32(sc, snext->physaddr) : EHCI_NULL(sc); - - /* - * Now loop through any qTDs before us and keep track of the pointer - * that points to us for the end. - */ - sqtd = sqh->sqtd; - while (sqtd && sqtd != exfer->sqtdstart) { - hit |= (cur == sqtd->physaddr); - if (EHCI_LINK_ADDR(hc32toh(sc, sqtd->qtd.qtd_next)) == us) - sqtd->qtd.qtd_next = next; - if (EHCI_LINK_ADDR(hc32toh(sc, sqtd->qtd.qtd_altnext)) == us) - sqtd->qtd.qtd_altnext = next; - sqtd = sqtd->nextqtd; - } - - /* - * If we already saw the active one then we are pretty much done. - * We've done all the relinking we need to do. - */ - if (!hit) { - - /* - * Now reinitialise the QH to point to the next qTD - * (if there is one). We only need to do this if - * it was previously pointing to us. - */ - for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) { - if (cur == sqtd->physaddr) { - hit++; - } - if (sqtd == exfer->sqtdend) - break; - } - sqtd = sqtd->nextqtd; - /* - * Only need to alter the QH if it was pointing at a qTD - * that we are removing. - */ - if (hit) { - sqh->qh.qh_qtd.qtd_next = htohc32(sc, snext->physaddr); - sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL(sc); - sqh->qh.qh_qtd.qtd_status &= - htohc32(sc, EHCI_QTD_TOGGLE_MASK); - for (i = 0; i < EHCI_QTD_NBUFFERS; i++) { - sqh->qh.qh_qtd.qtd_buffer[i] = 0; - sqh->qh.qh_qtd.qtd_buffer_hi[i] = 0; - } - } - } - ehci_add_qh(sc, sqh, psqh); - /* - * Step 5: Execute callback. - */ -#ifdef DIAGNOSTIC - exfer->isdone = 1; -#endif - /* Do the wakeup first to avoid touching the xfer after the callback. */ - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTING; - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTWAIT) { - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTWAIT; - wakeup(&exfer->ehci_xfer_flags); - } - usb_transfer_complete(xfer); - - /* printf("%s: %d TDs aborted\n", __func__, count); */ - 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_add_task(exfer->xfer.pipe->device, &exfer->abort_task, - USB_TASKQ_HC); -} - -void -ehci_abort_isoc_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - ehci_isoc_trans_t trans_status; - struct ehci_pipe *epipe; - struct ehci_xfer *exfer; - ehci_softc_t *sc; - struct ehci_soft_itd *itd; - int s, i; - - epipe = (struct ehci_pipe *) xfer->pipe; - exfer = EXFER(xfer); - sc = (ehci_softc_t *)epipe->pipe.device->bus; - - DPRINTF(("ehci_abort_isoc_xfer: xfer %p pipe %p\n", xfer, epipe)); - - if (sc->sc_dying) { - s = splusb(); - xfer->status = status; - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - usb_transfer_complete(xfer); - splx(s); - return; - } - - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) { - DPRINTFN(2, ("ehci_abort_isoc_xfer: already aborting\n")); - -#ifdef DIAGNOSTIC - if (status == USBD_TIMEOUT) - printf("ehci_abort_xfer: TIMEOUT while aborting\n"); -#endif - - xfer->status = status; - DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n")); - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTWAIT; - while (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING) - tsleep(&exfer->ehci_xfer_flags, PZERO, "ehciaw", 0); - return; - } - exfer->ehci_xfer_flags |= EHCI_XFER_ABORTING; - - xfer->status = status; - callout_stop(&xfer->timeout_handle); - usb_rem_task(epipe->pipe.device, &exfer->abort_task); - - s = splusb(); - for (itd = exfer->itdstart; itd != NULL; itd = itd->xfer_next) { - - for (i = 0; i < 8; i++) { - trans_status = hc32toh(sc, itd->itd.itd_ctl[i]); - trans_status &= ~EHCI_ITD_ACTIVE; - itd->itd.itd_ctl[i] = htohc32(sc, trans_status); - } - - } - splx(s); - - s = splusb(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - tsleep(&sc->sc_softwake, PZERO, "ehciab", 0); -#endif /* USB_USE_SOFTINTR */ - splx(s); - -#ifdef DIAGNOSTIC - exfer->isdone = 1; -#endif - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTING; - if (exfer->ehci_xfer_flags & EHCI_XFER_ABORTWAIT) { - exfer->ehci_xfer_flags &= ~EHCI_XFER_ABORTWAIT; - wakeup(&exfer->ehci_xfer_flags); - } - usb_transfer_complete(xfer); -} - -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); -} - -/* - * Some EHCI chips from VIA / ATI seem to trigger interrupts before writing - * back the qTD status, or miss signalling occasionally under heavy load. - * If the host machine is too fast, we can miss transaction completion - when - * we scan the active list the transaction still seems to be active. This - * generally exhibits itself as a umass stall that never recovers. - * - * We work around this behaviour by setting up this callback after any softintr - * that completes with transactions still pending, giving us another chance to - * check for completion after the writeback has taken place. - */ -void -ehci_intrlist_timeout(void *arg) -{ - ehci_softc_t *sc = arg; - int s = splusb(); - - DPRINTFN(3, ("ehci_intrlist_timeout\n")); - usb_schedsoftintr(&sc->sc_bus); - - 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(STAILQ_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"); - } -#endif - - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, epipe->sqh, ex->sqtdstart, - ex->sqtdend->nextqtd); - } - - 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; - ehci_soft_qtd_t *newinactive, *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_request: 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, dev->address, - epipe->pipe.endpoint->edesc->bEndpointAddress)); - - newinactive = ehci_alloc_sqtd(sc); - if (newinactive == NULL) { - err = USBD_NOMEM; - goto bad1; - } - newinactive->qtd.qtd_status = htohc32(sc, 0); - newinactive->qtd.qtd_next = EHCI_NULL(sc); - newinactive->qtd.qtd_altnext = EHCI_NULL(sc); - - stat = ehci_alloc_sqtd(sc); - if (stat == NULL) { - err = USBD_NOMEM; - goto bad2; - } - - sqh = epipe->sqh; - setup = sqh->inactivesqtd; - sqh->inactivesqtd = newinactive; - epipe->u.ctl.length = len; - - /* Set up data transaction */ - if (len != 0) { - ehci_soft_qtd_t *end; - - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - NULL, newinactive, &next, &end); - if (err) - goto bad3; - end->qtd.qtd_status &= htohc32(sc, ~EHCI_QTD_IOC); - end->nextqtd = stat; - end->qtd.qtd_next = htohc32(sc, stat->physaddr); - end->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - } else { - next = stat; - } - - memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req); - - /* Clear toggle, and do not activate until complete */ - setup->qtd.qtd_status = htohc32(sc, - EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_SET_TOGGLE(0) | - EHCI_QTD_SET_BYTES(sizeof *req) - ); - setup->qtd.qtd_buffer[0] = htohc32(sc, DMAADDR(&epipe->u.ctl.reqdma, 0)); - setup->qtd.qtd_buffer_hi[0] = 0; - setup->nextqtd = next; - setup->qtd.qtd_next = htohc32(sc, next->physaddr); - setup->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - setup->xfer = xfer; - setup->len = sizeof *req; - - stat->qtd.qtd_status = htohc32(sc, - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | - EHCI_QTD_SET_CERR(3) | - EHCI_QTD_SET_TOGGLE(1) | - EHCI_QTD_IOC - ); - stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */ - stat->qtd.qtd_buffer_hi[0] = 0; /* XXX not needed? */ - stat->nextqtd = newinactive; - stat->qtd.qtd_next = htohc32(sc, newinactive->physaddr); - stat->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - stat->xfer = xfer; - stat->len = 0; - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_request:\n")); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, 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 - - /* Activate the new qTD in the QH list. */ - s = splusb(); - ehci_activate_qh(sc, sqh, setup); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&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->sc_async_head); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, setup); - } -#endif - - return (USBD_NORMAL_COMPLETION); - - bad3: - sqh->inactivesqtd = setup; - ehci_free_sqtd(sc, stat); - bad2: - ehci_free_sqtd(sc, newinactive); - 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(STAILQ_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, *newinactive; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - int s; - - DPRINTFN(2, ("ehci_device_bulk_start: 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_start: a request"); -#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; - - newinactive = ehci_alloc_sqtd(sc); - if (newinactive == NULL) { - DPRINTFN(-1,("ehci_device_bulk_start: no sqtd memory\n")); - err = USBD_NOMEM; - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - newinactive->qtd.qtd_status = htohc32(sc, 0); - newinactive->qtd.qtd_next = EHCI_NULL(sc); - newinactive->qtd.qtd_altnext = EHCI_NULL(sc); - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - sqh->inactivesqtd, newinactive, &data, &dataend); - if (err) { - DPRINTFN(-1,("ehci_device_bulk_start: no memory\n")); - ehci_free_sqtd(sc, newinactive); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - dataend->nextqtd = newinactive; - dataend->qtd.qtd_next = htohc32(sc, newinactive->physaddr); - dataend->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - sqh->inactivesqtd = newinactive; - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_bulk_start: data(1)\n")); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, data); - } -#endif - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - printf("ehci_device_bulk_start: not done, ex=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - s = splusb(); - ehci_activate_qh(sc, sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&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_start: data(2)\n")); - delay(10000); - DPRINTF(("ehci_device_bulk_start: 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(sc, sqh); - ehci_dump_sqtds(sc, 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_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, epipe->sqh, ex->sqtdstart, - ex->sqtdend->nextqtd); - } - - DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen)); -} - -/************************/ - -static usbd_status -ehci_device_setintr(ehci_softc_t *sc, ehci_soft_qh_t *sqh, int ival) -{ - struct ehci_soft_islot *isp; - int islot, lev; - - /* Find a poll rate that is large enough. */ - for (lev = EHCI_IPOLLRATES - 1; lev > 0; lev--) - if (EHCI_ILEV_IVAL(lev) <= ival) - break; - - /* Pick an interrupt slot at the right level. */ - /* XXX could do better than picking at random. */ - islot = EHCI_IQHIDX(lev, arc4random()); - - sqh->islot = islot; - isp = &sc->sc_islots[islot]; - ehci_add_qh(sc, sqh, isp->sqh); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -ehci_device_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (ehci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ehci_device_intr_start(usbd_xfer_handle xfer) -{ -#define exfer EXFER(xfer) - struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe; - usbd_device_handle dev = xfer->pipe->device; - ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - ehci_soft_qtd_t *data, *dataend, *newinactive; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - int s; - - DPRINTFN(2, ("ehci_device_intr_start: 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_intr_start: a request"); -#endif - - len = xfer->length; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = epipe->sqh; - - epipe->u.intr.length = len; - - newinactive = ehci_alloc_sqtd(sc); - if (newinactive == NULL) { - DPRINTFN(-1,("ehci_device_intr_start: no sqtd memory\n")); - err = USBD_NOMEM; - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - newinactive->qtd.qtd_status = htohc32(sc, 0); - newinactive->qtd.qtd_next = EHCI_NULL(sc); - newinactive->qtd.qtd_altnext = EHCI_NULL(sc); - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - sqh->inactivesqtd, newinactive, &data, &dataend); - if (err) { - DPRINTFN(-1, ("ehci_device_intr_start: no memory\n")); - xfer->status = err; - usb_transfer_complete(xfer); - return (err); - } - dataend->nextqtd = newinactive; - dataend->qtd.qtd_next = htohc32(sc, newinactive->physaddr); - dataend->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - sqh->inactivesqtd = newinactive; - -#ifdef EHCI_DEBUG - if (ehcidebug > 5) { - DPRINTF(("ehci_device_intr_start: data(1)\n")); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, data); - } -#endif - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - printf("ehci_device_intr_start: not done, ex=%p\n", exfer); - } - exfer->isdone = 0; -#endif - - s = splusb(); - ehci_activate_qh(sc, sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&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_intr_start: data(2)\n")); - delay(10000); - DPRINTF(("ehci_device_intr_start: data(3)\n")); - ehci_dump_regs(sc); - printf("sqh:\n"); - ehci_dump_sqh(sc, sqh); - ehci_dump_sqtds(sc, data); - } -#endif - - if (sc->sc_bus.use_polling) - ehci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -#undef exfer -} - -static void -ehci_device_intr_abort(usbd_xfer_handle xfer) -{ - DPRINTFN(1, ("ehci_device_intr_abort: xfer=%p\n", xfer)); - if (xfer->pipe->intrxfer == xfer) { - DPRINTFN(1, ("ehci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - /* - * XXX - abort_xfer uses ehci_sync_hc, which syncs via the advance - * async doorbell. That's dependant on the async list, wheras - * intr xfers are periodic, should not use this? - */ - ehci_abort_xfer(xfer, USBD_CANCELLED); -} - -static void -ehci_device_intr_close(usbd_pipe_handle pipe) -{ - ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus; - struct ehci_pipe *epipe = (struct ehci_pipe *)pipe; - struct ehci_soft_islot *isp; - - isp = &sc->sc_islots[epipe->sqh->islot]; - ehci_close_pipe(pipe, isp->sqh); -} - -static void -ehci_device_intr_done(usbd_xfer_handle xfer) -{ -#define exfer EXFER(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; - ehci_soft_qtd_t *data, *dataend, *newinactive; - ehci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt, s; - - DPRINTFN(10, ("ehci_device_intr_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - sqh = epipe->sqh; - if (xfer->pipe->repeat) { - ehci_free_sqtd_chain(sc, sqh, ex->sqtdstart, - ex->sqtdend->nextqtd); - - len = epipe->u.intr.length; - xfer->length = len; - endpt = epipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - - newinactive = ehci_alloc_sqtd(sc); - if (newinactive == NULL) { - DPRINTFN(-1, - ("ehci_device_intr_done: no sqtd memory\n")); - err = USBD_NOMEM; - xfer->status = err; - return; - } - newinactive->qtd.qtd_status = htohc32(sc, 0); - newinactive->qtd.qtd_next = EHCI_NULL(sc); - newinactive->qtd.qtd_altnext = EHCI_NULL(sc); - err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, - sqh->inactivesqtd, newinactive, &data, &dataend); - if (err) { - DPRINTFN(-1, ("ehci_device_intr_done: no memory\n")); - xfer->status = err; - return; - } - dataend->nextqtd = newinactive; - dataend->qtd.qtd_next = htohc32(sc, newinactive->physaddr); - dataend->qtd.qtd_altnext = htohc32(sc, newinactive->physaddr); - sqh->inactivesqtd = newinactive; - - /* Set up interrupt info. */ - exfer->sqtdstart = data; - exfer->sqtdend = dataend; -#ifdef DIAGNOSTIC - if (!exfer->isdone) { - printf("ehci_device_intr_done: not done, ex=%p\n", - exfer); - } - exfer->isdone = 0; -#endif - - s = splusb(); - ehci_activate_qh(sc, sqh, data); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, - MS_TO_TICKS(xfer->timeout), ehci_timeout, xfer); - } - splx(s); - - xfer->status = USBD_IN_PROGRESS; - } else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) { - ehci_del_intr_list(ex); /* remove from active list */ - ehci_free_sqtd_chain(sc, sqh, ex->sqtdstart, - ex->sqtdend->nextqtd); - } -#undef exfer -} - -/************************/ - -static usbd_status -ehci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - err = usb_insert_transfer(xfer); - if (err && err != USBD_IN_PROGRESS) - return (err); - - return (ehci_device_isoc_start(xfer)); -} - -static usbd_status -ehci_device_isoc_start(usbd_xfer_handle xfer) -{ - struct ehci_pipe *epipe; - usbd_device_handle dev; - ehci_softc_t *sc; - struct ehci_xfer *exfer; - ehci_soft_itd_t *itd, *prev, *start, *stop; - usb_dma_t *dma_buf; - int i, j, k, frames, uframes, ufrperframe; - int s, trans_count, offs, total_length; - int frindex; - - start = NULL; - prev = NULL; - itd = NULL; - trans_count = 0; - total_length = 0; - exfer = (struct ehci_xfer *) xfer; - sc = (ehci_softc_t *)xfer->pipe->device->bus; - dev = xfer->pipe->device; - epipe = (struct ehci_pipe *)xfer->pipe; - - /* - * To allow continuous transfers, above we start all transfers - * immediately. However, we're still going to get usbd_start_next call - * this when another xfer completes. So, check if this is already - * in progress or not - */ - - if (exfer->itdstart != NULL) - return (USBD_IN_PROGRESS); - - DPRINTFN(2, ("ehci_device_isoc_start: xfer %p len %d flags %d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - /* - * To avoid complication, don't allow a request right now that'll span - * the entire frame table. To within 4 frames, to allow some leeway - * on either side of where the hc currently is. - */ - if ((1 << (epipe->pipe.endpoint->edesc->bInterval)) * - xfer->nframes >= (sc->sc_flsize - 4) * 8) { - printf("ehci: isoc descriptor requested that spans the entire" - " frametable, too many frames\n"); - return (USBD_INVAL); - } - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ehci_device_isoc_start: request\n"); - - if (!exfer->isdone) - printf("ehci_device_isoc_start: not done, ex = %p\n", exfer); - exfer->isdone = 0; -#endif - - /* - * Step 1: Allocate and initialize itds, how many do we need? - * One per transfer if interval >= 8 microframes, fewer if we use - * multiple microframes per frame. - */ - - i = epipe->pipe.endpoint->edesc->bInterval; - if (i > 16 || i == 0) { - /* Spec page 271 says intervals > 16 are invalid */ - DPRINTF(("ehci_device_isoc_start: bInvertal %d invalid\n", i)); - return (USBD_INVAL); - } - - switch (i) { - case 1: - ufrperframe = 8; - break; - case 2: - ufrperframe = 4; - break; - case 3: - ufrperframe = 2; - break; - default: - ufrperframe = 1; - break; - } - frames = (xfer->nframes + (ufrperframe - 1)) / ufrperframe; - uframes = 8 / ufrperframe; - - if (frames == 0) { - DPRINTF(("ehci_device_isoc_start: frames == 0\n")); - return (USBD_INVAL); - } - - dma_buf = xfer->buffer; - offs = 0; - - for (i = 0; i < frames; i++) { - int froffs = offs; - itd = ehci_alloc_itd(sc); - - if (prev != NULL) { - prev->itd.itd_next = - htohc32(sc, itd->physaddr | EHCI_LINK_ITD); - prev->xfer_next = itd; - } else { - start = itd; - } - - /* - * Step 1.5, initialize uframes - */ - for (j = 0; j < 8; j += uframes) { - /* Calculate which page in the list this starts in */ - int addr = DMAADDR(dma_buf, froffs); - addr = EHCI_PAGE_OFFSET(addr); - addr += (offs - froffs); - addr = EHCI_PAGE(addr); - addr /= EHCI_PAGE_SIZE; - - /* This gets the initial offset into the first page, - * looks how far further along the current uframe - * offset is. Works out how many pages that is. - */ - - itd->itd.itd_ctl[j] = htohc32(sc, EHCI_ITD_ACTIVE | - EHCI_ITD_SET_LEN(xfer->frlengths[trans_count]) | - EHCI_ITD_SET_PG(addr) | - EHCI_ITD_SET_OFFS(EHCI_PAGE_OFFSET(DMAADDR(dma_buf, - offs)))); - - total_length += xfer->frlengths[trans_count]; - offs += xfer->frlengths[trans_count]; - trans_count++; - - if (trans_count >= xfer->nframes) { /*Set IOC*/ - itd->itd.itd_ctl[j] |= htohc32(sc, EHCI_ITD_IOC); - } - } - - /* Step 1.75, set buffer pointers. To simplify matters, all - * pointers are filled out for the next 7 hardware pages in - * the dma block, so no need to worry what pages to cover - * and what to not. - */ - - for (j=0; j < 7; j++) { - /* - * Don't try to lookup a page that's past the end - * of buffer - */ - int page_offs = EHCI_PAGE(froffs + - (EHCI_PAGE_SIZE * j)); - if (page_offs >= dma_buf->block->size) - break; - - int page = DMAADDR(dma_buf, page_offs); - page = EHCI_PAGE(page); - itd->itd.itd_bufr[j] = - htohc32(sc, EHCI_ITD_SET_BPTR(page) | EHCI_LINK_ITD); - } - - /* - * Other special values - */ - - k = epipe->pipe.endpoint->edesc->bEndpointAddress; - itd->itd.itd_bufr[0] |= htohc32(sc, - EHCI_ITD_SET_EP(UE_GET_ADDR(k)) | - EHCI_ITD_SET_DADDR(epipe->pipe.device->address)); - - k = (UE_GET_DIR(epipe->pipe.endpoint->edesc->bEndpointAddress)) - ? 1 : 0; - j = UE_GET_SIZE( - UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)); - itd->itd.itd_bufr[1] |= htohc32(sc, EHCI_ITD_SET_DIR(k) | - EHCI_ITD_SET_MAXPKT(UE_GET_SIZE(j))); - - /* FIXME: handle invalid trans */ - itd->itd.itd_bufr[2] |= - htohc32(sc, EHCI_ITD_SET_MULTI(UE_GET_TRANS(j)+1)); - prev = itd; - } /* End of frame */ - - stop = itd; - stop->xfer_next = NULL; - exfer->isoc_len = total_length; - - /* - * Part 2: Transfer descriptors have now been set up, now they must - * be scheduled into the period frame list. Erk. Not wanting to - * complicate matters, transfer is denied if the transfer spans - * more than the period frame list. - */ - - s = splusb(); - - /* Start inserting frames */ - if (epipe->u.isoc.cur_xfers > 0) { - frindex = epipe->u.isoc.next_frame; - } else { - frindex = EOREAD4(sc, EHCI_FRINDEX); - frindex = frindex >> 3; /* Erase microframe index */ - frindex += 2; - } - - if (frindex >= sc->sc_flsize) - frindex &= (sc->sc_flsize - 1); - - /* Whats the frame interval? */ - i = (1 << epipe->pipe.endpoint->edesc->bInterval); - if (i / 8 == 0) - i = 1; - else - i /= 8; - - itd = start; - for (j = 0; j < frames; j++) { - if (itd == NULL) - panic("ehci: unexpectedly ran out of isoc itds," - "isoc_start\n"); - - itd->itd.itd_next = sc->sc_flist[frindex]; - if (itd->itd.itd_next == 0) - /* FIXME: frindex table gets initialized to NULL - * or EHCI_NULL? */ - itd->itd.itd_next = EHCI_NULL(sc); - - sc->sc_flist[frindex] = htohc32(sc, EHCI_LINK_ITD | itd->physaddr); - - itd->u.frame_list.next = sc->sc_softitds[frindex]; - sc->sc_softitds[frindex] = itd; - if (itd->u.frame_list.next != NULL) - itd->u.frame_list.next->u.frame_list.prev = itd; - itd->slot = frindex; - itd->u.frame_list.prev = NULL; - - frindex += i; - if (frindex >= sc->sc_flsize) - frindex -= sc->sc_flsize; - - itd = itd->xfer_next; - } - - epipe->u.isoc.cur_xfers++; - epipe->u.isoc.next_frame = frindex; - - exfer->itdstart = start; - exfer->itdend = stop; - exfer->sqtdstart = NULL; - exfer->sqtdstart = NULL; - - ehci_add_intr_list(sc, exfer); - xfer->status = USBD_IN_PROGRESS; - xfer->done = 0; - splx(s); - - if (sc->sc_bus.use_polling) { - printf("Starting ehci isoc xfer with polling. Bad idea?\n"); - ehci_waitintr(sc, xfer); - } - - return (USBD_IN_PROGRESS); -} - -static void -ehci_device_isoc_abort(usbd_xfer_handle xfer) -{ - DPRINTFN(1, ("ehci_device_isoc_abort: xfer = %p\n", xfer)); - ehci_abort_isoc_xfer(xfer, USBD_CANCELLED); -} - -static void -ehci_device_isoc_close(usbd_pipe_handle pipe) -{ - printf("ehci_device_isoc_close: nothing in the pipe to free?\n"); -} - -static void -ehci_device_isoc_done(usbd_xfer_handle xfer) -{ - struct ehci_xfer *exfer; - ehci_softc_t *sc; - struct ehci_pipe *epipe; - int s; - - exfer = EXFER(xfer); - sc = (ehci_softc_t *)xfer->pipe->device->bus; - epipe = (struct ehci_pipe *) xfer->pipe; - - s = splusb(); - epipe->u.isoc.cur_xfers--; - if (xfer->status != USBD_NOMEM && ehci_active_intr_list(exfer)) { - ehci_del_intr_list(exfer); - ehci_rem_free_itd_chain(sc, exfer); - } - splx(s); -} diff --git a/sys/dev/usb/ehci_ddb.c b/sys/dev/usb/ehci_ddb.c deleted file mode 100644 index 3ebd130..0000000 --- a/sys/dev/usb/ehci_ddb.c +++ /dev/null @@ -1,255 +0,0 @@ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_ddb.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/endian.h> -#include <sys/bus.h> -#include <sys/lock.h> -#include <sys/lockmgr.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/ehcireg.h> -#include <dev/usb/ehcivar.h> - -#ifdef DDB -#include <ddb/ddb.h> -#include <ddb/db_sym.h> -#else -#define db_printf printf -#endif - -extern ehci_softc_t *theehci; /* XXX */ - -void -ehci_dump_regs(ehci_softc_t *sc) -{ - int i; - db_printf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n", - EOREAD4(sc, EHCI_USBCMD), - EOREAD4(sc, EHCI_USBSTS), - EOREAD4(sc, EHCI_USBINTR)); - db_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++) - db_printf("port %d status=0x%08x\n", i, - EOREAD4(sc, EHCI_PORTSC(i))); -} - -static void -ehci_dump_link(ehci_softc_t *sc, ehci_link_t link, int type) -{ - link = hc32toh(sc, link); - db_printf("0x%08x", link); - if (link & EHCI_LINK_TERMINATE) - db_printf("<T>"); - else { - db_printf("<"); - if (type) { - switch (EHCI_LINK_TYPE(link)) { - case EHCI_LINK_ITD: db_printf("ITD"); break; - case EHCI_LINK_QH: db_printf("QH"); break; - case EHCI_LINK_SITD: db_printf("SITD"); break; - case EHCI_LINK_FSTN: db_printf("FSTN"); break; - } - } - db_printf(">"); - } -} - -void -ehci_dump_sqtds(ehci_softc_t *sc, 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(sc, sqtd); - stop = sqtd->qtd.qtd_next & htohc32(sc, EHCI_LINK_TERMINATE); - } - if (sqtd) - db_printf("dump aborted, too many TDs\n"); -} - -void -ehci_dump_qtd(ehci_softc_t *sc, ehci_qtd_t *qtd) -{ - u_int32_t s; - - db_printf(" next="); ehci_dump_link(sc, qtd->qtd_next, 0); - db_printf(" altnext="); ehci_dump_link(sc, qtd->qtd_altnext, 0); - db_printf("\n"); - s = hc32toh(sc, qtd->qtd_status); - db_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)); - db_printf(" cerr=%d pid=%d stat=%b\n", EHCI_QTD_GET_CERR(s), - EHCI_QTD_GET_PID(s), - EHCI_QTD_GET_STATUS(s), EHCI_QTD_STATUS_BITS); - for (s = 0; s < 5; s++) - db_printf(" buffer[%d]=0x%08x\n", s, hc32toh(sc, qtd->qtd_buffer[s])); -} - -void -ehci_dump_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd) -{ - db_printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr); - ehci_dump_qtd(sc, &sqtd->qtd); -} - -void -ehci_dump_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh) -{ - ehci_qh_t *qh = &sqh->qh; - u_int32_t endp, endphub; - - db_printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr); - db_printf(" sqtd=%p inactivesqtd=%p\n", sqh->sqtd, sqh->inactivesqtd); - db_printf(" link="); ehci_dump_link(sc, qh->qh_link, 1); db_printf("\n"); - endp = hc32toh(sc, qh->qh_endp); - db_printf(" endp=0x%08x\n", endp); - db_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)); - db_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 = hc32toh(sc, qh->qh_endphub); - db_printf(" endphub=0x%08x\n", endphub); - db_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)); - db_printf(" curqtd="); ehci_dump_link(sc, qh->qh_curqtd, 0); db_printf("\n"); - db_printf("Overlay qTD:\n"); - ehci_dump_qtd(sc, &qh->qh_qtd); -} - -void -ehci_dump_itd(ehci_softc_t *sc, struct ehci_soft_itd *itd) -{ - ehci_isoc_trans_t t; - ehci_isoc_bufr_ptr_t b, b2, b3; - int i; - - db_printf("ITD: next phys=%X\n", itd->itd.itd_next); - - for (i = 0; i < 8;i++) { - t = hc32toh(sc, itd->itd.itd_ctl[i]); - db_printf("ITDctl %d: stat=%X len=%X ioc=%X pg=%X offs=%X\n", i, - EHCI_ITD_GET_STATUS(t), EHCI_ITD_GET_LEN(t), - EHCI_ITD_GET_IOC(t), EHCI_ITD_GET_PG(t), - EHCI_ITD_GET_OFFS(t)); - } - db_printf("ITDbufr: "); - for (i = 0; i < 7; i++) - db_printf("%X,", EHCI_ITD_GET_BPTR(hc32toh(sc, itd->itd.itd_bufr[i]))); - - b = hc32toh(sc, itd->itd.itd_bufr[0]); - b2 = hc32toh(sc, itd->itd.itd_bufr[1]); - b3 = hc32toh(sc, itd->itd.itd_bufr[2]); - db_printf("\nep=%X daddr=%X dir=%d maxpkt=%X multi=%X\n", - EHCI_ITD_GET_EP(b), EHCI_ITD_GET_DADDR(b), EHCI_ITD_GET_DIR(b2), - EHCI_ITD_GET_MAXPKT(b2), EHCI_ITD_GET_MULTI(b3)); -} - -void -ehci_dump_sitd(ehci_softc_t *sc, struct ehci_soft_itd *itd) -{ - db_printf("SITD %p next=%p prev=%p xfernext=%p physaddr=%X slot=%d\n", - itd, itd->u.frame_list.next, itd->u.frame_list.prev, - itd->xfer_next, itd->physaddr, itd->slot); -} - -void -ehci_dump_exfer(struct ehci_xfer *ex) -{ -#ifdef DIAGNOSTIC - db_printf("%p: sqtdstart %p end %p itdstart %p end %p isdone %d\n", - ex, ex->sqtdstart, ex->sqtdend, ex->itdstart, - ex->itdend, ex->isdone); -#else - db_printf("%p: sqtdstart %p end %p itdstart %p end %p\n", - ex, ex->sqtdstart, ex->sqtdend, ex->itdstart, ex->itdend); -#endif -} - -#ifdef DDB -DB_SHOW_COMMAND(ehci, db_show_ehci) -{ - if (!have_addr) { - db_printf("usage: show ehci <addr>\n"); - return; - } - ehci_dump_regs((ehci_softc_t *) addr); -} - -DB_SHOW_COMMAND(ehci_sqtds, db_show_ehci_sqtds) -{ - if (!have_addr) { - db_printf("usage: show ehci_sqtds <addr>\n"); - return; - } - ehci_dump_sqtds(theehci, (ehci_soft_qtd_t *) addr); -} - -DB_SHOW_COMMAND(ehci_qtd, db_show_ehci_qtd) -{ - if (!have_addr) { - db_printf("usage: show ehci_qtd <addr>\n"); - return; - } - ehci_dump_qtd(theehci, (ehci_qtd_t *) addr); -} - -DB_SHOW_COMMAND(ehci_sqh, db_show_ehci_sqh) -{ - if (!have_addr) { - db_printf("usage: show ehci_sqh <addr>\n"); - return; - } - ehci_dump_sqh(theehci, (ehci_soft_qh_t *) addr); -} - -DB_SHOW_COMMAND(ehci_itd, db_show_ehci_itd) -{ - if (!have_addr) { - db_printf("usage: show ehci_itd <addr>\n"); - return; - } - ehci_dump_itd(theehci, (struct ehci_soft_itd *) addr); -} - -DB_SHOW_COMMAND(ehci_sitd, db_show_ehci_sitd) -{ - if (!have_addr) { - db_printf("usage: show ehci_sitd <addr>\n"); - return; - } - ehci_dump_itd(theehci, (struct ehci_soft_itd *) addr); -} - -DB_SHOW_COMMAND(ehci_xfer, db_show_ehci_xfer) -{ - if (!have_addr) { - db_printf("usage: show ehci_xfer <addr>\n"); - return; - } - ehci_dump_exfer((struct ehci_xfer *) addr); -} -#endif /* DDB */ diff --git a/sys/dev/usb/ehci_ixp4xx.c b/sys/dev/usb/ehci_ixp4xx.c deleted file mode 100644 index bc800d3..0000000 --- a/sys/dev/usb/ehci_ixp4xx.c +++ /dev/null @@ -1,360 +0,0 @@ -/*- - * Copyright (c) 2008 Sam Leffler. 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 ``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. - */ - -/* - * IXP435 attachment driver for the USB Enhanced Host Controller. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_bus.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/queue.h> -#include <sys/lockmgr.h> -#include <sys/rman.h> - -#include <machine/bus.h> -#include <machine/resource.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/ehcireg.h> -#include <dev/usb/ehcivar.h> - -#include <arm/xscale/ixp425/ixp425reg.h> -#include <arm/xscale/ixp425/ixp425var.h> - -#define EHCI_VENDORID_IXP4XX 0x42fa05 -#define EHCI_HC_DEVSTR "IXP4XX Integrated USB 2.0 controller" - -struct ixp_ehci_softc { - ehci_softc_t base; /* storage for EHCI code */ - bus_space_tag_t iot; - bus_space_handle_t ioh; - struct bus_space tag; /* tag for private bus space ops */ -}; - -static int ehci_ixp_detach(device_t self); - -static uint8_t ehci_bs_r_1(void *, bus_space_handle_t, bus_size_t); -static void ehci_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); -static uint16_t ehci_bs_r_2(void *, bus_space_handle_t, bus_size_t); -static void ehci_bs_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t); -static uint32_t ehci_bs_r_4(void *, bus_space_handle_t, bus_size_t); -static void ehci_bs_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t); - -static int -ehci_ixp_suspend(device_t self) -{ - ehci_softc_t *sc; - int err; - - err = bus_generic_suspend(self); - if (err == 0) { - sc = device_get_softc(self); - ehci_power(PWR_SUSPEND, sc); - } - return err; -} - -static int -ehci_ixp_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_power(PWR_RESUME, sc); - bus_generic_resume(self); - return 0; -} - -static int -ehci_ixp_shutdown(device_t self) -{ - ehci_softc_t *sc; - int err; - - err = bus_generic_shutdown(self); - if (err == 0) { - sc = device_get_softc(self); - ehci_shutdown(sc); - } - return err; -} - -static int -ehci_ixp_probe(device_t self) -{ - device_set_desc(self, EHCI_HC_DEVSTR); - return BUS_PROBE_DEFAULT; -} - -static int -ehci_ixp_attach(device_t self) -{ - struct ixp_ehci_softc *isc = device_get_softc(self); - ehci_softc_t *sc = &isc->base; - int err, rid; - - sc->sc_bus.usbrev = USBREV_2_0; - - /* NB: hints fix the memory location and irq */ - - rid = 0; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, - &rid, RF_ACTIVE); - if (sc->io_res == NULL) { - device_printf(self, "Could not map memory\n"); - return ENXIO; - } - - /* - * Craft special resource for bus space ops that handle - * byte-alignment of non-word addresses. Also, since - * we're already intercepting bus space ops we handle - * the register window offset that could otherwise be - * done with bus_space_subregion. - */ - isc->iot = rman_get_bustag(sc->io_res); - isc->tag.bs_cookie = isc->iot; - /* read single */ - isc->tag.bs_r_1 = ehci_bs_r_1, - isc->tag.bs_r_2 = ehci_bs_r_2, - isc->tag.bs_r_4 = ehci_bs_r_4, - /* write (single) */ - isc->tag.bs_w_1 = ehci_bs_w_1, - isc->tag.bs_w_2 = ehci_bs_w_2, - isc->tag.bs_w_4 = ehci_bs_w_4, - - sc->iot = &isc->tag; - sc->ioh = rman_get_bushandle(sc->io_res); - sc->sc_size = IXP435_USB1_SIZE - 0x100; - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, - &rid, RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ehci_ixp_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ehci_ixp_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - sprintf(sc->sc_vendor, "Intel"); - sc->sc_id_vendor = EHCI_VENDORID_IXP4XX; - - err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, - NULL, (driver_intr_t*)ehci_intr, sc, &sc->ih); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ehci_ixp_detach(self); - return ENXIO; - } - - /* There are no companion USB controllers */ - sc->sc_ncomp = 0; - - /* Allocate a parent dma tag for DMA maps */ - err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - NULL, NULL, &sc->sc_bus.parent_dmatag); - if (err) { - device_printf(self, "Could not allocate parent DMA tag (%d)\n", - err); - ehci_ixp_detach(self); - return ENXIO; - } - - /* Allocate a dma tag for transfer buffers */ - err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); - if (err) { - device_printf(self, "Could not allocate buffer DMA tag (%d)\n", - err); - ehci_ixp_detach(self); - return ENXIO; - } - - /* - * Arrange to force Host mode, select big-endian byte alignment, - * and arrange to not terminate reset operations (the adapter - * will ignore it if we do but might as well save a reg write). - * Also, the controller has an embedded Transaction Translator - * which means port speed must be read from the Port Status - * register following a port enable. - */ - sc->sc_flags |= EHCI_SCFLG_TT - | EHCI_SCFLG_SETMODE - | EHCI_SCFLG_BIGEDESC - | EHCI_SCFLG_BIGEMMIO - | EHCI_SCFLG_NORESTERM - ; - (void) ehci_reset(sc); - - err = ehci_init(sc); - if (!err) { - sc->sc_flags |= EHCI_SCFLG_DONEINIT; - err = device_probe_and_attach(sc->sc_bus.bdev); - } - - if (err) { - device_printf(self, "USB init failed err=%d\n", err); - ehci_ixp_detach(self); - return EIO; - } - return 0; -} - -static int -ehci_ixp_detach(device_t self) -{ - struct ixp_ehci_softc *isc = device_get_softc(self); - ehci_softc_t *sc = &isc->base; - int err; - - if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { - ehci_detach(sc, 0); - sc->sc_flags &= ~EHCI_SCFLG_DONEINIT; - } - - /* - * Disable interrupts that might have been switched on in ehci_init() - */ - if (sc->iot && sc->ioh) - bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0); - if (sc->sc_bus.parent_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.parent_dmatag); - if (sc->sc_bus.buffer_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag); - - if (sc->irq_res && sc->ih) { - err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev != NULL) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res != NULL) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res != NULL) { - bus_release_resource(self, SYS_RES_MEMORY, 0, sc->io_res); - sc->io_res = NULL; - } - sc->iot = 0; - sc->ioh = 0; - return 0; -} - -/* - * Bus space accessors for PIO operations. - */ - -static uint8_t -ehci_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o) -{ - return bus_space_read_1((bus_space_tag_t) t, h, - 0x100 + (o &~ 3) + (3 - (o & 3))); -} - -static void -ehci_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v) -{ - panic("%s", __func__); -} - -static uint16_t -ehci_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o) -{ - return bus_space_read_2((bus_space_tag_t) t, h, - 0x100 + (o &~ 3) + (2 - (o & 3))); -} - -static void -ehci_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v) -{ - panic("%s", __func__); -} - -static uint32_t -ehci_bs_r_4(void *t, bus_space_handle_t h, bus_size_t o) -{ - return bus_space_read_4((bus_space_tag_t) t, h, 0x100 + o); -} - -static void -ehci_bs_w_4(void *t, bus_space_handle_t h, bus_size_t o, uint32_t v) -{ - bus_space_write_4((bus_space_tag_t) t, h, 0x100 + o, v); -} - -static device_method_t ehci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ehci_ixp_probe), - DEVMETHOD(device_attach, ehci_ixp_attach), - DEVMETHOD(device_detach, ehci_ixp_detach), - DEVMETHOD(device_suspend, ehci_ixp_suspend), - DEVMETHOD(device_resume, ehci_ixp_resume), - DEVMETHOD(device_shutdown, ehci_ixp_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - {0, 0} -}; - -static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(struct ixp_ehci_softc), -}; -static devclass_t ehci_devclass; -DRIVER_MODULE(ehci, ixp, ehci_driver, ehci_devclass, 0, 0); diff --git a/sys/dev/usb/ehci_mbus.c b/sys/dev/usb/ehci_mbus.c deleted file mode 100644 index 792c89d..0000000 --- a/sys/dev/usb/ehci_mbus.c +++ /dev/null @@ -1,396 +0,0 @@ -/*- - * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. - * All rights reserved. - * - * Developed by Semihalf. - * - * 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. Neither the name of MARVELL nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY 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 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. - */ - -/* - * MBus attachment driver for the USB Enhanced Host Controller. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_bus.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/queue.h> -#include <sys/lockmgr.h> -#include <sys/rman.h> -#include <sys/endian.h> - -#include <machine/bus.h> -#include <machine/resource.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/ehcireg.h> -#include <dev/usb/ehcivar.h> - -#include <arm/mv/mvreg.h> -#include <arm/mv/mvvar.h> - -#define EHCI_VENDORID_MRVL 0x1286 -#define EHCI_HC_DEVSTR "Marvell Integrated USB 2.0 controller" - -static device_attach_t ehci_mbus_attach; -static device_detach_t ehci_mbus_detach; -static device_shutdown_t ehci_mbus_shutdown; -static device_suspend_t ehci_mbus_suspend; -static device_resume_t ehci_mbus_resume; - -static int err_intr(void *arg); - -struct resource *irq_err; -void *ih_err; - -#define USB_BRIDGE_INTR_CAUSE 0x210 -#define USB_BRIDGE_INTR_MASK 0x214 - -#define MV_USB_ADDR_DECODE_ERR (1 << 0) -#define MV_USB_HOST_UNDERFLOW (1 << 1) -#define MV_USB_HOST_OVERFLOW (1 << 2) -#define MV_USB_DEVICE_UNDERFLOW (1 << 3) - -static int -ehci_mbus_suspend(device_t self) -{ - ehci_softc_t *sc; - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - - sc = device_get_softc(self); - ehci_power(PWR_SUSPEND, sc); - - return (0); -} - -static int -ehci_mbus_resume(device_t self) -{ - ehci_softc_t *sc; - - sc = device_get_softc(self); - - ehci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return (0); -} - -static int -ehci_mbus_shutdown(device_t self) -{ - ehci_softc_t *sc; - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - - sc = device_get_softc(self); - ehci_shutdown(sc); - - return (0); -} - -static int -ehci_mbus_probe(device_t self) -{ - - device_set_desc(self, EHCI_HC_DEVSTR); - - return (BUS_PROBE_DEFAULT); -} - -static int -ehci_mbus_attach(device_t self) -{ - ehci_softc_t *sc; - bus_space_handle_t bsh; - int err, rid; - - sc = device_get_softc(self); - sc->sc_bus.usbrev = USBREV_2_0; - - rid = 0; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map memory\n"); - return (ENXIO); - } - sc->iot = rman_get_bustag(sc->io_res); - bsh = rman_get_bushandle(sc->io_res); - - /* - * Marvell EHCI host controller registers start at certain offset within - * the whole USB registers range, so create a subregion for the host - * mode configuration purposes. - */ - if (bus_space_subregion(sc->iot, bsh, MV_USB_HOST_OFST, - MV_USB_SIZE - MV_USB_HOST_OFST, &sc->ioh) != 0) - panic("%s: unable to subregion USB host registers", - device_get_name(self)); - sc->sc_size = MV_USB_SIZE - MV_USB_HOST_OFST; - - rid = 0; - irq_err = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (irq_err == NULL) { - device_printf(self, "Could not allocate error irq\n"); - ehci_mbus_detach(self); - return (ENXIO); - } - - /* - * Notice: Marvell EHCI controller has TWO interrupt lines, so make sure to - * use the correct rid for the main one (controller interrupt) -- - * refer to obio_devices[] for the right resource number to use here. - */ - rid = 1; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ehci_mbus_detach(self); - return (ENXIO); - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ehci_mbus_detach(self); - return (ENOMEM); - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - sprintf(sc->sc_vendor, "Marvell"); - sc->sc_id_vendor = EHCI_VENDORID_MRVL; - - err = bus_setup_intr(self, irq_err, INTR_FAST | INTR_TYPE_BIO, - err_intr, NULL, sc, &ih_err); - if (err) { - device_printf(self, "Could not setup error irq, %d\n", err); - ih_err = NULL; - ehci_mbus_detach(self); - return (ENXIO); - } - - EWRITE4(sc, USB_BRIDGE_INTR_MASK, MV_USB_ADDR_DECODE_ERR | - MV_USB_HOST_UNDERFLOW | MV_USB_HOST_OVERFLOW | - MV_USB_DEVICE_UNDERFLOW); - - err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, - NULL, (driver_intr_t*)ehci_intr, sc, &sc->ih); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ehci_mbus_detach(self); - return (ENXIO); - } - - /* There are no companion USB controllers */ - sc->sc_ncomp = 0; - - /* Allocate a parent dma tag for DMA maps */ - err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - NULL, NULL, &sc->sc_bus.parent_dmatag); - if (err) { - device_printf(self, "Could not allocate parent DMA tag (%d)\n", - err); - ehci_mbus_detach(self); - return (ENXIO); - } - - /* Allocate a dma tag for transfer buffers */ - err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); - if (err) { - device_printf(self, "Could not allocate buffer DMA tag (%d)\n", - err); - ehci_mbus_detach(self); - return (ENXIO); - } - - /* - * Workaround for Marvell integrated EHCI controller: reset of - * the EHCI core clears the USBMODE register, which sets the core in - * an undefined state (neither host nor agent), so it needs to be set - * again for proper operation. - * - * Refer to errata document MV-S500832-00D.pdf (p. 5.24 GL USB-2) for - * details. - */ - sc->sc_flags |= EHCI_SCFLG_SETMODE; - if (bootverbose) - device_printf(self, "5.24 GL USB-2 workaround enabled\n"); - - /* XXX all MV chips need it? */ - sc->sc_flags |= EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_NORESTERM; - - err = ehci_init(sc); - if (!err) { - sc->sc_flags |= EHCI_SCFLG_DONEINIT; - err = device_probe_and_attach(sc->sc_bus.bdev); - } - - if (err) { - device_printf(self, "USB init failed err=%d\n", err); - ehci_mbus_detach(self); - return (EIO); - } - return (0); -} - -static int -ehci_mbus_detach(device_t self) -{ - ehci_softc_t *sc; - int err; - - sc = device_get_softc(self); - if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { - ehci_detach(sc, 0); - sc->sc_flags &= ~EHCI_SCFLG_DONEINIT; - } - - /* - * Disable interrupts that might have been switched on in ehci_init() - */ - if (sc->iot && sc->ioh) - bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0); - if (sc->sc_bus.parent_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.parent_dmatag); - if (sc->sc_bus.buffer_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag); - - if (sc->irq_res && sc->ih) { - err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0); - - if (irq_err && ih_err) { - err = bus_teardown_intr(self, irq_err, ih_err); - - if (err) - device_printf(self, "Could not tear down irq, %d\n", - err); - ih_err = NULL; - } - - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (irq_err) { - bus_release_resource(self, SYS_RES_IRQ, 1, irq_err); - irq_err = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_MEMORY, 0, sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return (0); -} - -static int -err_intr(void *arg) -{ - ehci_softc_t *sc = arg; - unsigned int cause; - - cause = EREAD4(sc, USB_BRIDGE_INTR_CAUSE); - if (cause) { - printf("IRQ ERR: cause: 0x%08x\n", cause); - if (cause & MV_USB_ADDR_DECODE_ERR) - printf("IRQ ERR: Address decoding error\n"); - if (cause & MV_USB_HOST_UNDERFLOW) - printf("IRQ ERR: USB Host Underflow\n"); - if (cause & MV_USB_HOST_OVERFLOW) - printf("IRQ ERR: USB Host Overflow\n"); - if (cause & MV_USB_DEVICE_UNDERFLOW) - printf("IRQ ERR: USB Device Underflow\n"); - if (cause & ~(MV_USB_ADDR_DECODE_ERR | MV_USB_HOST_UNDERFLOW | - MV_USB_HOST_OVERFLOW | MV_USB_DEVICE_UNDERFLOW)) - printf("IRQ ERR: Unknown error\n"); - - EWRITE4(sc, USB_BRIDGE_INTR_CAUSE, 0); - } - return (FILTER_HANDLED); -} - -static device_method_t ehci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ehci_mbus_probe), - DEVMETHOD(device_attach, ehci_mbus_attach), - DEVMETHOD(device_detach, ehci_mbus_detach), - DEVMETHOD(device_suspend, ehci_mbus_suspend), - DEVMETHOD(device_resume, ehci_mbus_resume), - DEVMETHOD(device_shutdown, ehci_mbus_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - {0, 0} -}; - -static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(ehci_softc_t), -}; - -static devclass_t ehci_devclass; - -DRIVER_MODULE(ehci, mbus, ehci_driver, ehci_devclass, 0, 0); diff --git a/sys/dev/usb/ehci_pci.c b/sys/dev/usb/ehci_pci.c deleted file mode 100644 index 819bc25..0000000 --- a/sys/dev/usb/ehci_pci.c +++ /dev/null @@ -1,636 +0,0 @@ -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) 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> -__FBSDID("$FreeBSD$"); - -/* - * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller. - * - * The EHCI 1.0 spec can be found at - * http://developer.intel.com/technology/usb/download/ehci-r10.pdf - * and the USB 2.0 spec at - * http://www.usb.org/developers/docs/usb_20.zip - */ - -/* The low level controller code for EHCI has been split into - * PCI probes and EHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/queue.h> -#include <sys/lockmgr.h> -#include <sys/rman.h> -#include <sys/endian.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.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/ehcireg.h> -#include <dev/usb/ehcivar.h> - -#define PCI_EHCI_VENDORID_ACERLABS 0x10b9 -#define PCI_EHCI_VENDORID_AMD 0x1022 -#define PCI_EHCI_VENDORID_APPLE 0x106b -#define PCI_EHCI_VENDORID_ATI 0x1002 -#define PCI_EHCI_VENDORID_CMDTECH 0x1095 -#define PCI_EHCI_VENDORID_INTEL 0x8086 -#define PCI_EHCI_VENDORID_NEC 0x1033 -#define PCI_EHCI_VENDORID_OPTI 0x1045 -#define PCI_EHCI_VENDORID_PHILIPS 0x1131 -#define PCI_EHCI_VENDORID_SIS 0x1039 -#define PCI_EHCI_VENDORID_NVIDIA 0x12D2 -#define PCI_EHCI_VENDORID_NVIDIA2 0x10DE -#define PCI_EHCI_VENDORID_VIA 0x1106 - -/* AcerLabs/ALi */ -#define PCI_EHCI_DEVICEID_M5239 0x523910b9 -static const char *ehci_device_m5239 = "ALi M5239 USB 2.0 controller"; - -/* AMD */ -#define PCI_EHCI_DEVICEID_8111 0x10227463 -static const char *ehci_device_8111 = "AMD 8111 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_CS5536 0x20951022 -static const char *ehci_device_cs5536 = "AMD CS5536 (Geode) USB 2.0 controller"; - -/* ATI */ -#define PCI_EHCI_DEVICEID_SB200 0x43451002 -static const char *ehci_device_sb200 = "ATI SB200 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_SB400 0x43731002 -static const char *ehci_device_sb400 = "ATI SB400 USB 2.0 controller"; - -/* Intel */ -#define PCI_EHCI_DEVICEID_6300 0x25ad8086 -static const char *ehci_device_6300 = "Intel 6300ESB USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH4 0x24cd8086 -static const char *ehci_device_ich4 = "Intel 82801DB/L/M (ICH4) USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH5 0x24dd8086 -static const char *ehci_device_ich5 = "Intel 82801EB/R (ICH5) USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH6 0x265c8086 -static const char *ehci_device_ich6 = "Intel 82801FB (ICH6) USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH7 0x27cc8086 -static const char *ehci_device_ich7 = "Intel 82801GB/R (ICH7) USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_ICH8_A 0x28368086 -static const char *ehci_device_ich8_a = "Intel 82801H (ICH8) USB 2.0 controller USB2-A"; -#define PCI_EHCI_DEVICEID_ICH8_B 0x283a8086 -static const char *ehci_device_ich8_b = "Intel 82801H (ICH8) USB 2.0 controller USB2-B"; -#define PCI_EHCI_DEVICEID_ICH9_A 0x293a8086 -#define PCI_EHCI_DEVICEID_ICH9_B 0x293c8086 -static const char *ehci_device_ich9 = "Intel 82801I (ICH9) USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_63XX 0x268c8086 -static const char *ehci_device_63XX = "Intel 63XXESB USB 2.0 controller"; - -/* NEC */ -#define PCI_EHCI_DEVICEID_NEC 0x00e01033 -static const char *ehci_device_nec = "NEC uPD 720100 USB 2.0 controller"; - -/* NVIDIA */ -#define PCI_EHCI_DEVICEID_NF2 0x006810de -static const char *ehci_device_nf2 = "NVIDIA nForce2 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF2_400 0x008810de -static const char *ehci_device_nf2_400 = "NVIDIA nForce2 Ultra 400 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF3 0x00d810de -static const char *ehci_device_nf3 = "NVIDIA nForce3 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF3_250 0x00e810de -static const char *ehci_device_nf3_250 = "NVIDIA nForce3 250 USB 2.0 controller"; -#define PCI_EHCI_DEVICEID_NF4 0x005b10de -static const char *ehci_device_nf4 = "NVIDIA nForce4 USB 2.0 controller"; - -/* Philips */ -#define PCI_EHCI_DEVICEID_ISP156X 0x15621131 -static const char *ehci_device_isp156x = "Philips ISP156x USB 2.0 controller"; - -#define PCI_EHCI_DEVICEID_VIA 0x31041106 -static const char *ehci_device_via = "VIA VT6202 USB 2.0 controller"; - -static const char *ehci_device_generic = "EHCI (generic) USB 2.0 controller"; - -#define PCI_EHCI_BASE_REG 0x10 - -#ifdef USB_DEBUG -#define EHCI_DEBUG USB_DEBUG -#define DPRINTF(x) do { if (ehcidebug) printf x; } while (0) -extern int ehcidebug; -#else -#define DPRINTF(x) -#endif - -static device_attach_t ehci_pci_attach; -static device_detach_t ehci_pci_detach; -static device_shutdown_t ehci_pci_shutdown; -static device_suspend_t ehci_pci_suspend; -static device_resume_t ehci_pci_resume; -static void ehci_pci_givecontroller(device_t self); -static void ehci_pci_takecontroller(device_t self); - -static int -ehci_pci_suspend(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return (err); - ehci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -ehci_pci_resume(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - ehci_pci_takecontroller(self); - ehci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static int -ehci_pci_shutdown(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_shutdown(self); - if (err) - return (err); - ehci_shutdown(sc); - ehci_pci_givecontroller(self); - - return 0; -} - -static const char * -ehci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - switch (device_id) { - case PCI_EHCI_DEVICEID_M5239: - return (ehci_device_m5239); - case PCI_EHCI_DEVICEID_8111: - return (ehci_device_8111); - case PCI_EHCI_DEVICEID_CS5536: - return (ehci_device_cs5536); - case PCI_EHCI_DEVICEID_SB200: - return (ehci_device_sb200); - case PCI_EHCI_DEVICEID_SB400: - return (ehci_device_sb400); - case PCI_EHCI_DEVICEID_6300: - return (ehci_device_6300); - case PCI_EHCI_DEVICEID_63XX: - return (ehci_device_63XX); - case PCI_EHCI_DEVICEID_ICH4: - return (ehci_device_ich4); - case PCI_EHCI_DEVICEID_ICH5: - return (ehci_device_ich5); - case PCI_EHCI_DEVICEID_ICH6: - return (ehci_device_ich6); - case PCI_EHCI_DEVICEID_ICH7: - return (ehci_device_ich7); - case PCI_EHCI_DEVICEID_ICH8_A: - return (ehci_device_ich8_a); - case PCI_EHCI_DEVICEID_ICH8_B: - return (ehci_device_ich8_b); - case PCI_EHCI_DEVICEID_ICH9_A: - case PCI_EHCI_DEVICEID_ICH9_B: - return (ehci_device_ich9); - case PCI_EHCI_DEVICEID_NEC: - return (ehci_device_nec); - case PCI_EHCI_DEVICEID_NF2: - return (ehci_device_nf2); - case PCI_EHCI_DEVICEID_NF2_400: - return (ehci_device_nf2_400); - case PCI_EHCI_DEVICEID_NF3: - return (ehci_device_nf3); - case PCI_EHCI_DEVICEID_NF3_250: - return (ehci_device_nf3_250); - case PCI_EHCI_DEVICEID_NF4: - return (ehci_device_nf4); - case PCI_EHCI_DEVICEID_ISP156X: - return (ehci_device_isp156x); - case PCI_EHCI_DEVICEID_VIA: - return (ehci_device_via); - default: - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_EHCI) { - return (ehci_device_generic); - } - } - - return NULL; /* dunno */ -} - -static int -ehci_pci_probe(device_t self) -{ - const char *desc = ehci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - return BUS_PROBE_DEFAULT; - } else { - return ENXIO; - } -} - -static int -ehci_pci_attach(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - devclass_t dc; - device_t parent; - device_t *neighbors; - device_t *nbus; - struct usbd_bus *bsc; - int err; - int rid; - int ncomp; - int count, buscount; - int slot, function; - int res; - int i; - - switch(pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) { - case PCI_USBREV_PRE_1_0: - case PCI_USBREV_1_0: - case PCI_USBREV_1_1: - device_printf(self, "pre-2.0 USB rev\n"); - if (pci_get_devid(self) == PCI_EHCI_DEVICEID_CS5536) { - sc->sc_bus.usbrev = USBREV_2_0; - device_printf(self, "Quirk for CS5536 USB 2.0 enabled\n"); - break; - } - - /* - * Quirk for Parallels Desktop 4.0. - */ - if (pci_get_devid(self) == PCI_EHCI_DEVICEID_ICH6) { - sc->sc_bus.usbrev = USBREV_2_0; - break; - } - sc->sc_bus.usbrev = USBREV_UNKNOWN; - return ENXIO; - case PCI_USBREV_2_0: - sc->sc_bus.usbrev = USBREV_2_0; - break; - default: - sc->sc_bus.usbrev = USBREV_UNKNOWN; - break; - } - - pci_enable_busmaster(self); - - rid = PCI_CBMEM; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map memory\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ehci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ehci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* ehci_pci_match will never return NULL if ehci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_EHCI_VENDORID_ACERLABS: - sprintf(sc->sc_vendor, "AcerLabs"); - break; - case PCI_EHCI_VENDORID_AMD: - sprintf(sc->sc_vendor, "AMD"); - break; - case PCI_EHCI_VENDORID_APPLE: - sprintf(sc->sc_vendor, "Apple"); - break; - case PCI_EHCI_VENDORID_ATI: - sprintf(sc->sc_vendor, "ATI"); - break; - case PCI_EHCI_VENDORID_CMDTECH: - sprintf(sc->sc_vendor, "CMDTECH"); - break; - case PCI_EHCI_VENDORID_INTEL: - sprintf(sc->sc_vendor, "Intel"); - break; - case PCI_EHCI_VENDORID_NEC: - sprintf(sc->sc_vendor, "NEC"); - break; - case PCI_EHCI_VENDORID_OPTI: - sprintf(sc->sc_vendor, "OPTi"); - break; - case PCI_EHCI_VENDORID_SIS: - sprintf(sc->sc_vendor, "SiS"); - break; - case PCI_EHCI_VENDORID_NVIDIA: - case PCI_EHCI_VENDORID_NVIDIA2: - sprintf(sc->sc_vendor, "nVidia"); - break; - case PCI_EHCI_VENDORID_VIA: - sprintf(sc->sc_vendor, "VIA"); - break; - default: - if (bootverbose) - device_printf(self, "(New EHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, - NULL, (driver_intr_t *)ehci_intr, sc, &sc->ih); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ehci_pci_detach(self); - return ENXIO; - } - - /* Enable workaround for dropped interrupts as required */ - switch (pci_get_vendor(self)) { - case PCI_EHCI_VENDORID_ATI: - case PCI_EHCI_VENDORID_VIA: - sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG; - if (bootverbose) - device_printf(self, - "Dropped interrupts workaround enabled\n"); - break; - default: - break; - } - - /* - * Find companion controllers. According to the spec they always - * have lower function numbers so they should be enumerated already. - */ - parent = device_get_parent(self); - res = device_get_children(parent, &neighbors, &count); - if (res != 0) { - device_printf(self, "Error finding companion busses\n"); - ehci_pci_detach(self); - return ENXIO; - } - ncomp = 0; - dc = devclass_find("usb"); - slot = pci_get_slot(self); - function = pci_get_function(self); - for (i = 0; i < count; i++) { - if (pci_get_slot(neighbors[i]) == slot && \ - pci_get_function(neighbors[i]) < function) { - res = device_get_children(neighbors[i], - &nbus, &buscount); - if (res != 0) - continue; - if (buscount != 1) { - free(nbus, M_TEMP); - continue; - } - if (device_get_devclass(nbus[0]) != dc) { - free(nbus, M_TEMP); - continue; - } - bsc = device_get_softc(nbus[0]); - free(nbus, M_TEMP); - DPRINTF(("ehci_pci_attach: companion %s\n", - device_get_nameunit(bsc->bdev))); - sc->sc_comps[ncomp++] = bsc; - if (ncomp >= EHCI_COMPANION_MAX) - break; - } - } - sc->sc_ncomp = ncomp; - - /* Allocate a parent dma tag for DMA maps */ - err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - NULL, NULL, &sc->sc_bus.parent_dmatag); - if (err) { - device_printf(self, "Could not allocate parent DMA tag (%d)\n", - err); - ehci_pci_detach(self); - return ENXIO; - } - - /* Allocate a dma tag for transfer buffers */ - err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); - if (err) { - device_printf(self, "Could not allocate buffer DMA tag (%d)\n", - err); - ehci_pci_detach(self); - return ENXIO; - } - - ehci_pci_takecontroller(self); - err = ehci_init(sc); - if (!err) { - sc->sc_flags |= EHCI_SCFLG_DONEINIT; - err = device_probe_and_attach(sc->sc_bus.bdev); - } - - if (err) { - device_printf(self, "USB init failed err=%d\n", err); - ehci_pci_detach(self); - return EIO; - } - return 0; -} - -static int -ehci_pci_detach(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & EHCI_SCFLG_DONEINIT) { - ehci_detach(sc, 0); - sc->sc_flags &= ~EHCI_SCFLG_DONEINIT; - } - - /* - * disable interrupts that might have been switched on in ehci_init - */ - if (sc->iot && sc->ioh) - bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0); - if (sc->sc_bus.parent_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.parent_dmatag); - if (sc->sc_bus.buffer_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag); - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - -static void -ehci_pci_takecontroller(device_t self) -{ - ehci_softc_t *sc = device_get_softc(self); - u_int32_t cparams, eec; - uint8_t bios_sem; - int eecp, i; - - cparams = EREAD4(sc, EHCI_HCCPARAMS); - - /* Synchronise with the BIOS if it owns the controller. */ - for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; - eecp = EHCI_EECP_NEXT(eec)) { - eec = pci_read_config(self, eecp, 4); - if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) - continue; - bios_sem = pci_read_config(self, eecp + EHCI_LEGSUP_BIOS_SEM, - 1); - if (bios_sem) { - pci_write_config(self, eecp + EHCI_LEGSUP_OS_SEM, 1, 1); - printf("%s: waiting for BIOS to give up control\n", - device_get_nameunit(sc->sc_bus.bdev)); - for (i = 0; i < 5000; i++) { - bios_sem = pci_read_config(self, eecp + - EHCI_LEGSUP_BIOS_SEM, 1); - if (bios_sem == 0) - break; - DELAY(1000); - } - if (bios_sem) - printf("%s: timed out waiting for BIOS\n", - device_get_nameunit(sc->sc_bus.bdev)); - } - } -} - -static void -ehci_pci_givecontroller(device_t self) -{ -#if 0 - ehci_softc_t *sc = device_get_softc(self); - u_int32_t cparams, eec; - int eecp; - - cparams = EREAD4(sc, EHCI_HCCPARAMS); - for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; - eecp = EHCI_EECP_NEXT(eec)) { - eec = pci_read_config(self, eecp, 4); - if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) - continue; - pci_write_config(self, eecp + EHCI_LEGSUP_OS_SEM, 0, 1); - } -#endif -} - -static device_method_t ehci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ehci_pci_probe), - DEVMETHOD(device_attach, ehci_pci_attach), - DEVMETHOD(device_detach, ehci_pci_detach), - DEVMETHOD(device_suspend, ehci_pci_suspend), - DEVMETHOD(device_resume, ehci_pci_resume), - DEVMETHOD(device_shutdown, ehci_pci_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - {0, 0} -}; - -static driver_t ehci_driver = { - "ehci", - ehci_methods, - sizeof(ehci_softc_t), -}; - -static devclass_t ehci_devclass; - -DRIVER_MODULE(ehci, pci, ehci_driver, ehci_devclass, 0, 0); -DRIVER_MODULE(ehci, cardbus, ehci_driver, ehci_devclass, 0, 0); -MODULE_DEPEND(ehci, usb, 1, 1, 1); diff --git a/sys/dev/usb/ehcireg.h b/sys/dev/usb/ehcireg.h deleted file mode 100644 index 3c0f5e7..0000000 --- a/sys/dev/usb/ehcireg.h +++ /dev/null @@ -1,344 +0,0 @@ -/* $NetBSD: ehcireg.h,v 1.18 2004/10/22 10:38:17 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * 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) */ - -/* EHCI Extended Capabilities */ -#define EHCI_EC_LEGSUP 0x01 - -#define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff) -#define EHCI_EECP_ID(x) ((x) & 0xff) - -/* Legacy support extended capability */ -#define EHCI_LEGSUP_OS_SEM 0x03 /* OS owned semaphore */ -#define EHCI_LEGSUP_BIOS_SEM 0x02 /* BIOS owned semaphore */ -#define EHCI_LEGSUP_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_INDICATOR(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_USBMODE 0x68 /* RW USB Device mode register */ -#define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */ -#define EHCI_UM_CM_IDLE 0x0 /* Idle */ -#define EHCI_UM_CM_HOST 0x3 /* Host Controller */ -#define EHCI_UM_ES 0x00000004 /* R/WO Endian Select */ -#define EHCI_UM_ES_LE 0x0 /* Little-endian byte alignment */ -#define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */ -#define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */ - -#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) -#if defined(__FreeBSD__) -#define EHCI_PAGE_MASK(x) ((x) & 0xfff) -#endif - -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; - -typedef u_int32_t ehci_isoc_trans_t; -typedef u_int32_t ehci_isoc_bufr_ptr_t; - -/* Isochronous Transfer Descriptor */ -typedef struct { - ehci_link_t itd_next; - ehci_isoc_trans_t itd_ctl[8]; -#define EHCI_ITD_GET_STATUS(x) (((x) >> 28) & 0xf) -#define EHCI_ITD_SET_STATUS(x) (((x) & 0xf) << 28) -#define EHCI_ITD_ACTIVE 0x80000000 -#define EHCI_ITD_BUF_ERR 0x40000000 -#define EHCI_ITD_BABBLE 0x20000000 -#define EHCI_ITD_ERROR 0x10000000 -#define EHCI_ITD_GET_LEN(x) (((x) >> 16) & 0xfff) -#define EHCI_ITD_SET_LEN(x) (((x) & 0xfff) << 16) -#define EHCI_ITD_IOC 0x8000 -#define EHCI_ITD_GET_IOC(x) (((x) >> 15) & 1) -#define EHCI_ITD_SET_IOC(x) (((x) << 15) & EHCI_ITD_IOC) -#define EHCI_ITD_GET_PG(x) (((x) >> 12) & 0xf) -#define EHCI_ITD_SET_PG(x) (((x) & 0xf) << 12) -#define EHCI_ITD_GET_OFFS(x) (((x) >> 0) & 0xfff) -#define EHCI_ITD_SET_OFFS(x) (((x) & 0xfff) << 0) - ehci_isoc_bufr_ptr_t itd_bufr[7]; -#define EHCI_ITD_GET_BPTR(x) ((x) & 0xfffff000) -#define EHCI_ITD_SET_BPTR(x) ((x) & 0xfffff000) -#define EHCI_ITD_GET_EP(x) (((x) >> 8) & 0xf) -#define EHCI_ITD_SET_EP(x) (((x) & 0xf) << 8) -#define EHCI_ITD_GET_DADDR(x) ((x) & 0x7f) -#define EHCI_ITD_SET_DADDR(x) ((x) & 0x7f) -#define EHCI_ITD_GET_DIR(x) (((x) >> 11) & 1) -#define EHCI_ITD_SET_DIR(x) (((x) & 1) << 11) -#define EHCI_ITD_GET_MAXPKT(x) ((x) & 0x7ff) -#define EHCI_ITD_SET_MAXPKT(x) ((x) & 0x7ff) -#define EHCI_ITD_GET_MULTI(x) ((x) & 0x3) -#define EHCI_ITD_SET_MULTI(x) ((x) & 0x3) -} 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_SET_STATUS(x) ((x) << 0) -#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_SET_TOGGLE(x) ((x) << 31) -#define EHCI_QTD_TOGGLE_MASK 0x80000000 - ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS]; - ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS]; -} ehci_qtd_t; -#define EHCI_QTD_ALIGN 32 - -#define EHCI_QTD_STATUS_BITS \ - "\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR\3MISSED\2SPLIT\1PING" - -/* 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_QH_MPLMASK 0x07ff0000 -#define EHCI_QH_GET_CTL(x) (((x) >> 27) & 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 fdd19ba..0000000 --- a/sys/dev/usb/ehcivar.h +++ /dev/null @@ -1,278 +0,0 @@ -/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * 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_qh *prev; - struct ehci_soft_qtd *sqtd; - struct ehci_soft_qtd *inactivesqtd; - ehci_physaddr_t physaddr; - int islot; /* Interrupt list slot. */ -} 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) - -typedef struct ehci_soft_itd { - ehci_itd_t itd; - union { - struct { - /* soft_itds links in a periodic frame*/ - struct ehci_soft_itd *next; - struct ehci_soft_itd *prev; - } frame_list; - /* circular list of free itds */ - LIST_ENTRY(ehci_soft_itd) free_list; - } u; - struct ehci_soft_itd *xfer_next; /* Next soft_itd in xfer */ - ehci_physaddr_t physaddr; - usb_dma_t dma; - int offs; - int slot; - struct timeval t; /* store free time */ -} ehci_soft_itd_t; -#define EHCI_ITD_SIZE ((sizeof(struct ehci_soft_itd) + EHCI_QH_ALIGN - 1) / EHCI_ITD_ALIGN * EHCI_ITD_ALIGN) -#define EHCI_ITD_CHUNK (EHCI_PAGE_SIZE / EHCI_ITD_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; - ehci_soft_itd_t *itdstart; - ehci_soft_itd_t *itdend; - u_int isoc_len; - u_int32_t ehci_xfer_flags; -#ifdef DIAGNOSTIC - int isdone; -#endif -}; -#define EHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ -#define EHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ - -#define EXFER(xfer) ((struct ehci_xfer *)(xfer)) - -/* - * Information about an entry in the interrupt list. - */ -struct ehci_soft_islot { - ehci_soft_qh_t *sqh; /* Queue Head. */ -}; - -#define EHCI_FRAMELIST_MAXCOUNT 1024 -#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 ... 128) */ -#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1) -#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1)) -#define EHCI_IQHIDX(lev, pos) \ - ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1) -#define EHCI_ILEV_IVAL(lev) (1 << (lev)) - -#define EHCI_HASH_SIZE 128 -#define EHCI_COMPANION_MAX 8 - -#define EHCI_FREE_LIST_INTERVAL 100 - -#define EHCI_SCFLG_DONEINIT 0x0001 /* ehci_init() has been called. */ -#define EHCI_SCFLG_LOSTINTRBUG 0x0002 /* workaround for VIA / ATI chipsets */ -#define EHCI_SCFLG_SETMODE 0x0004 /* set bridge mode again after init (Marvell) */ -#define EHCI_SCFLG_FORCESPEED 0x0008 /* force speed (Marvell) */ -#define EHCI_SCFLG_NORESTERM 0x0010 /* don't terminate reset sequence (Marvell) */ -#define EHCI_SCFLG_BIGEDESC 0x0020 /* big-endian byte order descriptors */ -#define EHCI_SCFLG_BIGEMMIO 0x0040 /* big-endian byte order MMIO */ -#define EHCI_SCFLG_TT 0x0080 /* transaction translator present */ - -typedef struct ehci_softc { - struct usbd_bus sc_bus; /* base device */ - int sc_flags; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - void *ih; - - struct resource *io_res; - struct resource *irq_res; - u_int sc_offs; /* offset to operational regs */ - - char sc_vendor[32]; /* vendor string for root hub */ - int sc_id_vendor; /* vendor ID for root hub */ - - u_int32_t sc_cmd; /* shadow of cmd reg during suspend */ - - u_int sc_ncomp; - u_int sc_npcomp; - struct usbd_bus *sc_comps[EHCI_COMPANION_MAX]; - - usb_dma_t sc_fldma; - ehci_link_t *sc_flist; - u_int sc_flsize; - - struct ehci_soft_islot sc_islots[EHCI_INTRQHS]; - - /* jcmm - an array matching sc_flist, but with software pointers, - * not hardware address pointers - */ - struct ehci_soft_itd **sc_softitds; - - LIST_HEAD(, ehci_xfer) sc_intrhead; - - ehci_soft_qh_t *sc_freeqhs; - ehci_soft_qtd_t *sc_freeqtds; - LIST_HEAD(sc_freeitds, ehci_soft_itd) sc_freeitds; - - 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; -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - u_int32_t sc_eintrs; - ehci_soft_qh_t *sc_async_head; - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - struct lock sc_doorbell_lock; - - struct callout sc_tmo_intrlist; - - 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)) - -#ifdef USB_EHCI_BIG_ENDIAN_DESC -/* - * Handle byte order conversion between host and ``host controller''. - * Typically the latter is little-endian but some controllers require - * big-endian in which case we may need to manually swap. - */ -static __inline uint32_t -htohc32(const struct ehci_softc *sc, const uint32_t v) -{ - return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe32(v) : htole32(v); -} - -static __inline uint16_t -htohc16(const struct ehci_softc *sc, const uint16_t v) -{ - return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? htobe16(v) : htole16(v); -} - -static __inline uint32_t -hc32toh(const struct ehci_softc *sc, const uint32_t v) -{ - return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be32toh(v) : le32toh(v); -} - -static __inline uint16_t -hc16toh(const struct ehci_softc *sc, const uint16_t v) -{ - return sc->sc_flags & EHCI_SCFLG_BIGEDESC ? be16toh(v) : le16toh(v); -} -#else -/* - * Normal little-endian only conversion routines. - */ -static __inline uint32_t -htohc32(const struct ehci_softc *sc, const uint32_t v) -{ - return htole32(v); -} - -static __inline uint16_t -htohc16(const struct ehci_softc *sc, const uint16_t v) -{ - return htole16(v); -} - -static __inline uint32_t -hc32toh(const struct ehci_softc *sc, const uint32_t v) -{ - return le32toh(v); -} - -static __inline uint16_t -hc16toh(const struct ehci_softc *sc, const uint16_t v) -{ - return le16toh(v); -} -#endif - -usbd_status ehci_reset(ehci_softc_t *); -usbd_status ehci_init(ehci_softc_t *); -int ehci_intr(void *); -int ehci_detach(ehci_softc_t *, int); -void ehci_power(int state, void *priv); -void ehci_shutdown(void *v); - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -void ehci_dump_regs(ehci_softc_t *); -void ehci_dump_sqtds(ehci_softc_t *, ehci_soft_qtd_t *); -void ehci_dump_qtd(ehci_softc_t *, ehci_qtd_t *); -void ehci_dump_sqtd(ehci_softc_t *, ehci_soft_qtd_t *); -void ehci_dump_sqh(ehci_softc_t *, ehci_soft_qh_t *); -void ehci_dump_itd(ehci_softc_t *, struct ehci_soft_itd *); -void ehci_dump_sitd(ehci_softc_t *, struct ehci_soft_itd *); -void ehci_dump_exfer(struct ehci_xfer *); diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c deleted file mode 100644 index 70facb6..0000000 --- a/sys/dev/usb/hid.c +++ /dev/null @@ -1,469 +0,0 @@ -/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */ - - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -/*- - * Copyright (c) 1998 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/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/hid.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static void hid_clear_local(struct hid_item *); - -#define MAXUSAGE 100 -struct hid_data { - u_char *start; - u_char *end; - u_char *p; - struct hid_item cur; - int32_t usages[MAXUSAGE]; - int nu; - int minset; - int multi; - int multimax; - int kindset; -}; - -static void -hid_clear_local(struct hid_item *c) -{ - - c->usage = 0; - c->usage_minimum = 0; - c->usage_maximum = 0; - c->designator_index = 0; - c->designator_minimum = 0; - c->designator_maximum = 0; - c->string_index = 0; - c->string_minimum = 0; - c->string_maximum = 0; - c->set_delimiter = 0; -} - -struct hid_data * -hid_start_parse(void *d, int len, int kindset) -{ - struct hid_data *s; - - s = malloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO); - s->start = s->p = d; - s->end = (char *)d + len; - s->kindset = kindset; - return (s); -} - -void -hid_end_parse(struct hid_data *s) -{ - - while (s->cur.next != NULL) { - struct hid_item *hi = s->cur.next->next; - free(s->cur.next, M_TEMP); - s->cur.next = hi; - } - free(s, M_TEMP); -} - -int -hid_get_item(struct hid_data *s, struct hid_item *h) -{ - struct hid_item *c = &s->cur; - unsigned int bTag, bType, bSize; - u_int32_t oldpos; - u_char *data; - int32_t dval; - u_char *p; - struct hid_item *hi; - int i; - - top: - 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 = 0; - return (1); - } else { - c->loc.count = s->multimax; - s->multimax = 0; - s->nu = 0; - hid_clear_local(c); - } - } - for (;;) { - p = s->p; - if (p >= s->end) - return (0); - - bSize = *p++; - if (bSize == 0xfe) { - /* long item */ - bSize = *p++; - bSize |= *p++ << 8; - bTag = *p++; - data = p; - p += bSize; - bType = 0xff; /* XXX what should it be */ - } else { - /* short item */ - bTag = bSize >> 4; - bType = (bSize >> 2) & 3; - bSize &= 3; - if (bSize == 3) bSize = 4; - data = p; - p += bSize; - } - s->p = p; - switch(bSize) { - case 0: - dval = 0; - break; - case 1: - dval = (int8_t)*data++; - break; - case 2: - dval = *data++; - dval |= *data++ << 8; - dval = (int16_t)dval; - break; - case 4: - dval = *data++; - dval |= *data++ << 8; - dval |= *data++ << 16; - dval |= *data++ << 24; - break; - default: - printf("BAD LENGTH %d\n", bSize); - continue; - } - - switch (bType) { - case 0: /* Main */ - switch (bTag) { - case 8: /* Input */ - if (!(s->kindset & (1 << hid_input))) { - if (s->nu > 0) - s->nu--; - continue; - } - c->kind = hid_input; - c->flags = dval; - ret: - if (c->flags & HIO_VARIABLE) { - s->multimax = c->loc.count; - s->multi = 0; - c->loc.count = 1; - if (s->minset) { - for (i = c->usage_minimum; - i <= c->usage_maximum; - i++) { - s->usages[s->nu] = i; - if (s->nu < MAXUSAGE-1) - s->nu++; - } - s->minset = 0; - } - goto top; - } else { - *h = *c; - h->next = 0; - c->loc.pos += - c->loc.size * c->loc.count; - hid_clear_local(c); - s->minset = 0; - return (1); - } - case 9: /* Output */ - if (!(s->kindset & (1 << hid_output))) { - if (s->nu > 0) - s->nu--; - continue; - } - c->kind = hid_output; - c->flags = dval; - goto ret; - case 10: /* Collection */ - c->kind = hid_collection; - c->collection = dval; - c->collevel++; - *h = *c; - hid_clear_local(c); - s->nu = 0; - return (1); - case 11: /* Feature */ - if (!(s->kindset & (1 << hid_feature))) { - if (s->nu > 0) - s->nu--; - 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: - printf("Main bTag=%d\n", bTag); - break; - } - break; - case 1: /* Global */ - switch (bTag) { - case 0: - c->_usage_page = dval << 16; - break; - case 1: - c->logical_minimum = dval; - break; - case 2: - c->logical_maximum = dval; - break; - case 3: - c->physical_minimum = dval; - break; - case 4: - c->physical_maximum = dval; - break; - case 5: - c->unit_exponent = dval; - break; - case 6: - c->unit = dval; - break; - case 7: - c->loc.size = dval; - break; - case 8: - c->report_ID = dval; - break; - case 9: - c->loc.count = dval; - break; - case 10: /* Push */ - hi = malloc(sizeof *hi, M_TEMP, M_WAITOK); - *hi = s->cur; - c->next = hi; - break; - case 11: /* Pop */ - hi = c->next; - oldpos = c->loc.pos; - s->cur = *hi; - c->loc.pos = oldpos; - free(hi, M_TEMP); - break; - default: - printf("Global bTag=%d\n", bTag); - break; - } - break; - case 2: /* Local */ - switch (bTag) { - case 0: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage = dval; - if (s->nu < MAXUSAGE) - s->usages[s->nu++] = dval; - /* else XXX */ - break; - case 1: - s->minset = 1; - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_minimum = dval; - break; - case 2: - if (bSize == 1) - dval = c->_usage_page | (dval&0xff); - else if (bSize == 2) - dval = c->_usage_page | (dval&0xffff); - c->usage_maximum = dval; - break; - case 3: - c->designator_index = dval; - break; - case 4: - c->designator_minimum = dval; - break; - case 5: - c->designator_maximum = dval; - break; - case 7: - c->string_index = dval; - break; - case 8: - c->string_minimum = dval; - break; - case 9: - c->string_maximum = dval; - break; - case 10: - c->set_delimiter = dval; - break; - default: - printf("Local bTag=%d\n", bTag); - break; - } - break; - default: - printf("default bType=%d\n", bType); - break; - } - } -} - -int -hid_report_size(void *buf, int len, enum hid_kind k, u_int8_t *idp) -{ - struct hid_data *d; - struct hid_item h; - int hi, lo, size, id; - - id = 0; - hi = lo = -1; - for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); ) - if (h.kind == k) { - if (h.report_ID != 0 && !id) - id = h.report_ID; - if (h.report_ID == id) { - if (lo < 0) - lo = h.loc.pos; - hi = h.loc.pos + h.loc.size * h.loc.count; - } - } - hid_end_parse(d); - size = hi - lo; - 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, enum hid_kind k, - struct hid_location *loc, u_int32_t *flags) -{ - struct hid_data *d; - struct hid_item h; - - 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) - *flags = h.flags; - hid_end_parse(d); - return (1); - } - } - hid_end_parse(d); - loc->size = 0; - return (0); -} - -u_long -hid_get_data(u_char *buf, struct hid_location *loc) -{ - u_int hpos = loc->pos; - u_int hsize = loc->size; - u_int32_t data; - int i, s; - - DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize)); - - if (hsize == 0) - return (0); - - data = 0; - s = hpos / 8; - for (i = hpos; i < hpos+hsize; i += 8) - data |= buf[i / 8] << ((i / 8 - s) * 8); - data >>= hpos % 8; - data &= (1 << hsize) - 1; - hsize = 32 - hsize; - /* Sign extend */ - data = ((int32_t)data << hsize) >> hsize; - DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n", - loc->pos, loc->size, (long)data)); - return (data); -} - -int -hid_is_collection(void *desc, int size, u_int32_t usage) -{ - struct hid_data *hd; - struct hid_item hi; - int err; - - hd = hid_start_parse(desc, size, hid_input); - if (hd == NULL) - return (0); - - err = hid_get_item(hd, &hi) && - hi.kind == hid_collection && - hi.usage == usage; - hid_end_parse(hd); - return (err); -} diff --git a/sys/dev/usb/hid.h b/sys/dev/usb/hid.h deleted file mode 100644 index a4ab7d2..0000000 --- a/sys/dev/usb/hid.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $NetBSD: hid.h,v 1.6 2000/06/01 14:28:57 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -enum hid_kind { - hid_input, hid_output, hid_feature, hid_collection, hid_endcollection -}; - -struct hid_location { - u_int32_t size; - u_int32_t count; - u_int32_t pos; -}; - -struct hid_item { - /* Global */ - int32_t _usage_page; - int32_t logical_minimum; - int32_t logical_maximum; - int32_t physical_minimum; - int32_t physical_maximum; - int32_t unit_exponent; - int32_t unit; - int32_t report_ID; - /* Local */ - int32_t usage; - int32_t usage_minimum; - int32_t usage_maximum; - int32_t designator_index; - int32_t designator_minimum; - int32_t designator_maximum; - int32_t string_index; - int32_t string_minimum; - int32_t string_maximum; - int32_t set_delimiter; - /* Misc */ - int32_t collection; - int collevel; - enum hid_kind kind; - u_int32_t flags; - /* Location */ - struct hid_location loc; - /* */ - struct hid_item *next; -}; - -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, - 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_int32_t usage); diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c deleted file mode 100644 index 1c6d8a3..0000000 --- a/sys/dev/usb/if_aue.c +++ /dev/null @@ -1,1498 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. - * - * Copyright (c) 2006 - * Alfred Perlstein <alfred@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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver. - * Datasheet is available from http://www.admtek.com.tw. - * - * Written by Bill Paul <wpaul@ee.columbia.edu> - * Electrical Engineering Department - * Columbia University, New York City - * - * SMP locking by Alfred Perlstein <alfred@freebsd.org>. - * RED Inc. - */ - -/* - * The Pegasus chip uses four USB "endpoints" to provide 10/100 ethernet - * support: the control endpoint for reading/writing registers, burst - * read endpoint for packet reception, burst write for packet transmission - * and one for "interrupts." The chip uses the same RX filter scheme - * as the other ADMtek ethernet parts: one perfect filter entry for the - * the station address and a 64-bit multicast hash table. The chip supports - * both MII and HomePNA attachments. - * - * Since the maximum data transfer speed of USB is supposed to be 12Mbps, - * you're never really going to get 100Mbps speeds from this device. I - * think the idea is to allow the device to connect to 10 or 100Mbps - * networks, not necessarily to provide 100Mbps performance. Also, since - * the controller uses an external PHY chip, it's possible that board - * designers might simply choose a 10Mbps PHY. - * - * Registers are accessed using usbd_do_request(). Packet transfers are - * done using usbd_transfer() and friends. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/kdb.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sx.h> -#include <sys/taskqueue.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <dev/usb/if_auereg.h> - -MODULE_DEPEND(aue, usb, 1, 1, 1); -MODULE_DEPEND(aue, ether, 1, 1, 1); -MODULE_DEPEND(aue, miibus, 1, 1, 1); - -/* "device miibus" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -/* - * Various supported device vendors/products. - */ -struct aue_type { - struct usb_devno aue_dev; - u_int16_t aue_flags; -#define LSYS 0x0001 /* use Linksys reset */ -#define PNA 0x0002 /* has Home PNA */ -#define PII 0x0004 /* Pegasus II chip */ -}; - -static const struct aue_type aue_devs[] = { - {{ USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460B}, PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX1}, PNA|PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX2}, PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UFE1000}, LSYS }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX4}, PNA }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX5}, PNA }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX6}, PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX7}, PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX8}, PII }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX9}, PNA }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX10}, 0 }, - {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_DSB650TX_PNA}, 0 }, - {{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_USB320_EC}, 0 }, - {{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SS1001}, PII }, - {{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUS}, PNA }, - {{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII}, PII }, - {{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_2}, PII }, - {{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_3}, PII }, - {{ USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_4}, PII }, - {{ USB_VENDOR_AEI, USB_PRODUCT_AEI_FASTETHERNET}, PII }, - {{ USB_VENDOR_ALLIEDTELESYN, USB_PRODUCT_ALLIEDTELESYN_ATUSB100}, PII }, - {{ USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC110T}, PII }, - {{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2LAN}, PII }, - {{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB100}, 0 }, - {{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBLP100}, PNA }, - {{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBEL100}, 0 }, - {{ USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBE100}, PII }, - {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TX}, 0 }, - {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXS},PII }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX4}, LSYS|PII }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX1}, LSYS }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX}, LSYS }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX_PNA}, PNA }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX3}, LSYS|PII }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX2}, LSYS|PII }, - {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650}, LSYS }, - {{ USB_VENDOR_ELCON, USB_PRODUCT_ELCON_PLAN}, PNA|PII }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSB20}, PII }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX0}, 0 }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX1}, LSYS }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX2}, 0 }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX3}, LSYS }, - {{ USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBLTX}, PII }, - {{ USB_VENDOR_ELSA, USB_PRODUCT_ELSA_USB2ETHERNET}, 0 }, - {{ USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNBR402W}, 0 }, - {{ USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_UF100}, PII }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_HN210E}, PII }, - {{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTX}, 0 }, - {{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTXS}, PII }, - {{ USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_KNU101TX}, 0 }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX1}, LSYS|PII }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T}, LSYS }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100TX}, LSYS }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100H1}, LSYS|PNA }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TA}, LSYS }, - {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX2}, LSYS|PII }, - {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX1}, 0 }, - {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX5}, 0 }, - {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUA2TX5}, PII }, - {{ USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN110}, PII }, - {{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA101}, PII }, - {{ USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM}, PII }, - {{ USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_USBTOETHER}, PII }, - {{ USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTNIC},PII }, - {{ USB_VENDOR_SMC, USB_PRODUCT_SMC_2202USB}, 0 }, - {{ USB_VENDOR_SMC, USB_PRODUCT_SMC_2206USB}, PII }, - {{ USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB100}, 0 }, - {{ USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB110}, PII }, -}; -#define aue_lookup(v, p) ((const struct aue_type *)usb_lookup(aue_devs, v, p)) - -static device_probe_t aue_match; -static device_attach_t aue_attach; -static device_detach_t aue_detach; -static device_shutdown_t aue_shutdown; -static miibus_readreg_t aue_miibus_readreg; -static miibus_writereg_t aue_miibus_writereg; -static miibus_statchg_t aue_miibus_statchg; - -static void aue_reset_pegasus_II(struct aue_softc *sc); -static int aue_encap(struct aue_softc *, struct mbuf *, int); -#ifdef AUE_INTR_PIPE -static void aue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -#endif -static void aue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void aue_rxeof_thread(struct aue_softc *sc); -static void aue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void aue_txeof_thread(struct aue_softc *); -static void aue_task_sched(struct aue_softc *, int); -static void aue_task(void *xsc, int pending); -static void aue_tick(void *); -static void aue_rxstart(struct ifnet *); -static void aue_rxstart_thread(struct aue_softc *); -static void aue_start(struct ifnet *); -static void aue_start_thread(struct aue_softc *); -static int aue_ioctl(struct ifnet *, u_long, caddr_t); -static void aue_init(void *); -static void aue_init_body(struct aue_softc *); -static void aue_stop(struct aue_softc *); -static void aue_watchdog(struct aue_softc *); -static int aue_ifmedia_upd(struct ifnet *); -static void aue_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static void aue_eeprom_getword(struct aue_softc *, int, u_int16_t *); -static void aue_read_eeprom(struct aue_softc *, caddr_t, int, int, int); - -static void aue_setmulti(struct aue_softc *); -static void aue_reset(struct aue_softc *); - -static int aue_csr_read_1(struct aue_softc *, int); -static int aue_csr_write_1(struct aue_softc *, int, int); -static int aue_csr_read_2(struct aue_softc *, int); -static int aue_csr_write_2(struct aue_softc *, int, int); - -static device_method_t aue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, aue_match), - DEVMETHOD(device_attach, aue_attach), - DEVMETHOD(device_detach, aue_detach), - DEVMETHOD(device_shutdown, aue_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, aue_miibus_readreg), - DEVMETHOD(miibus_writereg, aue_miibus_writereg), - DEVMETHOD(miibus_statchg, aue_miibus_statchg), - - { 0, 0 } -}; - -static driver_t aue_driver = { - "aue", - aue_methods, - sizeof(struct aue_softc) -}; - -static devclass_t aue_devclass; - -DRIVER_MODULE(aue, uhub, aue_driver, aue_devclass, usbd_driver_load, 0); -DRIVER_MODULE(miibus, aue, miibus_driver, miibus_devclass, 0, 0); - -#define AUE_SETBIT(sc, reg, x) \ - aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x)) - -#define AUE_CLRBIT(sc, reg, x) \ - aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x)) - -static int -aue_csr_read_1(struct aue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int8_t val = 0; - - AUE_SXASSERTLOCKED(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AUE_UR_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - if (err) { - return (0); - } - - return (val); -} - -static int -aue_csr_read_2(struct aue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int16_t val = 0; - - AUE_SXASSERTLOCKED(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AUE_UR_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - if (err) { - return (0); - } - - return (val); -} - -static int -aue_csr_write_1(struct aue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - AUE_SXASSERTLOCKED(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = AUE_UR_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - if (err) { - return (-1); - } - - return (0); -} - -static int -aue_csr_write_2(struct aue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - AUE_SXASSERTLOCKED(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = AUE_UR_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->aue_udev, &req, &val); - - if (err) { - return (-1); - } - - return (0); -} - -/* - * Read a word of data stored in the EEPROM at address 'addr.' - */ -static void -aue_eeprom_getword(struct aue_softc *sc, int addr, u_int16_t *dest) -{ - int i; - u_int16_t word = 0; - - aue_csr_write_1(sc, AUE_EE_REG, addr); - aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) { - printf("aue%d: EEPROM read timed out\n", - sc->aue_unit); - } - - word = aue_csr_read_2(sc, AUE_EE_DATA); - *dest = word; - - return; -} - -/* - * Read a sequence of words from the EEPROM. - */ -static void -aue_read_eeprom(struct aue_softc *sc, caddr_t dest, int off, int cnt, int swap) -{ - int i; - u_int16_t word = 0, *ptr; - - for (i = 0; i < cnt; i++) { - aue_eeprom_getword(sc, off + i, &word); - ptr = (u_int16_t *)(dest + (i * 2)); - if (swap) - *ptr = ntohs(word); - else - *ptr = word; - } - - return; -} - -static int -aue_miibus_readreg(device_t dev, int phy, int reg) -{ - struct aue_softc *sc = device_get_softc(dev); - int i; - u_int16_t val = 0; - - /* - * The Am79C901 HomePNA PHY actually contains - * two transceivers: a 1Mbps HomePNA PHY and a - * 10Mbps full/half duplex ethernet PHY with - * NWAY autoneg. However in the ADMtek adapter, - * only the 1Mbps PHY is actually connected to - * anything, so we ignore the 10Mbps one. It - * happens to be configured for MII address 3, - * so we filter that out. - */ - if (sc->aue_vendor == USB_VENDOR_ADMTEK && - sc->aue_product == USB_PRODUCT_ADMTEK_PEGASUS) { - if (phy == 3) - return (0); -#ifdef notdef - if (phy != 1) - return (0); -#endif - } - - aue_csr_write_1(sc, AUE_PHY_ADDR, phy); - aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) { - printf("aue%d: MII read timed out\n", sc->aue_unit); - } - - val = aue_csr_read_2(sc, AUE_PHY_DATA); - - return (val); -} - -static int -aue_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct aue_softc *sc = device_get_softc(dev); - int i; - - if (phy == 3) - return (0); - - aue_csr_write_2(sc, AUE_PHY_DATA, data); - aue_csr_write_1(sc, AUE_PHY_ADDR, phy); - aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) - break; - } - - if (i == AUE_TIMEOUT) { - printf("aue%d: MII read timed out\n", - sc->aue_unit); - } - - return(0); -} - -static void -aue_miibus_statchg(device_t dev) -{ - struct aue_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); - - AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); - } else { - AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); - } - - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); - else - AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); - - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); - - /* - * Set the LED modes on the LinkSys adapter. - * This turns on the 'dual link LED' bin in the auxmode - * register of the Broadcom PHY. - */ - if (sc->aue_flags & LSYS) { - u_int16_t auxmode; - auxmode = aue_miibus_readreg(dev, 0, 0x1b); - aue_miibus_writereg(dev, 0, 0x1b, auxmode | 0x04); - } - - return; -} - -#define AUE_BITS 6 - -static void -aue_setmulti(struct aue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - u_int32_t h = 0, i; - u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - AUE_SXASSERTLOCKED(sc); - ifp = sc->aue_ifp; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); - return; - } - - AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); - - /* now program new ones */ - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_le(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1); - hashtbl[(h >> 3)] |= 1 << (h & 0x7); - } - IF_ADDR_UNLOCK(ifp); - - /* write the hashtable */ - for (i = 0; i < 8; i++) - aue_csr_write_1(sc, AUE_MAR0 + i, hashtbl[i]); - - return; -} - -static void -aue_reset_pegasus_II(struct aue_softc *sc) -{ - /* Magic constants taken from Linux driver. */ - aue_csr_write_1(sc, AUE_REG_1D, 0); - aue_csr_write_1(sc, AUE_REG_7B, 2); -#if 0 - if ((sc->aue_flags & HAS_HOME_PNA) && mii_mode) - aue_csr_write_1(sc, AUE_REG_81, 6); - else -#endif - aue_csr_write_1(sc, AUE_REG_81, 2); -} - -static void -aue_reset(struct aue_softc *sc) -{ - int i; - - AUE_SXASSERTLOCKED(sc); - AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC); - - for (i = 0; i < AUE_TIMEOUT; i++) { - if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC)) - break; - } - - if (i == AUE_TIMEOUT) - printf("aue%d: reset failed\n", sc->aue_unit); - - /* - * The PHY(s) attached to the Pegasus chip may be held - * in reset until we flip on the GPIO outputs. Make sure - * to set the GPIO pins high so that the PHY(s) will - * be enabled. - * - * Note: We force all of the GPIO pins low first, *then* - * enable the ones we want. - */ - aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0); - aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_OUT0|AUE_GPIO_SEL0|AUE_GPIO_SEL1); - - if (sc->aue_flags & LSYS) { - /* Grrr. LinkSys has to be different from everyone else. */ - aue_csr_write_1(sc, AUE_GPIO0, - AUE_GPIO_SEL0 | AUE_GPIO_SEL1); - aue_csr_write_1(sc, AUE_GPIO0, - AUE_GPIO_SEL0 | AUE_GPIO_SEL1 | AUE_GPIO_OUT0); - } - - if (sc->aue_flags & PII) - aue_reset_pegasus_II(sc); - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(10000); - - return; -} - -/* - * Probe for a Pegasus chip. - */ -static int -aue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - /* - * Belkin USB Bluetooth dongles of the F8T012xx1 model series conflict - * with older Belkin USB2LAN adapters. Skip if_aue if we detect one of - * the devices that look like Bluetooth adapters. - */ - if (uaa->vendor == USB_VENDOR_BELKIN && - uaa->product == USB_PRODUCT_BELKIN_F8T012 && uaa->release == 0x0413) - return (UMATCH_NONE); - - return (aue_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -aue_attach(device_t self) -{ - struct aue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usbd_interface_handle iface; - usbd_status err; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->aue_dev = self; - sc->aue_udev = uaa->device; - sc->aue_unit = device_get_unit(self); - - if (usbd_set_config_no(sc->aue_udev, AUE_CONFIG_NO, 0)) { - device_printf(self, "getting interface handle failed\n"); - return ENXIO; - } - - err = usbd_device2interface_handle(uaa->device, AUE_IFACE_IDX, &iface); - if (err) { - device_printf(self, "getting interface handle failed\n"); - return ENXIO; - } - - sc->aue_iface = iface; - sc->aue_flags = aue_lookup(uaa->vendor, uaa->product)->aue_flags; - - sc->aue_product = uaa->product; - sc->aue_vendor = uaa->vendor; - - id = usbd_get_interface_descriptor(sc->aue_iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->aue_ed[AUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->aue_ed[AUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->aue_ed[AUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - mtx_init(&sc->aue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - sx_init(&sc->aue_sx, device_get_nameunit(self)); - TASK_INIT(&sc->aue_task, 0, aue_task, sc); - usb_ether_task_init(self, 0, &sc->aue_taskqueue); - AUE_SXLOCK(sc); - - /* Reset the adapter. */ - aue_reset(sc); - - /* - * Get station address from the EEPROM. - */ - aue_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 0); - - ifp = sc->aue_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(self, "can not if_alloc()\n"); - AUE_SXUNLOCK(sc); - mtx_destroy(&sc->aue_mtx); - sx_destroy(&sc->aue_sx); - usb_ether_task_destroy(&sc->aue_taskqueue); - return ENXIO; - } - ifp->if_softc = sc; - if_initname(ifp, "aue", sc->aue_unit); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = aue_ioctl; - ifp->if_start = aue_start; - ifp->if_init = aue_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - /* - * Do MII setup. - * NOTE: Doing this causes child devices to be attached to us, - * which we would normally disconnect at in the detach routine - * using device_delete_child(). However the USB code is set up - * such that when this driver is removed, all children devices - * are removed as well. In effect, the USB code ends up detaching - * all of our children for us, so we don't have to do is ourselves - * in aue_detach(). It's important to point this out since if - * we *do* try to detach the child devices ourselves, we will - * end up getting the children deleted twice, which will crash - * the system. - */ - if (mii_phy_probe(self, &sc->aue_miibus, - aue_ifmedia_upd, aue_ifmedia_sts)) { - device_printf(self, "MII without any PHY!\n"); - if_free(ifp); - AUE_SXUNLOCK(sc); - mtx_destroy(&sc->aue_mtx); - sx_destroy(&sc->aue_sx); - usb_ether_task_destroy(&sc->aue_taskqueue); - return ENXIO; - } - - sc->aue_qdat.ifp = ifp; - sc->aue_qdat.if_rxstart = aue_rxstart; - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, eaddr); - usb_register_netisr(); - sc->aue_dying = 0; - sc->aue_link = 1; - - AUE_SXUNLOCK(sc); - return 0; -} - -static int -aue_detach(device_t dev) -{ - struct aue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - AUE_SXLOCK(sc); - ifp = sc->aue_ifp; - ether_ifdetach(ifp); - sc->aue_dying = 1; - AUE_SXUNLOCK(sc); - callout_drain(&sc->aue_tick_callout); - usb_ether_task_drain(&sc->aue_taskqueue, &sc->aue_task); - usb_ether_task_destroy(&sc->aue_taskqueue); - if_free(ifp); - - if (sc->aue_ep[AUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (sc->aue_ep[AUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_RX]); -#ifdef AUE_INTR_PIPE - if (sc->aue_ep[AUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]); -#endif - - mtx_destroy(&sc->aue_mtx); - sx_destroy(&sc->aue_sx); - - return (0); -} - -static void -aue_rxstart(struct ifnet *ifp) -{ - struct aue_softc *sc = ifp->if_softc; - aue_task_sched(sc, AUE_TASK_RXSTART); -} - -static void -aue_rxstart_thread(struct aue_softc *sc) -{ - struct ue_chain *c; - struct ifnet *ifp; - - ifp = sc->aue_ifp; - - sc = ifp->if_softc; - AUE_SXASSERTLOCKED(sc); - c = &sc->aue_cdata.ue_rx_chain[sc->aue_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - device_printf(sc->aue_dev, "no memory for rx list -- packet " - "dropped!\n"); - ifp->if_ierrors++; - AUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(c->ue_xfer); - - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -aue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - c->ue_status = status; - aue_task_sched(c->ue_sc, AUE_TASK_RXEOF); -} - -static void -aue_rxeof_thread(struct aue_softc *sc) -{ - struct ue_chain *c = &(sc->aue_cdata.ue_rx_chain[0]); - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - struct aue_rxpkt r; - usbd_status status = c->ue_status; - - - AUE_SXASSERTLOCKED(sc); - ifp = sc->aue_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - return; - } - if (usbd_ratecheck(&sc->aue_rx_notice)) - device_printf(sc->aue_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, &total_len, NULL); - - if (total_len <= 4 + ETHER_CRC_LEN) { - ifp->if_ierrors++; - goto done; - } - - m = c->ue_mbuf; - bcopy(mtod(m, char *) + total_len - 4, (char *)&r, sizeof(r)); - - /* Turn off all the non-error bits in the rx status word. */ - r.aue_rxstat &= AUE_RXSTAT_MASK; - - if (r.aue_rxstat) { - ifp->if_ierrors++; - goto done; - } - - /* No errors; receive the packet. */ - total_len -= (4 + ETHER_CRC_LEN); - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = (void *)&sc->aue_qdat; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - return; -done: - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(c->ue_xfer); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -aue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - c->ue_status = status; - aue_task_sched(c->ue_sc, AUE_TASK_TXEOF); -} - -static void -aue_txeof_thread(struct aue_softc *sc) -{ - struct ue_chain *c = &(sc->aue_cdata.ue_tx_chain[0]); - struct ifnet *ifp; - usbd_status err, status; - - AUE_SXASSERTLOCKED(sc); - status = c->ue_status; - ifp = sc->aue_ifp; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - return; - } - device_printf(sc->aue_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_TX]); - return; - } - - sc->aue_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); - - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - return; -} - -static void -aue_tick(void *xsc) -{ - struct aue_softc *sc = xsc; - - aue_task_sched(sc, AUE_TASK_TICK); -} - -static void -aue_tick_thread(struct aue_softc *sc) -{ - struct ifnet *ifp; - struct mii_data *mii; - - AUE_SXASSERTLOCKED(sc); - ifp = sc->aue_ifp; - /* - * If a timer is set (non-zero) then decrement it - * and if it hits zero, then call the watchdog routine. - */ - if (sc->aue_timer != 0 && --sc->aue_timer == 0) { - aue_watchdog(sc); - } - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - return; - } - - mii = GET_MII(sc); - if (mii == NULL) { - goto resched; - } - - mii_tick(mii); - if (!sc->aue_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->aue_link++; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - aue_start_thread(sc); - } -resched: - (void) callout_reset(&sc->aue_tick_callout, hz, aue_tick, sc); - return; -} - -static int -aue_encap(struct aue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct ue_chain *c; - usbd_status err; - - AUE_SXASSERTLOCKED(sc); - - c = &sc->aue_cdata.ue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2); - c->ue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - - /* - * The ADMtek documentation says that the packet length is - * supposed to be specified in the first two bytes of the - * transfer, however it actually seems to ignore this info - * and base the frame size on the bulk transfer length. - */ - c->ue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->ue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - usbd_setup_xfer(c->ue_xfer, sc->aue_ep[AUE_ENDPT_TX], - c, c->ue_buf, total_len, USBD_FORCE_SHORT_XFER, - 10000, aue_txeof); - - /* Transmit */ - err = usbd_transfer(c->ue_xfer); - if (err != USBD_IN_PROGRESS) { - aue_stop(sc); - return (EIO); - } - - sc->aue_cdata.ue_tx_cnt++; - - return (0); -} - - -static void -aue_start(struct ifnet *ifp) -{ - struct aue_softc *sc = ifp->if_softc; - aue_task_sched(sc, AUE_TASK_START); -} - -static void -aue_start_thread(struct aue_softc *sc) -{ - struct ifnet *ifp = sc->aue_ifp; - struct mbuf *m_head = NULL; - - AUE_SXASSERTLOCKED(sc); - - if (!sc->aue_link) { - return; - } - - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - return; - } - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - return; - } - - if (aue_encap(sc, m_head, 0)) { - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - sc->aue_timer = 5; - - return; -} - -static void -aue_init(void *xsc) -{ - struct aue_softc *sc = xsc; - - AUE_SXLOCK(sc); - aue_init_body(sc); - AUE_SXUNLOCK(sc); -} - -static void -aue_init_body(struct aue_softc *sc) -{ - struct ifnet *ifp = sc->aue_ifp; - struct mii_data *mii = GET_MII(sc); - struct ue_chain *c; - usbd_status err; - int i; - - AUE_SXASSERTLOCKED(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - return; - } - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - aue_reset(sc); - - /* Set MAC address */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - aue_csr_write_1(sc, AUE_PAR0 + i, IF_LLADDR(sc->aue_ifp)[i]); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - else - AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - - /* Init TX ring. */ - if (usb_ether_tx_list_init(sc, &sc->aue_cdata, - sc->aue_udev) == ENOBUFS) { - device_printf(sc->aue_dev, "tx list init failed\n"); - return; - } - - /* Init RX ring. */ - if (usb_ether_rx_list_init(sc, &sc->aue_cdata, - sc->aue_udev) == ENOBUFS) { - device_printf(sc->aue_dev, "rx list init failed\n"); - return; - } - - - /* Load the multicast filter. */ - aue_setmulti(sc); - - /* Enable RX and TX */ - aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); - AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); - - mii_mediachg(mii); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - device_printf(sc->aue_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - return; - } - err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - device_printf(sc->aue_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - return; - } - - - /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->aue_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->aue_ep[AUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, aue_rxeof); - usbd_transfer(c->ue_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - callout_init(&sc->aue_tick_callout, CALLOUT_MPSAFE); - (void) callout_reset(&sc->aue_tick_callout, hz, aue_tick, sc); - return; -} - -/* - * Set media options. - */ -static int -aue_ifmedia_upd(struct ifnet *ifp) -{ - struct aue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->aue_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - sc->aue_link = 1; - - return (0); -} - -/* - * Report current media status. - */ -static void -aue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct aue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - return; -} - -static int -aue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct aue_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - int error = 0; - - /* - * This prevents recursion in the interface while it's - * being torn down. - */ - if (sc->aue_dying) - return(0); - - AUE_GIANTLOCK(); - - switch(command) { - case SIOCSIFFLAGS: - AUE_SXLOCK(sc); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->aue_if_flags & IFF_PROMISC)) { - AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->aue_if_flags & IFF_PROMISC) { - AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - aue_init_body(sc); - } - sc->aue_dying = 0; - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - aue_stop(sc); - } - sc->aue_if_flags = ifp->if_flags; - AUE_SXUNLOCK(sc); - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - AUE_SXLOCK(sc); - aue_setmulti(sc); - AUE_SXUNLOCK(sc); - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - AUE_SXLOCK(sc); - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - AUE_SXUNLOCK(sc); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - AUE_GIANTUNLOCK(); - - return (error); -} - -static void -aue_watchdog(struct aue_softc *sc) -{ - struct ifnet *ifp = sc->aue_ifp; - struct ue_chain *c; - usbd_status stat; - - AUE_SXASSERTLOCKED(sc); - ifp->if_oerrors++; - device_printf(sc->aue_dev, "watchdog timeout\n"); - - c = &sc->aue_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - c->ue_status = stat; - aue_txeof_thread(sc); - - if (!IFQ_IS_EMPTY(&ifp->if_snd)) - aue_start_thread(sc); - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -aue_stop(struct aue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - AUE_SXASSERTLOCKED(sc); - ifp = sc->aue_ifp; - sc->aue_timer = 0; - - aue_csr_write_1(sc, AUE_CTL0, 0); - aue_csr_write_1(sc, AUE_CTL1, 0); - aue_reset(sc); - sc->aue_dying = 1; - - /* Stop transfers. */ - if (sc->aue_ep[AUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - device_printf(sc->aue_dev, - "abort rx pipe failed: %s\n", usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_RX]); - if (err) { - device_printf(sc->aue_dev, - "close rx pipe failed: %s\n", usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_RX] = NULL; - } - - if (sc->aue_ep[AUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - device_printf(sc->aue_dev, - "abort tx pipe failed: %s\n", usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_TX]); - if (err) { - device_printf(sc->aue_dev, - "close tx pipe failed: %s\n", usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_TX] = NULL; - } - -#ifdef AUE_INTR_PIPE - if (sc->aue_ep[AUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]); - if (err) { - device_printf(sc->aue_dev, - "abort intr pipe failed: %s\n", usbd_errstr(err)); - } - err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_INTR]); - if (err) { - device_printf(sc->aue_dev, - "close intr pipe failed: %s\n", usbd_errstr(err)); - } - sc->aue_ep[AUE_ENDPT_INTR] = NULL; - } -#endif - - /* Free RX resources. */ - usb_ether_rx_list_free(&sc->aue_cdata); - /* Free TX resources. */ - usb_ether_tx_list_free(&sc->aue_cdata); - -#ifdef AUE_INTR_PIPE - free(sc->aue_cdata.ue_ibuf, M_USBDEV); - sc->aue_cdata.ue_ibuf = NULL; -#endif - - sc->aue_link = 0; - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static int -aue_shutdown(device_t dev) -{ - struct aue_softc *sc; - - sc = device_get_softc(dev); - AUE_SXLOCK(sc); - sc->aue_dying++; - aue_reset(sc); - aue_stop(sc); - AUE_SXUNLOCK(sc); - - return (0); -} - -static void -aue_task_sched(struct aue_softc *sc, int task) -{ - - AUE_LOCK(sc); - sc->aue_deferedtasks |= task; - usb_ether_task_enqueue(&sc->aue_taskqueue, &sc->aue_task); - AUE_UNLOCK(sc); -} - -/* - * We defer all interrupt operations to this function. - * - * This allows us to do more complex operations, such as synchronous - * usb io that normally would not be allowed from interrupt context. - */ -static void -aue_task(void *arg, int pending) -{ - struct aue_softc *sc = arg; - int tasks; - - for ( ;; ) { - AUE_LOCK(sc); - tasks = sc->aue_deferedtasks; - sc->aue_deferedtasks = 0; - AUE_UNLOCK(sc); - - if (tasks == 0) - break; - - AUE_GIANTLOCK(); // XXX: usb not giant safe - AUE_SXLOCK(sc); - if (sc->aue_dying) { - AUE_SXUNLOCK(sc); - break; - } - if ((tasks & AUE_TASK_TICK) != 0) { - aue_tick_thread(sc); - } - if ((tasks & AUE_TASK_START) != 0) { - aue_start_thread(sc); - } - if ((tasks & AUE_TASK_RXSTART) != 0) { - aue_rxstart_thread(sc); - } - if ((tasks & AUE_TASK_RXEOF) != 0) { - aue_rxeof_thread(sc); - } - if ((tasks & AUE_TASK_TXEOF) != 0) { - aue_txeof_thread(sc); - } - AUE_SXUNLOCK(sc); - AUE_GIANTUNLOCK(); // XXX: usb not giant safe - } -} - diff --git a/sys/dev/usb/if_auereg.h b/sys/dev/usb/if_auereg.h deleted file mode 100644 index 18cc0f4..0000000 --- a/sys/dev/usb/if_auereg.h +++ /dev/null @@ -1,294 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999 - * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. - * - * Copyright (c) 2006 - * Alfred Perlstein <alfred@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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -/* - * Register definitions for ADMtek Pegasus AN986 USB to Ethernet - * chip. The Pegasus uses a total of four USB endpoints: the control - * endpoint (0), a bulk read endpoint for receiving packets (1), - * a bulk write endpoint for sending packets (2) and an interrupt - * endpoint for passing RX and TX status (3). Endpoint 0 is used - * to read and write the ethernet module's registers. All registers - * are 8 bits wide. - * - * Packet transfer is done in 64 byte chunks. The last chunk in a - * transfer is denoted by having a length less that 64 bytes. For - * the RX case, the data includes an optional RX status word. - */ - -#ifndef AUEREG_H -#define AUEREG_H - -#define AUE_UR_READREG 0xF0 -#define AUE_UR_WRITEREG 0xF1 - -#define AUE_CONFIG_NO 1 -#define AUE_IFACE_IDX 0 - -/* - * Note that while the ADMtek technically has four - * endpoints, the control endpoint (endpoint 0) is - * regarded as special by the USB code and drivers - * don't have direct access to it. (We access it - * using usbd_do_request() when reading/writing - * registers.) Consequently, our endpoint indexes - * don't match those in the ADMtek Pegasus manual: - * we consider the RX data endpoint to be index 0 - * and work up from there. - */ -#define AUE_ENDPT_RX 0x0 -#define AUE_ENDPT_TX 0x1 -#define AUE_ENDPT_INTR 0x2 -#define AUE_ENDPT_MAX 0x3 - -#define AUE_INTR_PKTLEN 0x8 - -#define AUE_CTL0 0x00 -#define AUE_CTL1 0x01 -#define AUE_CTL2 0x02 -#define AUE_MAR0 0x08 -#define AUE_MAR1 0x09 -#define AUE_MAR2 0x0A -#define AUE_MAR3 0x0B -#define AUE_MAR4 0x0C -#define AUE_MAR5 0x0D -#define AUE_MAR6 0x0E -#define AUE_MAR7 0x0F -#define AUE_MAR AUE_MAR0 -#define AUE_PAR0 0x10 -#define AUE_PAR1 0x11 -#define AUE_PAR2 0x12 -#define AUE_PAR3 0x13 -#define AUE_PAR4 0x14 -#define AUE_PAR5 0x15 -#define AUE_PAR AUE_PAR0 -#define AUE_PAUSE0 0x18 -#define AUE_PAUSE1 0x19 -#define AUE_PAUSE AUE_PAUSE0 -#define AUE_RX_FLOWCTL_CNT 0x1A -#define AUE_RX_FLOWCTL_FIFO 0x1B -#define AUE_REG_1D 0x1D -#define AUE_EE_REG 0x20 -#define AUE_EE_DATA0 0x21 -#define AUE_EE_DATA1 0x22 -#define AUE_EE_DATA AUE_EE_DATA0 -#define AUE_EE_CTL 0x23 -#define AUE_PHY_ADDR 0x25 -#define AUE_PHY_DATA0 0x26 -#define AUE_PHY_DATA1 0x27 -#define AUE_PHY_DATA AUE_PHY_DATA0 -#define AUE_PHY_CTL 0x28 -#define AUE_USB_STS 0x2A -#define AUE_TXSTAT0 0x2B -#define AUE_TXSTAT1 0x2C -#define AUE_TXSTAT AUE_TXSTAT0 -#define AUE_RXSTAT 0x2D -#define AUE_PKTLOST0 0x2E -#define AUE_PKTLOST1 0x2F -#define AUE_PKTLOST AUE_PKTLOST0 - -#define AUE_REG_7B 0x7B -#define AUE_GPIO0 0x7E -#define AUE_GPIO1 0x7F -#define AUE_REG_81 0x81 - -#define AUE_CTL0_INCLUDE_RXCRC 0x01 -#define AUE_CTL0_ALLMULTI 0x02 -#define AUE_CTL0_STOP_BACKOFF 0x04 -#define AUE_CTL0_RXSTAT_APPEND 0x08 -#define AUE_CTL0_WAKEON_ENB 0x10 -#define AUE_CTL0_RXPAUSE_ENB 0x20 -#define AUE_CTL0_RX_ENB 0x40 -#define AUE_CTL0_TX_ENB 0x80 - -#define AUE_CTL1_HOMELAN 0x04 -#define AUE_CTL1_RESETMAC 0x08 -#define AUE_CTL1_SPEEDSEL 0x10 /* 0 = 10mbps, 1 = 100mbps */ -#define AUE_CTL1_DUPLEX 0x20 /* 0 = half, 1 = full */ -#define AUE_CTL1_DELAYHOME 0x40 - -#define AUE_CTL2_EP3_CLR 0x01 /* reading EP3 clrs status regs */ -#define AUE_CTL2_RX_BADFRAMES 0x02 -#define AUE_CTL2_RX_PROMISC 0x04 -#define AUE_CTL2_LOOPBACK 0x08 -#define AUE_CTL2_EEPROMWR_ENB 0x10 -#define AUE_CTL2_EEPROM_LOAD 0x20 - -#define AUE_EECTL_WRITE 0x01 -#define AUE_EECTL_READ 0x02 -#define AUE_EECTL_DONE 0x04 - -#define AUE_PHYCTL_PHYREG 0x1F -#define AUE_PHYCTL_WRITE 0x20 -#define AUE_PHYCTL_READ 0x40 -#define AUE_PHYCTL_DONE 0x80 - -#define AUE_USBSTS_SUSPEND 0x01 -#define AUE_USBSTS_RESUME 0x02 - -#define AUE_TXSTAT0_JABTIMO 0x04 -#define AUE_TXSTAT0_CARLOSS 0x08 -#define AUE_TXSTAT0_NOCARRIER 0x10 -#define AUE_TXSTAT0_LATECOLL 0x20 -#define AUE_TXSTAT0_EXCESSCOLL 0x40 -#define AUE_TXSTAT0_UNDERRUN 0x80 - -#define AUE_TXSTAT1_PKTCNT 0x0F -#define AUE_TXSTAT1_FIFO_EMPTY 0x40 -#define AUE_TXSTAT1_FIFO_FULL 0x80 - -#define AUE_RXSTAT_OVERRUN 0x01 -#define AUE_RXSTAT_PAUSE 0x02 - -#define AUE_GPIO_IN0 0x01 -#define AUE_GPIO_OUT0 0x02 -#define AUE_GPIO_SEL0 0x04 -#define AUE_GPIO_IN1 0x08 -#define AUE_GPIO_OUT1 0x10 -#define AUE_GPIO_SEL1 0x20 - -struct aue_intrpkt { - u_int8_t aue_txstat0; - u_int8_t aue_txstat1; - u_int8_t aue_rxstat; - u_int8_t aue_rxlostpkt0; - u_int8_t aue_rxlostpkt1; - u_int8_t aue_wakeupstat; - u_int8_t aue_rsvd; -}; - -struct aue_rxpkt { - u_int16_t aue_pktlen; - u_int8_t aue_rxstat; -}; - -#define AUE_RXSTAT_MCAST 0x01 -#define AUE_RXSTAT_GIANT 0x02 -#define AUE_RXSTAT_RUNT 0x04 -#define AUE_RXSTAT_CRCERR 0x08 -#define AUE_RXSTAT_DRIBBLE 0x10 -#define AUE_RXSTAT_MASK 0x1E - -#define AUE_INC(x, y) (x) = (x + 1) % y - -struct aue_softc { -#if defined(__FreeBSD__) -#define GET_MII(sc) (device_get_softc((sc)->aue_miibus)) -#elif defined(__NetBSD__) -#define GET_MII(sc) (&(sc)->aue_mii) -#elif defined(__OpenBSD__) -#define GET_MII(sc) (&(sc)->aue_mii) -#endif - struct ifnet *aue_ifp; - device_t aue_dev; - device_t aue_miibus; - usbd_device_handle aue_udev; - usbd_interface_handle aue_iface; - u_int16_t aue_vendor; - u_int16_t aue_product; - int aue_ed[AUE_ENDPT_MAX]; - usbd_pipe_handle aue_ep[AUE_ENDPT_MAX]; - int aue_unit; - u_int8_t aue_link; - int aue_timer; - int aue_if_flags; - struct ue_cdata aue_cdata; - struct callout aue_tick_callout; - struct usb_taskqueue aue_taskqueue; - struct task aue_task; - struct mtx aue_mtx; - struct sx aue_sx; - u_int16_t aue_flags; - char aue_dying; - struct timeval aue_rx_notice; - struct usb_qdat aue_qdat; - int aue_deferedtasks; -}; - -#if 0 -/* - * Some debug code to make sure we don't take a blocking lock in - * interrupt context. - */ -#include <sys/types.h> -#include <sys/proc.h> -#include <sys/kdb.h> - -#define AUE_DUMPSTATE(tag) aue_dumpstate(__func__, tag) - -static inline void -aue_dumpstate(const char *func, const char *tag) -{ - if ((curthread->td_pflags & TDP_NOSLEEPING) || - (curthread->td_pflags & TDP_ITHREAD)) { - kdb_backtrace(); - printf("%s: %s sleep: %sok ithread: %s\n", func, tag, - curthread->td_pflags & TDP_NOSLEEPING ? "not" : "", - curthread->td_pflags & TDP_ITHREAD ? "yes" : "no"); - } -} -#else -#define AUE_DUMPSTATE(tag) -#endif - -#define AUE_LOCK(_sc) mtx_lock(&(_sc)->aue_mtx) -#define AUE_UNLOCK(_sc) mtx_unlock(&(_sc)->aue_mtx) -#define AUE_SXLOCK(_sc) \ - do { AUE_DUMPSTATE("sxlock"); sx_xlock(&(_sc)->aue_sx); } while(0) -#define AUE_SXUNLOCK(_sc) sx_xunlock(&(_sc)->aue_sx) -#define AUE_SXASSERTLOCKED(_sc) sx_assert(&(_sc)->aue_sx, SX_XLOCKED) -#define AUE_SXASSERTUNLOCKED(_sc) sx_assert(&(_sc)->aue_sx, SX_UNLOCKED) - -#define AUE_TIMEOUT 1000 -#define AUE_MIN_FRAMELEN 60 -#define AUE_INTR_INTERVAL 100 /* ms */ - -/* - * These bits are used to notify the task about pending events. - * The names correspond to the interrupt context routines that would - * be normally called. (example: AUE_TASK_WATCHDOG -> aue_watchdog()) - */ -#define AUE_TASK_WATCHDOG 0x0001 -#define AUE_TASK_TICK 0x0002 -#define AUE_TASK_START 0x0004 -#define AUE_TASK_RXSTART 0x0008 -#define AUE_TASK_RXEOF 0x0010 -#define AUE_TASK_TXEOF 0x0020 - -#define AUE_GIANTLOCK() mtx_lock(&Giant); -#define AUE_GIANTUNLOCK() mtx_unlock(&Giant); - -#endif /* !AUEREG_H */ diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c deleted file mode 100644 index 65da32b..0000000 --- a/sys/dev/usb/if_axe.c +++ /dev/null @@ -1,1428 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000-2003 - * Bill Paul <wpaul@windriver.com>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver. - * Used in the LinkSys USB200M and various other adapters. - * - * Manuals available from: - * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF - * Note: you need the manual for the AX88170 chip (USB 1.x ethernet - * controller) to find the definitions for the RX control register. - * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF - * - * Written by Bill Paul <wpaul@windriver.com> - * Senior Engineer - * Wind River Systems - */ - -/* - * The AX88172 provides USB ethernet supports at 10 and 100Mbps. - * It uses an external PHY (reference designs use a RealTek chip), - * and has a 64-bit multicast hash filter. There is some information - * missing from the manual which one needs to know in order to make - * the chip function: - * - * - You must set bit 7 in the RX control register, otherwise the - * chip won't receive any packets. - * - You must initialize all 3 IPG registers, or you won't be able - * to send any packets. - * - * Note that this device appears to only support loading the station - * address via autload from the EEPROM (i.e. there's no way to manaully - * set it). - * - * (Adam Weinberger wanted me to name this driver if_gir.c.) - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/endian.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/lock.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sx.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -/* "device miibus" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -/* - * AXE_178_MAX_FRAME_BURST - * max frame burst size for Ax88178 and Ax88772 - * 0 2048 bytes - * 1 4096 bytes - * 2 8192 bytes - * 3 16384 bytes - * use the largest your system can handle without usb stalling. - * - * NB: 88772 parts appear to generate lots of input errors with - * a 2K rx buffer and 8K is only slightly faster than 4K on an - * EHCI port on a T42 so change at your own risk. - */ -#define AXE_178_MAX_FRAME_BURST 1 - -#include <dev/usb/if_axereg.h> - -/* - * Various supported device vendors/products. - */ -const struct axe_type axe_devs[] = { - { { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 }, - { { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 }, - { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET}, AX772 }, - { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 }, - { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772}, AX772 }, - { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178}, AX178 }, - { { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T}, 0 }, - { { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D5055 }, AX178 }, - { { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR}, 0}, - { { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB200MV2}, AX772 }, - { { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0}, - { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100}, 0 }, - { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100B1 }, AX772 }, - { { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_GWUSB2E}, 0 }, - { { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_ETGUS2 }, AX178 }, - { { USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1}, 0 }, - { { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M}, 0 }, - { { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_USB1000 }, AX178 }, - { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX}, 0 }, - { { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120}, 0 }, - { { USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01PLUS }, AX772 }, - { { USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GU1000T }, AX178 }, - { { USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 }, - { { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029}, 0 }, - { { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN028 }, AX178 } -}; - -#define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p)) - -static device_probe_t axe_match; -static device_attach_t axe_attach; -static device_detach_t axe_detach; -static device_shutdown_t axe_shutdown; -static miibus_readreg_t axe_miibus_readreg; -static miibus_writereg_t axe_miibus_writereg; -static miibus_statchg_t axe_miibus_statchg; - -static int axe_encap(struct axe_softc *, struct mbuf *, int); -static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void axe_tick(void *); -static void axe_tick_task(void *); -static void axe_start(struct ifnet *); -static int axe_ioctl(struct ifnet *, u_long, caddr_t); -static void axe_init(void *); -static void axe_stop(struct axe_softc *); -static void axe_watchdog(struct ifnet *); -static int axe_cmd(struct axe_softc *, int, int, int, void *); -static int axe_ifmedia_upd(struct ifnet *); -static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static void axe_setmulti(struct axe_softc *); - -static device_method_t axe_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, axe_match), - DEVMETHOD(device_attach, axe_attach), - DEVMETHOD(device_detach, axe_detach), - DEVMETHOD(device_shutdown, axe_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, axe_miibus_readreg), - DEVMETHOD(miibus_writereg, axe_miibus_writereg), - DEVMETHOD(miibus_statchg, axe_miibus_statchg), - - { 0, 0 } -}; - -static driver_t axe_driver = { - "axe", - axe_methods, - sizeof(struct axe_softc) -}; - -static devclass_t axe_devclass; - -DRIVER_MODULE(axe, uhub, axe_driver, axe_devclass, usbd_driver_load, 0); -DRIVER_MODULE(miibus, axe, miibus_driver, miibus_devclass, 0, 0); -MODULE_DEPEND(axe, usb, 1, 1, 1); -MODULE_DEPEND(axe, miibus, 1, 1, 1); - -static int -axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf) -{ - usb_device_request_t req; - usbd_status err; - - AXE_SLEEPLOCKASSERT(sc); - if (sc->axe_dying) - return(0); - - if (AXE_CMD_DIR(cmd)) - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - else - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = AXE_CMD_CMD(cmd); - USETW(req.wValue, val); - USETW(req.wIndex, index); - USETW(req.wLength, AXE_CMD_LEN(cmd)); - - err = usbd_do_request(sc->axe_udev, &req, buf); - - if (err) - return(-1); - - return(0); -} - -static int -axe_miibus_readreg(device_t dev, int phy, int reg) -{ - struct axe_softc *sc = device_get_softc(dev); - usbd_status err; - u_int16_t val; - - if (sc->axe_dying) - return(0); - - AXE_SLEEPLOCKASSERT(sc); -#ifdef notdef - /* - * The chip tells us the MII address of any supported - * PHYs attached to the chip, so only read from those. - */ - - if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0]) - return (0); - - if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1]) - return (0); -#endif - if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy) - return (0); - - AXE_LOCK(sc); - axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); - err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, (void *)&val); - axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); - AXE_UNLOCK(sc); - - if (err) { - device_printf(sc->axe_dev, "read PHY failed\n"); - return(-1); - } - - if (val && val != 0xffff) - sc->axe_phyaddrs[0] = phy; - - return (le16toh(val)); -} - -static int -axe_miibus_writereg(device_t dev, int phy, int reg, int val) -{ - struct axe_softc *sc = device_get_softc(dev); - usbd_status err; - - if (sc->axe_dying) - return(0); - - AXE_SLEEPLOCKASSERT(sc); - AXE_LOCK(sc); - axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); - val = htole32(val); - err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, (void *)&val); - axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); - AXE_UNLOCK(sc); - - if (err) { - device_printf(sc->axe_dev, "write PHY failed\n"); - return(-1); - } - - return (0); -} - -static void -axe_miibus_statchg(device_t dev) -{ - struct axe_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); - int val, err; - - val = (mii->mii_media_active & IFM_GMASK) == IFM_FDX ? - AXE_MEDIA_FULL_DUPLEX : 0; - if (sc->axe_flags & (AX178|AX772)) { - val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC; - - switch (IFM_SUBTYPE(mii->mii_media_active)) { - case IFM_1000_T: - val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK; - break; - case IFM_100_TX: - val |= AXE_178_MEDIA_100TX; - break; - case IFM_10_T: - /* doesn't need to be handled */ - break; - } - } - err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL); - if (err) - device_printf(dev, "media change failed, error %d\n", err); -} - -/* - * Set media options. - */ -static int -axe_ifmedia_upd(struct ifnet *ifp) -{ - struct axe_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->axe_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - - return (0); -} - -/* - * Report current media status. - */ -static void -axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct axe_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - - return; -} - -static void -axe_setmulti(struct axe_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - u_int32_t h = 0; - u_int16_t rxmode; - u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - ifp = sc->axe_ifp; - - AXE_LOCK(sc); - axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, (void *)&rxmode); - rxmode = le16toh(rxmode); - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - rxmode |= AXE_RXCMD_ALLMULTI; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - AXE_UNLOCK(sc); - return; - } else - rxmode &= ~AXE_RXCMD_ALLMULTI; - - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; - hashtbl[h / 8] |= 1 << (h % 8); - } - IF_ADDR_UNLOCK(ifp); - - axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl); - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - AXE_UNLOCK(sc); - - return; -} - -static void -axe_ax88178_init(struct axe_softc *sc) -{ - int gpio0 = 0, phymode = 0; - u_int16_t eeprom; - - axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL); - /* XXX magic */ - axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom); - eeprom = le16toh(eeprom); - axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL); - - /* if EEPROM is invalid we have to use to GPIO0 */ - if (eeprom == 0xffff) { - phymode = 0; - gpio0 = 1; - } else { - phymode = eeprom & 7; - gpio0 = (eeprom & 0x80) ? 0 : 1; - } - - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL); - usbd_delay_ms(sc->axe_udev, 40); - if ((eeprom >> 8) != 1) { - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); - usbd_delay_ms(sc->axe_udev, 30); - - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL); - usbd_delay_ms(sc->axe_udev, 300); - - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); - usbd_delay_ms(sc->axe_udev, 30); - } else { - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL); - usbd_delay_ms(sc->axe_udev, 30); - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL); - usbd_delay_ms(sc->axe_udev, 30); - } - - /* soft reset */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 0, NULL); - usbd_delay_ms(sc->axe_udev, 150); - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, - AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL); - usbd_delay_ms(sc->axe_udev, 150); - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); -} - -static void -axe_ax88772_init(struct axe_softc *sc) -{ - axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL); - usbd_delay_ms(sc->axe_udev, 40); - - if (sc->axe_phyaddrs[1] == AXE_INTPHY) { - /* ask for embedded PHY */ - axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL); - usbd_delay_ms(sc->axe_udev, 10); - - /* power down and reset state, pin reset state */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); - usbd_delay_ms(sc->axe_udev, 60); - - /* power down/reset state, pin operating state */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, - AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); - usbd_delay_ms(sc->axe_udev, 150); - - /* power up, reset */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL); - - /* power up, operating */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, - AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL); - } else { - /* ask for external PHY */ - axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x00, NULL); - usbd_delay_ms(sc->axe_udev, 10); - - /* power down/reset state, pin operating state */ - axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, - AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); - } - - usbd_delay_ms(sc->axe_udev, 150); - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); -} - -static void -axe_reset(struct axe_softc *sc) -{ - if (sc->axe_dying) - return; - - if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1) || - usbd_device2interface_handle(sc->axe_udev, AXE_IFACE_IDX, - &sc->axe_iface)) { - device_printf(sc->axe_dev, "getting interface handle failed\n"); - } - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a AX88172 chip. - */ -static int -axe_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (!uaa->iface) - return(UMATCH_NONE); - return (axe_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -axe_attach(device_t self) -{ - struct axe_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - const struct axe_type *type; - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->axe_udev = uaa->device; - sc->axe_dev = self; - type = axe_lookup(uaa->vendor, uaa->product); - if (type != NULL) - sc->axe_flags = type->axe_flags; - - if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1)) { - device_printf(sc->axe_dev, "getting interface handle failed\n"); - return ENXIO; - } - - usb_init_task(&sc->axe_tick_task, axe_tick_task, sc); - - if (usbd_device2interface_handle(uaa->device, - AXE_IFACE_IDX, &sc->axe_iface)) { - device_printf(sc->axe_dev, "getting interface handle failed\n"); - return ENXIO; - } - - sc->axe_boundary = 64; - if (sc->axe_flags & (AX178|AX772)) { - if (sc->axe_udev->speed == USB_SPEED_HIGH) { - sc->axe_bufsz = AXE_178_MAX_BUFSZ; - sc->axe_boundary = 512; - } else - sc->axe_bufsz = AXE_178_MIN_BUFSZ; - } else - sc->axe_bufsz = AXE_172_BUFSZ; -{ /* XXX debug */ -device_printf(sc->axe_dev, "%s, bufsz %d, boundary %d\n", - sc->axe_flags & AX178 ? "AX88178" : - sc->axe_flags & AX772 ? "AX88772" : "AX88172", - sc->axe_bufsz, sc->axe_boundary); -} - - id = usbd_get_interface_descriptor(sc->axe_iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i); - if (!ed) { - device_printf(sc->axe_dev, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - mtx_init(&sc->axe_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - sx_init(&sc->axe_sleeplock, device_get_nameunit(self)); - AXE_SLEEPLOCK(sc); - AXE_LOCK(sc); - - /* We need the PHYID for the init dance in some cases */ - axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs); - - if (sc->axe_flags & AX178) - axe_ax88178_init(sc); - else if (sc->axe_flags & AX772) - axe_ax88772_init(sc); - - /* - * Get station address. - */ - if (sc->axe_flags & (AX178|AX772)) - axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr); - else - axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, &eaddr); - - /* - * Fetch IPG values. - */ - axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs); - - /* - * Work around broken adapters that appear to lie about - * their PHY addresses. - */ - sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF; - - ifp = sc->axe_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(sc->axe_dev, "can not if_alloc()\n"); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - sx_destroy(&sc->axe_sleeplock); - mtx_destroy(&sc->axe_mtx); - return ENXIO; - } - ifp->if_softc = sc; - if_initname(ifp, "axe", device_get_unit(sc->axe_dev)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_ioctl = axe_ioctl; - ifp->if_start = axe_start; - ifp->if_watchdog = axe_watchdog; - ifp->if_init = axe_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - if (mii_phy_probe(self, &sc->axe_miibus, - axe_ifmedia_upd, axe_ifmedia_sts)) { - device_printf(sc->axe_dev, "MII without any PHY!\n"); - if_free(ifp); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - sx_destroy(&sc->axe_sleeplock); - mtx_destroy(&sc->axe_mtx); - return ENXIO; - } - - /* - * Call MI attach routine. - */ - - ether_ifattach(ifp, eaddr); - callout_handle_init(&sc->axe_stat_ch); - usb_register_netisr(); - - sc->axe_dying = 0; - - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - - return 0; -} - -static int -axe_detach(device_t dev) -{ - struct axe_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - AXE_LOCK(sc); - ifp = sc->axe_ifp; - - sc->axe_dying = 1; - untimeout(axe_tick, sc, sc->axe_stat_ch); - usb_rem_task(sc->axe_udev, &sc->axe_tick_task); - - ether_ifdetach(ifp); - if_free(ifp); - - if (sc->axe_ep[AXE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (sc->axe_ep[AXE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - - AXE_UNLOCK(sc); - sx_destroy(&sc->axe_sleeplock); - mtx_destroy(&sc->axe_mtx); - - return(0); -} - -static int -axe_rx_list_init(struct axe_softc *sc) -{ - struct axe_cdata *cd; - struct axe_chain *c; - int i; - - cd = &sc->axe_cdata; - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - c = &cd->axe_rx_chain[i]; - c->axe_sc = sc; - c->axe_idx = i; - c->axe_mbuf = NULL; - if (c->axe_xfer == NULL) { - c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); - if (c->axe_xfer == NULL) - return (ENOBUFS); - c->axe_buf = usbd_alloc_buffer(c->axe_xfer, - sc->axe_bufsz); - if (c->axe_buf == NULL) { - usbd_free_xfer(c->axe_xfer); - return (ENOBUFS); - } - } - } - - return (0); -} - -static void -axe_rx_list_free(struct axe_softc *sc) -{ - int i; - - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) { - m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf); - sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL; - } - if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) { - usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer); - sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL; - } - } -} - -static int -axe_tx_list_init(struct axe_softc *sc) -{ - struct axe_cdata *cd; - struct axe_chain *c; - int i; - - cd = &sc->axe_cdata; - for (i = 0; i < AXE_TX_LIST_CNT; i++) { - c = &cd->axe_tx_chain[i]; - c->axe_sc = sc; - c->axe_idx = i; - c->axe_mbuf = NULL; - if (c->axe_xfer == NULL) { - c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); - if (c->axe_xfer == NULL) - return (ENOBUFS); - c->axe_buf = usbd_alloc_buffer(c->axe_xfer, - sc->axe_bufsz); - if (c->axe_buf == NULL) { - usbd_free_xfer(c->axe_xfer); - return (ENOBUFS); - } - } - } - - return (0); -} - -static void -axe_tx_list_free(struct axe_softc *sc) -{ - int i; - - /* Free TX resources. */ - for (i = 0; i < AXE_TX_LIST_CNT; i++) { - if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) { - m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf); - sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL; - } - if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) { - usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer); - sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL; - } - } -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct axe_softc *sc; - struct axe_chain *c = (struct axe_chain *) priv; - struct mbuf *m; - u_char *buf; - struct ifnet *ifp; - struct axe_sframe_hdr *hdr; - int total_len = 0; - int pktlen = 0; - - sc = c->axe_sc; - AXE_LOCK(sc); - ifp = sc->axe_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - AXE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - AXE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->axe_rx_notice)) - device_printf(sc->axe_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - buf = c->axe_buf; - - do { - if (sc->axe_flags & (AX178|AX772)) { - if (total_len < sizeof(struct axe_sframe_hdr)) { - ifp->if_ierrors++; - goto done; - } - if ((pktlen % 2) != 0) - pktlen++; - buf += pktlen; - - hdr = (struct axe_sframe_hdr *) buf; - total_len -= sizeof(struct axe_sframe_hdr); - if ((hdr->len ^ hdr->ilen) != 0xffff) { - ifp->if_ierrors++; - goto done; - } - pktlen = le16toh(hdr->len); - if (pktlen > total_len) { - ifp->if_ierrors++; - goto done; - } - - buf += sizeof(struct axe_sframe_hdr); - total_len -= pktlen + (pktlen % 2); - } else { - pktlen = total_len; - total_len = 0; - } - - if (pktlen < sizeof(struct ether_header)) { - ifp->if_ierrors++; - goto done; - } - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - ifp->if_ierrors++; - goto done; - } - m->m_data += ETHER_ALIGN; - memcpy(mtod(m, void *), buf, pktlen); - m->m_pkthdr.len = m->m_len = pktlen; - m->m_pkthdr.rcvif = ifp; - - ifp->if_input(ifp, m); - ifp->if_ipackets++; - } while (total_len > 0); - /* fall thru... */ -done: - /* Setup new transfer. */ - usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX], - c, c->axe_buf, sc->axe_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(xfer); - AXE_UNLOCK(sc); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct axe_softc *sc; - struct axe_chain *c; - struct ifnet *ifp; - usbd_status err; - - c = priv; - sc = c->axe_sc; - AXE_LOCK(sc); - ifp = sc->axe_ifp; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - AXE_UNLOCK(sc); - return; - } - device_printf(sc->axe_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_TX]); - AXE_UNLOCK(sc); - return; - } - - ifp->if_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &err); - - if (c->axe_mbuf != NULL) { - m_freem(c->axe_mbuf); - c->axe_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - AXE_UNLOCK(sc); - - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - axe_start(ifp); - - return; -} - -static void -axe_tick(void *xsc) -{ - struct axe_softc *sc = xsc; - - if (sc == NULL) - return; - if (sc->axe_dying) - return; - - /* Perform periodic stuff in process context */ - usb_add_task(sc->axe_udev, &sc->axe_tick_task, USB_TASKQ_DRIVER); -} - -static void -axe_tick_task(void *xsc) -{ - struct axe_softc *sc; - struct ifnet *ifp; - struct mii_data *mii; - - sc = xsc; - - if (sc == NULL) - return; - - AXE_SLEEPLOCK(sc); - AXE_LOCK(sc); - - ifp = sc->axe_ifp; - mii = GET_MII(sc); - if (mii == NULL) { - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - return; - } - - mii_tick(mii); - if (!sc->axe_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->axe_link++; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - axe_start(ifp); - } - - sc->axe_stat_ch = timeout(axe_tick, sc, hz); - - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - - return; -} - -static int -axe_encap(struct axe_softc *sc, struct mbuf *m, int idx) -{ - struct axe_chain *c; - usbd_status err; - struct axe_sframe_hdr hdr; - int length; - - c = &sc->axe_cdata.axe_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - if (sc->axe_flags & (AX178|AX772)) { - hdr.len = htole16(m->m_pkthdr.len); - hdr.ilen = ~hdr.len; - - memcpy(c->axe_buf, &hdr, sizeof(hdr)); - length = sizeof(hdr); - - m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length); - length += m->m_pkthdr.len; - - if ((length % sc->axe_boundary) == 0) { - hdr.len = 0; - hdr.ilen = 0xffff; - memcpy(c->axe_buf + length, &hdr, sizeof(hdr)); - length += sizeof(hdr); - } - } else { - m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf); - length = m->m_pkthdr.len; - } - c->axe_mbuf = m; - - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX], - c, c->axe_buf, length, USBD_FORCE_SHORT_XFER, 10000, axe_txeof); - - /* Transmit */ - err = usbd_transfer(c->axe_xfer); - if (err != USBD_IN_PROGRESS) { - /* XXX probably don't want to sleep here */ - AXE_SLEEPLOCK(sc); - axe_stop(sc); - AXE_SLEEPUNLOCK(sc); - return(EIO); - } - - sc->axe_cdata.axe_tx_cnt++; - - return(0); -} - -static void -axe_start(struct ifnet *ifp) -{ - struct axe_softc *sc; - struct mbuf *m_head = NULL; - - sc = ifp->if_softc; - AXE_LOCK(sc); - - if (!sc->axe_link) { - AXE_UNLOCK(sc); - return; - } - - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - AXE_UNLOCK(sc); - return; - } - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - AXE_UNLOCK(sc); - return; - } - - if (axe_encap(sc, m_head, 0)) { - IFQ_DRV_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - AXE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - AXE_UNLOCK(sc); - - return; -} - -static void -axe_init(void *xsc) -{ - struct axe_softc *sc = xsc; - struct ifnet *ifp = sc->axe_ifp; - struct axe_chain *c; - usbd_status err; - int i; - int rxmode; - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - return; - - AXE_SLEEPLOCK(sc); - AXE_LOCK(sc); - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - - axe_reset(sc); - -#ifdef notdef - /* Set MAC address */ - axe_mac(sc, IF_LLADDR(sc->axe_ifp), 1); -#endif - - /* Enable RX logic. */ - - /* Init TX ring. */ - if (axe_tx_list_init(sc) == ENOBUFS) { - device_printf(sc->axe_dev, "tx list init failed\n"); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (axe_rx_list_init(sc) == ENOBUFS) { - device_printf(sc->axe_dev, "rx list init failed\n"); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - return; - } - - /* Set transmitter IPG values */ - if (sc->axe_flags & (AX178|AX772)) { - axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2], - (sc->axe_ipgs[1]<<8) | sc->axe_ipgs[0], NULL); - } else { - axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL); - axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL); - axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL); - } - - /* Enable receiver, set RX mode */ - rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE; - if (sc->axe_flags & (AX178|AX772)) { - if (sc->axe_bufsz == AXE_178_MAX_BUFSZ) - rxmode |= AXE_178_RXCMD_MFB; - } else - rxmode |= AXE_172_RXCMD_UNICAST; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxmode |= AXE_RXCMD_PROMISC; - - if (ifp->if_flags & IFF_BROADCAST) - rxmode |= AXE_RXCMD_BROADCAST; - - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); - - /* Load the multicast filter. */ - axe_setmulti(sc); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - device_printf(sc->axe_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - return; - } - - err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - device_printf(sc->axe_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < AXE_RX_LIST_CNT; i++) { - c = &sc->axe_cdata.axe_rx_chain[i]; - usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, c->axe_buf, sc->axe_bufsz, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->axe_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - AXE_UNLOCK(sc); - AXE_SLEEPUNLOCK(sc); - - sc->axe_stat_ch = timeout(axe_tick, sc, hz); - - return; -} - -static int -axe_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct axe_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - u_int16_t rxmode; - int error = 0; - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->axe_if_flags & IFF_PROMISC)) { - AXE_SLEEPLOCK(sc); - AXE_LOCK(sc); - axe_cmd(sc, AXE_CMD_RXCTL_READ, - 0, 0, (void *)&rxmode); - rxmode = le16toh(rxmode); - rxmode |= AXE_RXCMD_PROMISC; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, - 0, rxmode, NULL); - AXE_UNLOCK(sc); - axe_setmulti(sc); - AXE_SLEEPUNLOCK(sc); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->axe_if_flags & IFF_PROMISC) { - AXE_SLEEPLOCK(sc); - AXE_LOCK(sc); - axe_cmd(sc, AXE_CMD_RXCTL_READ, - 0, 0, (void *)&rxmode); - rxmode = le16toh(rxmode); - rxmode &= ~AXE_RXCMD_PROMISC; - axe_cmd(sc, AXE_CMD_RXCTL_WRITE, - 0, rxmode, NULL); - AXE_UNLOCK(sc); - axe_setmulti(sc); - AXE_SLEEPUNLOCK(sc); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - axe_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - AXE_SLEEPLOCK(sc); - axe_stop(sc); - AXE_SLEEPUNLOCK(sc); - } - } - sc->axe_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - AXE_SLEEPLOCK(sc); - axe_setmulti(sc); - AXE_SLEEPUNLOCK(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - AXE_SLEEPLOCK(sc); - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - AXE_SLEEPUNLOCK(sc); - break; - - default: - error = ether_ioctl(ifp, command, data); - break; - } - - return(error); -} - -static void -axe_watchdog(struct ifnet *ifp) -{ - struct axe_softc *sc; - struct axe_chain *c; - usbd_status stat; - - sc = ifp->if_softc; - AXE_LOCK(sc); - - ifp->if_oerrors++; - device_printf(sc->axe_dev, "watchdog timeout\n"); - - c = &sc->axe_cdata.axe_tx_chain[0]; - usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat); - axe_txeof(c->axe_xfer, c, stat); - - AXE_UNLOCK(sc); - - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - axe_start(ifp); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -axe_stop(struct axe_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - AXE_SLEEPLOCKASSERT(sc); - AXE_LOCK(sc); - - ifp = sc->axe_ifp; - ifp->if_timer = 0; - - untimeout(axe_tick, sc, sc->axe_stat_ch); - - /* Stop transfers. */ - if (sc->axe_ep[AXE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - device_printf(sc->axe_dev, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]); - if (err) { - device_printf(sc->axe_dev, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_RX] = NULL; - } - - if (sc->axe_ep[AXE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - device_printf(sc->axe_dev, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]); - if (err) { - device_printf(sc->axe_dev, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_TX] = NULL; - } - - if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - if (err) { - device_printf(sc->axe_dev, - "abort intr pipe failed: %s\n", usbd_errstr(err)); - } - err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]); - if (err) { - device_printf(sc->axe_dev, - "close intr pipe failed: %s\n", usbd_errstr(err)); - } - sc->axe_ep[AXE_ENDPT_INTR] = NULL; - } - - axe_reset(sc); - - /* Free RX resources. */ - axe_rx_list_free(sc); - /* Free TX resources. */ - axe_tx_list_free(sc); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->axe_link = 0; - AXE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static int -axe_shutdown(device_t dev) -{ - struct axe_softc *sc; - - sc = device_get_softc(dev); - - AXE_SLEEPLOCK(sc); - axe_stop(sc); - AXE_SLEEPUNLOCK(sc); - - return (0); -} diff --git a/sys/dev/usb/if_axereg.h b/sys/dev/usb/if_axereg.h deleted file mode 100644 index 4503b19..0000000 --- a/sys/dev/usb/if_axereg.h +++ /dev/null @@ -1,254 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000-2003 - * Bill Paul <wpaul@windriver.com>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -/* - * Definitions for the ASIX Electronics AX88172 to ethernet controller. - */ - - -/* - * Vendor specific commands - * ASIX conveniently doesn't document the 'set NODEID' command in their - * datasheet (thanks a lot guys). - * To make handling these commands easier, I added some extra data - * which is decided by the axe_cmd() routine. Commands are encoded - * in 16 bites, with the format: LDCC. L and D are both nibbles in - * the high byte. L represents the data length (0 to 15) and D - * represents the direction (0 for vendor read, 1 for vendor write). - * CC is the command byte, as specified in the manual. - */ - -#define AXE_CMD_DIR(x) (((x) & 0x0F00) >> 8) -#define AXE_CMD_LEN(x) (((x) & 0xF000) >> 12) -#define AXE_CMD_CMD(x) ((x) & 0x00FF) - -#define AXE_172_CMD_READ_RXTX_SRAM 0x2002 -#define AXE_182_CMD_READ_RXTX_SRAM 0x8002 -#define AXE_172_CMD_WRITE_RX_SRAM 0x0103 -#define AXE_172_CMD_WRITE_TX_SRAM 0x0104 -#define AXE_182_CMD_WRITE_RXTX_SRAM 0x8103 -#define AXE_CMD_MII_OPMODE_SW 0x0106 -#define AXE_CMD_MII_READ_REG 0x2007 -#define AXE_CMD_MII_WRITE_REG 0x2108 -#define AXE_CMD_MII_READ_OPMODE 0x1009 -#define AXE_CMD_MII_OPMODE_HW 0x010A -#define AXE_CMD_SROM_READ 0x200B -#define AXE_CMD_SROM_WRITE 0x010C -#define AXE_CMD_SROM_WR_ENABLE 0x010D -#define AXE_CMD_SROM_WR_DISABLE 0x010E -#define AXE_CMD_RXCTL_READ 0x200F -#define AXE_CMD_RXCTL_WRITE 0x0110 -#define AXE_CMD_READ_IPG012 0x3011 -#define AXE_172_CMD_WRITE_IPG0 0x0112 -#define AXE_172_CMD_WRITE_IPG1 0x0113 -#define AXE_172_CMD_WRITE_IPG2 0x0114 -#define AXE_178_CMD_WRITE_IPG012 0x0112 -#define AXE_CMD_READ_MCAST 0x8015 -#define AXE_CMD_WRITE_MCAST 0x8116 -#define AXE_172_CMD_READ_NODEID 0x6017 -#define AXE_172_CMD_WRITE_NODEID 0x6118 -#define AXE_178_CMD_READ_NODEID 0x6013 -#define AXE_178_CMD_WRITE_NODEID 0x6114 -#define AXE_CMD_READ_PHYID 0x2019 -#define AXE_172_CMD_READ_MEDIA 0x101A -#define AXE_178_CMD_READ_MEDIA 0x201A -#define AXE_CMD_WRITE_MEDIA 0x011B -#define AXE_CMD_READ_MONITOR_MODE 0x101C -#define AXE_CMD_WRITE_MONITOR_MODE 0x011D -#define AXE_CMD_READ_GPIO 0x101E -#define AXE_CMD_WRITE_GPIO 0x011F -#define AXE_CMD_SW_RESET_REG 0x0120 -#define AXE_CMD_SW_PHY_STATUS 0x0021 -#define AXE_CMD_SW_PHY_SELECT 0x0122 - -#define AXE_SW_RESET_CLEAR 0x00 -#define AXE_SW_RESET_RR 0x01 -#define AXE_SW_RESET_RT 0x02 -#define AXE_SW_RESET_PRTE 0x04 -#define AXE_SW_RESET_PRL 0x08 -#define AXE_SW_RESET_BZ 0x10 -#define AXE_SW_RESET_IPRL 0x20 -#define AXE_SW_RESET_IPPD 0x40 - -/* AX88178 documentation says to always write this bit... */ -#define AXE_178_RESET_MAGIC 0x40 - -#define AXE_178_MEDIA_GMII 0x0001 -#define AXE_MEDIA_FULL_DUPLEX 0x0002 -#define AXE_172_MEDIA_TX_ABORT_ALLOW 0x0004 -/* AX88178/88772 documentation says to always write 1 to bit 2 */ -#define AXE_178_MEDIA_MAGIC 0x0004 -/* AX88772 documentation says to always write 0 to bit 3 */ -#define AXE_178_MEDIA_ENCK 0x0008 -#define AXE_172_MEDIA_FLOW_CONTROL_EN 0x0010 -#define AXE_178_MEDIA_RXFLOW_CONTROL_EN 0x0010 -#define AXE_178_MEDIA_TXFLOW_CONTROL_EN 0x0020 -#define AXE_178_MEDIA_JUMBO_EN 0x0040 -#define AXE_178_MEDIA_LTPF_ONLY 0x0080 -#define AXE_178_MEDIA_RX_EN 0x0100 -#define AXE_178_MEDIA_100TX 0x0200 -#define AXE_178_MEDIA_SBP 0x0800 -#define AXE_178_MEDIA_SUPERMAC 0x1000 - -#define AXE_RXCMD_PROMISC 0x0001 -#define AXE_RXCMD_ALLMULTI 0x0002 -#define AXE_172_RXCMD_UNICAST 0x0004 -#define AXE_178_RXCMD_KEEP_INVALID_CRC 0x0004 -#define AXE_RXCMD_BROADCAST 0x0008 -#define AXE_RXCMD_MULTICAST 0x0010 -#define AXE_178_RXCMD_AP 0x0020 -#define AXE_RXCMD_ENABLE 0x0080 -#define AXE_178_RXCMD_MFB_2048 0x0000 /* 2K max frame burst */ -#define AXE_178_RXCMD_MFB_4096 0x0100 /* 4K max frame burst */ -#define AXE_178_RXCMD_MFB_8192 0x0200 /* 8K max frame burst */ -#define AXE_178_RXCMD_MFB_16384 0x0300 /* 16K max frame burst*/ - -#define AXE_NOPHY 0xE0 -#define AXE_INTPHY 0x10 - -#define AXE_TIMEOUT 1000 -#define AXE_172_BUFSZ 1536 -#define AXE_178_MIN_BUFSZ 2048 -#define AXE_MIN_FRAMELEN 60 -#define AXE_RX_FRAMES 1 -#define AXE_TX_FRAMES 1 - -#if AXE_178_MAX_FRAME_BURST == 0 -#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_2048 -#define AXE_178_MAX_BUFSZ 2048 -#elif AXE_178_MAX_FRAME_BURST == 1 -#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_4096 -#define AXE_178_MAX_BUFSZ 4096 -#elif AXE_178_MAX_FRAME_BURST == 2 -#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_8192 -#define AXE_178_MAX_BUFSZ 8192 -#else -#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_16384 -#define AXE_178_MAX_BUFSZ 16384 -#endif - -#define AXE_RX_LIST_CNT 1 -#define AXE_TX_LIST_CNT 1 - -struct axe_chain { - struct axe_softc *axe_sc; - usbd_xfer_handle axe_xfer; - char *axe_buf; - struct mbuf *axe_mbuf; - int axe_accum; - int axe_idx; -}; - -struct axe_cdata { - struct axe_chain axe_tx_chain[AXE_TX_LIST_CNT]; - struct axe_chain axe_rx_chain[AXE_RX_LIST_CNT]; - int axe_tx_prod; - int axe_tx_cons; - int axe_tx_cnt; - int axe_rx_prod; -}; - -#define AXE_CTL_READ 0x01 -#define AXE_CTL_WRITE 0x02 - -#define AXE_CONFIG_NO 1 -#define AXE_IFACE_IDX 0 - -/* - * The interrupt endpoint is currently unused - * by the ASIX part. - */ -#define AXE_ENDPT_RX 0x0 -#define AXE_ENDPT_TX 0x1 -#define AXE_ENDPT_INTR 0x2 -#define AXE_ENDPT_MAX 0x3 - -struct axe_sframe_hdr { - uint16_t len; - uint16_t ilen; -} __packed; - -struct axe_type { - struct usb_devno axe_dev; - uint32_t axe_flags; -#define AX172 0x0000 /* AX88172 */ -#define AX178 0x0001 /* AX88178 */ -#define AX772 0x0002 /* AX88772 */ -}; - -#define AXE_INC(x, y) (x) = (x + 1) % y - -struct axe_softc { -#if defined(__FreeBSD__) -#define GET_MII(sc) (device_get_softc((sc)->axe_miibus)) -#elif defined(__NetBSD__) -#define GET_MII(sc) (&(sc)->axe_mii) -#elif defined(__OpenBSD__) -#define GET_MII(sc) (&(sc)->axe_mii) -#endif - struct ifnet *axe_ifp; - device_t axe_miibus; - device_t axe_dev; - usbd_device_handle axe_udev; - usbd_interface_handle axe_iface; - u_int16_t axe_vendor; - u_int16_t axe_product; - u_int16_t axe_flags; - int axe_ed[AXE_ENDPT_MAX]; - usbd_pipe_handle axe_ep[AXE_ENDPT_MAX]; - int axe_if_flags; - struct axe_cdata axe_cdata; - struct callout_handle axe_stat_ch; - struct mtx axe_mtx; - struct sx axe_sleeplock; - char axe_dying; - int axe_link; - unsigned char axe_ipgs[3]; - unsigned char axe_phyaddrs[2]; - struct timeval axe_rx_notice; - struct usb_task axe_tick_task; - int axe_bufsz; - int axe_boundary; -}; - -#if 0 -#define AXE_LOCK(_sc) mtx_lock(&(_sc)->axe_mtx) -#define AXE_UNLOCK(_sc) mtx_unlock(&(_sc)->axe_mtx) -#else -#define AXE_LOCK(_sc) -#define AXE_UNLOCK(_sc) -#endif -#define AXE_SLEEPLOCK(_sc) sx_xlock(&(_sc)->axe_sleeplock) -#define AXE_SLEEPUNLOCK(_sc) sx_xunlock(&(_sc)->axe_sleeplock) -#define AXE_SLEEPLOCKASSERT(_sc) sx_assert(&(_sc)->axe_sleeplock, SX_XLOCKED) diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c deleted file mode 100644 index d41a54f..0000000 --- a/sys/dev/usb/if_cdce.c +++ /dev/null @@ -1,771 +0,0 @@ -/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ - -/* - * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> - * Copyright (c) 2003-2005 Craig Boston - * Copyright (c) 2004 Daniel Hartmeier - * 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul, THE VOICES IN HIS HEAD OR - * THE 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 Communication Device Class (Ethernet Networking Control Model) - * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/endian.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_types.h> -#include <net/if_media.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usb_ethersubr.h> - -#include <dev/usb/usbcdc.h> -#include "usbdevs.h" -#include <dev/usb/if_cdcereg.h> - -static device_probe_t cdce_match; -static device_attach_t cdce_attach; -static device_detach_t cdce_detach; -static device_shutdown_t cdce_shutdown; - -static device_method_t cdce_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, cdce_match), - DEVMETHOD(device_attach, cdce_attach), - DEVMETHOD(device_detach, cdce_detach), - DEVMETHOD(device_shutdown, cdce_shutdown), - - { 0, 0 } -}; - -static driver_t cdce_driver = { - "cdce", - cdce_methods, - sizeof(struct cdce_softc) -}; - -static devclass_t cdce_devclass; - -DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, usbd_driver_load, 0); -MODULE_VERSION(cdce, 0); -MODULE_DEPEND(cdce, usb, 1, 1, 1); - -static int cdce_encap(struct cdce_softc *, struct mbuf *, int); -static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cdce_start(struct ifnet *); -static int cdce_ioctl(struct ifnet *, u_long, caddr_t); -static void cdce_init(void *); -static void cdce_reset(struct cdce_softc *); -static void cdce_stop(struct cdce_softc *); -static void cdce_rxstart(struct ifnet *); -static int cdce_ifmedia_upd(struct ifnet *ifp); -static void cdce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); - -static const struct cdce_type cdce_devs[] = { - {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, CDCE_NO_UNION }, - {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_NO_UNION }, - {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, CDCE_NO_UNION }, - {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, CDCE_NO_UNION }, - {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_ZAURUS | CDCE_NO_UNION }, - {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_ZAURUS | CDCE_NO_UNION }, - {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, CDCE_NO_UNION }, - {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300 }, CDCE_ZAURUS | CDCE_NO_UNION }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700 }, CDCE_ZAURUS | CDCE_NO_UNION }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750 }, CDCE_ZAURUS | CDCE_NO_UNION }, -}; -#define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) - -static int -cdce_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL) - return (UMATCH_NONE); - - if (cdce_lookup(uaa->vendor, uaa->product) != NULL) - return (UMATCH_VENDOR_PRODUCT); - - if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass == - UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) - return (UMATCH_IFACECLASS_GENERIC); - - return (UMATCH_NONE); -} - -static int -cdce_attach(device_t self) -{ - struct cdce_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ifnet *ifp; - usbd_device_handle dev = uaa->device; - const struct cdce_type *t; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const usb_cdc_union_descriptor_t *ud; - usb_config_descriptor_t *cd; - int data_ifcno; - int i, j, numalts; - u_char eaddr[ETHER_ADDR_LEN]; - const usb_cdc_ethernet_descriptor_t *ue; - char eaddr_str[USB_MAX_STRING_LEN]; - - sc->cdce_dev = self; - sc->cdce_udev = uaa->device; - - t = cdce_lookup(uaa->vendor, uaa->product); - if (t) - sc->cdce_flags = t->cdce_flags; - - if (sc->cdce_flags & CDCE_NO_UNION) - sc->cdce_data_iface = uaa->iface; - else { - ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev, - UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION); - if (ud == NULL) { - device_printf(sc->cdce_dev, "no union descriptor\n"); - return ENXIO; - } - data_ifcno = ud->bSlaveInterface[0]; - - for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i] != NULL) { - id = usbd_get_interface_descriptor( - uaa->ifaces[i]); - if (id != NULL && id->bInterfaceNumber == - data_ifcno) { - sc->cdce_data_iface = uaa->ifaces[i]; - uaa->ifaces[i] = NULL; - } - } - } - } - - if (sc->cdce_data_iface == NULL) { - device_printf(sc->cdce_dev, "no data interface\n"); - return ENXIO; - } - - /* - * <quote> - * The Data Class interface of a networking device shall have a minimum - * of two interface settings. The first setting (the default interface - * setting) includes no endpoints and therefore no networking traffic is - * exchanged whenever the default interface setting is selected. One or - * more additional interface settings are used for normal operation, and - * therefore each includes a pair of endpoints (one IN, and one OUT) to - * exchange network traffic. Select an alternate interface setting to - * initialize the network aspects of the device and to enable the - * exchange of network traffic. - * </quote> - * - * Some devices, most notably cable modems, include interface settings - * that have no IN or OUT endpoint, therefore loop through the list of all - * available interface settings looking for one with both IN and OUT - * endpoints. - */ - id = usbd_get_interface_descriptor(sc->cdce_data_iface); - cd = usbd_get_config_descriptor(sc->cdce_udev); - numalts = usbd_get_no_alts(cd, id->bInterfaceNumber); - - for (j = 0; j < numalts; j++) { - if (usbd_set_interface(sc->cdce_data_iface, j)) { - device_printf(sc->cdce_dev, - "setting alternate interface failed\n"); - return ENXIO; - } - /* Find endpoints. */ - id = usbd_get_interface_descriptor(sc->cdce_data_iface); - sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i); - if (!ed) { - device_printf(sc->cdce_dev, - "could not read endpoint descriptor\n"); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cdce_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cdce_bulkout_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - /* XXX: CDC spec defines an interrupt pipe, but it is not - * needed for simple host-to-host applications. */ - } else { - device_printf(sc->cdce_dev, - "unexpected endpoint\n"); - } - } - /* If we found something, try and use it... */ - if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) - break; - } - - if (sc->cdce_bulkin_no == -1) { - device_printf(sc->cdce_dev, "could not find data bulk in\n"); - return ENXIO; - } - if (sc->cdce_bulkout_no == -1 ) { - device_printf(sc->cdce_dev, "could not find data bulk out\n"); - return ENXIO; - } - - mtx_init(&sc->cdce_mtx, device_get_nameunit(sc->cdce_dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - ifmedia_init(&sc->cdce_ifmedia, 0, cdce_ifmedia_upd, cdce_ifmedia_sts); - CDCE_LOCK(sc); - - ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev, - UDESC_INTERFACE, UDESCSUB_CDC_ENF); - if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str, - sizeof(eaddr_str))) { - /* Fake MAC address */ - device_printf(sc->cdce_dev, "faking MAC address\n"); - eaddr[0]= 0x2a; - memcpy(&eaddr[1], &ticks, sizeof(u_int32_t)); - eaddr[5] = (u_int8_t)device_get_unit(sc->cdce_dev); - } else { - int i; - - memset(eaddr, 0, ETHER_ADDR_LEN); - for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { - int c = eaddr_str[i]; - - if ('0' <= c && c <= '9') - c -= '0'; - else - c -= 'A' - 10; - c &= 0xf; - if (c % 2 == 0) - c <<= 4; - eaddr[i / 2] |= c; - } - } - - ifp = GET_IFP(sc) = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(sc->cdce_dev, "can not if_alloc()\n"); - CDCE_UNLOCK(sc); - mtx_destroy(&sc->cdce_mtx); - return ENXIO; - } - ifp->if_softc = sc; - if_initname(ifp, "cdce", device_get_unit(sc->cdce_dev)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_ioctl = cdce_ioctl; - ifp->if_output = ether_output; - ifp->if_start = cdce_start; - ifp->if_init = cdce_init; - ifp->if_baudrate = 11000000; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - - sc->q.ifp = ifp; - sc->q.if_rxstart = cdce_rxstart; - - /* No IFM type for 11Mbps USB, so go with 10baseT */ - ifmedia_add(&sc->cdce_ifmedia, IFM_ETHER | IFM_10_T, 0, 0); - ifmedia_set(&sc->cdce_ifmedia, IFM_ETHER | IFM_10_T); - - ether_ifattach(ifp, eaddr); - usb_register_netisr(); - - CDCE_UNLOCK(sc); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev, - sc->cdce_dev); - - return 0; -} - -static int -cdce_detach(device_t self) -{ - struct cdce_softc *sc = device_get_softc(self); - struct ifnet *ifp; - - CDCE_LOCK(sc); - sc->cdce_dying = 1; - ifp = GET_IFP(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - cdce_shutdown(sc->cdce_dev); - - ether_ifdetach(ifp); - if_free(ifp); - ifmedia_removeall(&sc->cdce_ifmedia); - CDCE_UNLOCK(sc); - mtx_destroy(&sc->cdce_mtx); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->cdce_udev, - sc->cdce_dev); - - return (0); -} - -static void -cdce_start(struct ifnet *ifp) -{ - struct cdce_softc *sc; - struct mbuf *m_head = NULL; - - sc = ifp->if_softc; - CDCE_LOCK(sc); - - - if (sc->cdce_dying || - ifp->if_drv_flags & IFF_DRV_OACTIVE || - !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - CDCE_UNLOCK(sc); - return; - } - - IF_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - CDCE_UNLOCK(sc); - return; - } - - if (cdce_encap(sc, m_head, 0)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - CDCE_UNLOCK(sc); - return; - } - - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - CDCE_UNLOCK(sc); - - return; -} - -static int -cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) -{ - struct ue_chain *c; - usbd_status err; - int extra = 0; - - c = &sc->cdce_cdata.ue_tx_chain[idx]; - - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf); - if (sc->cdce_flags & CDCE_ZAURUS) { - /* Zaurus wants a 32-bit CRC appended to every frame */ - u_int32_t crc; - - crc = htole32(crc32(c->ue_buf, m->m_pkthdr.len)); - bcopy(&crc, c->ue_buf + m->m_pkthdr.len, 4); - extra = 4; - } - c->ue_mbuf = m; - - usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkout_pipe, c, c->ue_buf, - m->m_pkthdr.len + extra, 0, 10000, cdce_txeof); - err = usbd_transfer(c->ue_xfer); - if (err != USBD_IN_PROGRESS) { - cdce_stop(sc); - return (EIO); - } - - sc->cdce_cdata.ue_tx_cnt++; - - return (0); -} - -static void -cdce_stop(struct cdce_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - CDCE_LOCK(sc); - - cdce_reset(sc); - - ifp = GET_IFP(sc); - ifp->if_timer = 0; - - if (sc->cdce_bulkin_pipe != NULL) { - err = usbd_abort_pipe(sc->cdce_bulkin_pipe); - if (err) - device_printf(sc->cdce_dev, - "abort rx pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->cdce_bulkin_pipe); - if (err) - device_printf(sc->cdce_dev, - "close rx pipe failed: %s\n", usbd_errstr(err)); - sc->cdce_bulkin_pipe = NULL; - } - - if (sc->cdce_bulkout_pipe != NULL) { - err = usbd_abort_pipe(sc->cdce_bulkout_pipe); - if (err) - device_printf(sc->cdce_dev, - "abort tx pipe failed: %s\n", usbd_errstr(err)); - err = usbd_close_pipe(sc->cdce_bulkout_pipe); - if (err) - device_printf(sc->cdce_dev, - "close tx pipe failed: %s\n", usbd_errstr(err)); - sc->cdce_bulkout_pipe = NULL; - } - - usb_ether_rx_list_free(&sc->cdce_cdata); - usb_ether_tx_list_free(&sc->cdce_cdata); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - CDCE_UNLOCK(sc); - - return; -} - -static int -cdce_shutdown(device_t dev) -{ - struct cdce_softc *sc; - - sc = device_get_softc(dev); - cdce_stop(sc); - - return (0); -} - -static int -cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct cdce_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - int error = 0; - - if (sc->cdce_dying) - return (ENXIO); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - cdce_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - cdce_stop(sc); - } - error = 0; - break; - - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->cdce_ifmedia, command); - break; - - default: - error = ether_ioctl(ifp, command, data); - break; - } - - return (error); -} - -static void -cdce_reset(struct cdce_softc *sc) -{ - /* XXX Maybe reset the bulk pipes here? */ - return; -} - -static void -cdce_init(void *xsc) -{ - struct cdce_softc *sc = xsc; - struct ifnet *ifp = GET_IFP(sc); - struct ue_chain *c; - usbd_status err; - int i; - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - return; - - CDCE_LOCK(sc); - cdce_reset(sc); - - if (usb_ether_tx_list_init(sc, &sc->cdce_cdata, - sc->cdce_udev) == ENOBUFS) { - device_printf(sc->cdce_dev, "tx list init failed\n"); - CDCE_UNLOCK(sc); - return; - } - - if (usb_ether_rx_list_init(sc, &sc->cdce_cdata, - sc->cdce_udev) == ENOBUFS) { - device_printf(sc->cdce_dev, "rx list init failed\n"); - CDCE_UNLOCK(sc); - return; - } - - /* Maybe set multicast / broadcast here??? */ - - err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, - USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); - if (err) { - device_printf(sc->cdce_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - CDCE_UNLOCK(sc); - return; - } - - err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); - if (err) { - device_printf(sc->cdce_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - CDCE_UNLOCK(sc); - return; - } - - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->cdce_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, - mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cdce_rxeof); - usbd_transfer(c->ue_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - CDCE_UNLOCK(sc); - - return; -} - -static void -cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct cdce_softc *sc = c->ue_sc; - struct ifnet *ifp; - struct mbuf *m; - int total_len = 0; - - CDCE_LOCK(sc); - ifp = GET_IFP(sc); - - if (sc->cdce_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - CDCE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CDCE_UNLOCK(sc); - return; - } - if (sc->cdce_rxeof_errors == 0) - device_printf(sc->cdce_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); - DELAY(sc->cdce_rxeof_errors * 10000); - sc->cdce_rxeof_errors++; - goto done; - } - - sc->cdce_rxeof_errors = 0; - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - if (sc->cdce_flags & CDCE_ZAURUS) - total_len -= 4; /* Strip off CRC added by Zaurus */ - - m = c->ue_mbuf; - - if (total_len < sizeof(struct ether_header)) { - ifp->if_ierrors++; - goto done; - } - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = (struct ifnet *)&sc->q; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - CDCE_UNLOCK(sc); - - return; - -done: - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, - mtod(c->ue_mbuf, char *), - UE_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, - cdce_rxeof); - usbd_transfer(c->ue_xfer); - CDCE_UNLOCK(sc); - - return; -} - -static void -cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct cdce_softc *sc = c->ue_sc; - struct ifnet *ifp; - usbd_status err; - - CDCE_LOCK(sc); - ifp = GET_IFP(sc); - - if (sc->cdce_dying || - !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - CDCE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CDCE_UNLOCK(sc); - return; - } - ifp->if_oerrors++; - device_printf(sc->cdce_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); - CDCE_UNLOCK(sc); - return; - } - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); - - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - CDCE_UNLOCK(sc); - - return; -} - -static void -cdce_rxstart(struct ifnet *ifp) -{ - struct cdce_softc *sc; - struct ue_chain *c; - - sc = ifp->if_softc; - CDCE_LOCK(sc); - - if (sc->cdce_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - CDCE_UNLOCK(sc); - return; - } - - c = &sc->cdce_cdata.ue_rx_chain[sc->cdce_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - device_printf(sc->cdce_dev, "no memory for rx list " - "-- packet dropped!\n"); - ifp->if_ierrors++; - CDCE_UNLOCK(sc); - return; - } - - usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, - mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cdce_rxeof); - usbd_transfer(c->ue_xfer); - - CDCE_UNLOCK(sc); - return; -} - -static int -cdce_ifmedia_upd(struct ifnet *ifp) -{ - - /* no-op, cdce has only 1 possible media type */ - return 0; -} - -static void -cdce_ifmedia_sts(struct ifnet * const ifp, struct ifmediareq *req) -{ - - req->ifm_status = IFM_AVALID | IFM_ACTIVE; - req->ifm_active = IFM_ETHER | IFM_10_T; -} diff --git a/sys/dev/usb/if_cdcereg.h b/sys/dev/usb/if_cdcereg.h deleted file mode 100644 index e658eab..0000000 --- a/sys/dev/usb/if_cdcereg.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2003-2005 Craig Boston - * 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul, THE VOICES IN HIS HEAD OR - * THE 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$ - */ - -#ifndef _USB_IF_CDCEREG_H_ -#define _USB_IF_CDCEREG_H_ - -struct cdce_type { - struct usb_devno cdce_dev; - u_int16_t cdce_flags; -#define CDCE_ZAURUS 1 -#define CDCE_NO_UNION 2 -}; - -struct cdce_softc { - struct ifnet *cdce_ifp; -#define GET_IFP(sc) ((sc)->cdce_ifp) - struct ifmedia cdce_ifmedia; - - usbd_device_handle cdce_udev; - usbd_interface_handle cdce_data_iface; - int cdce_bulkin_no; - usbd_pipe_handle cdce_bulkin_pipe; - int cdce_bulkout_no; - usbd_pipe_handle cdce_bulkout_pipe; - char cdce_dying; - device_t cdce_dev; - - struct ue_cdata cdce_cdata; - struct timeval cdce_rx_notice; - int cdce_rxeof_errors; - - u_int16_t cdce_flags; - - struct mtx cdce_mtx; - - struct usb_qdat q; -}; - -/* We are still under Giant */ -#if 0 -#define CDCE_LOCK(_sc) mtx_lock(&(_sc)->cdce_mtx) -#define CDCE_UNLOCK(_sc) mtx_unlock(&(_sc)->cdce_mtx) -#else -#define CDCE_LOCK(_sc) -#define CDCE_UNLOCK(_sc) -#endif - -#endif /* _USB_IF_CDCEREG_H_ */ diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c deleted file mode 100644 index cd3a543..0000000 --- a/sys/dev/usb/if_cue.c +++ /dev/null @@ -1,1074 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate - * adapters and others. - * - * Written by Bill Paul <wpaul@ee.columbia.edu> - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The - * RX filter uses a 512-bit multicast hash table, single perfect entry - * for the station address, and promiscuous mode. Unlike the ADMtek - * and KLSI chips, the CATC ASIC supports read and write combining - * mode where multiple packets can be transfered using a single bulk - * transaction, which helps performance a great deal. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_types.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/usb/if_cuereg.h> - -/* - * Various supported device vendors/products. - */ -static struct cue_type cue_devs[] = { - { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE }, - { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 }, - { USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK }, - /* Belkin F5U111 adapter covered by NETMATE entry */ - { 0, 0 } -}; - -static device_probe_t cue_match; -static device_attach_t cue_attach; -static device_detach_t cue_detach; -static device_shutdown_t cue_shutdown; - -static int cue_encap(struct cue_softc *, struct mbuf *, int); -static void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void cue_tick(void *); -static void cue_rxstart(struct ifnet *); -static void cue_start(struct ifnet *); -static int cue_ioctl(struct ifnet *, u_long, caddr_t); -static void cue_init(void *); -static void cue_stop(struct cue_softc *); -static void cue_watchdog(struct ifnet *); - -static void cue_setmulti(struct cue_softc *); -static uint32_t cue_mchash(const uint8_t *); -static void cue_reset(struct cue_softc *); - -static int cue_csr_read_1(struct cue_softc *, int); -static int cue_csr_write_1(struct cue_softc *, int, int); -static int cue_csr_read_2(struct cue_softc *, int); -#ifdef notdef -static int cue_csr_write_2(struct cue_softc *, int, int); -#endif -static int cue_mem(struct cue_softc *, int, int, void *, int); -static int cue_getmac(struct cue_softc *, void *); - -static device_method_t cue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, cue_match), - DEVMETHOD(device_attach, cue_attach), - DEVMETHOD(device_detach, cue_detach), - DEVMETHOD(device_shutdown, cue_shutdown), - - { 0, 0 } -}; - -static driver_t cue_driver = { - "cue", - cue_methods, - sizeof(struct cue_softc) -}; - -static devclass_t cue_devclass; - -DRIVER_MODULE(cue, uhub, cue_driver, cue_devclass, usbd_driver_load, 0); -MODULE_DEPEND(cue, usb, 1, 1, 1); -MODULE_DEPEND(cue, ether, 1, 1, 1); - -#define CUE_SETBIT(sc, reg, x) \ - cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x)) - -#define CUE_CLRBIT(sc, reg, x) \ - cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x)) - -static int -cue_csr_read_1(struct cue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int8_t val = 0; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 1); - - err = usbd_do_request(sc->cue_udev, &req, &val); - - CUE_UNLOCK(sc); - - if (err) - return(0); - - return(val); -} - -static int -cue_csr_read_2(struct cue_softc *sc, int reg) -{ - usb_device_request_t req; - usbd_status err; - u_int16_t val = 0; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_READREG; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->cue_udev, &req, &val); - - CUE_UNLOCK(sc); - - if (err) - return(0); - - return(val); -} - -static int -cue_csr_write_1(struct cue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->cue_udev, &req, NULL); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} - -#ifdef notdef -static int -cue_csr_write_2(struct cue_softc *sc, int reg, int val) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_WRITEREG; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->cue_udev, &req, NULL); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} -#endif - -static int -cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - if (cmd == CUE_CMD_READSRAM) - req.bmRequestType = UT_READ_VENDOR_DEVICE; - else - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = cmd; - USETW(req.wValue, 0); - USETW(req.wIndex, addr); - USETW(req.wLength, len); - - err = usbd_do_request(sc->cue_udev, &req, buf); - - CUE_UNLOCK(sc); - - if (err) - return(-1); - - return(0); -} - -static int -cue_getmac(struct cue_softc *sc, void *buf) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return(0); - - CUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = CUE_CMD_GET_MACADDR; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, ETHER_ADDR_LEN); - - err = usbd_do_request(sc->cue_udev, &req, buf); - - CUE_UNLOCK(sc); - - if (err) { - device_printf(sc->cue_dev, "read MAC address failed\n"); - return(-1); - } - - return(0); -} - -#define CUE_BITS 9 - -static uint32_t -cue_mchash(const uint8_t *addr) -{ - uint32_t crc; - - /* Compute CRC for the address value. */ - crc = ether_crc32_le(addr, ETHER_ADDR_LEN); - - return (crc & ((1 << CUE_BITS) - 1)); -} - -static void -cue_setmulti(struct cue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - u_int32_t h = 0, i; - - ifp = sc->cue_ifp; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) - sc->cue_mctab[i] = 0xFF; - cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, - &sc->cue_mctab, CUE_MCAST_TABLE_LEN); - return; - } - - /* first, zot all the existing hash bits */ - for (i = 0; i < CUE_MCAST_TABLE_LEN; i++) - sc->cue_mctab[i] = 0; - - /* now program new ones */ - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); - } - IF_ADDR_UNLOCK(ifp); - - /* - * Also include the broadcast address in the filter - * so we can receive broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) { - h = cue_mchash(ifp->if_broadcastaddr); - sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); - } - - cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, - &sc->cue_mctab, CUE_MCAST_TABLE_LEN); - - return; -} - -static void -cue_reset(struct cue_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->cue_dying) - return; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = CUE_CMD_RESET; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - err = usbd_do_request(sc->cue_udev, &req, NULL); - if (err) - device_printf(sc->cue_dev, "reset failed\n"); - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a Pegasus chip. - */ -static int -cue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct cue_type *t; - - if (!uaa->iface) - return(UMATCH_NONE); - - t = cue_devs; - while(t->cue_vid) { - if (uaa->vendor == t->cue_vid && - uaa->product == t->cue_did) { - return(UMATCH_VENDOR_PRODUCT); - } - t++; - } - - return(UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -cue_attach(device_t self) -{ - struct cue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->cue_dev = self; - sc->cue_iface = uaa->iface; - sc->cue_udev = uaa->device; - - if (usbd_set_config_no(sc->cue_udev, CUE_CONFIG_NO, 0)) { - device_printf(sc->cue_dev, "getting interface handle failed\n"); - return ENXIO; - } - - id = usbd_get_interface_descriptor(uaa->iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (!ed) { - device_printf(sc->cue_dev, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - mtx_init(&sc->cue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - CUE_LOCK(sc); - -#ifdef notdef - /* Reset the adapter. */ - cue_reset(sc); -#endif - /* - * Get station address. - */ - cue_getmac(sc, &eaddr); - - ifp = sc->cue_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(sc->cue_dev, "can not if_alloc()\n"); - CUE_UNLOCK(sc); - mtx_destroy(&sc->cue_mtx); - return ENXIO; - } - ifp->if_softc = sc; - if_initname(ifp, "cue", device_get_unit(sc->cue_dev)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_ioctl = cue_ioctl; - ifp->if_start = cue_start; - ifp->if_watchdog = cue_watchdog; - ifp->if_init = cue_init; - ifp->if_baudrate = 10000000; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - - sc->cue_qdat.ifp = ifp; - sc->cue_qdat.if_rxstart = cue_rxstart; - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, eaddr); - callout_handle_init(&sc->cue_stat_ch); - usb_register_netisr(); - sc->cue_dying = 0; - - CUE_UNLOCK(sc); - return 0; -} - -static int -cue_detach(device_t dev) -{ - struct cue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - CUE_LOCK(sc); - ifp = sc->cue_ifp; - - sc->cue_dying = 1; - untimeout(cue_tick, sc, sc->cue_stat_ch); - ether_ifdetach(ifp); - if_free(ifp); - - if (sc->cue_ep[CUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (sc->cue_ep[CUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - - CUE_UNLOCK(sc); - mtx_destroy(&sc->cue_mtx); - - return(0); -} - -static void -cue_rxstart(struct ifnet *ifp) -{ - struct cue_softc *sc; - struct ue_chain *c; - - sc = ifp->if_softc; - CUE_LOCK(sc); - c = &sc->cue_cdata.ue_rx_chain[sc->cue_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - device_printf(sc->cue_dev, "no memory for rx list " - "-- packet dropped!\n"); - ifp->if_ierrors++; - CUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->ue_xfer); - CUE_UNLOCK(sc); - - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void -cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct cue_softc *sc; - struct ue_chain *c; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - u_int16_t len; - - c = priv; - sc = c->ue_sc; - CUE_LOCK(sc); - ifp = sc->cue_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - CUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->cue_rx_notice)) - device_printf(sc->cue_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - m = c->ue_mbuf; - len = *mtod(m, u_int16_t *); - - /* No errors; receive the packet. */ - total_len = len; - - if (len < sizeof(struct ether_header)) { - ifp->if_ierrors++; - goto done; - } - - ifp->if_ipackets++; - m_adj(m, sizeof(u_int16_t)); - m->m_pkthdr.rcvif = (void *)&sc->cue_qdat; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - CUE_UNLOCK(sc); - - return; -done: - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->ue_xfer); - CUE_UNLOCK(sc); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct cue_softc *sc; - struct ue_chain *c; - struct ifnet *ifp; - usbd_status err; - - c = priv; - sc = c->ue_sc; - CUE_LOCK(sc); - ifp = sc->cue_ifp; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - CUE_UNLOCK(sc); - return; - } - device_printf(sc->cue_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->cue_ep[CUE_ENDPT_TX]); - CUE_UNLOCK(sc); - return; - } - - ifp->if_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); - - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - CUE_UNLOCK(sc); - - return; -} - -static void -cue_tick(void *xsc) -{ - struct cue_softc *sc; - struct ifnet *ifp; - - sc = xsc; - - if (sc == NULL) - return; - - CUE_LOCK(sc); - - ifp = sc->cue_ifp; - - ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL); - ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL); - ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL); - - if (cue_csr_read_2(sc, CUE_RX_FRAMEERR)) - ifp->if_ierrors++; - - sc->cue_stat_ch = timeout(cue_tick, sc, hz); - - CUE_UNLOCK(sc); - - return; -} - -static int -cue_encap(struct cue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct ue_chain *c; - usbd_status err; - - c = &sc->cue_cdata.ue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2); - c->ue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - - /* The first two bytes are the frame length */ - c->ue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->ue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_TX], - c, c->ue_buf, total_len, 0, 10000, cue_txeof); - - /* Transmit */ - err = usbd_transfer(c->ue_xfer); - if (err != USBD_IN_PROGRESS) { - cue_stop(sc); - return(EIO); - } - - sc->cue_cdata.ue_tx_cnt++; - - return(0); -} - -static void -cue_start(struct ifnet *ifp) -{ - struct cue_softc *sc; - struct mbuf *m_head = NULL; - - sc = ifp->if_softc; - CUE_LOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - CUE_UNLOCK(sc); - return; - } - - IF_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - CUE_UNLOCK(sc); - return; - } - - if (cue_encap(sc, m_head, 0)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - CUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - CUE_UNLOCK(sc); - - return; -} - -static void -cue_init(void *xsc) -{ - struct cue_softc *sc = xsc; - struct ifnet *ifp = sc->cue_ifp; - struct ue_chain *c; - usbd_status err; - int i; - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - return; - - CUE_LOCK(sc); - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ -#ifdef foo - cue_reset(sc); -#endif - - /* Set MAC address */ - for (i = 0; i < ETHER_ADDR_LEN; i++) - cue_csr_write_1(sc, CUE_PAR0 - i, IF_LLADDR(sc->cue_ifp)[i]); - - /* Enable RX logic. */ - cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON|CUE_ETHCTL_MCAST_ON); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) { - CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - } else { - CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - } - - /* Init TX ring. */ - if (usb_ether_tx_list_init(sc, &sc->cue_cdata, - sc->cue_udev) == ENOBUFS) { - device_printf(sc->cue_dev, "tx list init failed\n"); - CUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (usb_ether_rx_list_init(sc, &sc->cue_cdata, - sc->cue_udev) == ENOBUFS) { - device_printf(sc->cue_dev, "rx list init failed\n"); - CUE_UNLOCK(sc); - return; - } - - /* Load the multicast filter. */ - cue_setmulti(sc); - - /* - * Set the number of RX and TX buffers that we want - * to reserve inside the ASIC. - */ - cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES); - cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES); - - /* Set advanced operation modes. */ - cue_csr_write_1(sc, CUE_ADVANCED_OPMODES, - CUE_AOP_EMBED_RXLEN|0x01); /* 1 wait state */ - - /* Program the LED operation. */ - cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - device_printf(sc->cue_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - CUE_UNLOCK(sc); - return; - } - err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - device_printf(sc->cue_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - CUE_UNLOCK(sc); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->cue_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->cue_ep[CUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof); - usbd_transfer(c->ue_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - CUE_UNLOCK(sc); - - sc->cue_stat_ch = timeout(cue_tick, sc, hz); - - return; -} - -static int -cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct cue_softc *sc = ifp->if_softc; - int error = 0; - - CUE_LOCK(sc); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->cue_if_flags & IFF_PROMISC)) { - CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - cue_setmulti(sc); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->cue_if_flags & IFF_PROMISC) { - CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); - cue_setmulti(sc); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - cue_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - cue_stop(sc); - } - sc->cue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - cue_setmulti(sc); - error = 0; - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - CUE_UNLOCK(sc); - - return(error); -} - -static void -cue_watchdog(struct ifnet *ifp) -{ - struct cue_softc *sc; - struct ue_chain *c; - usbd_status stat; - - sc = ifp->if_softc; - CUE_LOCK(sc); - - ifp->if_oerrors++; - device_printf(sc->cue_dev, "watchdog timeout\n"); - - c = &sc->cue_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - cue_txeof(c->ue_xfer, c, stat); - - if (ifp->if_snd.ifq_head != NULL) - cue_start(ifp); - CUE_UNLOCK(sc); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -cue_stop(struct cue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - CUE_LOCK(sc); - - ifp = sc->cue_ifp; - ifp->if_timer = 0; - - cue_csr_write_1(sc, CUE_ETHCTL, 0); - cue_reset(sc); - untimeout(cue_tick, sc, sc->cue_stat_ch); - - /* Stop transfers. */ - if (sc->cue_ep[CUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - device_printf(sc->cue_dev, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]); - if (err) { - device_printf(sc->cue_dev, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_RX] = NULL; - } - - if (sc->cue_ep[CUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - device_printf(sc->cue_dev, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]); - if (err) { - device_printf(sc->cue_dev, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_TX] = NULL; - } - - if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - if (err) { - device_printf(sc->cue_dev, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]); - if (err) { - device_printf(sc->cue_dev, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->cue_ep[CUE_ENDPT_INTR] = NULL; - } - - /* Free RX resources. */ - usb_ether_rx_list_free(&sc->cue_cdata); - /* Free TX resources. */ - usb_ether_tx_list_free(&sc->cue_cdata); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - CUE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static int -cue_shutdown(device_t dev) -{ - struct cue_softc *sc; - - sc = device_get_softc(dev); - - CUE_LOCK(sc); - cue_reset(sc); - cue_stop(sc); - CUE_UNLOCK(sc); - - return (0); -} diff --git a/sys/dev/usb/if_cuereg.h b/sys/dev/usb/if_cuereg.h deleted file mode 100644 index 4c81653..0000000 --- a/sys/dev/usb/if_cuereg.h +++ /dev/null @@ -1,168 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -/* - * Definitions for the CATC Netmate II USB to ethernet controller. - */ - - -/* - * Vendor specific control commands. - */ -#define CUE_CMD_RESET 0xF4 -#define CUE_CMD_GET_MACADDR 0xF2 -#define CUE_CMD_WRITEREG 0xFA -#define CUE_CMD_READREG 0xFB -#define CUE_CMD_READSRAM 0xF1 -#define CUE_CMD_WRITESRAM 0xFC - -/* - * Internal registers - */ -#define CUE_TX_BUFCNT 0x20 -#define CUE_RX_BUFCNT 0x21 -#define CUE_ADVANCED_OPMODES 0x22 -#define CUE_TX_BUFPKTS 0x23 -#define CUE_RX_BUFPKTS 0x24 -#define CUE_RX_MAXCHAIN 0x25 - -#define CUE_ETHCTL 0x60 -#define CUE_ETHSTS 0x61 -#define CUE_PAR5 0x62 -#define CUE_PAR4 0x63 -#define CUE_PAR3 0x64 -#define CUE_PAR2 0x65 -#define CUE_PAR1 0x66 -#define CUE_PAR0 0x67 - -/* Error counters, all 16 bits wide. */ -#define CUE_TX_SINGLECOLL 0x69 -#define CUE_TX_MULTICOLL 0x6B -#define CUE_TX_EXCESSCOLL 0x6D -#define CUE_RX_FRAMEERR 0x6F - -#define CUE_LEDCTL 0x81 - -/* Advenced operating mode register */ -#define CUE_AOP_SRAMWAITS 0x03 -#define CUE_AOP_EMBED_RXLEN 0x08 -#define CUE_AOP_RXCOMBINE 0x10 -#define CUE_AOP_TXCOMBINE 0x20 -#define CUE_AOP_EVEN_PKT_READS 0x40 -#define CUE_AOP_LOOPBK 0x80 - -/* Ethernet control register */ -#define CUE_ETHCTL_RX_ON 0x01 -#define CUE_ETHCTL_LINK_POLARITY 0x02 -#define CUE_ETHCTL_LINK_FORCE_OK 0x04 -#define CUE_ETHCTL_MCAST_ON 0x08 -#define CUE_ETHCTL_PROMISC 0x10 - -/* Ethernet status register */ -#define CUE_ETHSTS_NO_CARRIER 0x01 -#define CUE_ETHSTS_LATECOLL 0x02 -#define CUE_ETHSTS_EXCESSCOLL 0x04 -#define CUE_ETHSTS_TXBUF_AVAIL 0x08 -#define CUE_ETHSTS_BAD_POLARITY 0x10 -#define CUE_ETHSTS_LINK_OK 0x20 - -/* LED control register */ -#define CUE_LEDCTL_BLINK_1X 0x00 -#define CUE_LEDCTL_BLINK_2X 0x01 -#define CUE_LEDCTL_BLINK_QUARTER_ON 0x02 -#define CUE_LEDCTL_BLINK_QUARTER_OFF 0x03 -#define CUE_LEDCTL_OFF 0x04 -#define CUE_LEDCTL_FOLLOW_LINK 0x08 - -/* - * Address in ASIC's internal SRAM where the - * multicast hash table lives. The table is 64 bytes long, - * giving us a 512-bit table. We have to set the bit that - * corresponds to the broadcast address in order to enable - * reception of broadcast frames. - */ -#define CUE_MCAST_TABLE_ADDR 0xFA80 -#define CUE_MCAST_TABLE_LEN 64 - -#define CUE_TIMEOUT 1000 -#define CUE_MIN_FRAMELEN 60 -#define CUE_RX_FRAMES 1 -#define CUE_TX_FRAMES 1 - -#define CUE_CTL_READ 0x01 -#define CUE_CTL_WRITE 0x02 - -#define CUE_CONFIG_NO 1 - -/* - * The interrupt endpoint is currently unused - * by the KLSI part. - */ -#define CUE_ENDPT_RX 0x0 -#define CUE_ENDPT_TX 0x1 -#define CUE_ENDPT_INTR 0x2 -#define CUE_ENDPT_MAX 0x3 - -struct cue_type { - u_int16_t cue_vid; - u_int16_t cue_did; -}; - -#define CUE_INC(x, y) (x) = (x + 1) % y - -struct cue_softc { - struct ifnet *cue_ifp; - device_t cue_dev; - usbd_device_handle cue_udev; - usbd_interface_handle cue_iface; - int cue_ed[CUE_ENDPT_MAX]; - usbd_pipe_handle cue_ep[CUE_ENDPT_MAX]; - u_int8_t cue_mctab[CUE_MCAST_TABLE_LEN]; - int cue_if_flags; - u_int16_t cue_rxfilt; - struct ue_cdata cue_cdata; - struct callout_handle cue_stat_ch; - struct mtx cue_mtx; - char cue_dying; - struct timeval cue_rx_notice; - struct usb_qdat cue_qdat; -}; - -#if 0 -#define CUE_LOCK(_sc) mtx_lock(&(_sc)->cue_mtx) -#define CUE_UNLOCK(_sc) mtx_unlock(&(_sc)->cue_mtx) -#else -#define CUE_LOCK(_sc) -#define CUE_UNLOCK(_sc) -#endif diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c deleted file mode 100644 index f68eaa8..0000000 --- a/sys/dev/usb/if_kue.c +++ /dev/null @@ -1,1024 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver. - * - * Written by Bill Paul <wpaul@ee.columbia.edu> - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The KLSI USB to ethernet adapter chip contains an USB serial interface, - * ethernet MAC and embedded microcontroller (called the QT Engine). - * The chip must have firmware loaded into it before it will operate. - * Packets are passed between the chip and host via bulk transfers. - * There is an interrupt endpoint mentioned in the software spec, however - * it's currently unused. This device is 10Mbps half-duplex only, hence - * there is no media selection logic. The MAC supports a 128 entry - * multicast filter, though the exact size of the filter can depend - * on the firmware. Curiously, while the software spec describes various - * ethernet statistics counters, my sample adapter and firmware combination - * claims not to support any statistics counters at all. - * - * Note that once we load the firmware in the device, we have to be - * careful not to load it again: if you restart your computer but - * leave the adapter attached to the USB controller, it may remain - * powered on and retain its firmware. In this case, we don't need - * to load the firmware a second time. - * - * Special thanks to Rob Furr for providing an ADS Technologies - * adapter for development and testing. No monkeys were harmed during - * the development of this driver. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/usb/if_kuereg.h> -#include <dev/usb/kue_fw.h> - -MODULE_DEPEND(kue, usb, 1, 1, 1); -MODULE_DEPEND(kue, ether, 1, 1, 1); - -/* - * Various supported device vendors/products. - */ -static struct kue_type kue_devs[] = { - { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 }, - { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_URE450 }, - { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT }, - { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BTX }, - { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 }, - { USB_VENDOR_ASANTE, USB_PRODUCT_ASANTE_EA }, - { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T }, - { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_DSB650C }, - { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T }, - { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C }, - { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 }, - { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX1 }, - { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX2 }, - { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETT }, - { USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA }, - { USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_XX1 }, - { USB_VENDOR_KLSI, USB_PRODUCT_AOX_USB101 }, - { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BT }, - { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BTN }, - { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T }, - { USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA }, - { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 }, - { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101X }, - { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET }, - { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 }, - { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET3 }, - { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA8 }, - { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA9 }, - { USB_VENDOR_PORTSMITH, USB_PRODUCT_PORTSMITH_EEA }, - { USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA }, - { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E }, - { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_GPE }, - { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB }, - { 0, 0 } -}; - -static device_probe_t kue_match; -static device_attach_t kue_attach; -static device_detach_t kue_detach; -static device_shutdown_t kue_shutdown; -static int kue_encap(struct kue_softc *, struct mbuf *, int); -static void kue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void kue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void kue_start(struct ifnet *); -static void kue_rxstart(struct ifnet *); -static int kue_ioctl(struct ifnet *, u_long, caddr_t); -static void kue_init(void *); -static void kue_stop(struct kue_softc *); -static void kue_watchdog(struct ifnet *); - -static void kue_setmulti(struct kue_softc *); -static void kue_reset(struct kue_softc *); - -static usbd_status kue_do_request(usbd_device_handle, - usb_device_request_t *, void *); -static usbd_status kue_ctl(struct kue_softc *, int, u_int8_t, - u_int16_t, char *, int); -static usbd_status kue_setword(struct kue_softc *, u_int8_t, u_int16_t); -static int kue_load_fw(struct kue_softc *); - -static device_method_t kue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, kue_match), - DEVMETHOD(device_attach, kue_attach), - DEVMETHOD(device_detach, kue_detach), - DEVMETHOD(device_shutdown, kue_shutdown), - - { 0, 0 } -}; - -static driver_t kue_driver = { - "kue", - kue_methods, - sizeof(struct kue_softc) -}; - -static devclass_t kue_devclass; - -DRIVER_MODULE(kue, uhub, kue_driver, kue_devclass, usbd_driver_load, 0); - -/* - * We have a custom do_request function which is almost like the - * regular do_request function, except it has a much longer timeout. - * Why? Because we need to make requests over the control endpoint - * to download the firmware to the device, which can take longer - * than the default timeout. - */ -static usbd_status -kue_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) -{ - usbd_xfer_handle xfer; - usbd_status err; - - xfer = usbd_alloc_xfer(dev); - usbd_setup_default_xfer(xfer, dev, 0, 500000, req, - data, UGETW(req->wLength), USBD_SHORT_XFER_OK, 0); - err = usbd_sync_transfer(xfer); - usbd_free_xfer(xfer); - return(err); -} - -static usbd_status -kue_setword(struct kue_softc *sc, u_int8_t breq, u_int16_t word) -{ - usbd_device_handle dev; - usb_device_request_t req; - usbd_status err; - - if (sc->kue_dying) - return(USBD_NORMAL_COMPLETION); - - dev = sc->kue_udev; - - KUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - - req.bRequest = breq; - USETW(req.wValue, word); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = kue_do_request(dev, &req, NULL); - - KUE_UNLOCK(sc); - - return(err); -} - -static usbd_status -kue_ctl(struct kue_softc *sc, int rw, u_int8_t breq, u_int16_t val, - char *data, int len) -{ - usbd_device_handle dev; - usb_device_request_t req; - usbd_status err; - - dev = sc->kue_udev; - - if (sc->kue_dying) - return(USBD_NORMAL_COMPLETION); - - KUE_LOCK(sc); - - if (rw == KUE_CTL_WRITE) - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - else - req.bmRequestType = UT_READ_VENDOR_DEVICE; - - req.bRequest = breq; - USETW(req.wValue, val); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = kue_do_request(dev, &req, data); - - KUE_UNLOCK(sc); - - return(err); -} - -static int -kue_load_fw(struct kue_softc *sc) -{ - usbd_status err; - usb_device_descriptor_t *dd; - int hwrev; - - dd = &sc->kue_udev->ddesc; - hwrev = UGETW(dd->bcdDevice); - - /* - * First, check if we even need to load the firmware. - * If the device was still attached when the system was - * rebooted, it may already have firmware loaded in it. - * If this is the case, we don't need to do it again. - * And in fact, if we try to load it again, we'll hang, - * so we have to avoid this condition if we don't want - * to look stupid. - * - * We can test this quickly by checking the bcdRevision - * code. The NIC will return a different revision code if - * it's probed while the firmware is still loaded and - * running. - */ - if (hwrev == 0x0202) - return(0); - - /* Load code segment */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_code_seg, sizeof(kue_code_seg)); - if (err) { - device_printf(sc->kue_dev, "failed to load code segment: %s\n", - usbd_errstr(err)); - return(ENXIO); - } - - /* Load fixup segment */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_fix_seg, sizeof(kue_fix_seg)); - if (err) { - device_printf(sc->kue_dev, "failed to load fixup segment: %s\n", - usbd_errstr(err)); - return(ENXIO); - } - - /* Send trigger command. */ - err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, - 0, kue_trig_seg, sizeof(kue_trig_seg)); - if (err) { - device_printf(sc->kue_dev, "failed to load trigger segment: %s\n", - usbd_errstr(err)); - return(ENXIO); - } - - return(0); -} - -static void -kue_setmulti(struct kue_softc *sc) -{ - struct ifnet *ifp; - struct ifmultiaddr *ifma; - int i = 0; - - ifp = sc->kue_ifp; - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; - sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - return; - } - - sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI; - - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - /* - * If there are too many addresses for the - * internal filter, switch over to allmulti mode. - */ - if (i == KUE_MCFILTCNT(sc)) - break; - bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), - KUE_MCFILT(sc, i), ETHER_ADDR_LEN); - i++; - } - IF_ADDR_UNLOCK(ifp); - - if (i == KUE_MCFILTCNT(sc)) - sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; - else { - sc->kue_rxfilt |= KUE_RXFILT_MULTICAST; - kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS, - i, sc->kue_mcfilters, i * ETHER_ADDR_LEN); - } - - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - - return; -} - -/* - * Issue a SET_CONFIGURATION command to reset the MAC. This should be - * done after the firmware is loaded into the adapter in order to - * bring it into proper operation. - */ -static void -kue_reset(struct kue_softc *sc) -{ - if (usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 0) || - usbd_device2interface_handle(sc->kue_udev, KUE_IFACE_IDX, - &sc->kue_iface)) { - device_printf(sc->kue_dev, "getting interface handle failed\n"); - } - - /* Wait a little while for the chip to get its brains in order. */ - DELAY(1000); - return; -} - -/* - * Probe for a KLSI chip. - */ -static int -kue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct kue_type *t; - - if (!uaa->iface) - return(UMATCH_NONE); - - t = kue_devs; - while (t->kue_vid) { - if (uaa->vendor == t->kue_vid && uaa->product == t->kue_did) - return (UMATCH_VENDOR_PRODUCT); - t++; - } - return (UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do - * setup and ethernet/BPF attach. - */ -static int -kue_attach(device_t self) -{ - struct kue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ifnet *ifp; - usbd_status err; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - - sc->kue_dev = self; - sc->kue_iface = uaa->iface; - sc->kue_udev = uaa->device; - - id = usbd_get_interface_descriptor(uaa->iface); - - /* Find endpoints. */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (!ed) { - device_printf(sc->kue_dev, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - mtx_init(&sc->kue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - KUE_LOCK(sc); - - /* Load the firmware into the NIC. */ - if (kue_load_fw(sc)) { - KUE_UNLOCK(sc); - mtx_destroy(&sc->kue_mtx); - return ENXIO; - } - - /* Reset the adapter. */ - kue_reset(sc); - - /* Read ethernet descriptor */ - err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, - 0, (char *)&sc->kue_desc, sizeof(sc->kue_desc)); - - sc->kue_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, - M_USBDEV, M_NOWAIT); - - ifp = sc->kue_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(sc->kue_dev, "can not if_alloc()\n"); - KUE_UNLOCK(sc); - mtx_destroy(&sc->kue_mtx); - return ENXIO; - } - ifp->if_softc = sc; - if_initname(ifp, "kue", device_get_unit(sc->kue_dev)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_ioctl = kue_ioctl; - ifp->if_start = kue_start; - ifp->if_watchdog = kue_watchdog; - ifp->if_init = kue_init; - ifp->if_baudrate = 10000000; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - - sc->kue_qdat.ifp = ifp; - sc->kue_qdat.if_rxstart = kue_rxstart; - - /* - * Call MI attach routine. - */ - ether_ifattach(ifp, sc->kue_desc.kue_macaddr); - usb_register_netisr(); - sc->kue_dying = 0; - - KUE_UNLOCK(sc); - - return 0; -} - -static int -kue_detach(device_t dev) -{ - struct kue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - KUE_LOCK(sc); - ifp = sc->kue_ifp; - - sc->kue_dying = 1; - - if (ifp != NULL) { - ether_ifdetach(ifp); - if_free(ifp); - } - - if (sc->kue_ep[KUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (sc->kue_ep[KUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - - if (sc->kue_mcfilters != NULL) - free(sc->kue_mcfilters, M_USBDEV); - - KUE_UNLOCK(sc); - mtx_destroy(&sc->kue_mtx); - - return(0); -} - -static void -kue_rxstart(struct ifnet *ifp) -{ - struct kue_softc *sc; - struct ue_chain *c; - - sc = ifp->if_softc; - KUE_LOCK(sc); - c = &sc->kue_cdata.ue_rx_chain[sc->kue_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - device_printf(sc->kue_dev, "no memory for rx list " - "-- packet dropped!\n"); - ifp->if_ierrors++; - KUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->ue_xfer); - - KUE_UNLOCK(sc); - - return; -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ -static void kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct kue_softc *sc; - struct ue_chain *c; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - u_int16_t len; - - c = priv; - sc = c->ue_sc; - KUE_LOCK(sc); - ifp = sc->kue_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - KUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - KUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->kue_rx_notice)) - device_printf(sc->kue_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - m = c->ue_mbuf; - if (total_len <= 1) - goto done; - - len = *mtod(m, u_int16_t *); - m_adj(m, sizeof(u_int16_t)); - - /* No errors; receive the packet. */ - total_len = len; - - if (len < sizeof(struct ether_header)) { - ifp->if_ierrors++; - goto done; - } - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = (void *)&sc->kue_qdat; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - KUE_UNLOCK(sc); - - return; -done: - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->ue_xfer); - KUE_UNLOCK(sc); - - return; -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -kue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct kue_softc *sc; - struct ue_chain *c; - struct ifnet *ifp; - usbd_status err; - - c = priv; - sc = c->ue_sc; - KUE_LOCK(sc); - - ifp = sc->kue_ifp; - ifp->if_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - KUE_UNLOCK(sc); - return; - } - device_printf(sc->kue_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_TX]); - KUE_UNLOCK(sc); - return; - } - - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); - - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - KUE_UNLOCK(sc); - - return; -} - -static int -kue_encap(struct kue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct ue_chain *c; - usbd_status err; - - c = &sc->kue_cdata.ue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer, leaving two - * bytes at the beginning to hold the frame length. - */ - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2); - c->ue_mbuf = m; - - total_len = m->m_pkthdr.len + 2; - total_len += 64 - (total_len % 64); - - /* Frame length is specified in the first 2 bytes of the buffer. */ - c->ue_buf[0] = (u_int8_t)m->m_pkthdr.len; - c->ue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); - - usbd_setup_xfer(c->ue_xfer, sc->kue_ep[KUE_ENDPT_TX], - c, c->ue_buf, total_len, 0, 10000, kue_txeof); - - /* Transmit */ - err = usbd_transfer(c->ue_xfer); - if (err != USBD_IN_PROGRESS) { - kue_stop(sc); - return(EIO); - } - - sc->kue_cdata.ue_tx_cnt++; - - return(0); -} - -static void -kue_start(struct ifnet *ifp) -{ - struct kue_softc *sc; - struct mbuf *m_head = NULL; - - sc = ifp->if_softc; - KUE_LOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - KUE_UNLOCK(sc); - return; - } - - IF_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - KUE_UNLOCK(sc); - return; - } - - if (kue_encap(sc, m_head, 0)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - KUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - KUE_UNLOCK(sc); - - return; -} - -static void -kue_init(void *xsc) -{ - struct kue_softc *sc = xsc; - struct ifnet *ifp = sc->kue_ifp; - struct ue_chain *c; - usbd_status err; - int i; - - KUE_LOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - KUE_UNLOCK(sc); - return; - } - - /* Set MAC address */ - kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC, - 0, IF_LLADDR(sc->kue_ifp), ETHER_ADDR_LEN); - - sc->kue_rxfilt = KUE_RXFILT_UNICAST|KUE_RXFILT_BROADCAST; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - sc->kue_rxfilt |= KUE_RXFILT_PROMISC; - - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); - - /* I'm not sure how to tune these. */ -#ifdef notdef - /* - * Leave this one alone for now; setting it - * wrong causes lockups on some machines/controllers. - */ - kue_setword(sc, KUE_CMD_SET_SOFS, 1); -#endif - kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64); - - /* Init TX ring. */ - if (usb_ether_tx_list_init(sc, &sc->kue_cdata, - sc->kue_udev) == ENOBUFS) { - device_printf(sc->kue_dev, "tx list init failed\n"); - KUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (usb_ether_rx_list_init(sc, &sc->kue_cdata, - sc->kue_udev) == ENOBUFS) { - device_printf(sc->kue_dev, "rx list init failed\n"); - KUE_UNLOCK(sc); - return; - } - - /* Load the multicast filter. */ - kue_setmulti(sc); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - device_printf(sc->kue_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - KUE_UNLOCK(sc); - return; - } - - err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - device_printf(sc->kue_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - KUE_UNLOCK(sc); - return; - } - - /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->kue_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->kue_ep[KUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, kue_rxeof); - usbd_transfer(c->ue_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - KUE_UNLOCK(sc); - - return; -} - -static int -kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct kue_softc *sc = ifp->if_softc; - int error = 0; - - KUE_LOCK(sc); - - switch(command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->kue_if_flags & IFF_PROMISC)) { - sc->kue_rxfilt |= KUE_RXFILT_PROMISC; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, - sc->kue_rxfilt); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->kue_if_flags & IFF_PROMISC) { - sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC; - kue_setword(sc, KUE_CMD_SET_PKT_FILTER, - sc->kue_rxfilt); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - kue_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - kue_stop(sc); - } - sc->kue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - kue_setmulti(sc); - error = 0; - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - KUE_UNLOCK(sc); - - return(error); -} - -static void -kue_watchdog(struct ifnet *ifp) -{ - struct kue_softc *sc; - struct ue_chain *c; - usbd_status stat; - - sc = ifp->if_softc; - KUE_LOCK(sc); - ifp->if_oerrors++; - device_printf(sc->kue_dev, "watchdog timeout\n"); - - c = &sc->kue_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - kue_txeof(c->ue_xfer, c, stat); - - if (ifp->if_snd.ifq_head != NULL) - kue_start(ifp); - KUE_UNLOCK(sc); - - return; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -static void -kue_stop(struct kue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - KUE_LOCK(sc); - ifp = sc->kue_ifp; - ifp->if_timer = 0; - - /* Stop transfers. */ - if (sc->kue_ep[KUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - device_printf(sc->kue_dev, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_RX]); - if (err) { - device_printf(sc->kue_dev, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_RX] = NULL; - } - - if (sc->kue_ep[KUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - device_printf(sc->kue_dev, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_TX]); - if (err) { - device_printf(sc->kue_dev, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_TX] = NULL; - } - - if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - if (err) { - device_printf(sc->kue_dev, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_INTR]); - if (err) { - device_printf(sc->kue_dev, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->kue_ep[KUE_ENDPT_INTR] = NULL; - } - - /* Free RX resources. */ - usb_ether_rx_list_free(&sc->kue_cdata); - /* Free TX resources. */ - usb_ether_tx_list_free(&sc->kue_cdata); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - KUE_UNLOCK(sc); - - return; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static int -kue_shutdown(device_t dev) -{ - struct kue_softc *sc; - - sc = device_get_softc(dev); - - kue_stop(sc); - - return (0); -} diff --git a/sys/dev/usb/if_kuereg.h b/sys/dev/usb/if_kuereg.h deleted file mode 100644 index 595eaa7..0000000 --- a/sys/dev/usb/if_kuereg.h +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -/* - * Definitions for the KLSI KL5KUSB101B USB to ethernet controller. - * The KLSI part is controlled via vendor control requests, the structure - * of which depend a bit on the firmware running on the internal - * microcontroller. The one exception is the 'send scan data' command, - * which is used to load the firmware. - */ - -#define KUE_CMD_GET_ETHER_DESCRIPTOR 0x00 -#define KUE_CMD_SET_MCAST_FILTERS 0x01 -#define KUE_CMD_SET_PKT_FILTER 0x02 -#define KUE_CMD_GET_ETHERSTATS 0x03 -#define KUE_CMD_GET_GPIO 0x04 -#define KUE_CMD_SET_GPIO 0x05 -#define KUE_CMD_SET_MAC 0x06 -#define KUE_CMD_GET_MAC 0x07 -#define KUE_CMD_SET_URB_SIZE 0x08 -#define KUE_CMD_SET_SOFS 0x09 -#define KUE_CMD_SET_EVEN_PKTS 0x0A -#define KUE_CMD_SEND_SCAN 0xFF - -struct kue_ether_desc { - u_int8_t kue_len; - u_int8_t kue_rsvd0; - u_int8_t kue_rsvd1; - u_int8_t kue_macaddr[ETHER_ADDR_LEN]; - u_int8_t kue_etherstats[4]; - u_int8_t kue_maxseg[2]; - u_int8_t kue_mcastfilt[2]; - u_int8_t kue_rsvd2; -}; - -#define KUE_ETHERSTATS(x) \ - (*(u_int32_t *)&(x)->kue_desc.kue_etherstats) -#define KUE_MAXSEG(x) \ - (*(u_int16_t *)&(x)->kue_desc.kue_maxseg) -#define KUE_MCFILTCNT(x) \ - ((*(u_int16_t *)&(x)->kue_desc.kue_mcastfilt) & 0x7FFF) -#define KUE_MCFILT(x, y) \ - (char *)&(sc->kue_mcfilters[y * ETHER_ADDR_LEN]) - -#define KUE_STAT_TX_OK 0x00000001 -#define KUE_STAT_RX_OK 0x00000002 -#define KUE_STAT_TX_ERR 0x00000004 -#define KUE_STAT_RX_ERR 0x00000008 -#define KUE_STAT_RX_NOBUF 0x00000010 -#define KUE_STAT_TX_UCAST_BYTES 0x00000020 -#define KUE_STAT_TX_UCAST_FRAMES 0x00000040 -#define KUE_STAT_TX_MCAST_BYTES 0x00000080 -#define KUE_STAT_TX_MCAST_FRAMES 0x00000100 -#define KUE_STAT_TX_BCAST_BYTES 0x00000200 -#define KUE_STAT_TX_BCAST_FRAMES 0x00000400 -#define KUE_STAT_RX_UCAST_BYTES 0x00000800 -#define KUE_STAT_RX_UCAST_FRAMES 0x00001000 -#define KUE_STAT_RX_MCAST_BYTES 0x00002000 -#define KUE_STAT_RX_MCAST_FRAMES 0x00004000 -#define KUE_STAT_RX_BCAST_BYTES 0x00008000 -#define KUE_STAT_RX_BCAST_FRAMES 0x00010000 -#define KUE_STAT_RX_CRCERR 0x00020000 -#define KUE_STAT_TX_QUEUE_LENGTH 0x00040000 -#define KUE_STAT_RX_ALIGNERR 0x00080000 -#define KUE_STAT_TX_SINGLECOLL 0x00100000 -#define KUE_STAT_TX_MULTICOLL 0x00200000 -#define KUE_STAT_TX_DEFERRED 0x00400000 -#define KUE_STAT_TX_MAXCOLLS 0x00800000 -#define KUE_STAT_RX_OVERRUN 0x01000000 -#define KUE_STAT_TX_UNDERRUN 0x02000000 -#define KUE_STAT_TX_SQE_ERR 0x04000000 -#define KUE_STAT_TX_CARRLOSS 0x08000000 -#define KUE_STAT_RX_LATECOLL 0x10000000 - -#define KUE_RXFILT_PROMISC 0x0001 -#define KUE_RXFILT_ALLMULTI 0x0002 -#define KUE_RXFILT_UNICAST 0x0004 -#define KUE_RXFILT_BROADCAST 0x0008 -#define KUE_RXFILT_MULTICAST 0x0010 - -#define KUE_TIMEOUT 1000 -#define KUE_MIN_FRAMELEN 60 - -#define KUE_CTL_READ 0x01 -#define KUE_CTL_WRITE 0x02 - -#define KUE_CONFIG_NO 1 -#define KUE_IFACE_IDX 0 - -/* - * The interrupt endpoint is currently unused - * by the KLSI part. - */ -#define KUE_ENDPT_RX 0x0 -#define KUE_ENDPT_TX 0x1 -#define KUE_ENDPT_INTR 0x2 -#define KUE_ENDPT_MAX 0x3 - -struct kue_type { - u_int16_t kue_vid; - u_int16_t kue_did; -}; - -#define KUE_INC(x, y) (x) = (x + 1) % y - -struct kue_softc { - struct ifnet *kue_ifp; - device_t kue_dev; - usbd_device_handle kue_udev; - usbd_interface_handle kue_iface; - struct kue_ether_desc kue_desc; - int kue_ed[KUE_ENDPT_MAX]; - usbd_pipe_handle kue_ep[KUE_ENDPT_MAX]; - int kue_if_flags; - u_int16_t kue_rxfilt; - u_int8_t *kue_mcfilters; - struct ue_cdata kue_cdata; - struct mtx kue_mtx; - char kue_dying; - struct timeval kue_rx_notice; - struct usb_qdat kue_qdat; -}; - -#if 0 -#define KUE_LOCK(_sc) mtx_lock(&(_sc)->kue_mtx) -#define KUE_UNLOCK(_sc) mtx_unlock(&(_sc)->kue_mtx) -#else -#define KUE_LOCK(_sc) -#define KUE_UNLOCK(_sc) -#endif diff --git a/sys/dev/usb/if_rue.c b/sys/dev/usb/if_rue.c deleted file mode 100644 index 4449f7d..0000000 --- a/sys/dev/usb/if_rue.c +++ /dev/null @@ -1,1393 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@FreeBSD.org>. - * Copyright (c) 1997, 1998, 1999, 2000 Bill Paul <wpaul@ee.columbia.edu>. - * 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. - */ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * RealTek RTL8150 USB to fast ethernet controller driver. - * Datasheet is available from - * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net/bpf.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <dev/usb/if_ruereg.h> - -/* "device miibus" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -#ifdef USB_DEBUG -static int ruedebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, rue, CTLFLAG_RW, 0, "USB rue"); -SYSCTL_INT(_hw_usb_rue, OID_AUTO, debug, CTLFLAG_RW, - &ruedebug, 0, "rue debug level"); - -#define DPRINTFN(n, x) do { \ - if (ruedebug > (n)) \ - printf x; \ - } while (0); -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -/* - * Various supported device vendors/products. - */ - -static struct rue_type rue_devs[] = { - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, - { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100 }, - { 0, 0 } -}; - -static device_probe_t rue_match; -static device_attach_t rue_attach; -static device_detach_t rue_detach; -static device_shutdown_t rue_shutdown; -static miibus_readreg_t rue_miibus_readreg; -static miibus_writereg_t rue_miibus_writereg; -static miibus_statchg_t rue_miibus_statchg; - -static int rue_encap(struct rue_softc *, struct mbuf *, int); -#ifdef RUE_INTR_PIPE -static void rue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -#endif -static void rue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void rue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void rue_tick(void *); -static void rue_tick_task(void *); -static void rue_rxstart(struct ifnet *); -static void rue_start(struct ifnet *); -static int rue_ioctl(struct ifnet *, u_long, caddr_t); -static void rue_init(void *); -static void rue_stop(struct rue_softc *); -static void rue_watchdog(struct ifnet *); -static int rue_ifmedia_upd(struct ifnet *); -static void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static void rue_setmulti(struct rue_softc *); -static void rue_reset(struct rue_softc *); - -static int rue_read_mem(struct rue_softc *, u_int16_t, void *, u_int16_t); -static int rue_write_mem(struct rue_softc *, u_int16_t, void *, u_int16_t); -static int rue_csr_read_1(struct rue_softc *, int); -static int rue_csr_write_1(struct rue_softc *, int, u_int8_t); -static int rue_csr_read_2(struct rue_softc *, int); -static int rue_csr_write_2(struct rue_softc *, int, u_int16_t); -static int rue_csr_write_4(struct rue_softc *, int, u_int32_t); - -static device_method_t rue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rue_match), - DEVMETHOD(device_attach, rue_attach), - DEVMETHOD(device_detach, rue_detach), - DEVMETHOD(device_shutdown, rue_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, rue_miibus_readreg), - DEVMETHOD(miibus_writereg, rue_miibus_writereg), - DEVMETHOD(miibus_statchg, rue_miibus_statchg), - - { 0, 0 } -}; - -static driver_t rue_driver = { - "rue", - rue_methods, - sizeof(struct rue_softc) -}; - -static devclass_t rue_devclass; - -DRIVER_MODULE(rue, uhub, rue_driver, rue_devclass, usbd_driver_load, 0); -DRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, 0, 0); -MODULE_DEPEND(rue, usb, 1, 1, 1); -MODULE_DEPEND(rue, ether, 1, 1, 1); -MODULE_DEPEND(rue, miibus, 1, 1, 1); - -#define RUE_SETBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x)) - -#define RUE_CLRBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) & ~(x)) - -#define RUE_SETBIT_2(sc, reg, x) \ - rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) | (x)) - -#define RUE_CLRBIT_2(sc, reg, x) \ - rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) & ~(x)) - -static int -rue_read_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->rue_dying) - return (0); - - RUE_LOCK(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = usbd_do_request(sc->rue_udev, &req, buf); - - RUE_UNLOCK(sc); - - if (err) { - device_printf(sc->rue_dev, "control pipe read failed: %s\n", - usbd_errstr(err)); - return (-1); - } - - return (0); -} - -static int -rue_write_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len) -{ - usb_device_request_t req; - usbd_status err; - - if (sc->rue_dying) - return (0); - - RUE_LOCK(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - err = usbd_do_request(sc->rue_udev, &req, buf); - - RUE_UNLOCK(sc); - - if (err) { - device_printf(sc->rue_dev, "control pipe write failed: %s\n", - usbd_errstr(err)); - return (-1); - } - - return (0); -} - -static int -rue_csr_read_1(struct rue_softc *sc, int reg) -{ - int err; - u_int8_t val = 0; - - err = rue_read_mem(sc, reg, &val, 1); - - if (err) - return (0); - - return (val); -} - -static int -rue_csr_read_2(struct rue_softc *sc, int reg) -{ - int err; - u_int16_t val = 0; - uWord w; - - USETW(w, val); - err = rue_read_mem(sc, reg, &w, 2); - val = UGETW(w); - - if (err) - return (0); - - return (val); -} - -static int -rue_csr_write_1(struct rue_softc *sc, int reg, u_int8_t val) -{ - int err; - - err = rue_write_mem(sc, reg, &val, 1); - - if (err) - return (-1); - - return (0); -} - -static int -rue_csr_write_2(struct rue_softc *sc, int reg, u_int16_t val) -{ - int err; - uWord w; - - USETW(w, val); - err = rue_write_mem(sc, reg, &w, 2); - - if (err) - return (-1); - - return (0); -} - -static int -rue_csr_write_4(struct rue_softc *sc, int reg, u_int32_t val) -{ - int err; - uDWord dw; - - USETDW(dw, val); - err = rue_write_mem(sc, reg, &dw, 4); - - if (err) - return (-1); - - return (0); -} - -static int -rue_miibus_readreg(device_t dev, int phy, int reg) -{ - struct rue_softc *sc = device_get_softc(dev); - int rval; - int ruereg; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - return (0); - break; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rval = rue_csr_read_1(sc, reg); - return (rval); - } - device_printf(sc->rue_dev, "bad phy register\n"); - return (0); - } - - rval = rue_csr_read_2(sc, ruereg); - - return (rval); -} - -static int -rue_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct rue_softc *sc = device_get_softc(dev); - int ruereg; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - return (0); - break; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rue_csr_write_1(sc, reg, data); - return (0); - } - device_printf(sc->rue_dev, "bad phy register\n"); - return (0); - } - rue_csr_write_2(sc, ruereg, data); - - return (0); -} - -static void -rue_miibus_statchg(device_t dev) -{ - /* - * When the code below is enabled the card starts doing weird - * things after link going from UP to DOWN and back UP. - * - * Looks like some of register writes below messes up PHY - * interface. - * - * No visible regressions were found after commenting this code - * out, so that disable it for good. - */ -#if 0 - struct rue_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); - int bmcr; - - RUE_CLRBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); - - bmcr = rue_csr_read_2(sc, RUE_BMCR); - - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) - bmcr |= RUE_BMCR_SPD_SET; - else - bmcr &= ~RUE_BMCR_SPD_SET; - - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) - bmcr |= RUE_BMCR_DUPLEX; - else - bmcr &= ~RUE_BMCR_DUPLEX; - - rue_csr_write_2(sc, RUE_BMCR, bmcr); - - RUE_SETBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); -#endif -} - -/* - * Program the 64-bit multicast hash filter. - */ - -static void -rue_setmulti(struct rue_softc *sc) -{ - struct ifnet *ifp; - int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - struct ifmultiaddr *ifma; - u_int32_t rxcfg; - int mcnt = 0; - - ifp = sc->rue_ifp; - - rxcfg = rue_csr_read_2(sc, RUE_RCR); - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - rxcfg |= (RUE_RCR_AAM | RUE_RCR_AAP); - rxcfg &= ~RUE_RCR_AM; - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, 0xFFFFFFFF); - rue_csr_write_4(sc, RUE_MAR4, 0xFFFFFFFF); - return; - } - - /* first, zot all the existing hash bits */ - rue_csr_write_4(sc, RUE_MAR0, 0); - rue_csr_write_4(sc, RUE_MAR4, 0); - - /* now program new ones */ - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - mcnt++; - } - IF_ADDR_UNLOCK(ifp); - - if (mcnt) - rxcfg |= RUE_RCR_AM; - else - rxcfg &= ~RUE_RCR_AM; - - rxcfg &= ~(RUE_RCR_AAM | RUE_RCR_AAP); - - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, hashes[0]); - rue_csr_write_4(sc, RUE_MAR4, hashes[1]); -} - -static void -rue_reset(struct rue_softc *sc) -{ - int i; - - rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST); - - for (i = 0; i < RUE_TIMEOUT; i++) { - DELAY(500); - if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST)) - break; - } - if (i == RUE_TIMEOUT) - device_printf(sc->rue_dev, "reset never completed!\n"); - - DELAY(10000); -} - -/* - * Probe for a RTL8150 chip. - */ - -static int -rue_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct rue_type *t; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - t = rue_devs; - while (t->rue_vid) { - if (uaa->vendor == t->rue_vid && - uaa->product == t->rue_did) { - return (UMATCH_VENDOR_PRODUCT); - } - t++; - } - - return (UMATCH_NONE); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ - -static int -rue_attach(device_t self) -{ - struct rue_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - u_char eaddr[ETHER_ADDR_LEN]; - struct ifnet *ifp; - usbd_interface_handle iface; - usbd_status err; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - struct rue_type *t; - - sc->rue_dev = self; - sc->rue_udev = uaa->device; - - if (usbd_set_config_no(sc->rue_udev, RUE_CONFIG_NO, 0)) { - device_printf(sc->rue_dev, "getting interface handle failed\n"); - goto error; - } - - usb_init_task(&sc->rue_tick_task, rue_tick_task, sc); - - err = usbd_device2interface_handle(uaa->device, RUE_IFACE_IDX, &iface); - if (err) { - device_printf(sc->rue_dev, "getting interface handle failed\n"); - goto error; - } - - sc->rue_iface = iface; - - t = rue_devs; - while (t->rue_vid) { - if (uaa->vendor == t->rue_vid && - uaa->product == t->rue_did) { - sc->rue_info = t; - break; - } - t++; - } - - id = usbd_get_interface_descriptor(sc->rue_iface); - - /* Find endpoints */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(sc->rue_dev, "couldn't get ep %d\n", i); - goto error; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->rue_ed[RUE_ENDPT_RX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->rue_ed[RUE_ENDPT_TX] = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - sc->rue_ed[RUE_ENDPT_INTR] = ed->bEndpointAddress; - } - } - - mtx_init(&sc->rue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - RUE_LOCK(sc); - - /* Reset the adapter */ - rue_reset(sc); - - /* Get station address from the EEPROM */ - err = rue_read_mem(sc, RUE_EEPROM_IDR0, - (caddr_t)&eaddr, ETHER_ADDR_LEN); - if (err) { - device_printf(sc->rue_dev, "couldn't get station address\n"); - goto error1; - } - - ifp = sc->rue_ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - device_printf(sc->rue_dev, "can not if_alloc()\n"); - goto error1; - } - ifp->if_softc = sc; - if_initname(ifp, "rue", device_get_unit(sc->rue_dev)); - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_ioctl = rue_ioctl; - ifp->if_start = rue_start; - ifp->if_watchdog = rue_watchdog; - ifp->if_init = rue_init; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - - /* MII setup */ - if (mii_phy_probe(self, &sc->rue_miibus, - rue_ifmedia_upd, rue_ifmedia_sts)) { - device_printf(sc->rue_dev, "MII without any PHY!\n"); - goto error2; - } - - sc->rue_qdat.ifp = ifp; - sc->rue_qdat.if_rxstart = rue_rxstart; - - /* Call MI attach routine */ - ether_ifattach(ifp, eaddr); - callout_handle_init(&sc->rue_stat_ch); - usb_register_netisr(); - sc->rue_dying = 0; - - RUE_UNLOCK(sc); - return 0; - - error2: - if_free(ifp); - error1: - RUE_UNLOCK(sc); - mtx_destroy(&sc->rue_mtx); - error: - return ENXIO; -} - -static int -rue_detach(device_t dev) -{ - struct rue_softc *sc; - struct ifnet *ifp; - - sc = device_get_softc(dev); - RUE_LOCK(sc); - ifp = sc->rue_ifp; - - sc->rue_dying = 1; - untimeout(rue_tick, sc, sc->rue_stat_ch); - usb_rem_task(sc->rue_udev, &sc->rue_tick_task); - ether_ifdetach(ifp); - if_free(ifp); - - if (sc->rue_ep[RUE_ENDPT_TX] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (sc->rue_ep[RUE_ENDPT_RX] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]); -#ifdef RUE_INTR_PIPE - if (sc->rue_ep[RUE_ENDPT_INTR] != NULL) - usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]); -#endif - - RUE_UNLOCK(sc); - mtx_destroy(&sc->rue_mtx); - - return (0); -} - -#ifdef RUE_INTR_PIPE -static void -rue_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rue_softc *sc = priv; - struct ifnet *ifp; - struct rue_intrpkt *p; - - RUE_LOCK(sc); - ifp = sc->rue_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - RUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - device_printf(sc->rue_dev, "usb error on intr: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_INTR]); - RUE_UNLOCK(sc); - return; - } - - usbd_get_xfer_status(xfer, NULL, (void **)&p, NULL, NULL); - - ifp->if_ierrors += p->rue_rxlost_cnt; - ifp->if_ierrors += p->rue_crcerr_cnt; - ifp->if_collisions += p->rue_col_cnt; - - RUE_UNLOCK(sc); -} -#endif - -static void -rue_rxstart(struct ifnet *ifp) -{ - struct rue_softc *sc; - struct ue_chain *c; - - sc = ifp->if_softc; - RUE_LOCK(sc); - c = &sc->rue_cdata.ue_rx_chain[sc->rue_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", device_get_nameunit(sc->rue_dev)); - ifp->if_ierrors++; - RUE_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(c->ue_xfer); - - RUE_UNLOCK(sc); -} - -/* - * A frame has been uploaded: pass the resulting mbuf chain up to - * the higher level protocols. - */ - -static void -rue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct rue_softc *sc = c->ue_sc; - struct mbuf *m; - struct ifnet *ifp; - int total_len = 0; - struct rue_rxpkt r; - - if (sc->rue_dying) - return; - RUE_LOCK(sc); - ifp = sc->rue_ifp; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - RUE_UNLOCK(sc); - return; - } - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - if (usbd_ratecheck(&sc->rue_rx_notice)) - device_printf(sc->rue_dev, "usb error on rx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_RX]); - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - if (total_len <= ETHER_CRC_LEN) { - ifp->if_ierrors++; - goto done; - } - - m = c->ue_mbuf; - bcopy(mtod(m, char *) + total_len - 4, (char *)&r, sizeof (r)); - - /* Check recieve packet was valid or not */ - if ((r.rue_rxstat & RUE_RXSTAT_VALID) == 0) { - ifp->if_ierrors++; - goto done; - } - - /* No errors; receive the packet. */ - total_len -= ETHER_CRC_LEN; - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = (void *)&sc->rue_qdat; - m->m_pkthdr.len = m->m_len = total_len; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - - RUE_UNLOCK(sc); - return; - - done: - /* Setup new transfer. */ - usbd_setup_xfer(xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(xfer); - RUE_UNLOCK(sc); -} - -/* - * A frame was downloaded to the chip. It's safe for us to clean up - * the list buffers. - */ - -static void -rue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct rue_softc *sc = c->ue_sc; - struct ifnet *ifp; - usbd_status err; - - RUE_LOCK(sc); - - ifp = sc->rue_ifp; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - RUE_UNLOCK(sc); - return; - } - device_printf(sc->rue_dev, "usb error on tx: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_TX]); - RUE_UNLOCK(sc); - return; - } - - ifp->if_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); - - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; - } - - if (err) - ifp->if_oerrors++; - else - ifp->if_opackets++; - - RUE_UNLOCK(sc); -} - -static void -rue_tick(void *xsc) -{ - struct rue_softc *sc = xsc; - - if (sc == NULL) - return; - if (sc->rue_dying) - return; - - /* Perform periodic stuff in process context */ - usb_add_task(sc->rue_udev, &sc->rue_tick_task, USB_TASKQ_DRIVER); -} - -static void -rue_tick_task(void *xsc) -{ - struct rue_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; - - if (sc == NULL) - return; - - RUE_LOCK(sc); - - ifp = sc->rue_ifp; - mii = GET_MII(sc); - if (mii == NULL) { - RUE_UNLOCK(sc); - return; - } - - mii_tick(mii); - if (!sc->rue_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->rue_link++; - if (ifp->if_snd.ifq_head != NULL) - rue_start(ifp); - } - - sc->rue_stat_ch = timeout(rue_tick, sc, hz); - - RUE_UNLOCK(sc); -} - -static int -rue_encap(struct rue_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct ue_chain *c; - usbd_status err; - - c = &sc->rue_cdata.ue_tx_chain[idx]; - - /* - * Copy the mbuf data into a contiguous buffer - */ - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf); - c->ue_mbuf = m; - - total_len = m->m_pkthdr.len; - - /* - * This is an undocumented behavior. - * RTL8150 chip doesn't send frame length smaller than - * RUE_MIN_FRAMELEN (60) byte packet. - */ - if (total_len < RUE_MIN_FRAMELEN) - total_len = RUE_MIN_FRAMELEN; - - usbd_setup_xfer(c->ue_xfer, sc->rue_ep[RUE_ENDPT_TX], - c, c->ue_buf, total_len, USBD_FORCE_SHORT_XFER, - 10000, rue_txeof); - - /* Transmit */ - err = usbd_transfer(c->ue_xfer); - if (err != USBD_IN_PROGRESS) { - rue_stop(sc); - return (EIO); - } - - sc->rue_cdata.ue_tx_cnt++; - - return (0); -} - -static void -rue_start(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - RUE_LOCK(sc); - - if (!sc->rue_link) { - RUE_UNLOCK(sc); - return; - } - - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { - RUE_UNLOCK(sc); - return; - } - - IF_DEQUEUE(&ifp->if_snd, m_head); - if (m_head == NULL) { - RUE_UNLOCK(sc); - return; - } - - if (rue_encap(sc, m_head, 0)) { - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - RUE_UNLOCK(sc); - return; - } - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ - BPF_MTAP(ifp, m_head); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; - - RUE_UNLOCK(sc); -} - -static void -rue_init(void *xsc) -{ - struct rue_softc *sc = xsc; - struct ifnet *ifp = sc->rue_ifp; - struct mii_data *mii = GET_MII(sc); - struct ue_chain *c; - usbd_status err; - int i; - int rxcfg; - - RUE_LOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - RUE_UNLOCK(sc); - return; - } - - /* - * Cancel pending I/O and free all RX/TX buffers. - */ - rue_reset(sc); - - /* Set MAC address */ - rue_write_mem(sc, RUE_IDR0, IF_LLADDR(sc->rue_ifp), - ETHER_ADDR_LEN); - - /* Init TX ring. */ - if (usb_ether_tx_list_init(sc, &sc->rue_cdata, - sc->rue_udev) == ENOBUFS) { - device_printf(sc->rue_dev, "tx list init failed\n"); - RUE_UNLOCK(sc); - return; - } - - /* Init RX ring. */ - if (usb_ether_rx_list_init(sc, &sc->rue_cdata, - sc->rue_udev) == ENOBUFS) { - device_printf(sc->rue_dev, "rx list init failed\n"); - RUE_UNLOCK(sc); - return; - } - -#ifdef RUE_INTR_PIPE - sc->rue_cdata.ue_ibuf = malloc(RUE_INTR_PKTLEN, M_USBDEV, M_NOWAIT); -#endif - - /* - * Set the initial TX and RX configuration. - */ - rue_csr_write_1(sc, RUE_TCR, RUE_TCR_CONFIG); - - rxcfg = RUE_RCR_CONFIG; - - /* Set capture broadcast bit to capture broadcast frames. */ - if (ifp->if_flags & IFF_BROADCAST) - rxcfg |= RUE_RCR_AB; - else - rxcfg &= ~RUE_RCR_AB; - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - rxcfg |= RUE_RCR_AAP; - else - rxcfg &= ~RUE_RCR_AAP; - - rue_csr_write_2(sc, RUE_RCR, rxcfg); - - /* Load the multicast filter. */ - rue_setmulti(sc); - - /* Enable RX and TX */ - rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN)); - - mii_mediachg(mii); - - /* Open RX and TX pipes. */ - err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_RX], - USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - device_printf(sc->rue_dev, "open rx pipe failed: %s\n", - usbd_errstr(err)); - RUE_UNLOCK(sc); - return; - } - err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_TX], - USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - device_printf(sc->rue_dev, "open tx pipe failed: %s\n", - usbd_errstr(err)); - RUE_UNLOCK(sc); - return; - } - -#ifdef RUE_INTR_PIPE - err = usbd_open_pipe_intr(sc->rue_iface, sc->rue_ed[RUE_ENDPT_INTR], - USBD_SHORT_XFER_OK, - &sc->rue_ep[RUE_ENDPT_INTR], sc, - sc->rue_cdata.ue_ibuf, RUE_INTR_PKTLEN, - rue_intr, RUE_INTR_INTERVAL); - if (err) { - device_printf(sc->rue_dev, "open intr pipe failed: %s\n", - usbd_errstr(err)); - RUE_UNLOCK(sc); - return; - } -#endif - - /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->rue_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->rue_ep[RUE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof); - usbd_transfer(c->ue_xfer); - } - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - sc->rue_stat_ch = timeout(rue_tick, sc, hz); - - RUE_UNLOCK(sc); -} - -/* - * Set media options. - */ - -static int -rue_ifmedia_upd(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - sc->rue_link = 0; - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH (miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } - mii_mediachg(mii); - - return (0); -} - -/* - * Report current media status. - */ - -static void -rue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; -} - -static int -rue_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct rue_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; - int error = 0; - - RUE_LOCK(sc); - - switch (command) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->rue_if_flags & IFF_PROMISC)) { - RUE_SETBIT_2(sc, RUE_RCR, - (RUE_RCR_AAM | RUE_RCR_AAP)); - rue_setmulti(sc); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->rue_if_flags & IFF_PROMISC) { - RUE_CLRBIT_2(sc, RUE_RCR, - (RUE_RCR_AAM | RUE_RCR_AAP)); - rue_setmulti(sc); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - rue_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - rue_stop(sc); - } - sc->rue_if_flags = ifp->if_flags; - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - rue_setmulti(sc); - error = 0; - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - mii = GET_MII(sc); - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); - break; - default: - error = ether_ioctl(ifp, command, data); - break; - } - - RUE_UNLOCK(sc); - - return (error); -} - -static void -rue_watchdog(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct ue_chain *c; - usbd_status stat; - - RUE_LOCK(sc); - - ifp->if_oerrors++; - device_printf(sc->rue_dev, "watchdog timeout\n"); - - c = &sc->rue_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - rue_txeof(c->ue_xfer, c, stat); - - if (ifp->if_snd.ifq_head != NULL) - rue_start(ifp); - - RUE_UNLOCK(sc); -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ - -static void -rue_stop(struct rue_softc *sc) -{ - usbd_status err; - struct ifnet *ifp; - - RUE_LOCK(sc); - - ifp = sc->rue_ifp; - ifp->if_timer = 0; - - rue_csr_write_1(sc, RUE_CR, 0x00); - rue_reset(sc); - - untimeout(rue_tick, sc, sc->rue_stat_ch); - - /* Stop transfers. */ - if (sc->rue_ep[RUE_ENDPT_RX] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - device_printf(sc->rue_dev, "abort rx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_RX]); - if (err) { - device_printf(sc->rue_dev, "close rx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_RX] = NULL; - } - - if (sc->rue_ep[RUE_ENDPT_TX] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - device_printf(sc->rue_dev, "abort tx pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_TX]); - if (err) { - device_printf(sc->rue_dev, "close tx pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_TX] = NULL; - } - -#ifdef RUE_INTR_PIPE - if (sc->rue_ep[RUE_ENDPT_INTR] != NULL) { - err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]); - if (err) { - device_printf(sc->rue_dev, "abort intr pipe failed: %s\n", - usbd_errstr(err)); - } - err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_INTR]); - if (err) { - device_printf(sc->rue_dev, "close intr pipe failed: %s\n", - usbd_errstr(err)); - } - sc->rue_ep[RUE_ENDPT_INTR] = NULL; - } -#endif - - /* Free RX resources. */ - usb_ether_rx_list_free(&sc->rue_cdata); - /* Free TX resources. */ - usb_ether_tx_list_free(&sc->rue_cdata); - -#ifdef RUE_INTR_PIPE - free(sc->rue_cdata.ue_ibuf, M_USBDEV); - sc->rue_cdata.ue_ibuf = NULL; -#endif - - sc->rue_link = 0; - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - RUE_UNLOCK(sc); -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ - -static int -rue_shutdown(device_t dev) -{ - struct rue_softc *sc; - - sc = device_get_softc(dev); - - sc->rue_dying++; - RUE_LOCK(sc); - rue_reset(sc); - rue_stop(sc); - RUE_UNLOCK(sc); - - return (0); -} diff --git a/sys/dev/usb/if_ruereg.h b/sys/dev/usb/if_ruereg.h deleted file mode 100644 index da6470f..0000000 --- a/sys/dev/usb/if_ruereg.h +++ /dev/null @@ -1,226 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@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$ - */ - -#ifndef _IF_RUEREG_H_ -#define _IF_RUEREG_H_ - -#define RUE_INTR_PIPE 1 /* Use INTR PIPE */ - -#define RUE_CONFIG_NO 1 -#define RUE_IFACE_IDX 0 - -#define RUE_ENDPT_RX 0x0 -#define RUE_ENDPT_TX 0x1 -#define RUE_ENDPT_INTR 0x2 -#define RUE_ENDPT_MAX 0x3 - -#define RUE_INTR_PKTLEN 0x8 - -#define RUE_TIMEOUT 1000 -#define ETHER_ALIGN 2 -#define RUE_MIN_FRAMELEN 60 -#define RUE_INTR_INTERVAL 100 /* ms */ - -/* - * Registers - */ - -#define RUE_IDR0 0x0120 -#define RUE_IDR1 0x0121 -#define RUE_IDR2 0x0122 -#define RUE_IDR3 0x0123 -#define RUE_IDR4 0x0124 -#define RUE_IDR5 0x0125 - -#define RUE_MAR0 0x0126 -#define RUE_MAR1 0x0127 -#define RUE_MAR2 0x0128 -#define RUE_MAR3 0x0129 -#define RUE_MAR4 0x012A -#define RUE_MAR5 0x012B -#define RUE_MAR6 0x012C -#define RUE_MAR7 0x012D - -#define RUE_CR 0x012E /* B, R/W */ -#define RUE_CR_SOFT_RST 0x10 -#define RUE_CR_RE 0x08 -#define RUE_CR_TE 0x04 -#define RUE_CR_EP3CLREN 0x02 - -#define RUE_TCR 0x012F /* B, R/W */ -#define RUE_TCR_TXRR1 0x80 -#define RUE_TCR_TXRR0 0x40 -#define RUE_TCR_IFG1 0x10 -#define RUE_TCR_IFG0 0x08 -#define RUE_TCR_NOCRC 0x01 -#define RUE_TCR_CONFIG (RUE_TCR_TXRR1|RUE_TCR_TXRR0|RUE_TCR_IFG1|RUE_TCR_IFG0) - -#define RUE_RCR 0x0130 /* W, R/W */ -#define RUE_RCR_TAIL 0x80 -#define RUE_RCR_AER 0x40 -#define RUE_RCR_AR 0x20 -#define RUE_RCR_AM 0x10 -#define RUE_RCR_AB 0x08 -#define RUE_RCR_AD 0x04 -#define RUE_RCR_AAM 0x02 -#define RUE_RCR_AAP 0x01 -#define RUE_RCR_CONFIG (RUE_RCR_TAIL|RUE_RCR_AD) - -#define RUE_TSR 0x0132 -#define RUE_RSR 0x0133 -#define RUE_CON0 0x0135 -#define RUE_CON1 0x0136 -#define RUE_MSR 0x0137 -#define RUE_PHYADD 0x0138 -#define RUE_PHYDAT 0x0139 - -#define RUE_PHYCNT 0x013B /* B, R/W */ -#define RUE_PHYCNT_PHYOWN 0x40 -#define RUE_PHYCNT_RWCR 0x20 - -#define RUE_GPPC 0x013D -#define RUE_WAKECNT 0x013E - -#define RUE_BMCR 0x0140 -#define RUE_BMCR_SPD_SET 0x2000 -#define RUE_BMCR_DUPLEX 0x0100 - -#define RUE_BMSR 0x0142 - -#define RUE_ANAR 0x0144 /* W, R/W */ -#define RUE_ANAR_PAUSE 0x0400 - -#define RUE_ANLP 0x0146 /* W, R/O */ -#define RUE_ANLP_PAUSE 0x0400 - -#define RUE_AER 0x0148 - -#define RUE_NWAYT 0x014A -#define RUE_CSCR 0x014C - -#define RUE_CRC0 0x014E -#define RUE_CRC1 0x0150 -#define RUE_CRC2 0x0152 -#define RUE_CRC3 0x0154 -#define RUE_CRC4 0x0156 - -#define RUE_BYTEMASK0 0x0158 -#define RUE_BYTEMASK1 0x0160 -#define RUE_BYTEMASK2 0x0168 -#define RUE_BYTEMASK3 0x0170 -#define RUE_BYTEMASK4 0x0178 - -#define RUE_PHY1 0x0180 -#define RUE_PHY2 0x0184 - -#define RUE_TW1 0x0186 - -#define RUE_REG_MIN 0x0120 -#define RUE_REG_MAX 0x0189 - -/* - * EEPROM address declarations - */ - -#define RUE_EEPROM_BASE 0x1200 - -#define RUE_EEPROM_IDR0 (RUE_EEPROM_BASE + 0x02) -#define RUE_EEPROM_IDR1 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR2 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR3 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR4 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR5 (RUE_EEPROM_BASE + 0x03) - -#define RUE_EEPROM_INTERVAL (RUE_EEPROM_BASE + 0x17) - -struct rue_intrpkt { - u_int8_t rue_tsr; - u_int8_t rue_rsr; - u_int8_t rue_gep_msr; - u_int8_t rue_waksr; - u_int8_t rue_txok_cnt; - u_int8_t rue_rxlost_cnt; - u_int8_t rue_crcerr_cnt; - u_int8_t rue_col_cnt; -}; - -struct rue_rxpkt { - u_int16_t rue_pktlen : 12; - u_int16_t rue_rxstat : 4; -}; - -#define RUE_RXSTAT_VALID 0x01 -#define RUE_RXSTAT_RUNT 0x02 -#define RUE_RXSTAT_PMATCH 0x04 -#define RUE_RXSTAT_MCAST 0x08 - -#define RUE_RXSTAT_MASK RUE_RXSTAT_VALID - -struct rue_type { - u_int16_t rue_vid; - u_int16_t rue_did; -}; - -struct rue_softc { - struct ifnet *rue_ifp; - device_t rue_dev; - device_t rue_miibus; - usbd_device_handle rue_udev; - usbd_interface_handle rue_iface; - struct rue_type *rue_info; - int rue_ed[RUE_ENDPT_MAX]; - usbd_pipe_handle rue_ep[RUE_ENDPT_MAX]; - int rue_unit; - u_int8_t rue_link; - int rue_if_flags; - struct ue_cdata rue_cdata; - struct callout_handle rue_stat_ch; - struct mtx rue_mtx; - char rue_dying; - struct timeval rue_rx_notice; - struct usb_qdat rue_qdat; - struct usb_task rue_tick_task; -}; - -#if defined(__FreeBSD__) -#define GET_MII(sc) (device_get_softc((sc)->rue_miibus)) -#elif defined(__NetBSD__) -#define GET_MII(sc) (&(sc)->rue_mii) -#elif defined(__OpenBSD__) -#define GET_MII(sc) (&(sc)->rue_mii) -#endif - -#if 0 -#define RUE_LOCK(_sc) mtx_lock(&(_sc)->rue_mtx) -#define RUE_UNLOCK(_sc) mtx_unlock(&(_sc)->rue_mtx) -#else -#define RUE_LOCK(_sc) -#define RUE_UNLOCK(_sc) -#endif - -#endif /* _IF_RUEREG_H_ */ diff --git a/sys/dev/usb/if_rum.c b/sys/dev/usb/if_rum.c deleted file mode 100644 index c0c7cb6..0000000 --- a/sys/dev/usb/if_rum.c +++ /dev/null @@ -1,2560 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini@free.fr> - * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Ralink Technology RT2501USB/RT2601USB chipset driver - * http://www.ralinktech.com.tw/ - */ - -#include <sys/param.h> -#include <sys/sysctl.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/endian.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_phy.h> -#include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_regdomain.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/if_rumreg.h> -#include <dev/usb/if_rumvar.h> -#include <dev/usb/rt2573_ucode.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) do { if (rumdebug > 0) printf x; } while (0) -#define DPRINTFN(n, x) do { if (rumdebug >= (n)) printf x; } while (0) -int rumdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, rum, CTLFLAG_RW, 0, "USB rum"); -SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rumdebug, 0, - "rum debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) -#endif - -/* various supported device vendors/products */ -static const struct usb_devno rum_devs[] = { - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4 }, - { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700 }, - { USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO }, - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1 }, - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3 }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR }, - { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2 }, - { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL }, - { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX }, - { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F }, - { USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111 }, - { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110 }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS }, - { USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573 }, - { USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573 }, - { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB }, - { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP }, - { USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HG }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4 }, - { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573 }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2 }, - { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM }, - { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573 }, - { USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671 }, - { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2 }, - { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172 }, - { USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573 }, - { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573 } -}; - -MODULE_DEPEND(rum, wlan, 1, 1, 1); -MODULE_DEPEND(rum, wlan_amrr, 1, 1, 1); -MODULE_DEPEND(rum, usb, 1, 1, 1); - -static struct ieee80211vap *rum_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, int opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void rum_vap_delete(struct ieee80211vap *); -static int rum_alloc_tx_list(struct rum_softc *); -static void rum_free_tx_list(struct rum_softc *); -static int rum_alloc_rx_list(struct rum_softc *); -static void rum_free_rx_list(struct rum_softc *); -static void rum_task(void *); -static void rum_scantask(void *); -static int rum_newstate(struct ieee80211vap *, - enum ieee80211_state, int); -static void rum_txeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void rum_rxeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void rum_setup_tx_desc(struct rum_softc *, - struct rum_tx_desc *, uint32_t, uint16_t, int, - int); -static int rum_tx_mgt(struct rum_softc *, struct mbuf *, - struct ieee80211_node *); -static int rum_tx_raw(struct rum_softc *, struct mbuf *, - struct ieee80211_node *, - const struct ieee80211_bpf_params *); -static int rum_tx_data(struct rum_softc *, struct mbuf *, - struct ieee80211_node *); -static void rum_start(struct ifnet *); -static void rum_watchdog(void *); -static int rum_ioctl(struct ifnet *, u_long, caddr_t); -static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, - int); -static uint32_t rum_read(struct rum_softc *, uint16_t); -static void rum_read_multi(struct rum_softc *, uint16_t, void *, - int); -static void rum_write(struct rum_softc *, uint16_t, uint32_t); -static void rum_write_multi(struct rum_softc *, uint16_t, void *, - size_t); -static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t); -static uint8_t rum_bbp_read(struct rum_softc *, uint8_t); -static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t); -static void rum_select_antenna(struct rum_softc *); -static void rum_enable_mrr(struct rum_softc *); -static void rum_set_txpreamble(struct rum_softc *); -static void rum_set_basicrates(struct rum_softc *); -static void rum_select_band(struct rum_softc *, - struct ieee80211_channel *); -static void rum_set_chan(struct rum_softc *, - struct ieee80211_channel *); -static void rum_enable_tsf_sync(struct rum_softc *); -static void rum_update_slot(struct ifnet *); -static void rum_set_bssid(struct rum_softc *, const uint8_t *); -static void rum_set_macaddr(struct rum_softc *, const uint8_t *); -static void rum_update_promisc(struct rum_softc *); -static const char *rum_get_rf(int); -static void rum_read_eeprom(struct rum_softc *); -static int rum_bbp_init(struct rum_softc *); -static void rum_init_locked(struct rum_softc *); -static void rum_init(void *); -static void rum_stop(void *); -static int rum_load_microcode(struct rum_softc *, const u_char *, - size_t); -static int rum_prepare_beacon(struct rum_softc *, - struct ieee80211vap *); -static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static struct ieee80211_node *rum_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void rum_newassoc(struct ieee80211_node *, int); -static void rum_scan_start(struct ieee80211com *); -static void rum_scan_end(struct ieee80211com *); -static void rum_set_channel(struct ieee80211com *); -static int rum_get_rssi(struct rum_softc *, uint8_t); -static void rum_amrr_start(struct rum_softc *, - struct ieee80211_node *); -static void rum_amrr_timeout(void *); -static void rum_amrr_update(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -static const struct { - uint32_t reg; - uint32_t val; -} rum_def_mac[] = { - { RT2573_TXRX_CSR0, 0x025fb032 }, - { RT2573_TXRX_CSR1, 0x9eaa9eaf }, - { RT2573_TXRX_CSR2, 0x8a8b8c8d }, - { RT2573_TXRX_CSR3, 0x00858687 }, - { RT2573_TXRX_CSR7, 0x2e31353b }, - { RT2573_TXRX_CSR8, 0x2a2a2a2c }, - { RT2573_TXRX_CSR15, 0x0000000f }, - { RT2573_MAC_CSR6, 0x00000fff }, - { RT2573_MAC_CSR8, 0x016c030a }, - { RT2573_MAC_CSR10, 0x00000718 }, - { RT2573_MAC_CSR12, 0x00000004 }, - { RT2573_MAC_CSR13, 0x00007f00 }, - { RT2573_SEC_CSR0, 0x00000000 }, - { RT2573_SEC_CSR1, 0x00000000 }, - { RT2573_SEC_CSR5, 0x00000000 }, - { RT2573_PHY_CSR1, 0x000023b0 }, - { RT2573_PHY_CSR5, 0x00040a06 }, - { RT2573_PHY_CSR6, 0x00080606 }, - { RT2573_PHY_CSR7, 0x00000408 }, - { RT2573_AIFSN_CSR, 0x00002273 }, - { RT2573_CWMIN_CSR, 0x00002344 }, - { RT2573_CWMAX_CSR, 0x000034aa } -}; - -static const struct { - uint8_t reg; - uint8_t val; -} rum_def_bbp[] = { - { 3, 0x80 }, - { 15, 0x30 }, - { 17, 0x20 }, - { 21, 0xc8 }, - { 22, 0x38 }, - { 23, 0x06 }, - { 24, 0xfe }, - { 25, 0x0a }, - { 26, 0x0d }, - { 32, 0x0b }, - { 34, 0x12 }, - { 37, 0x07 }, - { 39, 0xf8 }, - { 41, 0x60 }, - { 53, 0x10 }, - { 54, 0x18 }, - { 60, 0x10 }, - { 61, 0x04 }, - { 62, 0x04 }, - { 75, 0xfe }, - { 86, 0xfe }, - { 88, 0xfe }, - { 90, 0x0f }, - { 99, 0x00 }, - { 102, 0x16 }, - { 107, 0x04 } -}; - -static const struct rfprog { - uint8_t chan; - uint32_t r1, r2, r3, r4; -} rum_rf5226[] = { - { 1, 0x00b03, 0x001e1, 0x1a014, 0x30282 }, - { 2, 0x00b03, 0x001e1, 0x1a014, 0x30287 }, - { 3, 0x00b03, 0x001e2, 0x1a014, 0x30282 }, - { 4, 0x00b03, 0x001e2, 0x1a014, 0x30287 }, - { 5, 0x00b03, 0x001e3, 0x1a014, 0x30282 }, - { 6, 0x00b03, 0x001e3, 0x1a014, 0x30287 }, - { 7, 0x00b03, 0x001e4, 0x1a014, 0x30282 }, - { 8, 0x00b03, 0x001e4, 0x1a014, 0x30287 }, - { 9, 0x00b03, 0x001e5, 0x1a014, 0x30282 }, - { 10, 0x00b03, 0x001e5, 0x1a014, 0x30287 }, - { 11, 0x00b03, 0x001e6, 0x1a014, 0x30282 }, - { 12, 0x00b03, 0x001e6, 0x1a014, 0x30287 }, - { 13, 0x00b03, 0x001e7, 0x1a014, 0x30282 }, - { 14, 0x00b03, 0x001e8, 0x1a014, 0x30284 }, - - { 34, 0x00b03, 0x20266, 0x36014, 0x30282 }, - { 38, 0x00b03, 0x20267, 0x36014, 0x30284 }, - { 42, 0x00b03, 0x20268, 0x36014, 0x30286 }, - { 46, 0x00b03, 0x20269, 0x36014, 0x30288 }, - - { 36, 0x00b03, 0x00266, 0x26014, 0x30288 }, - { 40, 0x00b03, 0x00268, 0x26014, 0x30280 }, - { 44, 0x00b03, 0x00269, 0x26014, 0x30282 }, - { 48, 0x00b03, 0x0026a, 0x26014, 0x30284 }, - { 52, 0x00b03, 0x0026b, 0x26014, 0x30286 }, - { 56, 0x00b03, 0x0026c, 0x26014, 0x30288 }, - { 60, 0x00b03, 0x0026e, 0x26014, 0x30280 }, - { 64, 0x00b03, 0x0026f, 0x26014, 0x30282 }, - - { 100, 0x00b03, 0x0028a, 0x2e014, 0x30280 }, - { 104, 0x00b03, 0x0028b, 0x2e014, 0x30282 }, - { 108, 0x00b03, 0x0028c, 0x2e014, 0x30284 }, - { 112, 0x00b03, 0x0028d, 0x2e014, 0x30286 }, - { 116, 0x00b03, 0x0028e, 0x2e014, 0x30288 }, - { 120, 0x00b03, 0x002a0, 0x2e014, 0x30280 }, - { 124, 0x00b03, 0x002a1, 0x2e014, 0x30282 }, - { 128, 0x00b03, 0x002a2, 0x2e014, 0x30284 }, - { 132, 0x00b03, 0x002a3, 0x2e014, 0x30286 }, - { 136, 0x00b03, 0x002a4, 0x2e014, 0x30288 }, - { 140, 0x00b03, 0x002a6, 0x2e014, 0x30280 }, - - { 149, 0x00b03, 0x002a8, 0x2e014, 0x30287 }, - { 153, 0x00b03, 0x002a9, 0x2e014, 0x30289 }, - { 157, 0x00b03, 0x002ab, 0x2e014, 0x30281 }, - { 161, 0x00b03, 0x002ac, 0x2e014, 0x30283 }, - { 165, 0x00b03, 0x002ad, 0x2e014, 0x30285 } -}, rum_rf5225[] = { - { 1, 0x00b33, 0x011e1, 0x1a014, 0x30282 }, - { 2, 0x00b33, 0x011e1, 0x1a014, 0x30287 }, - { 3, 0x00b33, 0x011e2, 0x1a014, 0x30282 }, - { 4, 0x00b33, 0x011e2, 0x1a014, 0x30287 }, - { 5, 0x00b33, 0x011e3, 0x1a014, 0x30282 }, - { 6, 0x00b33, 0x011e3, 0x1a014, 0x30287 }, - { 7, 0x00b33, 0x011e4, 0x1a014, 0x30282 }, - { 8, 0x00b33, 0x011e4, 0x1a014, 0x30287 }, - { 9, 0x00b33, 0x011e5, 0x1a014, 0x30282 }, - { 10, 0x00b33, 0x011e5, 0x1a014, 0x30287 }, - { 11, 0x00b33, 0x011e6, 0x1a014, 0x30282 }, - { 12, 0x00b33, 0x011e6, 0x1a014, 0x30287 }, - { 13, 0x00b33, 0x011e7, 0x1a014, 0x30282 }, - { 14, 0x00b33, 0x011e8, 0x1a014, 0x30284 }, - - { 34, 0x00b33, 0x01266, 0x26014, 0x30282 }, - { 38, 0x00b33, 0x01267, 0x26014, 0x30284 }, - { 42, 0x00b33, 0x01268, 0x26014, 0x30286 }, - { 46, 0x00b33, 0x01269, 0x26014, 0x30288 }, - - { 36, 0x00b33, 0x01266, 0x26014, 0x30288 }, - { 40, 0x00b33, 0x01268, 0x26014, 0x30280 }, - { 44, 0x00b33, 0x01269, 0x26014, 0x30282 }, - { 48, 0x00b33, 0x0126a, 0x26014, 0x30284 }, - { 52, 0x00b33, 0x0126b, 0x26014, 0x30286 }, - { 56, 0x00b33, 0x0126c, 0x26014, 0x30288 }, - { 60, 0x00b33, 0x0126e, 0x26014, 0x30280 }, - { 64, 0x00b33, 0x0126f, 0x26014, 0x30282 }, - - { 100, 0x00b33, 0x0128a, 0x2e014, 0x30280 }, - { 104, 0x00b33, 0x0128b, 0x2e014, 0x30282 }, - { 108, 0x00b33, 0x0128c, 0x2e014, 0x30284 }, - { 112, 0x00b33, 0x0128d, 0x2e014, 0x30286 }, - { 116, 0x00b33, 0x0128e, 0x2e014, 0x30288 }, - { 120, 0x00b33, 0x012a0, 0x2e014, 0x30280 }, - { 124, 0x00b33, 0x012a1, 0x2e014, 0x30282 }, - { 128, 0x00b33, 0x012a2, 0x2e014, 0x30284 }, - { 132, 0x00b33, 0x012a3, 0x2e014, 0x30286 }, - { 136, 0x00b33, 0x012a4, 0x2e014, 0x30288 }, - { 140, 0x00b33, 0x012a6, 0x2e014, 0x30280 }, - - { 149, 0x00b33, 0x012a8, 0x2e014, 0x30287 }, - { 153, 0x00b33, 0x012a9, 0x2e014, 0x30289 }, - { 157, 0x00b33, 0x012ab, 0x2e014, 0x30281 }, - { 161, 0x00b33, 0x012ac, 0x2e014, 0x30283 }, - { 165, 0x00b33, 0x012ad, 0x2e014, 0x30285 } -}; - -static int -rum_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(rum_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -rum_attach(device_t self) -{ - struct rum_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ieee80211com *ic; - struct ifnet *ifp; - const uint8_t *ucode = NULL; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i, ntries, size; - uint8_t bands; - uint32_t tmp; - - sc->sc_udev = uaa->device; - sc->sc_dev = self; - - if (usbd_set_config_no(sc->sc_udev, RT2573_CONFIG_NO, 0) != 0) { - device_printf(self, "could not set configuration no\n"); - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, RT2573_IFACE_INDEX, - &sc->sc_iface); - if (error != 0) { - device_printf(self, "could not get interface handle\n"); - return ENXIO; - } - - /* - * Find endpoints. - */ - id = usbd_get_interface_descriptor(sc->sc_iface); - - sc->sc_rx_no = sc->sc_tx_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - device_printf(self, - "no endpoint descriptor for iface %d\n", i); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_rx_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_tx_no = ed->bEndpointAddress; - } - if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { - device_printf(self, "missing endpoint\n"); - return ENXIO; - } - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(self, "can not if_alloc()\n"); - return ENXIO; - } - ic = ifp->if_l2com; - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - - usb_init_task(&sc->sc_task, rum_task, sc); - usb_init_task(&sc->sc_scantask, rum_scantask, sc); - callout_init(&sc->watchdog_ch, 0); - - /* retrieve RT2573 rev. no */ - for (ntries = 0; ntries < 1000; ntries++) { - if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0) - break; - DELAY(1000); - } - if (ntries == 1000) { - device_printf(self, "timeout waiting for chip to settle\n"); - goto bad; - } - - /* retrieve MAC address and various other things from EEPROM */ - rum_read_eeprom(sc); - - device_printf(self, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", - tmp, rum_get_rf(sc->rf_rev)); - - ucode = rt2573_ucode; - size = sizeof rt2573_ucode; - error = rum_load_microcode(sc, ucode, size); - if (error != 0) { - device_printf(self, "could not load 8051 microcode\n"); - goto bad; - } - - ifp->if_softc = sc; - if_initname(ifp, "rum", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ - ifp->if_init = rum_init; - ifp->if_ioctl = rum_ioctl; - ifp->if_start = rum_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - ic->ic_ifp = ifp; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode supported */ - | IEEE80211_C_IBSS /* IBSS mode supported */ - | IEEE80211_C_MONITOR /* monitor mode supported */ - | IEEE80211_C_HOSTAP /* HostAp mode supported */ - | IEEE80211_C_TXPMGT /* tx power management */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* bg scanning supported */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) - setbit(&bands, IEEE80211_MODE_11A); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic); - ic->ic_newassoc = rum_newassoc; - ic->ic_raw_xmit = rum_raw_xmit; - ic->ic_node_alloc = rum_node_alloc; - ic->ic_scan_start = rum_scan_start; - ic->ic_scan_end = rum_scan_end; - ic->ic_set_channel = rum_set_channel; - - ic->ic_vap_create = rum_vap_create; - ic->ic_vap_delete = rum_vap_delete; - - sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); - - bpfattach(ifp, DLT_IEEE802_11_RADIO, - sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap)); - - sc->sc_rxtap_len = sizeof sc->sc_rxtap; - sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); - sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2573_RX_RADIOTAP_PRESENT); - - sc->sc_txtap_len = sizeof sc->sc_txtap; - sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); - sc->sc_txtap.wt_ihdr.it_present = htole32(RT2573_TX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - return 0; -bad: - mtx_destroy(&sc->sc_mtx); - if_free(ifp); - return ENXIO; -} - -static int -rum_detach(device_t self) -{ - struct rum_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - rum_stop(sc); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - callout_stop(&sc->watchdog_ch); - - if (sc->amrr_xfer != NULL) { - usbd_free_xfer(sc->amrr_xfer); - sc->amrr_xfer = NULL; - } - - if (sc->sc_rx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_rx_pipeh); - usbd_close_pipe(sc->sc_rx_pipeh); - } - if (sc->sc_tx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_tx_pipeh); - usbd_close_pipe(sc->sc_tx_pipeh); - } - - rum_free_rx_list(sc); - rum_free_tx_list(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - - return 0; -} - -static struct ieee80211vap * -rum_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, int opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rum_vap *rvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return NULL; - vap = &rvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - rvp->newstate = vap->iv_newstate; - vap->iv_newstate = rum_newstate; - - callout_init(&rvp->amrr_ch, 0); - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); - ic->ic_opmode = opmode; - return vap; -} - -static void -rum_vap_delete(struct ieee80211vap *vap) -{ - struct rum_vap *rvp = RUM_VAP(vap); - - callout_stop(&rvp->amrr_ch); - ieee80211_amrr_cleanup(&rvp->amrr); - ieee80211_vap_detach(vap); - free(rvp, M_80211_VAP); -} - -static int -rum_alloc_tx_list(struct rum_softc *sc) -{ - struct rum_tx_data *data; - int i, error; - - sc->tx_queued = sc->tx_cur = 0; - - for (i = 0; i < RUM_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx xfer\n"); - error = ENOMEM; - goto fail; - } - data->buf = usbd_alloc_buffer(data->xfer, - RT2573_TX_DESC_SIZE + MCLBYTES); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx buffer\n"); - error = ENOMEM; - goto fail; - } - /* clean Tx descriptor */ - bzero(data->buf, RT2573_TX_DESC_SIZE); - } - - return 0; - -fail: rum_free_tx_list(sc); - return error; -} - -static void -rum_free_tx_list(struct rum_softc *sc) -{ - struct rum_tx_data *data; - int i; - - for (i = 0; i < RUM_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - } -} - -static int -rum_alloc_rx_list(struct rum_softc *sc) -{ - struct rum_rx_data *data; - int i, error; - - for (i = 0; i < RUM_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx xfer\n"); - error = ENOMEM; - goto fail; - } - if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx buffer\n"); - error = ENOMEM; - goto fail; - } - - data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (data->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - - data->buf = mtod(data->m, uint8_t *); - } - - return 0; - -fail: rum_free_rx_list(sc); - return error; -} - -static void -rum_free_rx_list(struct rum_softc *sc) -{ - struct rum_rx_data *data; - int i; - - for (i = 0; i < RUM_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - if (data->m != NULL) { - m_freem(data->m); - data->m = NULL; - } - } -} - -static void -rum_task(void *arg) -{ - struct rum_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct rum_vap *rvp = RUM_VAP(vap); - const struct ieee80211_txparam *tp; - enum ieee80211_state ostate; - struct ieee80211_node *ni; - uint32_t tmp; - - ostate = vap->iv_state; - - RUM_LOCK(sc); - - switch (sc->sc_state) { - case IEEE80211_S_INIT: - if (ostate == IEEE80211_S_RUN) { - /* abort TSF synchronization */ - tmp = rum_read(sc, RT2573_TXRX_CSR9); - rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff); - } - break; - - case IEEE80211_S_RUN: - ni = vap->iv_bss; - - if (vap->iv_opmode != IEEE80211_M_MONITOR) { - rum_update_slot(ic->ic_ifp); - rum_enable_mrr(sc); - rum_set_txpreamble(sc); - rum_set_basicrates(sc); - rum_set_bssid(sc, ni->ni_bssid); - } - - if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) - rum_prepare_beacon(sc, vap); - - if (vap->iv_opmode != IEEE80211_M_MONITOR) - rum_enable_tsf_sync(sc); - - /* enable automatic rate adaptation */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - rum_amrr_start(sc, ni); - break; - default: - break; - } - - RUM_UNLOCK(sc); - - IEEE80211_LOCK(ic); - rvp->newstate(vap, sc->sc_state, sc->sc_arg); - if (vap->iv_newstate_cb != NULL) - vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); - IEEE80211_UNLOCK(ic); -} - -static int -rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct rum_vap *rvp = RUM_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct rum_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - callout_stop(&rvp->amrr_ch); - - /* do it in a process context */ - sc->sc_state = nstate; - sc->sc_arg = arg; - - if (nstate == IEEE80211_S_INIT) { - rvp->newstate(vap, nstate, arg); - return 0; - } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); - return EINPROGRESS; - } -} - -static void -rum_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rum_tx_data *data = priv; - struct rum_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - - if (data->m != NULL && data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, 0/*XXX*/); - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_tx_pipeh); - - ifp->if_oerrors++; - return; - } - - m_freem(data->m); - data->m = NULL; - ieee80211_free_node(data->ni); - data->ni = NULL; - - sc->tx_queued--; - ifp->if_opackets++; - - DPRINTFN(10, ("tx done\n")); - - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rum_start(ifp); -} - -static void -rum_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct rum_rx_data *data = priv; - struct rum_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct rum_rx_desc *desc; - struct ieee80211_node *ni; - struct mbuf *mnew, *m; - int len, rssi; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - goto skip; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); - - if (len < RT2573_RX_DESC_SIZE + sizeof (struct ieee80211_frame_min)) { - DPRINTF(("%s: xfer too short %d\n", - device_get_nameunit(sc->sc_dev), len)); - ifp->if_ierrors++; - goto skip; - } - - desc = (struct rum_rx_desc *)data->buf; - - if (le32toh(desc->flags) & RT2573_RX_CRC_ERROR) { - /* - * This should not happen since we did not request to receive - * those frames when we filled RT2573_TXRX_CSR0. - */ - DPRINTFN(5, ("CRC error\n")); - ifp->if_ierrors++; - goto skip; - } - - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - ifp->if_ierrors++; - goto skip; - } - - m = data->m; - data->m = mnew; - data->buf = mtod(data->m, uint8_t *); - - /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; - m->m_data = (caddr_t)(desc + 1); - m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; - - rssi = rum_get_rssi(sc, desc->rssi); - - if (bpf_peers_present(ifp->if_bpf)) { - struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = IEEE80211_RADIOTAP_F_FCS; - tap->wr_rate = ieee80211_plcp2rate(desc->rate, - (desc->flags & htole32(RT2573_RX_OFDM)) ? - IEEE80211_T_OFDM : IEEE80211_T_CCK); - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wr_antenna = sc->rx_ant; - tap->wr_antsignal = rssi; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); - } - - ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - /* Error happened during RSSI conversion. */ - if (rssi < 0) - rssi = -30; /* XXX ignored by net80211 */ - (void) ieee80211_input(ni, m, rssi, RT2573_NOISE_FLOOR, 0); - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, RT2573_NOISE_FLOOR, 0); - - DPRINTFN(15, ("rx done\n")); - -skip: /* setup a new transfer */ - usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data, data->buf, MCLBYTES, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof); - usbd_transfer(xfer); -} - -static uint8_t -rum_plcp_signal(int rate) -{ - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: return 0x0; - case 4: return 0x1; - case 11: return 0x2; - case 22: return 0x3; - } - return 0xff; /* XXX unsupported/unknown rate */ -} - -static void -rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc, - uint32_t flags, uint16_t xflags, int len, int rate) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t plcp_length; - int remainder; - - desc->flags = htole32(flags); - desc->flags |= htole32(RT2573_TX_VALID); - desc->flags |= htole32(len << 16); - - desc->xflags = htole16(xflags); - - desc->wme = htole16(RT2573_QID(0) | RT2573_AIFSN(2) | - RT2573_LOGCWMIN(4) | RT2573_LOGCWMAX(10)); - - /* setup PLCP fields */ - desc->plcp_signal = rum_plcp_signal(rate); - desc->plcp_service = 4; - - len += IEEE80211_CRC_LEN; - if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) { - desc->flags |= htole32(RT2573_TX_OFDM); - - plcp_length = len & 0xfff; - desc->plcp_length_hi = plcp_length >> 6; - desc->plcp_length_lo = plcp_length & 0x3f; - } else { - plcp_length = (16 * len + rate - 1) / rate; - if (rate == 22) { - remainder = (16 * len) % 22; - if (remainder != 0 && remainder < 7) - desc->plcp_service |= RT2573_PLCP_LENGEXT; - } - desc->plcp_length_hi = plcp_length >> 8; - desc->plcp_length_lo = plcp_length & 0xff; - - if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->plcp_signal |= 0x08; - } -} - -#define RUM_TX_TIMEOUT 5000 - -static int -rum_sendprot(struct rum_softc *sc, - const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) -{ - struct ieee80211com *ic = ni->ni_ic; - const struct ieee80211_frame *wh; - struct rum_tx_desc *desc; - struct rum_tx_data *data; - struct mbuf *mprot; - int protrate, ackrate, pktlen, flags, isshort; - uint16_t dur; - usbd_status error; - - KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, - ("protection %d", prot)); - - wh = mtod(m, const struct ieee80211_frame *); - pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; - - protrate = ieee80211_ctl_rate(sc->sc_rates, rate); - ackrate = ieee80211_ack_rate(sc->sc_rates, rate); - - isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; - dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort); - + ieee80211_ack_duration(sc->sc_rates, rate, isshort); - flags = RT2573_TX_MORE_FRAG; - if (prot == IEEE80211_PROT_RTSCTS) { - /* NB: CTS is the same size as an ACK */ - dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort); - flags |= RT2573_TX_NEED_ACK; - mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); - } else { - mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); - } - if (mprot == NULL) { - /* XXX stat + msg */ - return ENOBUFS; - } - data = &sc->tx_data[sc->tx_cur]; - desc = (struct rum_tx_desc *)data->buf; - - data->m = mprot; - data->ni = ieee80211_ref_node(ni); - m_copydata(mprot, 0, mprot->m_pkthdr.len, - data->buf + RT2573_TX_DESC_SIZE); - rum_setup_tx_desc(sc, desc, flags, 0, mprot->m_pkthdr.len, protrate); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - /* NB: no roundup necessary */ - RT2573_TX_DESC_SIZE + mprot->m_pkthdr.len, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT; - - return 0; -} - -static int -rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct rum_tx_desc *desc; - struct rum_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - uint32_t flags = 0; - uint16_t dur; - usbd_status error; - int xferlen; - - data = &sc->tx_data[sc->tx_cur]; - data->m = m0; - data->ni = ni; - desc = (struct rum_tx_desc *)data->buf; - - wh = mtod(m0, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - wh = mtod(m0, struct ieee80211_frame *); - } - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RT2573_TX_NEED_ACK; - - dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - - /* tell hardware to add timestamp for probe responses */ - if ((wh->i_fc[0] & - (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == - (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) - flags |= RT2573_TX_TIMESTAMP; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct rum_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = tp->mgmtrate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE); - rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, tp->mgmtrate); - - /* align end on a 4-bytes boundary */ - xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3; - - /* - * No space left in the last URB to store the extra 4 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 4; - - DPRINTFN(10, ("sending mgt frame len=%d rate=%d xfer len=%d\n", - m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, tp->mgmtrate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - m_freem(m0); - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT; - - return 0; -} - -static int -rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, - const struct ieee80211_bpf_params *params) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct rum_tx_desc *desc; - struct rum_tx_data *data; - uint32_t flags; - usbd_status error; - int xferlen, rate; - - KASSERT(params != NULL, ("no raw xmit params")); - - data = &sc->tx_data[sc->tx_cur]; - desc = (struct rum_tx_desc *)data->buf; - - rate = params->ibp_rate0 & IEEE80211_RATE_VAL; - /* XXX validate */ - if (rate == 0) { - m_freem(m0); - return EINVAL; - } - flags = 0; - if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) - flags |= RT2573_TX_NEED_ACK; - if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { - error = rum_sendprot(sc, m0, ni, - params->ibp_flags & IEEE80211_BPF_RTS ? - IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, - rate); - if (error) { - m_freem(m0); - return error; - } - flags |= RT2573_TX_LONG_RETRY | RT2573_TX_IFS_SIFS; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct rum_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - data->m = m0; - data->ni = ni; - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE); - /* XXX need to setup descriptor ourself */ - rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate); - - /* align end on a 4-bytes boundary */ - xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3; - - /* - * No space left in the last URB to store the extra 4 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 4; - - DPRINTFN(10, ("sending raw frame len=%u rate=%u xfer len=%u\n", - m0->m_pkthdr.len, rate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, - rum_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) - return error; - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT; - - return 0; -} - -static int -rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct rum_tx_desc *desc; - struct rum_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - uint32_t flags = 0; - uint16_t dur; - usbd_status error; - int rate, xferlen; - - wh = mtod(m0, struct ieee80211_frame *); - - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else { - (void) ieee80211_amrr_choose(ni, &RUM_NODE(ni)->amn); - rate = ni->ni_txrate; - } - - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - int prot = IEEE80211_PROT_NONE; - if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) - prot = IEEE80211_PROT_RTSCTS; - else if ((ic->ic_flags & IEEE80211_F_USEPROT) && - ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) - prot = ic->ic_protmode; - if (prot != IEEE80211_PROT_NONE) { - error = rum_sendprot(sc, m0, ni, prot, rate); - if (error) { - m_freem(m0); - return error; - } - flags |= RT2573_TX_LONG_RETRY | RT2573_TX_IFS_SIFS; - } - } - - data = &sc->tx_data[sc->tx_cur]; - desc = (struct rum_tx_desc *)data->buf; - - data->m = m0; - data->ni = ni; - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RT2573_TX_NEED_ACK; - flags |= RT2573_TX_MORE_FRAG; - - dur = ieee80211_ack_duration(sc->sc_rates, rate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct rum_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RT2573_TX_DESC_SIZE); - rum_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate); - - /* align end on a 4-bytes boundary */ - xferlen = (RT2573_TX_DESC_SIZE + m0->m_pkthdr.len + 3) & ~3; - - /* - * No space left in the last URB to store the extra 4 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 4; - - DPRINTFN(10, ("sending frame len=%d rate=%d xfer len=%d\n", - m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, rate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, xferlen, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RUM_TX_TIMEOUT, rum_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - m_freem(m0); - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RUM_TX_LIST_COUNT; - - return 0; -} - -static void -rum_start(struct ifnet *ifp) -{ - struct rum_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->tx_queued >= RUM_TX_LIST_COUNT-1) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - m = ieee80211_encap(ni, m); - if (m == NULL) { - ieee80211_free_node(ni); - continue; - } - if (rum_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - sc->sc_tx_timer = 5; - callout_reset(&sc->watchdog_ch, hz, rum_watchdog, sc); - } -} - -static void -rum_watchdog(void *arg) -{ - struct rum_softc *sc = arg; - - RUM_LOCK(sc); - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - /*rum_init(ifp); XXX needs a process context! */ - sc->sc_ifp->if_oerrors++; - RUM_UNLOCK(sc); - return; - } - callout_reset(&sc->watchdog_ch, hz, rum_watchdog, sc); - } - - RUM_UNLOCK(sc); -} - -static int -rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct rum_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - RUM_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - rum_init(sc); - startall = 1; - } else - rum_update_promisc(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - rum_stop(sc); - } - RUM_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - return error; -} - -static void -rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RT2573_READ_EEPROM; - USETW(req.wValue, 0); - USETW(req.wIndex, addr); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not read EEPROM: %s\n", - usbd_errstr(error)); - } -} - -static uint32_t -rum_read(struct rum_softc *sc, uint16_t reg) -{ - uint32_t val; - - rum_read_multi(sc, reg, &val, sizeof val); - - return le32toh(val); -} - -static void -rum_read_multi(struct rum_softc *sc, uint16_t reg, void *buf, int len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RT2573_READ_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, - "could not multi read MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -rum_write(struct rum_softc *sc, uint16_t reg, uint32_t val) -{ - uint32_t tmp = htole32(val); - - rum_write_multi(sc, reg, &tmp, sizeof tmp); -} - -static void -rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RT2573_WRITE_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, - "could not multi write MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val) -{ - uint32_t tmp; - int ntries; - - for (ntries = 0; ntries < 5; ntries++) { - if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not write to BBP\n"); - return; - } - - tmp = RT2573_BBP_BUSY | (reg & 0x7f) << 8 | val; - rum_write(sc, RT2573_PHY_CSR3, tmp); -} - -static uint8_t -rum_bbp_read(struct rum_softc *sc, uint8_t reg) -{ - uint32_t val; - int ntries; - - for (ntries = 0; ntries < 5; ntries++) { - if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not read BBP\n"); - return 0; - } - - val = RT2573_BBP_BUSY | RT2573_BBP_READ | reg << 8; - rum_write(sc, RT2573_PHY_CSR3, val); - - for (ntries = 0; ntries < 100; ntries++) { - val = rum_read(sc, RT2573_PHY_CSR3); - if (!(val & RT2573_BBP_BUSY)) - return val & 0xff; - DELAY(1); - } - - device_printf(sc->sc_dev, "could not read BBP\n"); - return 0; -} - -static void -rum_rf_write(struct rum_softc *sc, uint8_t reg, uint32_t val) -{ - uint32_t tmp; - int ntries; - - for (ntries = 0; ntries < 5; ntries++) { - if (!(rum_read(sc, RT2573_PHY_CSR4) & RT2573_RF_BUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not write to RF\n"); - return; - } - - tmp = RT2573_RF_BUSY | RT2573_RF_20BIT | (val & 0xfffff) << 2 | - (reg & 3); - rum_write(sc, RT2573_PHY_CSR4, tmp); - - /* remember last written value in sc */ - sc->rf_regs[reg] = val; - - DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 3, val & 0xfffff)); -} - -static void -rum_select_antenna(struct rum_softc *sc) -{ - uint8_t bbp4, bbp77; - uint32_t tmp; - - bbp4 = rum_bbp_read(sc, 4); - bbp77 = rum_bbp_read(sc, 77); - - /* TBD */ - - /* make sure Rx is disabled before switching antenna */ - tmp = rum_read(sc, RT2573_TXRX_CSR0); - rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX); - - rum_bbp_write(sc, 4, bbp4); - rum_bbp_write(sc, 77, bbp77); - - rum_write(sc, RT2573_TXRX_CSR0, tmp); -} - -/* - * Enable multi-rate retries for frames sent at OFDM rates. - * In 802.11b/g mode, allow fallback to CCK rates. - */ -static void -rum_enable_mrr(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t tmp; - - tmp = rum_read(sc, RT2573_TXRX_CSR4); - - tmp &= ~RT2573_MRR_CCK_FALLBACK; - if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) - tmp |= RT2573_MRR_CCK_FALLBACK; - tmp |= RT2573_MRR_ENABLED; - - rum_write(sc, RT2573_TXRX_CSR4, tmp); -} - -static void -rum_set_txpreamble(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t tmp; - - tmp = rum_read(sc, RT2573_TXRX_CSR4); - - tmp &= ~RT2573_SHORT_PREAMBLE; - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - tmp |= RT2573_SHORT_PREAMBLE; - - rum_write(sc, RT2573_TXRX_CSR4, tmp); -} - -static void -rum_set_basicrates(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - /* update basic rate set */ - if (ic->ic_curmode == IEEE80211_MODE_11B) { - /* 11b basic rates: 1, 2Mbps */ - rum_write(sc, RT2573_TXRX_CSR5, 0x3); - } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) { - /* 11a basic rates: 6, 12, 24Mbps */ - rum_write(sc, RT2573_TXRX_CSR5, 0x150); - } else { - /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */ - rum_write(sc, RT2573_TXRX_CSR5, 0xf); - } -} - -/* - * Reprogram MAC/BBP to switch to a new band. Values taken from the reference - * driver. - */ -static void -rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c) -{ - uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104; - uint32_t tmp; - - /* update all BBP registers that depend on the band */ - bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c; - bbp35 = 0x50; bbp97 = 0x48; bbp98 = 0x48; - if (IEEE80211_IS_CHAN_5GHZ(c)) { - bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c; - bbp35 += 0x10; bbp97 += 0x10; bbp98 += 0x10; - } - if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) || - (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) { - bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10; - } - - sc->bbp17 = bbp17; - rum_bbp_write(sc, 17, bbp17); - rum_bbp_write(sc, 96, bbp96); - rum_bbp_write(sc, 104, bbp104); - - if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) || - (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) { - rum_bbp_write(sc, 75, 0x80); - rum_bbp_write(sc, 86, 0x80); - rum_bbp_write(sc, 88, 0x80); - } - - rum_bbp_write(sc, 35, bbp35); - rum_bbp_write(sc, 97, bbp97); - rum_bbp_write(sc, 98, bbp98); - - tmp = rum_read(sc, RT2573_PHY_CSR0); - tmp &= ~(RT2573_PA_PE_2GHZ | RT2573_PA_PE_5GHZ); - if (IEEE80211_IS_CHAN_2GHZ(c)) - tmp |= RT2573_PA_PE_2GHZ; - else - tmp |= RT2573_PA_PE_5GHZ; - rum_write(sc, RT2573_PHY_CSR0, tmp); -} - -static void -rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - const struct rfprog *rfprog; - uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT; - int8_t power; - u_int i, chan; - - chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) - return; - - /* select the appropriate RF settings based on what EEPROM says */ - rfprog = (sc->rf_rev == RT2573_RF_5225 || - sc->rf_rev == RT2573_RF_2527) ? rum_rf5225 : rum_rf5226; - - /* find the settings for this channel (we know it exists) */ - for (i = 0; rfprog[i].chan != chan; i++); - - power = sc->txpow[i]; - if (power < 0) { - bbp94 += power; - power = 0; - } else if (power > 31) { - bbp94 += power - 31; - power = 31; - } - - /* - * If we are switching from the 2GHz band to the 5GHz band or - * vice-versa, BBP registers need to be reprogrammed. - */ - if (c->ic_flags != ic->ic_curchan->ic_flags) { - rum_select_band(sc, c); - rum_select_antenna(sc); - } - ic->ic_curchan = c; - - rum_rf_write(sc, RT2573_RF1, rfprog[i].r1); - rum_rf_write(sc, RT2573_RF2, rfprog[i].r2); - rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7); - rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10); - - rum_rf_write(sc, RT2573_RF1, rfprog[i].r1); - rum_rf_write(sc, RT2573_RF2, rfprog[i].r2); - rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7 | 1); - rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10); - - rum_rf_write(sc, RT2573_RF1, rfprog[i].r1); - rum_rf_write(sc, RT2573_RF2, rfprog[i].r2); - rum_rf_write(sc, RT2573_RF3, rfprog[i].r3 | power << 7); - rum_rf_write(sc, RT2573_RF4, rfprog[i].r4 | sc->rffreq << 10); - - DELAY(10); - - /* enable smart mode for MIMO-capable RFs */ - bbp3 = rum_bbp_read(sc, 3); - - bbp3 &= ~RT2573_SMART_MODE; - if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_2527) - bbp3 |= RT2573_SMART_MODE; - - rum_bbp_write(sc, 3, bbp3); - - if (bbp94 != RT2573_BBPR94_DEFAULT) - rum_bbp_write(sc, 94, bbp94); -} - -/* - * Enable TSF synchronization and tell h/w to start sending beacons for IBSS - * and HostAP operating modes. - */ -static void -rum_enable_tsf_sync(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t tmp; - - if (vap->iv_opmode != IEEE80211_M_STA) { - /* - * Change default 16ms TBTT adjustment to 8ms. - * Must be done before enabling beacon generation. - */ - rum_write(sc, RT2573_TXRX_CSR10, 1 << 12 | 8); - } - - tmp = rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000; - - /* set beacon interval (in 1/16ms unit) */ - tmp |= vap->iv_bss->ni_intval * 16; - - tmp |= RT2573_TSF_TICKING | RT2573_ENABLE_TBTT; - if (vap->iv_opmode == IEEE80211_M_STA) - tmp |= RT2573_TSF_MODE(1); - else - tmp |= RT2573_TSF_MODE(2) | RT2573_GENERATE_BEACON; - - rum_write(sc, RT2573_TXRX_CSR9, tmp); -} - -static void -rum_update_slot(struct ifnet *ifp) -{ - struct rum_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t slottime; - uint32_t tmp; - - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; - - tmp = rum_read(sc, RT2573_MAC_CSR9); - tmp = (tmp & ~0xff) | slottime; - rum_write(sc, RT2573_MAC_CSR9, tmp); - - DPRINTF(("setting slot time to %uus\n", slottime)); -} - -static void -rum_set_bssid(struct rum_softc *sc, const uint8_t *bssid) -{ - uint32_t tmp; - - tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24; - rum_write(sc, RT2573_MAC_CSR4, tmp); - - tmp = bssid[4] | bssid[5] << 8 | RT2573_ONE_BSSID << 16; - rum_write(sc, RT2573_MAC_CSR5, tmp); -} - -static void -rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr) -{ - uint32_t tmp; - - tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24; - rum_write(sc, RT2573_MAC_CSR2, tmp); - - tmp = addr[4] | addr[5] << 8 | 0xff << 16; - rum_write(sc, RT2573_MAC_CSR3, tmp); -} - -static void -rum_update_promisc(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - uint32_t tmp; - - tmp = rum_read(sc, RT2573_TXRX_CSR0); - - tmp &= ~RT2573_DROP_NOT_TO_ME; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RT2573_DROP_NOT_TO_ME; - - rum_write(sc, RT2573_TXRX_CSR0, tmp); - - DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? - "entering" : "leaving")); -} - -static const char * -rum_get_rf(int rev) -{ - switch (rev) { - case RT2573_RF_2527: return "RT2527 (MIMO XR)"; - case RT2573_RF_2528: return "RT2528"; - case RT2573_RF_5225: return "RT5225 (MIMO XR)"; - case RT2573_RF_5226: return "RT5226"; - default: return "unknown"; - } -} - -static void -rum_read_eeprom(struct rum_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t val; -#ifdef RUM_DEBUG - int i; -#endif - - /* read MAC address */ - rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, ic->ic_myaddr, 6); - - rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); - val = le16toh(val); - sc->rf_rev = (val >> 11) & 0x1f; - sc->hw_radio = (val >> 10) & 0x1; - sc->rx_ant = (val >> 4) & 0x3; - sc->tx_ant = (val >> 2) & 0x3; - sc->nb_ant = val & 0x3; - - DPRINTF(("RF revision=%d\n", sc->rf_rev)); - - rum_eeprom_read(sc, RT2573_EEPROM_CONFIG2, &val, 2); - val = le16toh(val); - sc->ext_5ghz_lna = (val >> 6) & 0x1; - sc->ext_2ghz_lna = (val >> 4) & 0x1; - - DPRINTF(("External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n", - sc->ext_2ghz_lna, sc->ext_5ghz_lna)); - - rum_eeprom_read(sc, RT2573_EEPROM_RSSI_2GHZ_OFFSET, &val, 2); - val = le16toh(val); - if ((val & 0xff) != 0xff) - sc->rssi_2ghz_corr = (int8_t)(val & 0xff); /* signed */ - - /* Only [-10, 10] is valid */ - if (sc->rssi_2ghz_corr < -10 || sc->rssi_2ghz_corr > 10) - sc->rssi_2ghz_corr = 0; - - rum_eeprom_read(sc, RT2573_EEPROM_RSSI_5GHZ_OFFSET, &val, 2); - val = le16toh(val); - if ((val & 0xff) != 0xff) - sc->rssi_5ghz_corr = (int8_t)(val & 0xff); /* signed */ - - /* Only [-10, 10] is valid */ - if (sc->rssi_5ghz_corr < -10 || sc->rssi_5ghz_corr > 10) - sc->rssi_5ghz_corr = 0; - - if (sc->ext_2ghz_lna) - sc->rssi_2ghz_corr -= 14; - if (sc->ext_5ghz_lna) - sc->rssi_5ghz_corr -= 14; - - DPRINTF(("RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n", - sc->rssi_2ghz_corr, sc->rssi_5ghz_corr)); - - rum_eeprom_read(sc, RT2573_EEPROM_FREQ_OFFSET, &val, 2); - val = le16toh(val); - if ((val & 0xff) != 0xff) - sc->rffreq = val & 0xff; - - DPRINTF(("RF freq=%d\n", sc->rffreq)); - - /* read Tx power for all a/b/g channels */ - rum_eeprom_read(sc, RT2573_EEPROM_TXPOWER, sc->txpow, 14); - /* XXX default Tx power for 802.11a channels */ - memset(sc->txpow + 14, 24, sizeof (sc->txpow) - 14); -#ifdef RUM_DEBUG - for (i = 0; i < 14; i++) - DPRINTF(("Channel=%d Tx power=%d\n", i + 1, sc->txpow[i])); -#endif - - /* read default values for BBP registers */ - rum_eeprom_read(sc, RT2573_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); -#ifdef RUM_DEBUG - for (i = 0; i < 14; i++) { - if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff) - continue; - DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg, - sc->bbp_prom[i].val)); - } -#endif -} - -static int -rum_bbp_init(struct rum_softc *sc) -{ -#define N(a) (sizeof (a) / sizeof ((a)[0])) - int i, ntries; - - /* wait for BBP to be ready */ - for (ntries = 0; ntries < 100; ntries++) { - const uint8_t val = rum_bbp_read(sc, 0); - if (val != 0 && val != 0xff) - break; - DELAY(1000); - } - if (ntries == 100) { - device_printf(sc->sc_dev, "timeout waiting for BBP\n"); - return EIO; - } - - /* initialize BBP registers to default values */ - for (i = 0; i < N(rum_def_bbp); i++) - rum_bbp_write(sc, rum_def_bbp[i].reg, rum_def_bbp[i].val); - - /* write vendor-specific BBP values (from EEPROM) */ - for (i = 0; i < 16; i++) { - if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff) - continue; - rum_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); - } - - return 0; -#undef N -} - -static void -rum_init_locked(struct rum_softc *sc) -{ -#define N(a) (sizeof (a) / sizeof ((a)[0])) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct rum_rx_data *data; - uint32_t tmp; - usbd_status error; - int i, ntries; - - rum_stop(sc); - - /* initialize MAC registers to default values */ - for (i = 0; i < N(rum_def_mac); i++) - rum_write(sc, rum_def_mac[i].reg, rum_def_mac[i].val); - - /* set host ready */ - rum_write(sc, RT2573_MAC_CSR1, 3); - rum_write(sc, RT2573_MAC_CSR1, 0); - - /* wait for BBP/RF to wakeup */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rum_read(sc, RT2573_MAC_CSR12) & 8) - break; - rum_write(sc, RT2573_MAC_CSR12, 4); /* force wakeup */ - DELAY(1000); - } - if (ntries == 1000) { - device_printf(sc->sc_dev, - "timeout waiting for BBP/RF to wakeup\n"); - goto fail; - } - - if ((error = rum_bbp_init(sc)) != 0) - goto fail; - - /* select default channel */ - rum_select_band(sc, ic->ic_curchan); - rum_select_antenna(sc); - rum_set_chan(sc, ic->ic_curchan); - - /* clear STA registers */ - rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); - - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - rum_set_macaddr(sc, ic->ic_myaddr); - - /* initialize ASIC */ - rum_write(sc, RT2573_MAC_CSR1, 4); - - /* - * Allocate xfer for AMRR statistics requests. - */ - sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->amrr_xfer == NULL) { - device_printf(sc->sc_dev, "could not allocate AMRR xfer\n"); - goto fail; - } - - /* - * Open Tx and Rx USB bulk pipes. - */ - error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, - &sc->sc_tx_pipeh); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Tx pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, - &sc->sc_rx_pipeh); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Rx pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - - /* - * Allocate Tx and Rx xfer queues. - */ - error = rum_alloc_tx_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Tx list\n"); - goto fail; - } - error = rum_alloc_rx_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Rx list\n"); - goto fail; - } - - /* - * Start up the receive pipe. - */ - for (i = 0; i < RUM_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf, - MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rum_rxeof); - usbd_transfer(data->xfer); - } - - /* update Rx filter */ - tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; - - tmp |= RT2573_DROP_PHY_ERROR | RT2573_DROP_CRC_ERROR; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - tmp |= RT2573_DROP_CTL | RT2573_DROP_VER_ERROR | - RT2573_DROP_ACKCTS; - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - tmp |= RT2573_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RT2573_DROP_NOT_TO_ME; - } - rum_write(sc, RT2573_TXRX_CSR0, tmp); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - return; - -fail: rum_stop(sc); -#undef N -} - -static void -rum_init(void *priv) -{ - struct rum_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - RUM_LOCK(sc); - rum_init_locked(sc); - RUM_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -rum_stop(void *priv) -{ - struct rum_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - uint32_t tmp; - - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - /* disable Rx */ - tmp = rum_read(sc, RT2573_TXRX_CSR0); - rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX); - - /* reset ASIC */ - rum_write(sc, RT2573_MAC_CSR1, 3); - rum_write(sc, RT2573_MAC_CSR1, 0); - - if (sc->amrr_xfer != NULL) { - usbd_free_xfer(sc->amrr_xfer); - sc->amrr_xfer = NULL; - } - - if (sc->sc_rx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_rx_pipeh); - usbd_close_pipe(sc->sc_rx_pipeh); - sc->sc_rx_pipeh = NULL; - } - if (sc->sc_tx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_tx_pipeh); - usbd_close_pipe(sc->sc_tx_pipeh); - sc->sc_tx_pipeh = NULL; - } - - rum_free_rx_list(sc); - rum_free_tx_list(sc); -} - -static int -rum_load_microcode(struct rum_softc *sc, const u_char *ucode, size_t size) -{ - usb_device_request_t req; - uint16_t reg = RT2573_MCU_CODE_BASE; - usbd_status error; - - /* copy firmware image into NIC */ - for (; size >= 4; reg += 4, ucode += 4, size -= 4) - rum_write(sc, reg, UGETDW(ucode)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RT2573_MCU_CNTL; - USETW(req.wValue, RT2573_MCU_RUN); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - error = usbd_do_request(sc->sc_udev, &req, NULL); - if (error != 0) { - device_printf(sc->sc_dev, "could not run firmware: %s\n", - usbd_errstr(error)); - } - return error; -} - -static int -rum_prepare_beacon(struct rum_softc *sc, struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - const struct ieee80211_txparam *tp; - struct rum_tx_desc desc; - struct mbuf *m0; - - m0 = ieee80211_beacon_alloc(vap->iv_bss, &RUM_VAP(vap)->bo); - if (m0 == NULL) { - return ENOBUFS; - } - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; - rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ, - m0->m_pkthdr.len, tp->mgmtrate); - - /* copy the first 24 bytes of Tx descriptor into NIC memory */ - rum_write_multi(sc, RT2573_HW_BEACON_BASE0, (uint8_t *)&desc, 24); - - /* copy beacon header and payload into NIC memory */ - rum_write_multi(sc, RT2573_HW_BEACON_BASE0 + 24, mtod(m0, uint8_t *), - m0->m_pkthdr.len); - - m_freem(m0); - - return 0; -} - -static int -rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ifnet *ifp = ni->ni_ic->ic_ifp; - struct rum_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - if (sc->tx_queued >= RUM_TX_LIST_COUNT-1) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m); - ieee80211_free_node(ni); - return EIO; - } - - ifp->if_opackets++; - - if (params == NULL) { - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - */ - if (rum_tx_mgt(sc, m, ni) != 0) - goto bad; - } else { - /* - * Caller supplied explicit parameters to use in - * sending the frame. - */ - if (rum_tx_raw(sc, m, ni, params) != 0) - goto bad; - } - sc->sc_tx_timer = 5; - callout_reset(&sc->watchdog_ch, hz, rum_watchdog, sc); - - return 0; -bad: - ifp->if_oerrors++; - ieee80211_free_node(ni); - return EIO; -} - -static void -rum_amrr_start(struct rum_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct rum_vap *rvp = RUM_VAP(vap); - - /* clear statistic registers (STA_CSR0 to STA_CSR5) */ - rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); - - ieee80211_amrr_node_init(&rvp->amrr, &RUM_NODE(ni)->amn, ni); - - callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, vap); -} - -static void -rum_amrr_timeout(void *arg) -{ - struct ieee80211vap *vap = arg; - struct rum_softc *sc = vap->iv_ic->ic_ifp->if_softc; - usb_device_request_t req; - - /* - * Asynchronously read statistic registers (cleared by read). - */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RT2573_READ_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, RT2573_STA_CSR0); - USETW(req.wLength, sizeof sc->sta); - - usbd_setup_default_xfer(sc->amrr_xfer, sc->sc_udev, vap, - USBD_DEFAULT_TIMEOUT, &req, sc->sta, sizeof sc->sta, 0, - rum_amrr_update); - (void)usbd_transfer(sc->amrr_xfer); -} - -static void -rum_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct ieee80211vap *vap = priv; - struct rum_vap *rvp = RUM_VAP(vap); - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct rum_softc *sc = ifp->if_softc; - int ok, fail; - - if (status != USBD_NORMAL_COMPLETION) { - device_printf(sc->sc_dev, "could not retrieve Tx statistics - " - "cancelling automatic rate control\n"); - return; - } - - ok = (le32toh(sc->sta[4]) >> 16) + /* TX ok w/o retry */ - (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */ - fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */ - - ieee80211_amrr_tx_update(&RUM_NODE(vap->iv_bss)->amn, - ok+fail, ok, (le32toh(sc->sta[5]) & 0xffff) + fail); - - ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ - - callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, vap); -} - -/* ARGUSED */ -static struct ieee80211_node * -rum_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct rum_node *rn; - - rn = malloc(sizeof(struct rum_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return rn != NULL ? &rn->ni : NULL; -} - -static void -rum_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RUM_VAP(vap)->amrr, &RUM_NODE(ni)->amn, ni); -} - -static void -rum_scan_start(struct ieee80211com *ic) -{ - struct rum_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = RUM_SCAN_START; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -rum_scan_end(struct ieee80211com *ic) -{ - struct rum_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = RUM_SCAN_END; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -rum_set_channel(struct ieee80211com *ic) -{ - struct rum_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = RUM_SET_CHANNEL; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); - - sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); -} - -static void -rum_scantask(void *arg) -{ - struct rum_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t tmp; - - RUM_LOCK(sc); - - switch (sc->sc_scan_action) { - case RUM_SCAN_START: - /* abort TSF synchronization */ - tmp = rum_read(sc, RT2573_TXRX_CSR9); - rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff); - rum_set_bssid(sc, ifp->if_broadcastaddr); - break; - - case RUM_SCAN_END: - rum_enable_tsf_sync(sc); - /* XXX keep local copy */ - rum_set_bssid(sc, vap->iv_bss->ni_bssid); - break; - - case RUM_SET_CHANNEL: - mtx_lock(&Giant); - rum_set_chan(sc, ic->ic_curchan); - mtx_unlock(&Giant); - break; - - default: - panic("unknown scan action %d\n", sc->sc_scan_action); - /* NEVER REACHED */ - break; - } - - RUM_UNLOCK(sc); -} - -static int -rum_get_rssi(struct rum_softc *sc, uint8_t raw) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - int lna, agc, rssi; - - lna = (raw >> 5) & 0x3; - agc = raw & 0x1f; - - if (lna == 0) { - /* - * No RSSI mapping - * - * NB: Since RSSI is relative to noise floor, -1 is - * adequate for caller to know error happened. - */ - return -1; - } - - rssi = (2 * agc) - RT2573_NOISE_FLOOR; - - if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) { - rssi += sc->rssi_2ghz_corr; - - if (lna == 1) - rssi -= 64; - else if (lna == 2) - rssi -= 74; - else if (lna == 3) - rssi -= 90; - } else { - rssi += sc->rssi_5ghz_corr; - - if (!sc->ext_5ghz_lna && lna != 1) - rssi += 4; - - if (lna == 1) - rssi -= 64; - else if (lna == 2) - rssi -= 86; - else if (lna == 3) - rssi -= 100; - } - return rssi; -} - -static device_method_t rum_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rum_match), - DEVMETHOD(device_attach, rum_attach), - DEVMETHOD(device_detach, rum_detach), - - { 0, 0 } -}; - -static driver_t rum_driver = { - "rum", - rum_methods, - sizeof(struct rum_softc) -}; - -static devclass_t rum_devclass; - -DRIVER_MODULE(rum, uhub, rum_driver, rum_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/if_rumreg.h b/sys/dev/usb/if_rumreg.h deleted file mode 100644 index 75a51bc..0000000 --- a/sys/dev/usb/if_rumreg.h +++ /dev/null @@ -1,235 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini@free.fr> - * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RT2573_NOISE_FLOOR -95 - -#define RT2573_TX_DESC_SIZE (sizeof (struct rum_tx_desc)) -#define RT2573_RX_DESC_SIZE (sizeof (struct rum_rx_desc)) - -#define RT2573_CONFIG_NO 1 -#define RT2573_IFACE_INDEX 0 - -#define RT2573_MCU_CNTL 0x01 -#define RT2573_WRITE_MAC 0x02 -#define RT2573_READ_MAC 0x03 -#define RT2573_WRITE_MULTI_MAC 0x06 -#define RT2573_READ_MULTI_MAC 0x07 -#define RT2573_READ_EEPROM 0x09 -#define RT2573_WRITE_LED 0x0a - -/* - * Control and status registers. - */ -#define RT2573_AIFSN_CSR 0x0400 -#define RT2573_CWMIN_CSR 0x0404 -#define RT2573_CWMAX_CSR 0x0408 -#define RT2573_MCU_CODE_BASE 0x0800 -#define RT2573_HW_BEACON_BASE0 0x2400 -#define RT2573_MAC_CSR0 0x3000 -#define RT2573_MAC_CSR1 0x3004 -#define RT2573_MAC_CSR2 0x3008 -#define RT2573_MAC_CSR3 0x300c -#define RT2573_MAC_CSR4 0x3010 -#define RT2573_MAC_CSR5 0x3014 -#define RT2573_MAC_CSR6 0x3018 -#define RT2573_MAC_CSR7 0x301c -#define RT2573_MAC_CSR8 0x3020 -#define RT2573_MAC_CSR9 0x3024 -#define RT2573_MAC_CSR10 0x3028 -#define RT2573_MAC_CSR11 0x302c -#define RT2573_MAC_CSR12 0x3030 -#define RT2573_MAC_CSR13 0x3034 -#define RT2573_MAC_CSR14 0x3038 -#define RT2573_MAC_CSR15 0x303c -#define RT2573_TXRX_CSR0 0x3040 -#define RT2573_TXRX_CSR1 0x3044 -#define RT2573_TXRX_CSR2 0x3048 -#define RT2573_TXRX_CSR3 0x304c -#define RT2573_TXRX_CSR4 0x3050 -#define RT2573_TXRX_CSR5 0x3054 -#define RT2573_TXRX_CSR6 0x3058 -#define RT2573_TXRX_CSR7 0x305c -#define RT2573_TXRX_CSR8 0x3060 -#define RT2573_TXRX_CSR9 0x3064 -#define RT2573_TXRX_CSR10 0x3068 -#define RT2573_TXRX_CSR11 0x306c -#define RT2573_TXRX_CSR12 0x3070 -#define RT2573_TXRX_CSR13 0x3074 -#define RT2573_TXRX_CSR14 0x3078 -#define RT2573_TXRX_CSR15 0x307c -#define RT2573_PHY_CSR0 0x3080 -#define RT2573_PHY_CSR1 0x3084 -#define RT2573_PHY_CSR2 0x3088 -#define RT2573_PHY_CSR3 0x308c -#define RT2573_PHY_CSR4 0x3090 -#define RT2573_PHY_CSR5 0x3094 -#define RT2573_PHY_CSR6 0x3098 -#define RT2573_PHY_CSR7 0x309c -#define RT2573_SEC_CSR0 0x30a0 -#define RT2573_SEC_CSR1 0x30a4 -#define RT2573_SEC_CSR2 0x30a8 -#define RT2573_SEC_CSR3 0x30ac -#define RT2573_SEC_CSR4 0x30b0 -#define RT2573_SEC_CSR5 0x30b4 -#define RT2573_STA_CSR0 0x30c0 -#define RT2573_STA_CSR1 0x30c4 -#define RT2573_STA_CSR2 0x30c8 -#define RT2573_STA_CSR3 0x30cc -#define RT2573_STA_CSR4 0x30d0 -#define RT2573_STA_CSR5 0x30d4 - - -/* possible flags for register RT2573_MAC_CSR1 */ -#define RT2573_RESET_ASIC (1 << 0) -#define RT2573_RESET_BBP (1 << 1) -#define RT2573_HOST_READY (1 << 2) - -/* possible flags for register MAC_CSR5 */ -#define RT2573_ONE_BSSID 3 - -/* possible flags for register TXRX_CSR0 */ -/* Tx filter flags are in the low 16 bits */ -#define RT2573_AUTO_TX_SEQ (1 << 15) -/* Rx filter flags are in the high 16 bits */ -#define RT2573_DISABLE_RX (1 << 16) -#define RT2573_DROP_CRC_ERROR (1 << 17) -#define RT2573_DROP_PHY_ERROR (1 << 18) -#define RT2573_DROP_CTL (1 << 19) -#define RT2573_DROP_NOT_TO_ME (1 << 20) -#define RT2573_DROP_TODS (1 << 21) -#define RT2573_DROP_VER_ERROR (1 << 22) -#define RT2573_DROP_MULTICAST (1 << 23) -#define RT2573_DROP_BROADCAST (1 << 24) -#define RT2573_DROP_ACKCTS (1 << 25) - -/* possible flags for register TXRX_CSR4 */ -#define RT2573_SHORT_PREAMBLE (1 << 18) -#define RT2573_MRR_ENABLED (1 << 19) -#define RT2573_MRR_CCK_FALLBACK (1 << 22) - -/* possible flags for register TXRX_CSR9 */ -#define RT2573_TSF_TICKING (1 << 16) -#define RT2573_TSF_MODE(x) (((x) & 0x3) << 17) -/* TBTT stands for Target Beacon Transmission Time */ -#define RT2573_ENABLE_TBTT (1 << 19) -#define RT2573_GENERATE_BEACON (1 << 20) - -/* possible flags for register PHY_CSR0 */ -#define RT2573_PA_PE_2GHZ (1 << 16) -#define RT2573_PA_PE_5GHZ (1 << 17) - -/* possible flags for register PHY_CSR3 */ -#define RT2573_BBP_READ (1 << 15) -#define RT2573_BBP_BUSY (1 << 16) -/* possible flags for register PHY_CSR4 */ -#define RT2573_RF_20BIT (20 << 24) -#define RT2573_RF_BUSY (1 << 31) - -/* LED values */ -#define RT2573_LED_RADIO (1 << 8) -#define RT2573_LED_G (1 << 9) -#define RT2573_LED_A (1 << 10) -#define RT2573_LED_ON 0x1e1e -#define RT2573_LED_OFF 0x0 - -#define RT2573_MCU_RUN (1 << 3) - -#define RT2573_SMART_MODE (1 << 0) - -#define RT2573_BBPR94_DEFAULT 6 - -#define RT2573_BBP_WRITE (1 << 15) - -/* dual-band RF */ -#define RT2573_RF_5226 1 -#define RT2573_RF_5225 3 -/* single-band RF */ -#define RT2573_RF_2528 2 -#define RT2573_RF_2527 4 - -#define RT2573_BBP_VERSION 0 - -struct rum_tx_desc { - uint32_t flags; -#define RT2573_TX_BURST (1 << 0) -#define RT2573_TX_VALID (1 << 1) -#define RT2573_TX_MORE_FRAG (1 << 2) -#define RT2573_TX_NEED_ACK (1 << 3) -#define RT2573_TX_TIMESTAMP (1 << 4) -#define RT2573_TX_OFDM (1 << 5) -#define RT2573_TX_IFS_SIFS (1 << 6) -#define RT2573_TX_LONG_RETRY (1 << 7) - - uint16_t wme; -#define RT2573_QID(v) (v) -#define RT2573_AIFSN(v) ((v) << 4) -#define RT2573_LOGCWMIN(v) ((v) << 8) -#define RT2573_LOGCWMAX(v) ((v) << 12) - - uint16_t xflags; -#define RT2573_TX_HWSEQ (1 << 12) - - uint8_t plcp_signal; - uint8_t plcp_service; -#define RT2573_PLCP_LENGEXT 0x80 - - uint8_t plcp_length_lo; - uint8_t plcp_length_hi; - - uint32_t iv; - uint32_t eiv; - - uint8_t offset; - uint8_t qid; - uint8_t txpower; -#define RT2573_DEFAULT_TXPOWER 0 - - uint8_t reserved; -} __packed; - -struct rum_rx_desc { - uint32_t flags; -#define RT2573_RX_BUSY (1 << 0) -#define RT2573_RX_DROP (1 << 1) -#define RT2573_RX_CRC_ERROR (1 << 6) -#define RT2573_RX_OFDM (1 << 7) - - uint8_t rate; - uint8_t rssi; - uint8_t reserved1; - uint8_t offset; - uint32_t iv; - uint32_t eiv; - uint32_t reserved2[2]; -} __packed; - -#define RT2573_RF1 0 -#define RT2573_RF2 2 -#define RT2573_RF3 1 -#define RT2573_RF4 3 - -#define RT2573_EEPROM_MACBBP 0x0000 -#define RT2573_EEPROM_ADDRESS 0x0004 -#define RT2573_EEPROM_ANTENNA 0x0020 -#define RT2573_EEPROM_CONFIG2 0x0022 -#define RT2573_EEPROM_BBP_BASE 0x0026 -#define RT2573_EEPROM_TXPOWER 0x0046 -#define RT2573_EEPROM_FREQ_OFFSET 0x005e -#define RT2573_EEPROM_RSSI_2GHZ_OFFSET 0x009a -#define RT2573_EEPROM_RSSI_5GHZ_OFFSET 0x009c diff --git a/sys/dev/usb/if_rumvar.h b/sys/dev/usb/if_rumvar.h deleted file mode 100644 index 59980c0..0000000 --- a/sys/dev/usb/if_rumvar.h +++ /dev/null @@ -1,161 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini@free.fr> - * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RUM_RX_LIST_COUNT 1 -#define RUM_TX_LIST_COUNT 8 - -struct rum_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - uint8_t wr_antenna; - uint8_t wr_antsignal; -}; - -#define RT2573_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)) - -struct rum_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; - uint8_t wt_antenna; -}; - -#define RT2573_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA)) - -struct rum_softc; - -struct rum_tx_data { - struct rum_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct mbuf *m; - struct ieee80211_node *ni; -}; - -struct rum_rx_data { - struct rum_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct mbuf *m; -}; - -struct rum_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amn; -}; -#define RUM_NODE(ni) ((struct rum_node *)(ni)) - -struct rum_vap { - struct ieee80211vap vap; - struct ieee80211_beacon_offsets bo; - struct ieee80211_amrr amrr; - struct callout amrr_ch; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define RUM_VAP(vap) ((struct rum_vap *)(vap)) - -struct rum_softc { - struct ifnet *sc_ifp; - const struct ieee80211_rate_table *sc_rates; - - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - int sc_rx_no; - int sc_tx_no; - - uint8_t rf_rev; - uint8_t rffreq; - - usbd_xfer_handle amrr_xfer; - - usbd_pipe_handle sc_rx_pipeh; - usbd_pipe_handle sc_tx_pipeh; - - enum ieee80211_state sc_state; - int sc_arg; - struct usb_task sc_task; - - struct usb_task sc_scantask; - int sc_scan_action; -#define RUM_SCAN_START 0 -#define RUM_SCAN_END 1 -#define RUM_SET_CHANNEL 2 - - struct rum_rx_data rx_data[RUM_RX_LIST_COUNT]; - struct rum_tx_data tx_data[RUM_TX_LIST_COUNT]; - int tx_queued; - int tx_cur; - - struct mtx sc_mtx; - - struct callout watchdog_ch; - - int sc_tx_timer; - - uint32_t sta[6]; - uint32_t rf_regs[4]; - uint8_t txpow[44]; - - struct { - uint8_t val; - uint8_t reg; - } __packed bbp_prom[16]; - - int hw_radio; - int rx_ant; - int tx_ant; - int nb_ant; - int ext_2ghz_lna; - int ext_5ghz_lna; - int rssi_2ghz_corr; - int rssi_5ghz_corr; - uint8_t bbp17; - - struct rum_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - - struct rum_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#if 0 -#define RUM_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RUM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#else -#define RUM_LOCK(sc) do { ((sc) = (sc)); mtx_lock(&Giant); } while (0) -#define RUM_UNLOCK(sc) mtx_unlock(&Giant) -#endif diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c deleted file mode 100644 index e13170e..0000000 --- a/sys/dev/usb/if_udav.c +++ /dev/null @@ -1,1962 +0,0 @@ -/* $NetBSD: if_udav.c,v 1.2 2003/09/04 15:17:38 tsutsui Exp $ */ -/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2003 - * 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. 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. - * - */ - -/* - * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY) - * The spec can be found at the following url. - * http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf - */ - -/* - * TODO: - * Interrupt Endpoint support - * External PHYs - * powerhook() support? - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_inet.h" -#if defined(__NetBSD__) -#include "opt_ns.h" -#endif -#if defined(__NetBSD__) -#include "bpfilter.h" -#endif -#if defined(__FreeBSD__) -#define NBPFILTER 1 -#endif -#if defined(__NetBSD__) -#include "rnd.h" -#endif - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#if defined(__FreeBSD__) -#include <sys/types.h> -#include <sys/lockmgr.h> -#include <sys/sockio.h> -#endif - -#if defined(__NetBSD__) -#include <sys/device.h> -#endif - -#if defined(NRND) && 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> -#include <net/ethernet.h> -#include <net/if_types.h> - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif -#if defined(__NetBSD__) -#ifndef BPF_MTAP -#define BPF_MTAP(_ifp, _m) do { \ - if ((_ifp)->if_bpf)) { \ - bpf_mtap((_ifp)->if_bpf, (_m)) ; \ - } \ -} while (0) -#endif -#endif - -#if defined(__NetBSD__) -#include <net/if_ether.h> -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_inarp.h> -#endif /* INET */ -#elif defined(__FreeBSD__) /* defined(__NetBSD__) */ -#include <netinet/in.h> -#include <netinet/if_ether.h> -#endif /* defined(__FreeBSD__) */ - -#if defined(__NetBSD__) -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif -#endif /* defined (__NetBSD__) */ - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <dev/usb/usb_port.h> -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usbdivar.h> -#include <dev/usb/usb_ethersubr.h> - -#include <dev/usb/if_udavreg.h> - -#if defined(__FreeBSD__) -MODULE_DEPEND(udav, usb, 1, 1, 1); -MODULE_DEPEND(udav, ether, 1, 1, 1); -MODULE_DEPEND(udav, miibus, 1, 1, 1); -#endif - -/* "device miibus" required. See GENERIC if you get errors here. */ -#include "miibus_if.h" - -#if !defined(__FreeBSD__) -/* Function declarations */ -USB_DECLARE_DRIVER(udav); -#endif - -#if defined(__FreeBSD__) -static device_probe_t udav_match; -static device_attach_t udav_attach; -static device_detach_t udav_detach; -static device_shutdown_t udav_shutdown; -static miibus_readreg_t udav_miibus_readreg; -static miibus_writereg_t udav_miibus_writereg; -static miibus_statchg_t udav_miibus_statchg; -#endif - -static int udav_openpipes(struct udav_softc *); -static void udav_start(struct ifnet *); -static int udav_send(struct udav_softc *, struct mbuf *, int); -static void udav_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -#if defined(__FreeBSD__) -static void udav_rxstart(struct ifnet *ifp); -#endif -static void udav_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void udav_tick(void *); -static void udav_tick_task(void *); -static int udav_ioctl(struct ifnet *, u_long, caddr_t); -static void udav_stop_task(struct udav_softc *); -static void udav_stop(struct ifnet *, int); -static void udav_watchdog(struct ifnet *); -static int udav_ifmedia_change(struct ifnet *); -static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *); -static void udav_lock_mii(struct udav_softc *); -static void udav_unlock_mii(struct udav_softc *); -#if defined(__NetBSD__) -static int udav_miibus_readreg(device_t, int, int); -static void udav_miibus_writereg(device_t, int, int, int); -static void udav_miibus_statchg(device_t); -static int udav_init(struct ifnet *); -#elif defined(__FreeBSD__) -static void udav_init(void *); -#endif -static void udav_setmulti(struct udav_softc *); -static void udav_reset(struct udav_softc *); - -static int udav_csr_read(struct udav_softc *, int, void *, int); -static int udav_csr_write(struct udav_softc *, int, void *, int); -static int udav_csr_read1(struct udav_softc *, int); -static int udav_csr_write1(struct udav_softc *, int, unsigned char); - -#if 0 -static int udav_mem_read(struct udav_softc *, int, void *, int); -static int udav_mem_write(struct udav_softc *, int, void *, int); -static int udav_mem_write1(struct udav_softc *, int, unsigned char); -#endif - -#if defined(__FreeBSD__) -static device_method_t udav_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, udav_match), - DEVMETHOD(device_attach, udav_attach), - DEVMETHOD(device_detach, udav_detach), - DEVMETHOD(device_shutdown, udav_shutdown), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - /* MII interface */ - DEVMETHOD(miibus_readreg, udav_miibus_readreg), - DEVMETHOD(miibus_writereg, udav_miibus_writereg), - DEVMETHOD(miibus_statchg, udav_miibus_statchg), - - { 0, 0 } -}; - -static driver_t udav_driver = { - "udav", - udav_methods, - sizeof(struct udav_softc) -}; - -static devclass_t udav_devclass; - -DRIVER_MODULE(udav, uhub, udav_driver, udav_devclass, usbd_driver_load, 0); -DRIVER_MODULE(miibus, udav, miibus_driver, miibus_devclass, 0, 0); - -#endif /* defined(__FreeBSD__) */ - -/* Macros */ -#ifdef UDAV_DEBUG -#define DPRINTF(x) if (udavdebug) printf x -#define DPRINTFN(n,x) if (udavdebug >= (n)) printf x -int udavdebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define delay(d) DELAY(d) - -#define UDAV_SETBIT(sc, reg, x) \ - udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x)) - -#define UDAV_CLRBIT(sc, reg, x) \ - udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x)) - -static const struct udav_type { - struct usb_devno udav_dev; - u_int16_t udav_flags; -#define UDAV_EXT_PHY 0x0001 -} udav_devs [] = { - /* Corega USB-TXC */ - {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0}, - /* ShanTou ST268 USB NIC */ - {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268 }, 0}, - /* ShanTou DM9601 USB NIC */ - {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601}, 0}, -}; -#define udav_lookup(v, p) ((const struct udav_type *)usb_lookup(udav_devs, v, p)) - - -/* Probe */ -static int -udav_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (udav_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -/* Attach */ -static int -udav_attach(device_t self) -{ - USB_ATTACH_START(udav, 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; - const char *devname ; - struct ifnet *ifp; -#if defined(__NetBSD__) - struct mii_data *mii; -#endif - u_char eaddr[ETHER_ADDR_LEN]; - int i; -#if defined(__NetBSD__) - int s; -#endif - - sc->sc_dev = self; - devname = device_get_nameunit(self); - /* Move the device into the configured state. */ - err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1); - if (err) { - printf("%s: setting config no failed\n", devname); - goto bad; - } - - usb_init_task(&sc->sc_tick_task, udav_tick_task, sc); - lockinit(&sc->sc_mii_lock, PZERO, "udavmii", 0, 0); - usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc); - - /* get control interface */ - err = usbd_device2interface_handle(dev, UDAV_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 = udav_lookup(uaa->vendor, uaa->product)->udav_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; - } - -#if defined(__FreeBSD__) - mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); -#endif -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - /* reset the adapter */ - udav_reset(sc); - - /* Get Ethernet Address */ - err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN); - if (err) { - printf("%s: read MAC address failed\n", devname); -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); - mtx_destroy(&sc->sc_mtx); -#endif - goto bad; - } - - /* Print Ethernet Address */ - printf("%s: Ethernet address %s\n", devname, ether_sprintf(eaddr)); - - /* initialize interface infomation */ -#if defined(__FreeBSD__) - ifp = GET_IFP(sc) = if_alloc(IFT_ETHER); - if (ifp == NULL) { - printf("%s: can not if_alloc\n", devname); - UDAV_UNLOCK(sc); - mtx_destroy(&sc->sc_mtx); - goto bad; - } -#else - ifp = GET_IFP(sc); -#endif - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; -#if defined(__NetBSD__) - strncpy(ifp->if_xname, devname, IFNAMSIZ); -#elif defined(__FreeBSD__) - if_initname(ifp, "udav", device_get_unit(self)); -#endif - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_start = udav_start; - ifp->if_ioctl = udav_ioctl; - ifp->if_watchdog = udav_watchdog; - ifp->if_init = udav_init; -#if defined(__NetBSD__) - ifp->if_stop = udav_stop; -#endif -#if defined(__FreeBSD__) - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; -#endif -#if defined(__NetBSD__) - IFQ_SET_READY(&ifp->if_snd); -#endif - - -#if defined(__NetBSD__) - /* - * Do ifmedia setup. - */ - mii = &sc->sc_mii; - mii->mii_ifp = ifp; - mii->mii_readreg = udav_miibus_readreg; - mii->mii_writereg = udav_miibus_writereg; - mii->mii_statchg = udav_miibus_statchg; - mii->mii_flags = MIIF_AUTOTSLEEP; - ifmedia_init(&mii->mii_media, 0, - udav_ifmedia_change, udav_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); -#elif defined(__FreeBSD__) - if (mii_phy_probe(self, &sc->sc_miibus, - udav_ifmedia_change, udav_ifmedia_status)) { - printf("%s: MII without any PHY!\n", device_get_nameunit(sc->sc_dev)); - if_free(ifp); - UDAV_UNLOCK(sc); - mtx_destroy(&sc->sc_mtx); - return ENXIO; - } - - sc->sc_qdat.ifp = ifp; - sc->sc_qdat.if_rxstart = udav_rxstart; - - /* - * Call MI attach routine. - */ - - ether_ifattach(ifp, eaddr); -#endif - -#if defined(NRND) && NRND > 0 - rnd_attach_source(&sc->rnd_source, devname, RND_TYPE_NET, 0); -#endif - - usb_callout_init(sc->sc_stat_ch); -#if defined(__FreeBSD__) - usb_register_netisr(); -#endif - sc->sc_attached = 1; -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); - - return 0; - - bad: - sc->sc_dying = 1; - return ENXIO; -} - -/* detach */ -static int -udav_detach(device_t self) -{ - USB_DETACH_START(udav, sc); - struct ifnet *ifp = GET_IFP(sc); -#if defined(__NetBSD__) - int s; -#endif - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - /* Detached before attached finished */ - if (!sc->sc_attached) - return (0); - - UDAV_LOCK(sc); - - usb_uncallout(sc->sc_stat_ch, udav_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); - -#if defined(__NetBSD__) - s = splusb(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away */ - usb_detach_wait(sc->sc_dev); - } -#if defined(__FreeBSD__) - if (ifp->if_drv_flags & IFF_DRV_RUNNING) -#else - if (ifp->if_flags & IFF_RUNNING) -#endif - udav_stop(GET_IFP(sc), 1); - -#if defined(NRND) && NRND > 0 - rnd_detach_source(&sc->rnd_source); -#endif -#if defined(__NetBSD__) - mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); - ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); -#endif - ether_ifdetach(ifp); -#if defined(__NetBSD__) - if_detach(ifp); -#endif -#if defined(__FreeBSD__) - if_free(ifp); -#endif - -#ifdef DIAGNOSTIC - if (sc->sc_pipe_tx != NULL) - printf("%s: detach has active tx endpoint.\n", - device_get_nameunit(sc->sc_dev)); - if (sc->sc_pipe_rx != NULL) - printf("%s: detach has active rx endpoint.\n", - device_get_nameunit(sc->sc_dev)); - if (sc->sc_pipe_intr != NULL) - printf("%s: detach has active intr endpoint.\n", - device_get_nameunit(sc->sc_dev)); -#endif - sc->sc_attached = 0; - -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - -#if defined(__FreeBSD__) - mtx_destroy(&sc->sc_mtx); -#endif - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - return (0); -} - -#if 0 -/* read memory */ -static int -udav_mem_read(struct udav_softc *sc, 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", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xffff; - len &= 0xff; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_MEM_READ; - USETW(req.wValue, 0x0000); - USETW(req.wIndex, offset); - USETW(req.wLength, len); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} - -/* write memory */ -static int -udav_mem_write(struct udav_softc *sc, 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", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xffff; - len &= 0xff; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_MEM_WRITE; - USETW(req.wValue, 0x0000); - USETW(req.wIndex, offset); - USETW(req.wLength, len); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} - -/* write memory */ -static int -udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch) -{ - usb_device_request_t req; - usbd_status err; - - if (sc == NULL) - return (0); - - DPRINTFN(0x200, - ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xffff; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_MEM_WRITE1; - USETW(req.wValue, ch); - USETW(req.wIndex, offset); - USETW(req.wLength, 0x0000); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} -#endif - -/* read register(s) */ -static int -udav_csr_read(struct udav_softc *sc, 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", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xff; - len &= 0xff; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_REG_READ; - USETW(req.wValue, 0x0000); - USETW(req.wIndex, offset); - USETW(req.wLength, len); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} - -/* write register(s) */ -static int -udav_csr_write(struct udav_softc *sc, 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", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xff; - len &= 0xff; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_REG_WRITE; - USETW(req.wValue, 0x0000); - USETW(req.wIndex, offset); - USETW(req.wLength, len); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} - -static int -udav_csr_read1(struct udav_softc *sc, int offset) -{ - u_int8_t val = 0; - - if (sc == NULL) - return (0); - - DPRINTFN(0x200, - ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - return (udav_csr_read(sc, offset, &val, 1) ? 0 : val); -} - -/* write a register */ -static int -udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch) -{ - usb_device_request_t req; - usbd_status err; - - if (sc == NULL) - return (0); - - DPRINTFN(0x200, - ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (0); - - offset &= 0xff; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UDAV_REQ_REG_WRITE1; - USETW(req.wValue, ch); - USETW(req.wIndex, offset); - USETW(req.wLength, 0x0000); - - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err) { - DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_get_nameunit(sc->sc_dev), __func__, offset, err)); - } - - return (err); -} - -#if defined(__NetBSD__) -static int -udav_init(struct ifnet *ifp) -#elif defined(__FreeBSD__) -static void -udav_init(void *xsc) -#endif -{ -#if defined(__NetBSD__) - struct udav_softc *sc = ifp->if_softc; -#elif defined(__FreeBSD__) - struct udav_softc *sc = (struct udav_softc *)xsc; - struct ifnet *ifp = GET_IFP(sc); -#endif - struct mii_data *mii = GET_MII(sc); - u_char *eaddr; -#if defined(__NetBSD__) - int s; -#endif - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) -#if defined(__NetBSD__) - return (EIO); -#elif defined(__FreeBSD__) - return ; -#endif - -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - /* Cancel pending I/O and free all TX/RX buffers */ - udav_stop(ifp, 1); - -#if defined(__NetBSD__) - eaddr = LLADDR(ifp->if_sadl); -#elif defined(__FreeBSD__) - eaddr = IF_LLADDR(ifp); -#endif - udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN); - - /* Initialize network control register */ - /* Disable loopback */ - UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1); - - /* Initialize RX control register */ - UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC); - - /* If we want promiscuous mode, accept all physical frames. */ - if (ifp->if_flags & IFF_PROMISC) - UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC); - else - UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC); - - /* Initialize transmit ring */ - if (usb_ether_tx_list_init(sc, &sc->sc_cdata, - sc->sc_udev) == ENOBUFS) { - printf("%s: tx list init failed\n", device_get_nameunit(sc->sc_dev)); -#if defined(__NetBSD__) - splx(s); - return (EIO); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); - return ; -#endif - - } - - /* Initialize receive ring */ - if (usb_ether_rx_list_init(sc, &sc->sc_cdata, - sc->sc_udev) == ENOBUFS) { - printf("%s: rx list init failed\n", device_get_nameunit(sc->sc_dev)); -#if defined(__NetBSD__) - splx(s); - return (EIO); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); - return ; -#endif - } - - /* Load the multicast filter */ - udav_setmulti(sc); - - /* Enable RX */ - UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN); - - /* clear POWER_DOWN state of internal PHY */ - UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0); - UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0); - - mii_mediachg(mii); - - if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { - if (udav_openpipes(sc)) { -#if defined(__NetBSD__) - splx(s); - return (EIO); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); - return ; -#endif - } - } - -#if defined(__FreeBSD__) - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -#else - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; -#endif - -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - - usb_callout(sc->sc_stat_ch, hz, udav_tick, sc); - -#if defined(__NetBSD__) - return (0); -#elif defined(__FreeBSD__) - return ; -#endif -} - -static void -udav_reset(struct udav_softc *sc) -{ - int i; - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return; - - /* Select PHY */ -#if 1 - /* - * XXX: force select internal phy. - * external phy routines are not tested. - */ - UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY); -#else - if (sc->sc_flags & UDAV_EXT_PHY) { - UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY); - } else { - UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY); - } -#endif - - UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST); - - for (i = 0; i < UDAV_TX_TIMEOUT; i++) { - if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST)) - break; - delay(10); /* XXX */ - } - delay(10000); /* XXX */ -} - -#if defined(__NetBSD__) || defined(__OpenBSD__) -int -udav_activate(device_t self, enum devact act) -{ - struct udav_softc *sc = (struct udav_softc *)self; - - DPRINTF(("%s: %s: enter, act=%d\n", device_get_nameunit(sc->sc_dev), - __func__, 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); -} -#endif - -#define UDAV_BITS 6 - -#define UDAV_CALCHASH(addr) \ - (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1)) - -static void -udav_setmulti(struct udav_softc *sc) -{ - struct ifnet *ifp; -#if defined(__NetBSD__) - struct ether_multi *enm; - struct ether_multistep step; -#elif defined(__FreeBSD__) - struct ifmultiaddr *ifma; -#endif - u_int8_t hashes[8]; - int h = 0; - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return; - - ifp = GET_IFP(sc); - - if (ifp->if_flags & IFF_PROMISC) { - UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC); - return; - } else if (ifp->if_flags & IFF_ALLMULTI) { -#if defined(__NetBSD__) - allmulti: -#endif - ifp->if_flags |= IFF_ALLMULTI; - UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL); - UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC); - return; - } - - /* first, zot all the existing hash bits */ - memset(hashes, 0x00, sizeof(hashes)); - hashes[7] |= 0x80; /* broadcast address */ - udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes)); - - /* now program new ones */ -#if defined(__NetBSD__) - 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 = UDAV_CALCHASH(enm->enm_addrlo); - hashes[h>>3] |= 1 << (h & 0x7); - ETHER_NEXT_MULTI(step, enm); - } -#elif defined(__FreeBSD__) - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = UDAV_CALCHASH(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr)); - hashes[h>>3] |= 1 << (h & 0x7); - } - IF_ADDR_UNLOCK(ifp); -#endif - - /* disable all multicast */ - ifp->if_flags &= ~IFF_ALLMULTI; - UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL); - - /* write hash value to the register */ - udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes)); -} - -static int -udav_openpipes(struct udav_softc *sc) -{ - struct ue_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", - device_get_nameunit(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", - device_get_nameunit(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.ue_ibuf, UDAV_INTR_PKGLEN, - udav_intr, UDAV_INTR_INTERVAL); - if (err) { - printf("%s: open intr pipe failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } -#endif - - - /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->sc_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_rx, - c, c->ue_buf, UE_BUFSZ, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, udav_rxeof); - (void)usbd_transfer(c->ue_xfer); - DPRINTF(("%s: %s: start read\n", device_get_nameunit(sc->sc_dev), - __func__)); - } - - done: - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - return (error); -} - -static void -udav_start(struct ifnet *ifp) -{ - struct udav_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - DPRINTF(("%s: %s: enter, link=%d\n", device_get_nameunit(sc->sc_dev), - __func__, sc->sc_link)); - - if (sc->sc_dying) - return; - - if (!sc->sc_link) - return; - -#if defined(__FreeBSD__) - if (ifp->if_drv_flags & IFF_DRV_OACTIVE) -#else - if (ifp->if_flags & IFF_OACTIVE) -#endif - return; -#if defined(__NetBSD__) - IFQ_POLL(&ifp->if_snd, m_head); -#elif defined(__FreeBSD__) - IF_DEQUEUE(&ifp->if_snd, m_head); -#endif - if (m_head == NULL) - return; - - if (udav_send(sc, m_head, 0)) { -#if defined(__FreeBSD__) - IF_PREPEND(&ifp->if_snd, m_head); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; -#else - ifp->if_flags |= IFF_OACTIVE; -#endif - return; - } - -#if defined(__NetBSD__) - IFQ_DEQUEUE(&ifp->if_snd, m_head); -#endif - -#if NBPFILTER > 0 - BPF_MTAP(ifp, m_head); -#endif - -#if defined(__FreeBSD__) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; -#else - ifp->if_flags |= IFF_OACTIVE; -#endif - - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; -} - -static int -udav_send(struct udav_softc *sc, struct mbuf *m, int idx) -{ - int total_len; - struct ue_chain *c; - usbd_status err; - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev),__func__)); - - c = &sc->sc_cdata.ue_tx_chain[idx]; - - /* Copy the mbuf data into a contiguous buffer */ - /* first 2 bytes are packet length */ - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2); - c->ue_mbuf = m; - total_len = m->m_pkthdr.len; - if (total_len < UDAV_MIN_FRAME_LEN) { - memset(c->ue_buf + 2 + total_len, 0, - UDAV_MIN_FRAME_LEN - total_len); - total_len = UDAV_MIN_FRAME_LEN; - } - - /* Frame length is specified in the first 2bytes of the buffer */ - c->ue_buf[0] = (u_int8_t)total_len; - c->ue_buf[1] = (u_int8_t)(total_len >> 8); - total_len += 2; - - usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_tx, c, c->ue_buf, total_len, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, - UDAV_TX_TIMEOUT, udav_txeof); - - /* Transmit */ - sc->sc_refcnt++; - err = usbd_transfer(c->ue_xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - if (err != USBD_IN_PROGRESS) { - printf("%s: udav_send error=%s\n", device_get_nameunit(sc->sc_dev), - usbd_errstr(err)); - /* Stop the interface */ - usb_add_task(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER); - return (EIO); - } - - DPRINTF(("%s: %s: send %d bytes\n", device_get_nameunit(sc->sc_dev), - __func__, total_len)); - - sc->sc_cdata.ue_tx_cnt++; - - return (0); -} - -static void -udav_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct udav_softc *sc = c->ue_sc; - struct ifnet *ifp = GET_IFP(sc); -#if defined(__NetBSD__) - int s; -#endif - - if (sc->sc_dying) - return; - -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - ifp->if_timer = 0; -#if defined(__FreeBSD__) - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -#else - ifp->if_flags &= ~IFF_OACTIVE; -#endif - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - return; - } - ifp->if_oerrors++; - printf("%s: usb error on tx: %s\n", device_get_nameunit(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(sc->sc_dev); - } -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - return; - } - - ifp->if_opackets++; - - m_freem(c->ue_mbuf); - c->ue_mbuf = NULL; - -#if defined(__NetBSD__) - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) -#elif defined(__FreeBSD__) - if ( ifp->if_snd.ifq_head != NULL ) -#endif - udav_start(ifp); - -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif -} - -static void -udav_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ue_chain *c = priv; - struct udav_softc *sc = c->ue_sc; - struct ifnet *ifp = GET_IFP(sc); - struct mbuf *m; - u_int32_t total_len; - u_int8_t *pktstat; -#if defined(__NetBSD__) - int s; -#endif - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev),__func__)); - - 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", - device_get_nameunit(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(sc->sc_dev); - } - goto done; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - - /* copy data to mbuf */ - m = c->ue_mbuf; - memcpy(mtod(m, char *), c->ue_buf, total_len); - - /* first byte in received data */ - pktstat = mtod(m, u_int8_t *); - m_adj(m, sizeof(u_int8_t)); - DPRINTF(("%s: RX Status: 0x%02x\n", device_get_nameunit(sc->sc_dev), *pktstat)); - - total_len = UGETW(mtod(m, u_int8_t *)); - m_adj(m, sizeof(u_int16_t)); - - if (*pktstat & UDAV_RSR_LCS) { - ifp->if_collisions++; - goto done; - } - - if (total_len < sizeof(struct ether_header) || - *pktstat & UDAV_RSR_ERR) { - ifp->if_ierrors++; - goto done; - } - - ifp->if_ipackets++; - total_len -= ETHER_CRC_LEN; - - m->m_pkthdr.len = m->m_len = total_len; -#if defined(__NetBSD__) - m->m_pkthdr.rcvif = ifp; -#elif defined(__FreeBSD__) - m->m_pkthdr.rcvif = (struct ifnet *)&sc->sc_qdat; -#endif - -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - -#if defined(__NetBSD__) - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", device_get_nameunit(sc->sc_dev)); - ifp->if_ierrors++; - goto done1; - } -#endif - -#if NBPFILTER > 0 - BPF_MTAP(ifp, m); -#endif - - DPRINTF(("%s: %s: deliver %d\n", device_get_nameunit(sc->sc_dev), - __func__, m->m_len)); -#if defined(__NetBSD__) - IF_INPUT(ifp, m); -#endif -#if defined(__FreeBSD__) - usb_ether_input(m); - UDAV_UNLOCK(sc); - return ; -#endif - -#if defined(__NetBSD__) - done1: - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - done: - /* Setup new transfer */ - usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->ue_buf, UE_BUFSZ, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, udav_rxeof); - sc->sc_refcnt++; - usbd_transfer(xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - DPRINTF(("%s: %s: start rx\n", device_get_nameunit(sc->sc_dev), __func__)); -} - -#if 0 -static void udav_intr() -{ -} -#endif - -static int -udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct udav_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - struct mii_data *mii; -#if defined(__NetBSD__) - int s; -#endif - int error = 0; - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return (EIO); - -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - switch (cmd) { -#if defined(__FreeBSD__) - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC) { - UDAV_SETBIT(sc, UDAV_RCR, - UDAV_RCR_ALL|UDAV_RCR_PRMSC); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC)) { - if (ifp->if_flags & IFF_ALLMULTI) - UDAV_CLRBIT(sc, UDAV_RCR, - UDAV_RCR_PRMSC); - else - UDAV_CLRBIT(sc, UDAV_RCR, - UDAV_RCR_ALL|UDAV_RCR_PRMSC); - } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - udav_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - udav_stop(ifp, 1); - } - error = 0; - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - udav_setmulti(sc); - error = 0; - break; -#endif - 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 defined(__NetBSD__) - if (error == ENETRESET) { - udav_setmulti(sc); - error = 0; - } -#endif - break; - } - -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif - - return (error); -} - -static void -udav_watchdog(struct ifnet *ifp) -{ - struct udav_softc *sc = ifp->if_softc; - struct ue_chain *c; - usbd_status stat; -#if defined(__NetBSD__) - int s; -#endif - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - ifp->if_oerrors++; - printf("%s: watchdog timeout\n", device_get_nameunit(sc->sc_dev)); - -#if defined(__NetBSD__) - s = splusb(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc) -#endif - c = &sc->sc_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - udav_txeof(c->ue_xfer, c, stat); - -#if defined(__NetBSD__) - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) -#elif defined(__FreeBSD__) - if ( ifp->if_snd.ifq_head != NULL ) -#endif - udav_start(ifp); -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif -} - -static void -udav_stop_task(struct udav_softc *sc) -{ - udav_stop(GET_IFP(sc), 1); -} - -/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ -static void -udav_stop(struct ifnet *ifp, int disable) -{ - struct udav_softc *sc = ifp->if_softc; - usbd_status err; - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - ifp->if_timer = 0; - - udav_reset(sc); - - usb_uncallout(sc->sc_stat_ch, udav_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", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_rx); - if (err) - printf("%s: close rx pipe failed: %s\n", - device_get_nameunit(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", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_tx); - if (err) - printf("%s: close tx pipe failed: %s\n", - device_get_nameunit(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", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_intr); - if (err) - printf("%s: close intr pipe failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_intr = NULL; - } -#endif - - /* Free RX resources. */ - usb_ether_rx_list_free(&sc->sc_cdata); - /* Free TX resources. */ - usb_ether_tx_list_free(&sc->sc_cdata); - - sc->sc_link = 0; -#if defined(__FreeBSD__) - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#else - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); -#endif -} - -/* Set media options */ -static int -udav_ifmedia_change(struct ifnet *ifp) -{ - struct udav_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - 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 -udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct udav_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return; - -#if defined(__FreeBSD__) - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { -#else - if ((ifp->if_flags & IFF_RUNNING) == 0) { -#endif - 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 -udav_tick(void *xsc) -{ - struct udav_softc *sc = xsc; - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), - __func__)); - - if (sc->sc_dying) - return; - - /* Perform periodic stuff in process context */ - usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER); -} - -static void -udav_tick_task(void *xsc) -{ - struct udav_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; -#if defined(__NetBSD__) - int s; -#endif - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), - __func__)); - - if (sc->sc_dying) - return; - - ifp = GET_IFP(sc); - mii = GET_MII(sc); - - if (mii == NULL) - return; - -#if defined(__NetBSD__) - s = splnet(); -#elif defined(__FreeBSD__) - UDAV_LOCK(sc); -#endif - - 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", - device_get_nameunit(sc->sc_dev), __func__)); - sc->sc_link++; -#if defined(__NetBSD__) - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) -#elif defined(__FreeBSD__) - if ( ifp->if_snd.ifq_head != NULL ) -#endif - udav_start(ifp); - } - } - - usb_callout(sc->sc_stat_ch, hz, udav_tick, sc); - -#if defined(__NetBSD__) - splx(s); -#elif defined(__FreeBSD__) - UDAV_UNLOCK(sc); -#endif -} - -/* Get exclusive access to the MII registers */ -static void -udav_lock_mii(struct udav_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), - __func__)); - - sc->sc_refcnt++; - lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL); -} - -static void -udav_unlock_mii(struct udav_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), - __func__)); - - lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); -} - -static int -udav_miibus_readreg(device_t dev, int phy, int reg) -{ - struct udav_softc *sc; - u_int8_t val[2]; - u_int16_t data16; - - if (dev == NULL) - return (0); - - sc = USBGETSOFTC(dev); - - DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", - device_get_nameunit(sc->sc_dev), __func__, phy, reg)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", device_get_nameunit(sc->sc_dev), - __func__); -#endif - return (0); - } - - /* XXX: one PHY only for the internal PHY */ - if (phy != 0) { - DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - device_get_nameunit(sc->sc_dev), __func__, phy)); - return (0); - } - - udav_lock_mii(sc); - - /* select internal PHY and set PHY register address */ - udav_csr_write1(sc, UDAV_EPAR, - UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK)); - - /* select PHY operation and start read command */ - udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR); - - /* XXX: should be wait? */ - - /* end read command */ - UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR); - - /* retrieve the result from data registers */ - udav_csr_read(sc, UDAV_EPDRL, val, 2); - - udav_unlock_mii(sc); - - data16 = val[0] | (val[1] << 8); - - DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", - device_get_nameunit(sc->sc_dev), __func__, phy, reg, data16)); - - return (data16); -} - -static int -udav_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct udav_softc *sc; - u_int8_t val[2]; - - if (dev == NULL) - return (0); /* XXX real error? */ - - sc = USBGETSOFTC(dev); - - DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", - device_get_nameunit(sc->sc_dev), __func__, phy, reg, data)); - - if (sc->sc_dying) { -#ifdef DIAGNOSTIC - printf("%s: %s: dying\n", device_get_nameunit(sc->sc_dev), - __func__); -#endif - return (0); /* XXX real error? */ - } - - /* XXX: one PHY only for the internal PHY */ - if (phy != 0) { - DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - device_get_nameunit(sc->sc_dev), __func__, phy)); - return (0); /* XXX real error? */ - } - - udav_lock_mii(sc); - - /* select internal PHY and set PHY register address */ - udav_csr_write1(sc, UDAV_EPAR, - UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK)); - - /* put the value to the data registers */ - val[0] = data & 0xff; - val[1] = (data >> 8) & 0xff; - udav_csr_write(sc, UDAV_EPDRL, val, 2); - - /* select PHY operation and start write command */ - udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW); - - /* XXX: should be wait? */ - - /* end write command */ - UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW); - - udav_unlock_mii(sc); - - return (0); -} - -static void -udav_miibus_statchg(device_t dev) -{ -#ifdef UDAV_DEBUG - struct udav_softc *sc; - - if (dev == NULL) - return; - - sc = USBGETSOFTC(dev); - DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__)); -#endif - /* Nothing to do */ -} - -#if defined(__FreeBSD__) -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static int -udav_shutdown(device_t dev) -{ - struct udav_softc *sc; - - sc = device_get_softc(dev); - - udav_stop_task(sc); - - return (0); -} - -static void -udav_rxstart(struct ifnet *ifp) -{ - struct udav_softc *sc; - struct ue_chain *c; - - sc = ifp->if_softc; - UDAV_LOCK(sc); - c = &sc->sc_cdata.ue_rx_chain[sc->sc_cdata.ue_rx_prod]; - - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", device_get_nameunit(sc->sc_dev)); - ifp->if_ierrors++; - UDAV_UNLOCK(sc); - return; - } - - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_rx, - c, c->ue_buf, UE_BUFSZ, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, udav_rxeof); - usbd_transfer(c->ue_xfer); - - UDAV_UNLOCK(sc); - return; -} -#endif diff --git a/sys/dev/usb/if_udavreg.h b/sys/dev/usb/if_udavreg.h deleted file mode 100644 index cb7da28..0000000 --- a/sys/dev/usb/if_udavreg.h +++ /dev/null @@ -1,210 +0,0 @@ -/* $NetBSD: if_udavreg.h,v 1.2 2003/09/04 15:17:39 tsutsui Exp $ */ -/* $nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $ */ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2003 - * 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. 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 UDAV_IFACE_INDEX 0 -#define UDAV_CONFIG_NO 1 - -#define UDAV_TX_TIMEOUT 1000 -#define UDAV_TIMEOUT 10000 - -#define ETHER_ALIGN 2 - - -/* Packet length */ -#define UDAV_MIN_FRAME_LEN 60 - -/* Request */ -#define UDAV_REQ_REG_READ 0x00 /* Read from register(s) */ -#define UDAV_REQ_REG_WRITE 0x01 /* Write to register(s) */ -#define UDAV_REQ_REG_WRITE1 0x03 /* Write to a register */ - -#define UDAV_REQ_MEM_READ 0x02 /* Read from memory */ -#define UDAV_REQ_MEM_WRITE 0x05 /* Write to memory */ -#define UDAV_REQ_MEM_WRITE1 0x07 /* Write a byte to memory */ - -/* Registers */ -#define UDAV_NCR 0x00 /* Network Control Register */ -#define UDAV_NCR_EXT_PHY (1<<7) /* Select External PHY */ -#define UDAV_NCR_WAKEEN (1<<6) /* Wakeup Event Enable */ -#define UDAV_NCR_FCOL (1<<4) /* Force Collision Mode */ -#define UDAV_NCR_FDX (1<<3) /* Full-Duplex Mode (RO on Int. PHY) */ -#define UDAV_NCR_LBK1 (1<<2) /* Lookback Mode */ -#define UDAV_NCR_LBK0 (1<<1) /* Lookback Mode */ -#define UDAV_NCR_RST (1<<0) /* Software reset */ - -#define UDAV_RCR 0x05 /* RX Control Register */ -#define UDAV_RCR_WTDIS (1<<6) /* Watchdog Timer Disable */ -#define UDAV_RCR_DIS_LONG (1<<5) /* Discard Long Packet(over 1522Byte) */ -#define UDAV_RCR_DIS_CRC (1<<4) /* Discard CRC Error Packet */ -#define UDAV_RCR_ALL (1<<3) /* Pass All Multicast */ -#define UDAV_RCR_RUNT (1<<2) /* Pass Runt Packet */ -#define UDAV_RCR_PRMSC (1<<1) /* Promiscuous Mode */ -#define UDAV_RCR_RXEN (1<<0) /* RX Enable */ - -#define UDAV_RSR 0x06 /* RX Status Register */ -#define UDAV_RSR_RF (1<<7) /* Runt Frame */ -#define UDAV_RSR_MF (1<<6) /* Multicast Frame */ -#define UDAV_RSR_LCS (1<<5) /* Late Collision Seen */ -#define UDAV_RSR_RWTO (1<<4) /* Receive Watchdog Time-Out */ -#define UDAV_RSR_PLE (1<<3) /* Physical Layer Error */ -#define UDAV_RSR_AE (1<<2) /* Alignment Error */ -#define UDAV_RSR_CE (1<<1) /* CRC Error */ -#define UDAV_RSR_FOE (1<<0) /* FIFO Overflow Error */ -#define UDAV_RSR_ERR (UDAV_RSR_RF | UDAV_RSR_LCS | UDAV_RSR_RWTO |\ - UDAV_RSR_PLE | UDAV_RSR_AE | UDAV_RSR_CE |\ - UDAV_RSR_FOE) - -#define UDAV_EPCR 0x0b /* EEPROM & PHY Control Register */ -#define UDAV_EPCR_REEP (1<<5) /* Reload EEPROM */ -#define UDAV_EPCR_WEP (1<<4) /* Write EEPROM enable */ -#define UDAV_EPCR_EPOS (1<<3) /* EEPROM or PHY Operation Select */ -#define UDAV_EPCR_ERPRR (1<<2) /* EEPROM/PHY Register Read Command */ -#define UDAV_EPCR_ERPRW (1<<1) /* EEPROM/PHY Register Write Command */ -#define UDAV_EPCR_ERRE (1<<0) /* EEPROM/PHY Access Status */ - -#define UDAV_EPAR 0x0c /* EEPROM & PHY Control Register */ -#define UDAV_EPAR_PHY_ADR1 (1<<7) /* PHY Address bit 1 */ -#define UDAV_EPAR_PHY_ADR0 (1<<6) /* PHY Address bit 0 */ -#define UDAV_EPAR_EROA (1<<0) /* EEPROM Word/PHY Register Address */ -#define UDAV_EPAR_EROA_MASK (0x1f) /* [5:0] */ - -#define UDAV_EPDRL 0x0d /* EEPROM & PHY Data Register */ -#define UDAV_EPDRH 0x0e /* EEPROM & PHY Data Register */ - -#define UDAV_PAR0 0x10 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR1 0x11 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR2 0x12 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR3 0x13 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR4 0x14 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR5 0x15 /* Ethernet Address, load from EEPROM */ -#define UDAV_PAR UDAV_PAR0 - -#define UDAV_MAR0 0x16 /* Multicast Register */ -#define UDAV_MAR1 0x17 /* Multicast Register */ -#define UDAV_MAR2 0x18 /* Multicast Register */ -#define UDAV_MAR3 0x19 /* Multicast Register */ -#define UDAV_MAR4 0x1a /* Multicast Register */ -#define UDAV_MAR5 0x1b /* Multicast Register */ -#define UDAV_MAR6 0x1c /* Multicast Register */ -#define UDAV_MAR7 0x1d /* Multicast Register */ -#define UDAV_MAR UDAV_MAR0 - -#define UDAV_GPCR 0x1e /* General purpose control register */ -#define UDAV_GPCR_GEP_CNTL6 (1<<6) /* General purpose control 6 */ -#define UDAV_GPCR_GEP_CNTL5 (1<<5) /* General purpose control 5 */ -#define UDAV_GPCR_GEP_CNTL4 (1<<4) /* General purpose control 4 */ -#define UDAV_GPCR_GEP_CNTL3 (1<<3) /* General purpose control 3 */ -#define UDAV_GPCR_GEP_CNTL2 (1<<2) /* General purpose control 2 */ -#define UDAV_GPCR_GEP_CNTL1 (1<<1) /* General purpose control 1 */ -#define UDAV_GPCR_GEP_CNTL0 (1<<0) /* General purpose control 0 */ - -#define UDAV_GPR 0x1f /* General purpose register */ -#define UDAV_GPR_GEPIO6 (1<<6) /* General purpose 6 */ -#define UDAV_GPR_GEPIO5 (1<<5) /* General purpose 5 */ -#define UDAV_GPR_GEPIO4 (1<<4) /* General purpose 4 */ -#define UDAV_GPR_GEPIO3 (1<<3) /* General purpose 3 */ -#define UDAV_GPR_GEPIO2 (1<<2) /* General purpose 2 */ -#define UDAV_GPR_GEPIO1 (1<<1) /* General purpose 1 */ -#define UDAV_GPR_GEPIO0 (1<<0) /* General purpose 0 */ - -#if defined(__FreeBSD__) -#define GET_IFP(sc) ((sc)->sc_ifp) -#elif defined(__OpenBSD__) -#define GET_IFP(sc) (&(sc)->sc_ac.ac_if) -#elif defined(__NetBSD__) -#define GET_IFP(sc) (&(sc)->sc_ec.ec_if) -#endif -#if defined(__FreeBSD__) -#define GET_MII(sc) (device_get_softc((sc)->sc_miibus)) -#else -#define GET_MII(sc) (&(sc)->sc_mii) -#endif - -#if defined(__FreeBSD__) -#if 0 -#define UDAV_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define UDAV_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#else -#define UDAV_LOCK(_sc) -#define UDAV_UNLOCK(_sc) -#endif -#endif - -struct udav_softc { -#if defined(__FreeBSD__) - struct ifnet *sc_ifp; -#endif - device_t 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 */ - -#if defined(__FreeBSD__) - device_t sc_miibus ; - struct mtx sc_mtx ; - struct usb_qdat sc_qdat; -#elif defined(__NetBSD__) - struct ethercom sc_ec; /* ethernet common */ - struct mii_data sc_mii; -#endif - struct lock sc_mii_lock; - int sc_link; -#define sc_media udav_mii.mii_media -#if defined(NRND) && NRND > 0 - rndsource_element_t rnd_source; -#endif - struct ue_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/if_upgt.c b/sys/dev/usb/if_upgt.c deleted file mode 100644 index 9ab226f..0000000 --- a/sys/dev/usb/if_upgt.c +++ /dev/null @@ -1,2375 +0,0 @@ -/* $OpenBSD: if_upgt.c,v 1.35 2008/04/16 18:32:15 damien Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/endian.h> -#include <sys/firmware.h> -#include <sys/linker.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_phy.h> -#include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_regdomain.h> - -#include <net/bpf.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/usb/if_upgtvar.h> - -/* - * Driver for the USB PrismGT devices. - * - * For now just USB 2.0 devices with the GW3887 chipset are supported. - * The driver has been written based on the firmware version 2.13.1.0_LM87. - * - * TODO's: - * - MONITOR mode test. - * - Add HOSTAP mode. - * - Add IBSS mode. - * - Support the USB 1.0 devices (NET2280, ISL3880, ISL3886 chipsets). - * - * Parts of this driver has been influenced by reading the p54u driver - * written by Jean-Baptiste Note <jean-baptiste.note@m4x.org> and - * Sebastien Bourdeauducq <lekernel@prism54.org>. - */ - -SYSCTL_NODE(_hw, OID_AUTO, upgt, CTLFLAG_RD, 0, - "USB PrismGT GW3887 driver parameters"); - -/* - * NB: normally `upgt_txbuf' value can be increased to maximum 6, mininum 1. - * However, we're using just 2 txbufs to protect packet losses in some cases - * so the performance was sacrificed that with this value its speed is about - * 2.1Mb/s. - * - * With setting txbuf value as 6, you can get full speed, 3.0Mb/s, of this - * device but sometimes you'd meet some packet losses then retransmision. - */ -static int upgt_txbuf = UPGT_TX_COUNT; /* # tx buffers to allocate */ -SYSCTL_INT(_hw_upgt, OID_AUTO, txbuf, CTLFLAG_RW, &upgt_txbuf, - 0, "tx buffers allocated"); -TUNABLE_INT("hw.upgt.txbuf", &upgt_txbuf); - -#ifdef UPGT_DEBUG -int upgt_debug = 0; -SYSCTL_INT(_hw_upgt, OID_AUTO, debug, CTLFLAG_RW, &upgt_debug, - 0, "control debugging printfs"); -TUNABLE_INT("hw.upgt.debug", &upgt_debug); -enum { - UPGT_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - UPGT_DEBUG_RECV = 0x00000002, /* basic recv operation */ - UPGT_DEBUG_RESET = 0x00000004, /* reset processing */ - UPGT_DEBUG_INTR = 0x00000008, /* INTR */ - UPGT_DEBUG_TX_PROC = 0x00000010, /* tx ISR proc */ - UPGT_DEBUG_RX_PROC = 0x00000020, /* rx ISR proc */ - UPGT_DEBUG_STATE = 0x00000040, /* 802.11 state transitions */ - UPGT_DEBUG_STAT = 0x00000080, /* statistic */ - UPGT_DEBUG_FW = 0x00000100, /* firmware */ - UPGT_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif - -/* - * Prototypes. - */ -static device_probe_t upgt_match; -static device_attach_t upgt_attach; -static device_detach_t upgt_detach; -static int upgt_alloc_tx(struct upgt_softc *); -static int upgt_alloc_rx(struct upgt_softc *); -static int upgt_alloc_cmd(struct upgt_softc *); -static int upgt_attach_hook(device_t); -static int upgt_device_reset(struct upgt_softc *); -static int upgt_bulk_xmit(struct upgt_softc *, struct upgt_data *, - usbd_pipe_handle, uint32_t *, int); -static int upgt_fw_verify(struct upgt_softc *); -static int upgt_mem_init(struct upgt_softc *); -static int upgt_fw_load(struct upgt_softc *); -static int upgt_fw_copy(const uint8_t *, char *, int); -static uint32_t upgt_crc32_le(const void *, size_t); -static void upgt_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void upgt_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static int upgt_eeprom_read(struct upgt_softc *); -static int upgt_eeprom_parse(struct upgt_softc *); -static void upgt_eeprom_parse_hwrx(struct upgt_softc *, uint8_t *); -static void upgt_eeprom_parse_freq3(struct upgt_softc *, uint8_t *, int); -static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int); -static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int); -static uint32_t upgt_chksum_le(const uint32_t *, size_t); -static void upgt_tx_done(struct upgt_softc *, uint8_t *); -static void upgt_rx(struct upgt_softc *, uint8_t *, int); -static void upgt_init(void *); -static void upgt_init_locked(struct upgt_softc *); -static int upgt_ioctl(struct ifnet *, u_long, caddr_t); -static void upgt_start(struct ifnet *); -static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void upgt_scan_start(struct ieee80211com *); -static void upgt_scan_end(struct ieee80211com *); -static void upgt_set_channel(struct ieee80211com *); -static struct ieee80211vap *upgt_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, int opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void upgt_vap_delete(struct ieee80211vap *); -static void upgt_update_mcast(struct ifnet *); -static uint8_t upgt_rx_rate(struct upgt_softc *, const int); -static void upgt_set_multi(void *); -static void upgt_stop(struct upgt_softc *, int); -static void upgt_setup_rates(struct ieee80211vap *, struct ieee80211com *); -static int upgt_set_macfilter(struct upgt_softc *, uint8_t); -static int upgt_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static void upgt_task(void *); -static void upgt_scantask(void *); -static void upgt_set_chan(struct upgt_softc *, struct ieee80211_channel *); -static void upgt_set_led(struct upgt_softc *, int); -static void upgt_set_led_blink(void *); -static void upgt_tx_task(void *); -static int upgt_get_stats(struct upgt_softc *); -static void upgt_mem_free(struct upgt_softc *, uint32_t); -static uint32_t upgt_mem_alloc(struct upgt_softc *); -static void upgt_free_tx(struct upgt_softc *); -static void upgt_free_rx(struct upgt_softc *); -static void upgt_free_cmd(struct upgt_softc *); -static void upgt_watchdog(void *); - -static const char *upgt_fwname = "upgt-gw3887"; - -static const struct usb_devno upgt_devs_2[] = { - /* version 2 devices */ - { USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_PRISM_GT }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050 }, - { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_PRISM_GT }, - { USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_1 }, - { USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_2 }, - { USB_VENDOR_FSC, USB_PRODUCT_FSC_E5400 }, - { USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_1 }, - { USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_2 }, - { USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_GT }, - { USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG }, - { USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR045G }, - { USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_1 }, - { USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_2 }, - { USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XG703A } -}; - -static int -upgt_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (!uaa->iface) - return UMATCH_NONE; - - if (usb_lookup(upgt_devs_2, uaa->vendor, uaa->product) != NULL) - return (UMATCH_VENDOR_PRODUCT); - - return (UMATCH_NONE); -} - -static int -upgt_attach(device_t dev) -{ - int i; - struct upgt_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_endpoint_descriptor_t *ed; - usb_interface_descriptor_t *id; - usbd_status error; - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; -#ifdef UPGT_DEBUG - sc->sc_debug = upgt_debug; -#endif - - /* set configuration number */ - if (usbd_set_config_no(sc->sc_udev, UPGT_CONFIG_NO, 0) != 0) { - device_printf(dev, "could not set configuration no!\n"); - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, UPGT_IFACE_INDEX, - &sc->sc_iface); - if (error != 0) { - device_printf(dev, "could not get interface handle!\n"); - return ENXIO; - } - - /* find endpoints */ - id = usbd_get_interface_descriptor(sc->sc_iface); - sc->sc_rx_no = sc->sc_tx_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - device_printf(dev, - "no endpoint descriptor for iface %d!\n", i); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_tx_no = ed->bEndpointAddress; - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_rx_no = ed->bEndpointAddress; - - /* - * 0x01 TX pipe - * 0x81 RX pipe - * - * Deprecated scheme (not used with fw version >2.5.6.x): - * 0x02 TX MGMT pipe - * 0x82 TX MGMT pipe - */ - if (sc->sc_tx_no != -1 && sc->sc_rx_no != -1) - break; - } - if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { - device_printf(dev, "missing endpoint!\n"); - return ENXIO; - } - - /* - * Open TX and RX USB bulk pipes. - */ - error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, - &sc->sc_tx_pipeh); - if (error != 0) { - device_printf(dev, "could not open TX pipe: %s!\n", - usbd_errstr(error)); - goto fail; - } - error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, - &sc->sc_rx_pipeh); - if (error != 0) { - device_printf(dev, "could not open RX pipe: %s!\n", - usbd_errstr(error)); - goto fail; - } - - /* Allocate TX, RX, and CMD xfers. */ - if (upgt_alloc_tx(sc) != 0) - goto fail; - if (upgt_alloc_rx(sc) != 0) - goto fail; - if (upgt_alloc_cmd(sc) != 0) - goto fail; - - /* We need the firmware loaded to complete the attach. */ - return upgt_attach_hook(dev); - -fail: - device_printf(dev, "%s failed!\n", __func__); - return ENXIO; -} - -static int -upgt_attach_hook(device_t dev) -{ - struct ieee80211com *ic; - struct ifnet *ifp; - struct upgt_softc *sc = device_get_softc(dev); - struct upgt_data *data_rx = &sc->rx_data; - uint8_t bands; - usbd_status error; - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not if_alloc()\n"); - return ENXIO; - } - - mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - usb_init_task(&sc->sc_mcasttask, upgt_set_multi, sc); - usb_init_task(&sc->sc_scantask, upgt_scantask, sc); - usb_init_task(&sc->sc_task, upgt_task, sc); - usb_init_task(&sc->sc_task_tx, upgt_tx_task, sc); - callout_init(&sc->sc_led_ch, 0); - callout_init(&sc->sc_watchdog_ch, 0); - - /* Initialize the device. */ - if (upgt_device_reset(sc) != 0) - goto fail; - - /* Verify the firmware. */ - if (upgt_fw_verify(sc) != 0) - goto fail; - - /* Calculate device memory space. */ - if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) { - device_printf(dev, - "could not find memory space addresses on FW!\n"); - goto fail; - } - sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1; - sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1; - - DPRINTF(sc, UPGT_DEBUG_FW, "memory address frame start=0x%08x\n", - sc->sc_memaddr_frame_start); - DPRINTF(sc, UPGT_DEBUG_FW, "memory address frame end=0x%08x\n", - sc->sc_memaddr_frame_end); - DPRINTF(sc, UPGT_DEBUG_FW, "memory address rx start=0x%08x\n", - sc->sc_memaddr_rx_start); - - upgt_mem_init(sc); - - /* Load the firmware. */ - if (upgt_fw_load(sc) != 0) - goto fail; - - /* Startup the RX pipe. */ - usbd_setup_xfer(data_rx->xfer, sc->sc_rx_pipeh, data_rx, data_rx->buf, - MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, upgt_rxeof); - error = usbd_transfer(data_rx->xfer); - if (error != 0 && error != USBD_IN_PROGRESS) { - device_printf(dev, "could not queue RX transfer!\n"); - goto fail; - } - usbd_delay_ms(sc->sc_udev, 100); - - /* Read the whole EEPROM content and parse it. */ - if (upgt_eeprom_read(sc) != 0) - goto fail; - if (upgt_eeprom_parse(sc) != 0) - goto fail; - - /* Setup the 802.11 device. */ - ifp->if_softc = sc; - if_initname(ifp, "upgt", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ - ifp->if_init = upgt_init; - ifp->if_ioctl = upgt_ioctl; - ifp->if_start = upgt_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode */ - | IEEE80211_C_MONITOR /* monitor mode */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic); - ic->ic_raw_xmit = upgt_raw_xmit; - ic->ic_scan_start = upgt_scan_start; - ic->ic_scan_end = upgt_scan_end; - ic->ic_set_channel = upgt_set_channel; - - ic->ic_vap_create = upgt_vap_create; - ic->ic_vap_delete = upgt_vap_delete; - ic->ic_update_mcast = upgt_update_mcast; - - bpfattach(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap)); - sc->sc_rxtap_len = sizeof(sc->sc_rxtap); - sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); - sc->sc_rxtap.wr_ihdr.it_present = htole32(UPGT_RX_RADIOTAP_PRESENT); - sc->sc_txtap_len = sizeof(sc->sc_txtap); - sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); - sc->sc_txtap.wt_ihdr.it_present = htole32(UPGT_TX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); - return 0; -fail: - device_printf(dev, "%s failed!\n", __func__); - mtx_destroy(&sc->sc_mtx); - if_free(ifp); - return ENXIO; -} - -static void -upgt_tx_task(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_frame *wh; - struct ieee80211_key *k; - struct upgt_data *data_tx; - struct upgt_lmac_mem *mem; - struct upgt_lmac_tx_desc *txdesc; - struct mbuf *m; - uint32_t addr; - int len, i; - usbd_status error; - - upgt_set_led(sc, UPGT_LED_BLINK); - - UPGT_LOCK(sc); - for (i = 0; i < upgt_txbuf; i++) { - data_tx = &sc->tx_data[i]; - if (data_tx->m == NULL) - continue; - - m = data_tx->m; - addr = data_tx->addr + UPGT_MEMSIZE_FRAME_HEAD; - - /* - * Software crypto. - */ - wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(data_tx->ni, m); - if (k == NULL) { - device_printf(sc->sc_dev, - "ieee80211_crypto_encap returns NULL.\n"); - goto done; - } - - /* in case packet header moved, reset pointer */ - wh = mtod(m, struct ieee80211_frame *); - } - - /* - * Transmit the URB containing the TX data. - */ - bzero(data_tx->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_tx->buf; - mem->addr = htole32(addr); - - txdesc = (struct upgt_lmac_tx_desc *)(mem + 1); - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT) { - /* mgmt frames */ - txdesc->header1.flags = UPGT_H1_FLAGS_TX_MGMT; - /* always send mgmt frames at lowest rate (DS1) */ - memset(txdesc->rates, 0x10, sizeof(txdesc->rates)); - } else { - /* data frames */ - txdesc->header1.flags = UPGT_H1_FLAGS_TX_DATA; - bcopy(sc->sc_cur_rateset, txdesc->rates, - sizeof(txdesc->rates)); - } - txdesc->header1.type = UPGT_H1_TYPE_TX_DATA; - txdesc->header1.len = htole16(m->m_pkthdr.len); - txdesc->header2.reqid = htole32(data_tx->addr); - txdesc->header2.type = htole16(UPGT_H2_TYPE_TX_ACK_YES); - txdesc->header2.flags = htole16(UPGT_H2_FLAGS_TX_ACK_YES); - txdesc->type = htole32(UPGT_TX_DESC_TYPE_DATA); - txdesc->pad3[0] = UPGT_TX_DESC_PAD3_SIZE; - - if (bpf_peers_present(ifp->if_bpf)) { - struct upgt_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = 0; /* XXX where to get from? */ - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); - } - - /* copy frame below our TX descriptor header */ - m_copydata(m, 0, m->m_pkthdr.len, - data_tx->buf + (sizeof(*mem) + sizeof(*txdesc))); - /* calculate frame size */ - len = sizeof(*mem) + sizeof(*txdesc) + m->m_pkthdr.len; - /* we need to align the frame to a 4 byte boundary */ - len = (len + 3) & ~3; - /* calculate frame checksum */ - mem->chksum = upgt_chksum_le((uint32_t *)txdesc, - len - sizeof(*mem)); - /* we do not need the mbuf anymore */ - m_freem(m); - data_tx->m = NULL; - - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: TX start data sending\n", - __func__); - KASSERT(len <= MCLBYTES, ("mbuf is small for saving data")); - - usbd_setup_xfer(data_tx->xfer, sc->sc_tx_pipeh, data_tx, - data_tx->buf, len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, - UPGT_USB_TIMEOUT, upgt_txeof); - UPGT_UNLOCK(sc); - mtx_lock(&Giant); - error = usbd_transfer(data_tx->xfer); - mtx_unlock(&Giant); - UPGT_LOCK(sc); - if (error != 0 && error != USBD_IN_PROGRESS) { - device_printf(sc->sc_dev, - "could not transmit TX data URB!\n"); - goto done; - } - - DPRINTF(sc, UPGT_DEBUG_XMIT, "TX sent (%d bytes)\n", len); - } -done: - UPGT_UNLOCK(sc); - /* - * If we don't regulary read the device statistics, the RX queue - * will stall. It's strange, but it works, so we keep reading - * the statistics here. *shrug* - */ - (void)upgt_get_stats(sc); -} - -static void -upgt_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct upgt_data *data_tx = priv; - struct upgt_softc *sc = data_tx->sc; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if (status == USBD_STALLED) { - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - return; - } - - device_printf(sc->sc_dev, "TX warning(%s)\n", - usbd_errstr(status)); - } -} - -static int -upgt_get_stats(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_lmac_mem *mem; - struct upgt_lmac_stats *stats; - int len; - - /* - * Transmit the URB containing the CMD data. - */ - bzero(data_cmd->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - stats = (struct upgt_lmac_stats *)(mem + 1); - - stats->header1.flags = 0; - stats->header1.type = UPGT_H1_TYPE_CTRL; - stats->header1.len = htole16( - sizeof(struct upgt_lmac_stats) - sizeof(struct upgt_lmac_header)); - - stats->header2.reqid = htole32(sc->sc_memaddr_frame_start); - stats->header2.type = htole16(UPGT_H2_TYPE_STATS); - stats->header2.flags = 0; - - len = sizeof(*mem) + sizeof(*stats); - - mem->chksum = upgt_chksum_le((uint32_t *)stats, - len - sizeof(*mem)); - - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not transmit statistics CMD data URB!\n"); - return (EIO); - } - - return (0); -} - -static int -upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct upgt_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - mtx_lock(&Giant); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & - (IFF_ALLMULTI | IFF_PROMISC)) - upgt_set_multi(sc); - } else { - upgt_init(sc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_stop(sc, 1); - } - sc->sc_if_flags = ifp->if_flags; - if (startall) - ieee80211_start_all(ic); - mtx_unlock(&Giant); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - return error; -} - -static void -upgt_stop(struct upgt_softc *sc, int disable) -{ - struct ifnet *ifp = sc->sc_ifp; - - /* abort and close TX / RX pipes */ - if (sc->sc_tx_pipeh != NULL) - usbd_abort_pipe(sc->sc_tx_pipeh); - if (sc->sc_rx_pipeh != NULL) - usbd_abort_pipe(sc->sc_rx_pipeh); - - /* device down */ - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -} - -static void -upgt_task(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct upgt_vap *uvp = UPGT_VAP(vap); - - DPRINTF(sc, UPGT_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[sc->sc_state]); - - switch (sc->sc_state) { - case IEEE80211_S_INIT: - /* do not accept any frames if the device is down */ - UPGT_LOCK(sc); - upgt_set_macfilter(sc, sc->sc_state); - UPGT_UNLOCK(sc); - upgt_set_led(sc, UPGT_LED_OFF); - break; - case IEEE80211_S_SCAN: - upgt_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_AUTH: - upgt_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_ASSOC: - break; - case IEEE80211_S_RUN: - UPGT_LOCK(sc); - upgt_set_macfilter(sc, sc->sc_state); - UPGT_UNLOCK(sc); - upgt_set_led(sc, UPGT_LED_ON); - break; - default: - break; - } - - IEEE80211_LOCK(ic); - uvp->newstate(vap, sc->sc_state, sc->sc_arg); - if (vap->iv_newstate_cb != NULL) - vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); - IEEE80211_UNLOCK(ic); -} - -static void -upgt_set_led(struct upgt_softc *sc, int action) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_lmac_mem *mem; - struct upgt_lmac_led *led; - int len; - - /* - * Transmit the URB containing the CMD data. - */ - bzero(data_cmd->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - led = (struct upgt_lmac_led *)(mem + 1); - - led->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - led->header1.type = UPGT_H1_TYPE_CTRL; - led->header1.len = htole16( - sizeof(struct upgt_lmac_led) - - sizeof(struct upgt_lmac_header)); - - led->header2.reqid = htole32(sc->sc_memaddr_frame_start); - led->header2.type = htole16(UPGT_H2_TYPE_LED); - led->header2.flags = 0; - - switch (action) { - case UPGT_LED_OFF: - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = 0; - led->action_tmp = htole16(UPGT_LED_ACTION_OFF); - led->action_tmp_dur = 0; - break; - case UPGT_LED_ON: - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = 0; - led->action_tmp = htole16(UPGT_LED_ACTION_ON); - led->action_tmp_dur = 0; - break; - case UPGT_LED_BLINK: - if (sc->sc_state != IEEE80211_S_RUN) - return; - if (sc->sc_led_blink) - /* previous blink was not finished */ - return; - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = htole16(UPGT_LED_ACTION_OFF); - led->action_tmp = htole16(UPGT_LED_ACTION_ON); - led->action_tmp_dur = htole16(UPGT_LED_ACTION_TMP_DUR); - /* lock blink */ - sc->sc_led_blink = 1; - callout_reset(&sc->sc_led_ch, hz, upgt_set_led_blink, sc); - break; - default: - return; - } - - len = sizeof(*mem) + sizeof(*led); - - mem->chksum = upgt_chksum_le((uint32_t *)led, - len - sizeof(*mem)); - - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) - device_printf(sc->sc_dev, "could not transmit led CMD URB!\n"); -} - -static void -upgt_set_led_blink(void *arg) -{ - struct upgt_softc *sc = arg; - - /* blink finished, we are ready for a next one */ - sc->sc_led_blink = 0; -} - -static void -upgt_init(void *priv) -{ - struct upgt_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - UPGT_LOCK(sc); - upgt_init_locked(sc); - UPGT_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -upgt_init_locked(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - DPRINTF(sc, UPGT_DEBUG_RESET, "setting MAC address to %s\n", - ether_sprintf(ic->ic_myaddr)); - - upgt_set_macfilter(sc, IEEE80211_S_SCAN); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; -} - -static int -upgt_set_macfilter(struct upgt_softc *sc, uint8_t state) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_lmac_mem *mem; - struct upgt_lmac_filter *filter; - int len; - uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - /* - * Transmit the URB containing the CMD data. - */ - bzero(data_cmd->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - filter = (struct upgt_lmac_filter *)(mem + 1); - - filter->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - filter->header1.type = UPGT_H1_TYPE_CTRL; - filter->header1.len = htole16( - sizeof(struct upgt_lmac_filter) - - sizeof(struct upgt_lmac_header)); - - filter->header2.reqid = htole32(sc->sc_memaddr_frame_start); - filter->header2.type = htole16(UPGT_H2_TYPE_MACFILTER); - filter->header2.flags = 0; - - switch (state) { - case IEEE80211_S_INIT: - DPRINTF(sc, UPGT_DEBUG_STATE, "%s: set MAC filter to INIT\n", - __func__); - filter->type = htole16(UPGT_FILTER_TYPE_RESET); - break; - case IEEE80211_S_SCAN: - DPRINTF(sc, UPGT_DEBUG_STATE, - "set MAC filter to SCAN (bssid %s)\n", - ether_sprintf(broadcast)); - filter->type = htole16(UPGT_FILTER_TYPE_NONE); - IEEE80211_ADDR_COPY(filter->dst, ic->ic_myaddr); - IEEE80211_ADDR_COPY(filter->src, broadcast); - filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3); - break; - case IEEE80211_S_RUN: - /* XXX monitor mode isn't tested yet. */ - if (vap->iv_opmode == IEEE80211_M_MONITOR) { - filter->type = htole16(UPGT_FILTER_TYPE_MONITOR); - IEEE80211_ADDR_COPY(filter->dst, ic->ic_myaddr); - IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid); - filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_MONITOR_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_MONITOR_UNKNOWN3); - } else { - DPRINTF(sc, UPGT_DEBUG_STATE, - "set MAC filter to RUN (bssid %s)\n", - ether_sprintf(ni->ni_bssid)); - filter->type = htole16(UPGT_FILTER_TYPE_STA); - IEEE80211_ADDR_COPY(filter->dst, ic->ic_myaddr); - IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid); - filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3); - } - break; - default: - device_printf(sc->sc_dev, - "MAC filter does not know that state!\n"); - break; - } - - len = sizeof(*mem) + sizeof(*filter); - - mem->chksum = upgt_chksum_le((uint32_t *)filter, - len - sizeof(*mem)); - - UPGT_UNLOCK(sc); - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not transmit macfilter CMD data URB!\n"); - UPGT_LOCK(sc); - return (EIO); - } - UPGT_LOCK(sc); - - return (0); -} - -static void -upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct upgt_softc *sc = ifp->if_softc; - const struct ieee80211_txparam *tp; - - /* - * 0x01 = OFMD6 0x10 = DS1 - * 0x04 = OFDM9 0x11 = DS2 - * 0x06 = OFDM12 0x12 = DS5 - * 0x07 = OFDM18 0x13 = DS11 - * 0x08 = OFDM24 - * 0x09 = OFDM36 - * 0x0a = OFDM48 - * 0x0b = OFDM54 - */ - const uint8_t rateset_auto_11b[] = - { 0x13, 0x13, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10 }; - const uint8_t rateset_auto_11g[] = - { 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x04, 0x01 }; - const uint8_t rateset_fix_11bg[] = - { 0x10, 0x11, 0x12, 0x13, 0x01, 0x04, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b }; - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - - /* XXX */ - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { - /* - * Automatic rate control is done by the device. - * We just pass the rateset from which the device - * will pickup a rate. - */ - if (ic->ic_curmode == IEEE80211_MODE_11B) - bcopy(rateset_auto_11b, sc->sc_cur_rateset, - sizeof(sc->sc_cur_rateset)); - if (ic->ic_curmode == IEEE80211_MODE_11G || - ic->ic_curmode == IEEE80211_MODE_AUTO) - bcopy(rateset_auto_11g, sc->sc_cur_rateset, - sizeof(sc->sc_cur_rateset)); - } else { - /* set a fixed rate */ - memset(sc->sc_cur_rateset, rateset_fix_11bg[tp->ucastrate], - sizeof(sc->sc_cur_rateset)); - } -} - -static void -upgt_set_multi(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (!(ifp->if_flags & IFF_UP)) - return; - - /* - * XXX don't know how to set a device. Lack of docs. Just try to set - * IFF_ALLMULTI flag here. - */ - IF_ADDR_LOCK(ifp); - ifp->if_flags |= IFF_ALLMULTI; - IF_ADDR_UNLOCK(ifp); -} - -static void -upgt_start(struct ifnet *ifp) -{ - struct upgt_softc *sc = ifp->if_softc; - struct upgt_data *data_tx; - struct ieee80211_node *ni; - struct mbuf *m; - int i; - - UPGT_LOCK(sc); - for (i = 0; i < upgt_txbuf; i++) { - data_tx = &sc->tx_data[i]; - if (data_tx->use == 1) - continue; - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m = ieee80211_encap(ni, m); - if (m == NULL) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - continue; - } - - if ((data_tx->addr = upgt_mem_alloc(sc)) == 0) { - device_printf(sc->sc_dev, "no free prism memory!\n"); - UPGT_UNLOCK(sc); - return; - } - data_tx->ni = ni; - data_tx->m = m; - data_tx->use = 1; - sc->tx_queued++; - } - - if (sc->tx_queued > 0) { - DPRINTF(sc, UPGT_DEBUG_XMIT, "tx_queued=%d\n", sc->tx_queued); - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - sc->sc_tx_timer = 5; - callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); - /* process the TX queue in process context */ - usb_rem_task(sc->sc_udev, &sc->sc_task_tx); - usb_add_task(sc->sc_udev, &sc->sc_task_tx, USB_TASKQ_DRIVER); - } - UPGT_UNLOCK(sc); -} - -static int -upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct upgt_softc *sc = ifp->if_softc; - struct upgt_data *data_tx = NULL; - int i; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - - UPGT_LOCK(sc); - if (sc->tx_queued >= upgt_txbuf) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m); - ieee80211_free_node(ni); - UPGT_UNLOCK(sc); - return ENOBUFS; /* XXX */ - } - - ifp->if_opackets++; - - /* choose a unused buffer. */ - for (i = 0; i < upgt_txbuf; i++) { - data_tx = &sc->tx_data[i]; - if (data_tx->use == 0) - break; - } - KASSERT(data_tx != NULL, ("data_tx is NULL")); - KASSERT(data_tx->use == 0, ("no empty TX queue")); - if ((data_tx->addr = upgt_mem_alloc(sc)) == 0) { - device_printf(sc->sc_dev, "no free prism memory!\n"); - UPGT_UNLOCK(sc); - return ENOBUFS; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct upgt_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = 0; /* TODO: where to get from? */ - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); - } - - data_tx->ni = ni; - data_tx->m = m; - data_tx->use = 1; - sc->tx_queued++; - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - UPGT_UNLOCK(sc); - - sc->sc_tx_timer = 5; - callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); - usb_rem_task(sc->sc_udev, &sc->sc_task_tx); - usb_add_task(sc->sc_udev, &sc->sc_task_tx, USB_TASKQ_DRIVER); - - return 0; -} - -static void -upgt_watchdog(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "watchdog timeout\n"); - /* upgt_init(ifp); XXX needs a process context ? */ - ifp->if_oerrors++; - return; - } - callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); - } -} - -static uint32_t -upgt_mem_alloc(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < sc->sc_memory.pages; i++) { - if (sc->sc_memory.page[i].used == 0) { - sc->sc_memory.page[i].used = 1; - return (sc->sc_memory.page[i].addr); - } - } - - return (0); -} - -static void -upgt_scantask(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - switch (sc->sc_scan_action) { - case UPGT_SET_CHANNEL: - upgt_set_chan(sc, ic->ic_curchan); - break; - default: - device_printf(sc->sc_dev, "unknown scan action %d\n", - sc->sc_scan_action); - break; - } -} - -static void -upgt_scan_start(struct ieee80211com *ic) -{ - /* do nothing. */ -} - -static void -upgt_scan_end(struct ieee80211com *ic) -{ - /* do nothing. */ -} - -static void -upgt_set_channel(struct ieee80211com *ic) -{ - struct upgt_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = UPGT_SET_CHANNEL; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_lmac_mem *mem; - struct upgt_lmac_channel *chan; - int len, channel; - - channel = ieee80211_chan2ieee(ic, c); - if (channel == 0 || channel == IEEE80211_CHAN_ANY) { - /* XXX should NEVER happen */ - device_printf(sc->sc_dev, - "%s: invalid channel %x\n", __func__, channel); - return; - } - - DPRINTF(sc, UPGT_DEBUG_STATE, "%s: channel %d\n", __func__, channel); - - /* - * Transmit the URB containing the CMD data. - */ - bzero(data_cmd->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - chan = (struct upgt_lmac_channel *)(mem + 1); - - chan->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - chan->header1.type = UPGT_H1_TYPE_CTRL; - chan->header1.len = htole16( - sizeof(struct upgt_lmac_channel) - sizeof(struct upgt_lmac_header)); - - chan->header2.reqid = htole32(sc->sc_memaddr_frame_start); - chan->header2.type = htole16(UPGT_H2_TYPE_CHANNEL); - chan->header2.flags = 0; - - chan->unknown1 = htole16(UPGT_CHANNEL_UNKNOWN1); - chan->unknown2 = htole16(UPGT_CHANNEL_UNKNOWN2); - chan->freq6 = sc->sc_eeprom_freq6[channel]; - chan->settings = sc->sc_eeprom_freq6_settings; - chan->unknown3 = UPGT_CHANNEL_UNKNOWN3; - - bcopy(&sc->sc_eeprom_freq3[channel].data, chan->freq3_1, - sizeof(chan->freq3_1)); - bcopy(&sc->sc_eeprom_freq4[channel], chan->freq4, - sizeof(sc->sc_eeprom_freq4[channel])); - bcopy(&sc->sc_eeprom_freq3[channel].data, chan->freq3_2, - sizeof(chan->freq3_2)); - - len = sizeof(*mem) + sizeof(*chan); - - mem->chksum = upgt_chksum_le((uint32_t *)chan, - len - sizeof(*mem)); - - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) - device_printf(sc->sc_dev, - "could not transmit channel CMD data URB!\n"); -} - -static struct ieee80211vap * -upgt_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, int opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct upgt_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - uvp = (struct upgt_vap *) malloc(sizeof(struct upgt_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return NULL; - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = upgt_newstate; - - /* setup device rates */ - upgt_setup_rates(vap, ic); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return vap; -} - -static int -upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct upgt_vap *uvp = UPGT_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct upgt_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_task); - - /* do it in a process context */ - sc->sc_state = nstate; - sc->sc_arg = arg; - - if (nstate == IEEE80211_S_INIT) { - uvp->newstate(vap, nstate, arg); - return 0; - } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); - return EINPROGRESS; - } -} - -static void -upgt_vap_delete(struct ieee80211vap *vap) -{ - struct upgt_vap *uvp = UPGT_VAP(vap); - - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static void -upgt_update_mcast(struct ifnet *ifp) -{ - struct upgt_softc *sc = ifp->if_softc; - - usb_add_task(sc->sc_udev, &sc->sc_mcasttask, USB_TASKQ_DRIVER); -} - -static int -upgt_eeprom_parse(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct upgt_eeprom_header *eeprom_header; - struct upgt_eeprom_option *eeprom_option; - uint16_t option_len; - uint16_t option_type; - uint16_t preamble_len; - int option_end = 0; - - /* calculate eeprom options start offset */ - eeprom_header = (struct upgt_eeprom_header *)sc->sc_eeprom; - preamble_len = le16toh(eeprom_header->preamble_len); - eeprom_option = (struct upgt_eeprom_option *)(sc->sc_eeprom + - (sizeof(struct upgt_eeprom_header) + preamble_len)); - - while (!option_end) { - /* the eeprom option length is stored in words */ - option_len = - (le16toh(eeprom_option->len) - 1) * sizeof(uint16_t); - option_type = - le16toh(eeprom_option->type); - - switch (option_type) { - case UPGT_EEPROM_TYPE_NAME: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM name len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_SERIAL: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM serial len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_MAC: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM mac len=%d\n", option_len); - - IEEE80211_ADDR_COPY(ic->ic_myaddr, eeprom_option->data); - break; - case UPGT_EEPROM_TYPE_HWRX: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM hwrx len=%d\n", option_len); - - upgt_eeprom_parse_hwrx(sc, eeprom_option->data); - break; - case UPGT_EEPROM_TYPE_CHIP: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM chip len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_FREQ3: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq3 len=%d\n", option_len); - - upgt_eeprom_parse_freq3(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_FREQ4: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq4 len=%d\n", option_len); - - upgt_eeprom_parse_freq4(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_FREQ5: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq5 len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_FREQ6: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq6 len=%d\n", option_len); - - upgt_eeprom_parse_freq6(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_END: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM end len=%d\n", option_len); - option_end = 1; - break; - case UPGT_EEPROM_TYPE_OFF: - DPRINTF(sc, UPGT_DEBUG_FW, - "%s: EEPROM off without end option!\n", __func__); - return (EIO); - default: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM unknown type 0x%04x len=%d\n", - option_type, option_len); - break; - } - - /* jump to next EEPROM option */ - eeprom_option = (struct upgt_eeprom_option *) - (eeprom_option->data + option_len); - } - - return (0); -} - -static void -upgt_eeprom_parse_freq3(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_eeprom_freq3_header *freq3_header; - struct upgt_lmac_freq3 *freq3; - int i, elements, flags; - unsigned channel; - - freq3_header = (struct upgt_eeprom_freq3_header *)data; - freq3 = (struct upgt_lmac_freq3 *)(freq3_header + 1); - - flags = freq3_header->flags; - elements = freq3_header->elements; - - DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d\n", - flags, elements); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq3[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - sc->sc_eeprom_freq3[channel] = freq3[i]; - - DPRINTF(sc, UPGT_DEBUG_FW, "frequence=%d, channel=%d\n", - le16toh(sc->sc_eeprom_freq3[channel].freq), channel); - } -} - -void -upgt_eeprom_parse_freq4(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_eeprom_freq4_header *freq4_header; - struct upgt_eeprom_freq4_1 *freq4_1; - struct upgt_eeprom_freq4_2 *freq4_2; - int i, j, elements, settings, flags; - unsigned channel; - - freq4_header = (struct upgt_eeprom_freq4_header *)data; - freq4_1 = (struct upgt_eeprom_freq4_1 *)(freq4_header + 1); - flags = freq4_header->flags; - elements = freq4_header->elements; - settings = freq4_header->settings; - - /* we need this value later */ - sc->sc_eeprom_freq6_settings = freq4_header->settings; - - DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d settings=%d\n", - flags, elements, settings); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq4_1[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - freq4_2 = (struct upgt_eeprom_freq4_2 *)freq4_1[i].data; - for (j = 0; j < settings; j++) { - sc->sc_eeprom_freq4[channel][j].cmd = freq4_2[j]; - sc->sc_eeprom_freq4[channel][j].pad = 0; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "frequence=%d, channel=%d\n", - le16toh(freq4_1[i].freq), channel); - } -} - -void -upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_lmac_freq6 *freq6; - int i, elements; - unsigned channel; - - freq6 = (struct upgt_lmac_freq6 *)data; - elements = len / sizeof(struct upgt_lmac_freq6); - - DPRINTF(sc, UPGT_DEBUG_FW, "elements=%d\n", elements); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq6[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - sc->sc_eeprom_freq6[channel] = freq6[i]; - - DPRINTF(sc, UPGT_DEBUG_FW, "frequence=%d, channel=%d\n", - le16toh(sc->sc_eeprom_freq6[channel].freq), channel); - } -} - -static void -upgt_eeprom_parse_hwrx(struct upgt_softc *sc, uint8_t *data) -{ - struct upgt_eeprom_option_hwrx *option_hwrx; - - option_hwrx = (struct upgt_eeprom_option_hwrx *)data; - - sc->sc_eeprom_hwrx = option_hwrx->rxfilter - UPGT_EEPROM_RX_CONST; - - DPRINTF(sc, UPGT_DEBUG_FW, "hwrx option value=0x%04x\n", - sc->sc_eeprom_hwrx); -} - -static int -upgt_eeprom_read(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_lmac_mem *mem; - struct upgt_lmac_eeprom *eeprom; - int offset, block, len; - - offset = 0; - block = UPGT_EEPROM_BLOCK_SIZE; - while (offset < UPGT_EEPROM_SIZE) { - DPRINTF(sc, UPGT_DEBUG_FW, - "request EEPROM block (offset=%d, len=%d)\n", offset, block); - - /* - * Transmit the URB containing the CMD data. - */ - bzero(data_cmd->buf, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - eeprom = (struct upgt_lmac_eeprom *)(mem + 1); - eeprom->header1.flags = 0; - eeprom->header1.type = UPGT_H1_TYPE_CTRL; - eeprom->header1.len = htole16(( - sizeof(struct upgt_lmac_eeprom) - - sizeof(struct upgt_lmac_header)) + block); - - eeprom->header2.reqid = htole32(sc->sc_memaddr_frame_start); - eeprom->header2.type = htole16(UPGT_H2_TYPE_EEPROM); - eeprom->header2.flags = 0; - - eeprom->offset = htole16(offset); - eeprom->len = htole16(block); - - len = sizeof(*mem) + sizeof(*eeprom) + block; - - mem->chksum = upgt_chksum_le((uint32_t *)eeprom, - len - sizeof(*mem)); - - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, - USBD_FORCE_SHORT_XFER) != 0) { - device_printf(sc->sc_dev, - "could not transmit EEPROM data URB!\n"); - return (EIO); - } - if (tsleep(sc, 0, "eeprom_request", UPGT_USB_TIMEOUT)) { - device_printf(sc->sc_dev, - "timeout while waiting for EEPROM data!\n"); - return (EIO); - } - - offset += block; - if (UPGT_EEPROM_SIZE - offset < block) - block = UPGT_EEPROM_SIZE - offset; - } - - return (0); -} - -/* - * The firmware awaits a checksum for each frame we send to it. - * The algorithm used therefor is uncommon but somehow similar to CRC32. - */ -static uint32_t -upgt_chksum_le(const uint32_t *buf, size_t size) -{ - int i; - uint32_t crc = 0; - - for (i = 0; i < size; i += sizeof(uint32_t)) { - crc = htole32(crc ^ *buf++); - crc = htole32((crc >> 5) ^ (crc << 3)); - } - - return (crc); -} - -static void -upgt_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct upgt_data *data_rx = priv; - struct upgt_softc *sc = data_rx->sc; - int len; - struct upgt_lmac_header *header; - struct upgt_lmac_eeprom *eeprom; - uint8_t h1_type; - uint16_t h2_type; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - goto skip; - } - usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); - - /* - * Check what type of frame came in. - */ - header = (struct upgt_lmac_header *)(data_rx->buf + 4); - - h1_type = header->header1.type; - h2_type = le16toh(header->header2.type); - - if (h1_type == UPGT_H1_TYPE_CTRL && h2_type == UPGT_H2_TYPE_EEPROM) { - eeprom = (struct upgt_lmac_eeprom *)(data_rx->buf + 4); - uint16_t eeprom_offset = le16toh(eeprom->offset); - uint16_t eeprom_len = le16toh(eeprom->len); - - DPRINTF(sc, UPGT_DEBUG_FW, - "received EEPROM block (offset=%d, len=%d)\n", - eeprom_offset, eeprom_len); - - bcopy(data_rx->buf + sizeof(struct upgt_lmac_eeprom) + 4, - sc->sc_eeprom + eeprom_offset, eeprom_len); - - /* EEPROM data has arrived in time, wakeup tsleep() */ - wakeup(sc); - } else if (h1_type == UPGT_H1_TYPE_CTRL && - h2_type == UPGT_H2_TYPE_TX_DONE) { - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: received 802.11 TX done\n", - __func__); - upgt_tx_done(sc, data_rx->buf + 4); - } else if (h1_type == UPGT_H1_TYPE_RX_DATA || - h1_type == UPGT_H1_TYPE_RX_DATA_MGMT) { - DPRINTF(sc, UPGT_DEBUG_RECV, "%s: received 802.11 RX data\n", - __func__); - upgt_rx(sc, data_rx->buf + 4, le16toh(header->header1.len)); - } else if (h1_type == UPGT_H1_TYPE_CTRL && - h2_type == UPGT_H2_TYPE_STATS) { - DPRINTF(sc, UPGT_DEBUG_STAT, "%s: received statistic data\n", - __func__); - /* TODO: what could we do with the statistic data? */ - } else { - /* ignore unknown frame types */ - DPRINTF(sc, UPGT_DEBUG_INTR, - "received unknown frame type 0x%02x\n", - header->header1.type); - } - -skip: /* setup new transfer */ - usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data_rx, data_rx->buf, MCLBYTES, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, upgt_rxeof); - (void)usbd_transfer(xfer); -} - -static void -upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct upgt_lmac_rx_desc *rxdesc; - struct ieee80211_node *ni; - struct mbuf *m; - int nf; - - /* - * don't pass packets to the ieee80211 framework if the driver isn't - * RUNNING. - */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - return; - - /* access RX packet descriptor */ - rxdesc = (struct upgt_lmac_rx_desc *)data; - - /* create mbuf which is suitable for strict alignment archs */ - KASSERT((pkglen + ETHER_ALIGN) < MCLBYTES, - ("A current mbuf storage is small (%d)", pkglen + ETHER_ALIGN)); - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - device_printf(sc->sc_dev, "could not create RX mbuf!\n"); - return; - } - m_adj(m, ETHER_ALIGN); - bcopy(rxdesc->data, mtod(m, char *), pkglen); - /* trim FCS */ - m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN; - m->m_pkthdr.rcvif = ifp; - - if (bpf_peers_present(ifp->if_bpf)) { - struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate); - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wr_antsignal = rxdesc->rssi; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); - } - ifp->if_ipackets++; - - nf = -95; /* XXX */ - ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - (void)ieee80211_input(ni, m, rxdesc->rssi, nf, 0); - ieee80211_free_node(ni); - } else - (void)ieee80211_input_all(ic, m, rxdesc->rssi, nf, 0); - - DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__); -} - -static uint8_t -upgt_rx_rate(struct upgt_softc *sc, const int rate) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 }; - static const uint8_t ofdm_upgt2rate[12] = - { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - - if (ic->ic_curmode == IEEE80211_MODE_11B && - !(rate < 0 || rate > 3)) - return cck_upgt2rate[rate & 0xf]; - - if (ic->ic_curmode == IEEE80211_MODE_11G && - !(rate < 0 || rate > 11)) - return ofdm_upgt2rate[rate & 0xf]; - - return (0); -} - -static void -upgt_tx_done(struct upgt_softc *sc, uint8_t *data) -{ - struct ifnet *ifp = sc->sc_ifp; - struct upgt_lmac_tx_done_desc *desc; - int i; - - desc = (struct upgt_lmac_tx_done_desc *)data; - - UPGT_LOCK(sc); - for (i = 0; i < upgt_txbuf; i++) { - struct upgt_data *data_tx = &sc->tx_data[i]; - - if (data_tx->addr == le32toh(desc->header2.reqid)) { - upgt_mem_free(sc, data_tx->addr); - ieee80211_free_node(data_tx->ni); - data_tx->ni = NULL; - data_tx->addr = 0; - data_tx->m = NULL; - data_tx->use = 0; - - sc->tx_queued--; - ifp->if_opackets++; - - DPRINTF(sc, UPGT_DEBUG_TX_PROC, - "TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ", - le32toh(desc->header2.reqid), - le16toh(desc->status), le16toh(desc->rssi)); - DPRINTF(sc, UPGT_DEBUG_TX_PROC, "seq=%d\n", - le16toh(desc->seq)); - break; - } - } - if (sc->tx_queued == 0) { - /* TX queued was processed, continue */ - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - UPGT_UNLOCK(sc); - upgt_start(ifp); - return; - } - UPGT_UNLOCK(sc); -} - -static void -upgt_mem_free(struct upgt_softc *sc, uint32_t addr) -{ - int i; - - for (i = 0; i < sc->sc_memory.pages; i++) { - if (sc->sc_memory.page[i].addr == addr) { - sc->sc_memory.page[i].used = 0; - return; - } - } - - device_printf(sc->sc_dev, - "could not free memory address 0x%08x!\n", addr); -} - -static int -upgt_fw_load(struct upgt_softc *sc) -{ - const struct firmware *fw; - struct upgt_data *data_cmd = &sc->cmd_data; - struct upgt_data *data_rx = &sc->rx_data; - struct upgt_fw_x2_header *x2; - char start_fwload_cmd[] = { 0x3c, 0x0d }; - int error = 0, offset, bsize, n, i, len; - uint32_t crc32; - - fw = firmware_get(upgt_fwname); - if (fw == NULL) { - device_printf(sc->sc_dev, "could not read microcode %s!\n", - upgt_fwname); - return EIO; - } - - /* send firmware start load command */ - len = sizeof(start_fwload_cmd); - bcopy(start_fwload_cmd, data_cmd->buf, len); - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not send start_firmware_load command!\n"); - error = EIO; - goto fail; - } - - /* send X2 header */ - len = sizeof(struct upgt_fw_x2_header); - x2 = (struct upgt_fw_x2_header *)data_cmd->buf; - bcopy(UPGT_X2_SIGNATURE, x2->signature, UPGT_X2_SIGNATURE_SIZE); - x2->startaddr = htole32(UPGT_MEMADDR_FIRMWARE_START); - x2->len = htole32(fw->datasize); - x2->crc = upgt_crc32_le((uint8_t *)data_cmd->buf + - UPGT_X2_SIGNATURE_SIZE, - sizeof(struct upgt_fw_x2_header) - UPGT_X2_SIGNATURE_SIZE - - sizeof(uint32_t)); - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not send firmware X2 header!\n"); - error = EIO; - goto fail; - } - - /* download firmware */ - for (offset = 0; offset < fw->datasize; offset += bsize) { - if (fw->datasize - offset > UPGT_FW_BLOCK_SIZE) - bsize = UPGT_FW_BLOCK_SIZE; - else - bsize = fw->datasize - offset; - - n = upgt_fw_copy((const uint8_t *)fw->data + offset, - data_cmd->buf, bsize); - - DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%d, read=%d, sent=%d\n", - offset, n, bsize); - - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &bsize, 0) - != 0) { - device_printf(sc->sc_dev, - "error while downloading firmware block!\n"); - error = EIO; - goto fail; - } - - bsize = n; - } - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware downloaded\n", __func__); - - /* load firmware */ - crc32 = upgt_crc32_le(fw->data, fw->datasize); - *((uint32_t *)(data_cmd->buf) ) = crc32; - *((uint8_t *)(data_cmd->buf) + 4) = 'g'; - *((uint8_t *)(data_cmd->buf) + 5) = '\r'; - len = 6; - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not send load_firmware command!\n"); - error = EIO; - goto fail; - } - - for (i = 0; i < UPGT_FIRMWARE_TIMEOUT; i++) { - len = UPGT_FW_BLOCK_SIZE; - bzero(data_rx->buf, MCLBYTES); - if (upgt_bulk_xmit(sc, data_rx, sc->sc_rx_pipeh, &len, - USBD_SHORT_XFER_OK) != 0) { - device_printf(sc->sc_dev, - "could not read firmware response!\n"); - error = EIO; - goto fail; - } - - if (memcmp(data_rx->buf, "OK", 2) == 0) - break; /* firmware load was successful */ - } - if (i == UPGT_FIRMWARE_TIMEOUT) { - device_printf(sc->sc_dev, "firmware load failed!\n"); - error = EIO; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware loaded\n", __func__); -fail: - firmware_put(fw, FIRMWARE_UNLOAD); - return (error); -} - -static uint32_t -upgt_crc32_le(const void *buf, size_t size) -{ - uint32_t crc; - - crc = ether_crc32_le(buf, size); - - /* apply final XOR value as common for CRC-32 */ - crc = htole32(crc ^ 0xffffffffU); - - return (crc); -} - -/* - * While copying the version 2 firmware, we need to replace two characters: - * - * 0x7e -> 0x7d 0x5e - * 0x7d -> 0x7d 0x5d - */ -static int -upgt_fw_copy(const uint8_t *src, char *dst, int size) -{ - int i, j; - - for (i = 0, j = 0; i < size && j < size; i++) { - switch (src[i]) { - case 0x7e: - dst[j] = 0x7d; - j++; - dst[j] = 0x5e; - j++; - break; - case 0x7d: - dst[j] = 0x7d; - j++; - dst[j] = 0x5d; - j++; - break; - default: - dst[j] = src[i]; - j++; - break; - } - } - - return (i); -} - -static int -upgt_mem_init(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < UPGT_MEMORY_MAX_PAGES; i++) { - sc->sc_memory.page[i].used = 0; - - if (i == 0) { - /* - * The first memory page is always reserved for - * command data. - */ - sc->sc_memory.page[i].addr = - sc->sc_memaddr_frame_start + MCLBYTES; - } else { - sc->sc_memory.page[i].addr = - sc->sc_memory.page[i - 1].addr + MCLBYTES; - } - - if (sc->sc_memory.page[i].addr + MCLBYTES >= - sc->sc_memaddr_frame_end) - break; - - DPRINTF(sc, UPGT_DEBUG_FW, "memory address page %d=0x%08x\n", - i, sc->sc_memory.page[i].addr); - } - - sc->sc_memory.pages = i; - if (upgt_txbuf > sc->sc_memory.pages) - - DPRINTF(sc, UPGT_DEBUG_FW, "memory pages=%d\n", sc->sc_memory.pages); - return (0); -} - -static int -upgt_fw_verify(struct upgt_softc *sc) -{ - const struct firmware *fw; - const struct upgt_fw_bra_option *bra_opt; - const struct upgt_fw_bra_descr *descr; - const uint8_t *p; - const uint32_t *uc; - uint32_t bra_option_type, bra_option_len; - int offset, bra_end = 0, error = 0; - - fw = firmware_get(upgt_fwname); - if (fw == NULL) { - device_printf(sc->sc_dev, "could not read microcode %s!\n", - upgt_fwname); - return EIO; - } - - /* - * Seek to beginning of Boot Record Area (BRA). - */ - for (offset = 0; offset < fw->datasize; offset += sizeof(*uc)) { - uc = (const uint32_t *)((const uint8_t *)fw->data + offset); - if (*uc == 0) - break; - } - for (; offset < fw->datasize; offset += sizeof(*uc)) { - uc = (const uint32_t *)((const uint8_t *)fw->data + offset); - if (*uc != 0) - break; - } - if (offset == fw->datasize) { - device_printf(sc->sc_dev, - "firmware Boot Record Area not found!\n"); - error = EIO; - goto fail; - } - - DPRINTF(sc, UPGT_DEBUG_FW, - "firmware Boot Record Area found at offset %d\n", offset); - - /* - * Parse Boot Record Area (BRA) options. - */ - while (offset < fw->datasize && bra_end == 0) { - /* get current BRA option */ - p = (const uint8_t *)fw->data + offset; - bra_opt = (const struct upgt_fw_bra_option *)p; - bra_option_type = le32toh(bra_opt->type); - bra_option_len = le32toh(bra_opt->len) * sizeof(*uc); - - switch (bra_option_type) { - case UPGT_BRA_TYPE_FW: - DPRINTF(sc, UPGT_DEBUG_FW, "UPGT_BRA_TYPE_FW len=%d\n", - bra_option_len); - - if (bra_option_len != UPGT_BRA_FWTYPE_SIZE) { - device_printf(sc->sc_dev, - "wrong UPGT_BRA_TYPE_FW len!\n"); - error = EIO; - goto fail; - } - if (memcmp(UPGT_BRA_FWTYPE_LM86, bra_opt->data, - bra_option_len) == 0) { - sc->sc_fw_type = UPGT_FWTYPE_LM86; - break; - } - if (memcmp(UPGT_BRA_FWTYPE_LM87, bra_opt->data, - bra_option_len) == 0) { - sc->sc_fw_type = UPGT_FWTYPE_LM87; - break; - } - device_printf(sc->sc_dev, - "unsupported firmware type!\n"); - error = EIO; - goto fail; - case UPGT_BRA_TYPE_VERSION: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_VERSION len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_DEPIF: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_DEPIF len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_EXPIF: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_EXPIF len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_DESCR: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_DESCR len=%d\n", bra_option_len); - - descr = (const struct upgt_fw_bra_descr *)bra_opt->data; - - sc->sc_memaddr_frame_start = - le32toh(descr->memaddr_space_start); - sc->sc_memaddr_frame_end = - le32toh(descr->memaddr_space_end); - - DPRINTF(sc, UPGT_DEBUG_FW, - "memory address space start=0x%08x\n", - sc->sc_memaddr_frame_start); - DPRINTF(sc, UPGT_DEBUG_FW, - "memory address space end=0x%08x\n", - sc->sc_memaddr_frame_end); - break; - case UPGT_BRA_TYPE_END: - DPRINTF(sc, UPGT_DEBUG_FW, "UPGT_BRA_TYPE_END len=%d\n", - bra_option_len); - bra_end = 1; - break; - default: - DPRINTF(sc, UPGT_DEBUG_FW, "unknown BRA option len=%d\n", - bra_option_len); - error = EIO; - goto fail; - } - - /* jump to next BRA option */ - offset += sizeof(struct upgt_fw_bra_option) + bra_option_len; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware verified", __func__); -fail: - firmware_put(fw, FIRMWARE_UNLOAD); - return (error); -} - -static int -upgt_bulk_xmit(struct upgt_softc *sc, struct upgt_data *data, - usbd_pipe_handle pipeh, uint32_t *size, int flags) -{ - usbd_status status; - - mtx_lock(&Giant); - status = usbd_bulk_transfer(data->xfer, pipeh, - USBD_NO_COPY | flags, UPGT_USB_TIMEOUT, data->buf, size, - "upgt_bulk_xmit"); - if (status != USBD_NORMAL_COMPLETION) { - device_printf(sc->sc_dev, "%s: error %s!\n", - __func__, usbd_errstr(status)); - mtx_unlock(&Giant); - return (EIO); - } - mtx_unlock(&Giant); - - return (0); -} - -static int -upgt_device_reset(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - char init_cmd[] = { 0x7e, 0x7e, 0x7e, 0x7e }; - int len; - - len = sizeof(init_cmd); - bcopy(init_cmd, data_cmd->buf, len); - if (upgt_bulk_xmit(sc, data_cmd, sc->sc_tx_pipeh, &len, 0) != 0) { - device_printf(sc->sc_dev, - "could not send device init string!\n"); - return (EIO); - } - usbd_delay_ms(sc->sc_udev, 100); - - DPRINTF(sc, UPGT_DEBUG_FW, "%s: device initialized\n", __func__); - return (0); -} - -static int -upgt_alloc_tx(struct upgt_softc *sc) -{ - int i; - - sc->tx_queued = 0; - - for (i = 0; i < upgt_txbuf; i++) { - struct upgt_data *data_tx = &sc->tx_data[i]; - - data_tx->sc = sc; - data_tx->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data_tx->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate TX xfer!\n"); - return (ENOMEM); - } - - data_tx->buf = usbd_alloc_buffer(data_tx->xfer, MCLBYTES); - if (data_tx->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate TX buffer!\n"); - return (ENOMEM); - } - - bzero(data_tx->buf, MCLBYTES); - } - - return (0); -} - -static int -upgt_alloc_rx(struct upgt_softc *sc) -{ - struct upgt_data *data_rx = &sc->rx_data; - - data_rx->sc = sc; - data_rx->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data_rx->xfer == NULL) { - device_printf(sc->sc_dev, "could not allocate RX xfer!\n"); - return (ENOMEM); - } - - data_rx->buf = usbd_alloc_buffer(data_rx->xfer, MCLBYTES); - if (data_rx->buf == NULL) { - device_printf(sc->sc_dev, "could not allocate RX buffer!\n"); - return (ENOMEM); - } - - bzero(data_rx->buf, MCLBYTES); - - return (0); -} - -static int -upgt_alloc_cmd(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - - data_cmd->sc = sc; - data_cmd->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data_cmd->xfer == NULL) { - device_printf(sc->sc_dev, "could not allocate RX xfer!\n"); - return (ENOMEM); - } - - data_cmd->buf = usbd_alloc_buffer(data_cmd->xfer, MCLBYTES); - if (data_cmd->buf == NULL) { - device_printf(sc->sc_dev, "could not allocate RX buffer!\n"); - return (ENOMEM); - } - - bzero(data_cmd->buf, MCLBYTES); - - return (0); -} - -static int -upgt_detach(device_t dev) -{ - struct upgt_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return 0; - - upgt_stop(sc, 1); - - /* abort and close TX / RX pipes */ - if (sc->sc_tx_pipeh != NULL) - usbd_close_pipe(sc->sc_tx_pipeh); - if (sc->sc_rx_pipeh != NULL) - usbd_close_pipe(sc->sc_rx_pipeh); - - mtx_destroy(&sc->sc_mtx); - usb_rem_task(sc->sc_udev, &sc->sc_mcasttask); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_task_tx); - callout_stop(&sc->sc_led_ch); - callout_stop(&sc->sc_watchdog_ch); - - /* free xfers */ - upgt_free_tx(sc); - upgt_free_rx(sc); - upgt_free_cmd(sc); - - bpfdetach(ifp); - ieee80211_ifdetach(ic); - if_free(ifp); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return 0; -} - -static void -upgt_free_rx(struct upgt_softc *sc) -{ - struct upgt_data *data_rx = &sc->rx_data; - - if (data_rx->xfer != NULL) { - usbd_free_xfer(data_rx->xfer); - data_rx->xfer = NULL; - } - - data_rx->ni = NULL; -} - -static void -upgt_free_tx(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < upgt_txbuf; i++) { - struct upgt_data *data_tx = &sc->tx_data[i]; - - if (data_tx->xfer != NULL) { - usbd_free_xfer(data_tx->xfer); - data_tx->xfer = NULL; - } - - data_tx->ni = NULL; - } -} - -static void -upgt_free_cmd(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd = &sc->cmd_data; - - if (data_cmd->xfer != NULL) { - usbd_free_xfer(data_cmd->xfer); - data_cmd->xfer = NULL; - } -} - -static device_method_t upgt_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, upgt_match), - DEVMETHOD(device_attach, upgt_attach), - DEVMETHOD(device_detach, upgt_detach), - - { 0, 0 } -}; - -static driver_t upgt_driver = { - "upgt", - upgt_methods, - sizeof(struct upgt_softc) -}; - -static devclass_t upgt_devclass; - -DRIVER_MODULE(if_upgt, uhub, upgt_driver, upgt_devclass, usbd_driver_load, 0); -MODULE_VERSION(if_upgt, 1); -MODULE_DEPEND(if_upgt, usb, 1, 1, 1); -MODULE_DEPEND(if_upgt, wlan, 1, 1, 1); -MODULE_DEPEND(if_upgt, upgtfw_fw, 1, 1, 1); diff --git a/sys/dev/usb/if_upgtvar.h b/sys/dev/usb/if_upgtvar.h deleted file mode 100644 index 298fb63..0000000 --- a/sys/dev/usb/if_upgtvar.h +++ /dev/null @@ -1,462 +0,0 @@ -/* $OpenBSD: if_upgtvar.h,v 1.14 2008/02/02 13:48:44 mglocker Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct upgt_softc; - -/* - * General values. - */ -#define UPGT_IFACE_INDEX 0 -#define UPGT_CONFIG_NO 1 -#define UPGT_USB_TIMEOUT 1000 -#define UPGT_FIRMWARE_TIMEOUT 10 - -#define UPGT_MEMADDR_FIRMWARE_START 0x00020000 /* 512 bytes large */ -#define UPGT_MEMSIZE_FRAME_HEAD 0x0070 -#define UPGT_MEMSIZE_RX 0x3500 - -#define UPGT_TX_COUNT 2 - -/* device flags */ -#define UPGT_DEVICE_ATTACHED (1 << 0) - -/* leds */ -#define UPGT_LED_OFF 0 -#define UPGT_LED_ON 1 -#define UPGT_LED_BLINK 2 - -/* - * Firmware. - */ -#define UPGT_FW_BLOCK_SIZE 512 - -#define UPGT_BRA_FWTYPE_SIZE 4 -#define UPGT_BRA_FWTYPE_LM86 "LM86" -#define UPGT_BRA_FWTYPE_LM87 "LM87" -enum upgt_fw_type { - UPGT_FWTYPE_LM86, - UPGT_FWTYPE_LM87 -}; - -#define UPGT_BRA_TYPE_FW 0x80000001 -#define UPGT_BRA_TYPE_VERSION 0x80000002 -#define UPGT_BRA_TYPE_DEPIF 0x80000003 -#define UPGT_BRA_TYPE_EXPIF 0x80000004 -#define UPGT_BRA_TYPE_DESCR 0x80000101 -#define UPGT_BRA_TYPE_END 0xff0000ff -struct upgt_fw_bra_option { - uint32_t type; - uint32_t len; - uint8_t data[]; -} __packed; - -struct upgt_fw_bra_descr { - uint32_t unknown1; - uint32_t memaddr_space_start; - uint32_t memaddr_space_end; - uint32_t unknown2; - uint32_t unknown3; - uint8_t rates[20]; -} __packed; - -#define UPGT_X2_SIGNATURE_SIZE 4 -#define UPGT_X2_SIGNATURE "x2 " -struct upgt_fw_x2_header { - uint8_t signature[4]; - uint32_t startaddr; - uint32_t len; - uint32_t crc; -} __packed; - -/* - * EEPROM. - */ -#define UPGT_EEPROM_SIZE 8192 -#define UPGT_EEPROM_BLOCK_SIZE 1020 - -struct upgt_eeprom_header { - /* 14 bytes */ - uint32_t magic; - uint16_t pad1; - uint16_t preamble_len; - uint32_t pad2; - /* data */ -} __packed; - -#define UPGT_EEPROM_TYPE_END 0x0000 -#define UPGT_EEPROM_TYPE_NAME 0x0001 -#define UPGT_EEPROM_TYPE_SERIAL 0x0003 -#define UPGT_EEPROM_TYPE_MAC 0x0101 -#define UPGT_EEPROM_TYPE_HWRX 0x1001 -#define UPGT_EEPROM_TYPE_CHIP 0x1002 -#define UPGT_EEPROM_TYPE_FREQ3 0x1903 -#define UPGT_EEPROM_TYPE_FREQ4 0x1904 -#define UPGT_EEPROM_TYPE_FREQ5 0x1905 -#define UPGT_EEPROM_TYPE_FREQ6 0x1906 -#define UPGT_EEPROM_TYPE_OFF 0xffff -struct upgt_eeprom_option { - uint16_t len; - uint16_t type; - uint8_t data[]; - /* data */ -} __packed; - -#define UPGT_EEPROM_RX_CONST 0x88 -struct upgt_eeprom_option_hwrx { - uint32_t pad1; - uint8_t rxfilter; - uint8_t pad2[15]; -} __packed; - -struct upgt_eeprom_freq3_header { - uint8_t flags; - uint8_t elements; -} __packed; - -struct upgt_eeprom_freq4_header { - uint8_t flags; - uint8_t elements; - uint8_t settings; - uint8_t type; -} __packed; - -struct upgt_eeprom_freq4_1 { - uint16_t freq; - uint8_t data[50]; -} __packed; - -struct upgt_eeprom_freq4_2 { - uint16_t head; - uint8_t subtails[4]; - uint8_t tail; -} __packed; - -/* - * LMAC protocol. - */ -struct upgt_lmac_mem { - uint32_t addr; - uint32_t chksum; -} __packed; - -#define UPGT_H1_FLAGS_TX_MGMT 0x00 /* for TX: mgmt frame */ -#define UPGT_H1_FLAGS_TX_NO_CALLBACK 0x01 /* for TX: no USB callback */ -#define UPGT_H1_FLAGS_TX_DATA 0x10 /* for TX: data frame */ -#define UPGT_H1_TYPE_RX_DATA 0x00 /* 802.11 RX data frame */ -#define UPGT_H1_TYPE_RX_DATA_MGMT 0x04 /* 802.11 RX mgmt frame */ -#define UPGT_H1_TYPE_TX_DATA 0x40 /* 802.11 TX data frame */ -#define UPGT_H1_TYPE_CTRL 0x80 /* control frame */ -struct upgt_lmac_h1 { - /* 4 bytes */ - uint8_t flags; - uint8_t type; - uint16_t len; -} __packed; - -#define UPGT_H2_TYPE_TX_ACK_NO 0x0000 -#define UPGT_H2_TYPE_TX_ACK_YES 0x0001 -#define UPGT_H2_TYPE_MACFILTER 0x0000 -#define UPGT_H2_TYPE_CHANNEL 0x0001 -#define UPGT_H2_TYPE_TX_DONE 0x0008 -#define UPGT_H2_TYPE_STATS 0x000a -#define UPGT_H2_TYPE_EEPROM 0x000c -#define UPGT_H2_TYPE_LED 0x000d -#define UPGT_H2_FLAGS_TX_ACK_NO 0x0101 -#define UPGT_H2_FLAGS_TX_ACK_YES 0x0707 -struct upgt_lmac_h2 { - /* 8 bytes */ - uint32_t reqid; - uint16_t type; - uint16_t flags; -} __packed; - -struct upgt_lmac_header { - /* 12 bytes */ - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; -} __packed; - -struct upgt_lmac_eeprom { - /* 16 bytes */ - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t offset; - uint16_t len; - /* data */ -} __packed; - -#define UPGT_FILTER_TYPE_NONE 0x0000 -#define UPGT_FILTER_TYPE_STA 0x0001 -#define UPGT_FILTER_TYPE_IBSS 0x0002 -#define UPGT_FILTER_TYPE_HOSTAP 0x0004 -#define UPGT_FILTER_TYPE_MONITOR 0x0010 -#define UPGT_FILTER_TYPE_RESET 0x0020 -#define UPGT_FILTER_UNKNOWN1 0x0002 -#define UPGT_FILTER_UNKNOWN2 0x0ca8 -#define UPGT_FILTER_UNKNOWN3 0xffff -#define UPGT_FILTER_MONITOR_UNKNOWN1 0x0000 -#define UPGT_FILTER_MONITOR_UNKNOWN2 0x0000 -#define UPGT_FILTER_MONITOR_UNKNOWN3 0x0000 -struct upgt_lmac_filter { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - /* 32 bytes */ - uint16_t type; - uint8_t dst[IEEE80211_ADDR_LEN]; - uint8_t src[IEEE80211_ADDR_LEN]; - uint16_t unknown1; - uint32_t rxaddr; - uint16_t unknown2; - uint32_t rxhw; - uint16_t unknown3; - uint32_t unknown4; -} __packed; - -/* frequence 3 data */ -struct upgt_lmac_freq3 { - uint16_t freq; - uint8_t data[6]; -} __packed; - -/* frequence 4 data */ -struct upgt_lmac_freq4 { - struct upgt_eeprom_freq4_2 cmd; - uint8_t pad; -}; - -/* frequence 6 data */ -struct upgt_lmac_freq6 { - uint16_t freq; - uint8_t data[8]; -} __packed; - -#define UPGT_CHANNEL_UNKNOWN1 0x0001 -#define UPGT_CHANNEL_UNKNOWN2 0x0000 -#define UPGT_CHANNEL_UNKNOWN3 0x48 -struct upgt_lmac_channel { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - /* 112 bytes */ - uint16_t unknown1; - uint16_t unknown2; - uint8_t pad1[20]; - struct upgt_lmac_freq6 freq6; - uint8_t settings; - uint8_t unknown3; - uint8_t freq3_1[4]; - struct upgt_lmac_freq4 freq4[8]; - uint8_t freq3_2[4]; - uint32_t pad2; -} __packed; - -#define UPGT_LED_MODE_SET 0x0003 -#define UPGT_LED_ACTION_OFF 0x0002 -#define UPGT_LED_ACTION_ON 0x0003 -#define UPGT_LED_ACTION_TMP_DUR 100 /* ms */ -struct upgt_lmac_led { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t mode; - uint16_t action_fix; - uint16_t action_tmp; - uint16_t action_tmp_dur; -} __packed; - -struct upgt_lmac_stats { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint8_t data[76]; -} __packed; - -struct upgt_lmac_rx_desc { - struct upgt_lmac_h1 header1; - /* 16 bytes */ - uint16_t freq; - uint8_t unknown1; - uint8_t rate; - uint8_t rssi; - uint8_t pad; - uint16_t unknown2; - uint32_t timestamp; - uint32_t unknown3; - uint8_t data[]; -} __packed; - -#define UPGT_TX_DESC_KEY_EXISTS 0x01 -struct upgt_lmac_tx_desc_wep { - uint8_t key_exists; - uint8_t key_len; - uint8_t key_val[16]; -} __packed; - -#define UPGT_TX_DESC_TYPE_BEACON 0x00000000 -#define UPGT_TX_DESC_TYPE_PROBE 0x00000001 -#define UPGT_TX_DESC_TYPE_MGMT 0x00000002 -#define UPGT_TX_DESC_TYPE_DATA 0x00000004 -#define UPGT_TX_DESC_PAD3_SIZE 2 -struct upgt_lmac_tx_desc { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint8_t rates[8]; - uint16_t pad1; - struct upgt_lmac_tx_desc_wep wep_key; - uint32_t type; - uint32_t pad2; - uint32_t unknown1; - uint32_t unknown2; - uint8_t pad3[2]; - /* 802.11 frame data */ -} __packed; - -#define UPGT_TX_DONE_DESC_STATUS_OK 0x0001 -struct upgt_lmac_tx_done_desc { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t status; - uint16_t rssi; - uint16_t seq; - uint16_t unknown; -} __packed; - -/* - * USB xfers. - */ -struct upgt_data { - struct upgt_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct ieee80211_node *ni; - struct mbuf *m; - uint32_t addr; - uint8_t use; -}; - -/* - * Prism memory. - */ -struct upgt_memory_page { - uint8_t used; - uint32_t addr; -} __packed; - -#define UPGT_MEMORY_MAX_PAGES 8 -struct upgt_memory { - uint8_t pages; - struct upgt_memory_page page[UPGT_MEMORY_MAX_PAGES]; -} __packed; - -/* - * BPF - */ -struct upgt_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; -} __packed; - -#define UPGT_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)) - -struct upgt_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define UPGT_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct upgt_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define UPGT_VAP(vap) ((struct upgt_vap *)(vap)) - -struct upgt_softc { - device_t sc_dev; - struct ifnet *sc_ifp; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - struct mtx sc_mtx; - int sc_if_flags; - int sc_debug; - - struct usb_task sc_mcasttask; - struct usb_task sc_task; - struct usb_task sc_scantask; -#define UPGT_SET_CHANNEL 2 - int sc_scan_action; - enum ieee80211_state sc_state; - int sc_arg; - int sc_led_blink; - struct callout sc_led_ch; - uint8_t sc_cur_rateset[8]; - - /* watchdog */ - int sc_tx_timer; - struct callout sc_watchdog_ch; - - /* Firmware. */ - int sc_fw_type; - /* memory addresses on device */ - uint32_t sc_memaddr_frame_start; - uint32_t sc_memaddr_frame_end; - uint32_t sc_memaddr_rx_start; - struct upgt_memory sc_memory; - - /* data which we found in the EEPROM */ - uint8_t sc_eeprom[UPGT_EEPROM_SIZE]; - uint16_t sc_eeprom_hwrx; - struct upgt_lmac_freq3 sc_eeprom_freq3[IEEE80211_CHAN_MAX]; - struct upgt_lmac_freq4 sc_eeprom_freq4[IEEE80211_CHAN_MAX][8]; - struct upgt_lmac_freq6 sc_eeprom_freq6[IEEE80211_CHAN_MAX]; - uint8_t sc_eeprom_freq6_settings; - - /* RX/TX */ - int sc_rx_no; - int sc_tx_no; - usbd_pipe_handle sc_rx_pipeh; - usbd_pipe_handle sc_tx_pipeh; - struct upgt_data tx_data[UPGT_TX_COUNT]; - struct upgt_data rx_data; - struct upgt_data cmd_data; - int tx_queued; - struct usb_task sc_task_tx; - - /* BPF */ - struct upgt_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - - struct upgt_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define UPGT_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define UPGT_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/if_ural.c b/sys/dev/usb/if_ural.c deleted file mode 100644 index 4595761..0000000 --- a/sys/dev/usb/if_ural.c +++ /dev/null @@ -1,2505 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 - * Damien Bergamini <damien.bergamini@free.fr> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Ralink Technology RT2500USB chipset driver - * http://www.ralinktech.com/ - */ - -#include <sys/param.h> -#include <sys/sysctl.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/endian.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_phy.h> -#include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_regdomain.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/if_uralreg.h> -#include <dev/usb/if_uralvar.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) do { if (uraldebug > 0) printf x; } while (0) -#define DPRINTFN(n, x) do { if (uraldebug >= (n)) printf x; } while (0) -int uraldebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural"); -SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &uraldebug, 0, - "ural debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) -#endif - -#define URAL_RSSI(rssi) \ - ((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \ - ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0) - -/* various supported device vendors/products */ -static const struct usb_devno ural_devs[] = { - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL167G }, - { USB_VENDOR_ASUS, USB_PRODUCT_RALINK_RT2570 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7051 }, - { USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU }, - { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122 }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWBKG }, - { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GN54G }, - { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254 }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54G }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GP }, - { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_HU200TS }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54 }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54AI }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54YB }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_NINWIFI }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_2 }, - { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_3 }, - { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_NV902 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2 }, - { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_3 }, - { USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WL54G }, - { USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG }, - { USB_VENDOR_SPHAIRON, USB_PRODUCT_SPHAIRON_UB801R}, - { USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2570 }, - { USB_VENDOR_VTECH, USB_PRODUCT_VTECH_RT2570 }, - { USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570 } -}; - -MODULE_DEPEND(ural, wlan, 1, 1, 1); -MODULE_DEPEND(ural, wlan_amrr, 1, 1, 1); -MODULE_DEPEND(ural, usb, 1, 1, 1); - -static struct ieee80211vap *ural_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, int opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void ural_vap_delete(struct ieee80211vap *); -static int ural_alloc_tx_list(struct ural_softc *); -static void ural_free_tx_list(struct ural_softc *); -static int ural_alloc_rx_list(struct ural_softc *); -static void ural_free_rx_list(struct ural_softc *); -static void ural_task(void *); -static void ural_scantask(void *); -static int ural_newstate(struct ieee80211vap *, - enum ieee80211_state, int); -static void ural_txeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void ural_rxeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void ural_setup_tx_desc(struct ural_softc *, - struct ural_tx_desc *, uint32_t, int, int); -static int ural_tx_bcn(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static int ural_tx_mgt(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static int ural_tx_data(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static void ural_start(struct ifnet *); -static void ural_watchdog(void *); -static int ural_ioctl(struct ifnet *, u_long, caddr_t); -static void ural_set_testmode(struct ural_softc *); -static void ural_eeprom_read(struct ural_softc *, uint16_t, void *, - int); -static uint16_t ural_read(struct ural_softc *, uint16_t); -static void ural_read_multi(struct ural_softc *, uint16_t, void *, - int); -static void ural_write(struct ural_softc *, uint16_t, uint16_t); -static void ural_write_multi(struct ural_softc *, uint16_t, void *, - int) __unused; -static void ural_bbp_write(struct ural_softc *, uint8_t, uint8_t); -static uint8_t ural_bbp_read(struct ural_softc *, uint8_t); -static void ural_rf_write(struct ural_softc *, uint8_t, uint32_t); -static struct ieee80211_node *ural_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void ural_newassoc(struct ieee80211_node *, int); -static void ural_scan_start(struct ieee80211com *); -static void ural_scan_end(struct ieee80211com *); -static void ural_set_channel(struct ieee80211com *); -static void ural_set_chan(struct ural_softc *, - struct ieee80211_channel *); -static void ural_disable_rf_tune(struct ural_softc *); -static void ural_enable_tsf_sync(struct ural_softc *); -static void ural_update_slot(struct ifnet *); -static void ural_set_txpreamble(struct ural_softc *); -static void ural_set_basicrates(struct ural_softc *, - const struct ieee80211_channel *); -static void ural_set_bssid(struct ural_softc *, const uint8_t *); -static void ural_set_macaddr(struct ural_softc *, uint8_t *); -static void ural_update_promisc(struct ural_softc *); -static const char *ural_get_rf(int); -static void ural_read_eeprom(struct ural_softc *); -static int ural_bbp_init(struct ural_softc *); -static void ural_set_txantenna(struct ural_softc *, int); -static void ural_set_rxantenna(struct ural_softc *, int); -static void ural_init_locked(struct ural_softc *); -static void ural_init(void *); -static void ural_stop(void *); -static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void ural_amrr_start(struct ural_softc *, - struct ieee80211_node *); -static void ural_amrr_timeout(void *); -static void ural_amrr_update(usbd_xfer_handle, usbd_private_handle, - usbd_status status); - -/* - * Default values for MAC registers; values taken from the reference driver. - */ -static const struct { - uint16_t reg; - uint16_t val; -} ural_def_mac[] = { - { RAL_TXRX_CSR5, 0x8c8d }, - { RAL_TXRX_CSR6, 0x8b8a }, - { RAL_TXRX_CSR7, 0x8687 }, - { RAL_TXRX_CSR8, 0x0085 }, - { RAL_MAC_CSR13, 0x1111 }, - { RAL_MAC_CSR14, 0x1e11 }, - { RAL_TXRX_CSR21, 0xe78f }, - { RAL_MAC_CSR9, 0xff1d }, - { RAL_MAC_CSR11, 0x0002 }, - { RAL_MAC_CSR22, 0x0053 }, - { RAL_MAC_CSR15, 0x0000 }, - { RAL_MAC_CSR8, 0x0780 }, - { RAL_TXRX_CSR19, 0x0000 }, - { RAL_TXRX_CSR18, 0x005a }, - { RAL_PHY_CSR2, 0x0000 }, - { RAL_TXRX_CSR0, 0x1ec0 }, - { RAL_PHY_CSR4, 0x000f } -}; - -/* - * Default values for BBP registers; values taken from the reference driver. - */ -static const struct { - uint8_t reg; - uint8_t val; -} ural_def_bbp[] = { - { 3, 0x02 }, - { 4, 0x19 }, - { 14, 0x1c }, - { 15, 0x30 }, - { 16, 0xac }, - { 17, 0x48 }, - { 18, 0x18 }, - { 19, 0xff }, - { 20, 0x1e }, - { 21, 0x08 }, - { 22, 0x08 }, - { 23, 0x08 }, - { 24, 0x80 }, - { 25, 0x50 }, - { 26, 0x08 }, - { 27, 0x23 }, - { 30, 0x10 }, - { 31, 0x2b }, - { 32, 0xb9 }, - { 34, 0x12 }, - { 35, 0x50 }, - { 39, 0xc4 }, - { 40, 0x02 }, - { 41, 0x60 }, - { 53, 0x10 }, - { 54, 0x18 }, - { 56, 0x08 }, - { 57, 0x10 }, - { 58, 0x08 }, - { 61, 0x60 }, - { 62, 0x10 }, - { 75, 0xff } -}; - -/* - * Default values for RF register R2 indexed by channel numbers. - */ -static const uint32_t ural_rf2522_r2[] = { - 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814, - 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e -}; - -static const uint32_t ural_rf2523_r2[] = { - 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, - 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 -}; - -static const uint32_t ural_rf2524_r2[] = { - 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, - 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 -}; - -static const uint32_t ural_rf2525_r2[] = { - 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d, - 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346 -}; - -static const uint32_t ural_rf2525_hi_r2[] = { - 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345, - 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e -}; - -static const uint32_t ural_rf2525e_r2[] = { - 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463, - 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b -}; - -static const uint32_t ural_rf2526_hi_r2[] = { - 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d, - 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241 -}; - -static const uint32_t ural_rf2526_r2[] = { - 0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229, - 0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d -}; - -/* - * For dual-band RF, RF registers R1 and R4 also depend on channel number; - * values taken from the reference driver. - */ -static const struct { - uint8_t chan; - uint32_t r1; - uint32_t r2; - uint32_t r4; -} ural_rf5222[] = { - { 1, 0x08808, 0x0044d, 0x00282 }, - { 2, 0x08808, 0x0044e, 0x00282 }, - { 3, 0x08808, 0x0044f, 0x00282 }, - { 4, 0x08808, 0x00460, 0x00282 }, - { 5, 0x08808, 0x00461, 0x00282 }, - { 6, 0x08808, 0x00462, 0x00282 }, - { 7, 0x08808, 0x00463, 0x00282 }, - { 8, 0x08808, 0x00464, 0x00282 }, - { 9, 0x08808, 0x00465, 0x00282 }, - { 10, 0x08808, 0x00466, 0x00282 }, - { 11, 0x08808, 0x00467, 0x00282 }, - { 12, 0x08808, 0x00468, 0x00282 }, - { 13, 0x08808, 0x00469, 0x00282 }, - { 14, 0x08808, 0x0046b, 0x00286 }, - - { 36, 0x08804, 0x06225, 0x00287 }, - { 40, 0x08804, 0x06226, 0x00287 }, - { 44, 0x08804, 0x06227, 0x00287 }, - { 48, 0x08804, 0x06228, 0x00287 }, - { 52, 0x08804, 0x06229, 0x00287 }, - { 56, 0x08804, 0x0622a, 0x00287 }, - { 60, 0x08804, 0x0622b, 0x00287 }, - { 64, 0x08804, 0x0622c, 0x00287 }, - - { 100, 0x08804, 0x02200, 0x00283 }, - { 104, 0x08804, 0x02201, 0x00283 }, - { 108, 0x08804, 0x02202, 0x00283 }, - { 112, 0x08804, 0x02203, 0x00283 }, - { 116, 0x08804, 0x02204, 0x00283 }, - { 120, 0x08804, 0x02205, 0x00283 }, - { 124, 0x08804, 0x02206, 0x00283 }, - { 128, 0x08804, 0x02207, 0x00283 }, - { 132, 0x08804, 0x02208, 0x00283 }, - { 136, 0x08804, 0x02209, 0x00283 }, - { 140, 0x08804, 0x0220a, 0x00283 }, - - { 149, 0x08808, 0x02429, 0x00281 }, - { 153, 0x08808, 0x0242b, 0x00281 }, - { 157, 0x08808, 0x0242d, 0x00281 }, - { 161, 0x08808, 0x0242f, 0x00281 } -}; - -static device_probe_t ural_match; -static device_attach_t ural_attach; -static device_detach_t ural_detach; - -static device_method_t ural_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ural_match), - DEVMETHOD(device_attach, ural_attach), - DEVMETHOD(device_detach, ural_detach), - - { 0, 0 } -}; - -static driver_t ural_driver = { - "ural", - ural_methods, - sizeof(struct ural_softc) -}; - -static devclass_t ural_devclass; - -DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, usbd_driver_load, 0); - -static int -ural_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(ural_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -ural_attach(device_t self) -{ - struct ural_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ifnet *ifp; - struct ieee80211com *ic; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - uint8_t bands; - - sc->sc_udev = uaa->device; - sc->sc_dev = self; - - if (usbd_set_config_no(sc->sc_udev, RAL_CONFIG_NO, 0) != 0) { - device_printf(self, "could not set configuration no\n"); - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, RAL_IFACE_INDEX, - &sc->sc_iface); - if (error != 0) { - device_printf(self, "could not get interface handle\n"); - return ENXIO; - } - - /* - * Find endpoints. - */ - id = usbd_get_interface_descriptor(sc->sc_iface); - - sc->sc_rx_no = sc->sc_tx_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - device_printf(self, "no endpoint descriptor for %d\n", - i); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_rx_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - sc->sc_tx_no = ed->bEndpointAddress; - } - if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) { - device_printf(self, "missing endpoint\n"); - return ENXIO; - } - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - return ENXIO; - } - ic = ifp->if_l2com; - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF | MTX_RECURSE); - - usb_init_task(&sc->sc_task, ural_task, sc); - usb_init_task(&sc->sc_scantask, ural_scantask, sc); - callout_init(&sc->watchdog_ch, 0); - - /* retrieve RT2570 rev. no */ - sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); - - /* retrieve MAC address and various other things from EEPROM */ - ural_read_eeprom(sc); - - device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", - sc->asic_rev, ural_get_rf(sc->rf_rev)); - - ifp->if_softc = sc; - if_initname(ifp, "ural", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ - ifp->if_init = ural_init; - ifp->if_ioctl = ural_ioctl; - ifp->if_start = ural_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - ic->ic_ifp = ifp; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode supported */ - | IEEE80211_C_IBSS /* IBSS mode supported */ - | IEEE80211_C_MONITOR /* monitor mode supported */ - | IEEE80211_C_HOSTAP /* HostAp mode supported */ - | IEEE80211_C_TXPMGT /* tx power management */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* bg scanning supported */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - if (sc->rf_rev == RAL_RF_5222) - setbit(&bands, IEEE80211_MODE_11A); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic); - ic->ic_newassoc = ural_newassoc; - ic->ic_raw_xmit = ural_raw_xmit; - ic->ic_node_alloc = ural_node_alloc; - ic->ic_scan_start = ural_scan_start; - ic->ic_scan_end = ural_scan_end; - ic->ic_set_channel = ural_set_channel; - - ic->ic_vap_create = ural_vap_create; - ic->ic_vap_delete = ural_vap_delete; - - sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); - - bpfattach(ifp, DLT_IEEE802_11_RADIO, - sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap)); - - sc->sc_rxtap_len = sizeof sc->sc_rxtap; - sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); - sc->sc_rxtap.wr_ihdr.it_present = htole32(RAL_RX_RADIOTAP_PRESENT); - - sc->sc_txtap_len = sizeof sc->sc_txtap; - sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); - sc->sc_txtap.wt_ihdr.it_present = htole32(RAL_TX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - return 0; -} - -static int -ural_detach(device_t self) -{ - struct ural_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ural_stop(sc); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - - usb_rem_task(sc->sc_udev, &sc->sc_task); - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - callout_stop(&sc->watchdog_ch); - - if (sc->amrr_xfer != NULL) { - usbd_free_xfer(sc->amrr_xfer); - sc->amrr_xfer = NULL; - } - - if (sc->sc_rx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_rx_pipeh); - usbd_close_pipe(sc->sc_rx_pipeh); - } - - if (sc->sc_tx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_tx_pipeh); - usbd_close_pipe(sc->sc_tx_pipeh); - } - - ural_free_rx_list(sc); - ural_free_tx_list(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - - return 0; -} - -static struct ieee80211vap * -ural_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, int opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ural_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - uvp = (struct ural_vap *) malloc(sizeof(struct ural_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return NULL; - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = ural_newstate; - - callout_init(&uvp->amrr_ch, 0); - ieee80211_amrr_init(&uvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); - ic->ic_opmode = opmode; - return vap; -} - -static void -ural_vap_delete(struct ieee80211vap *vap) -{ - struct ural_vap *uvp = URAL_VAP(vap); - - callout_stop(&uvp->amrr_ch); - ieee80211_amrr_cleanup(&uvp->amrr); - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static int -ural_alloc_tx_list(struct ural_softc *sc) -{ - struct ural_tx_data *data; - int i, error; - - sc->tx_queued = sc->tx_cur = 0; - - for (i = 0; i < RAL_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx xfer\n"); - error = ENOMEM; - goto fail; - } - - data->buf = usbd_alloc_buffer(data->xfer, - RAL_TX_DESC_SIZE + MCLBYTES); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx buffer\n"); - error = ENOMEM; - goto fail; - } - } - - return 0; - -fail: ural_free_tx_list(sc); - return error; -} - -static void -ural_free_tx_list(struct ural_softc *sc) -{ - struct ural_tx_data *data; - int i; - - for (i = 0; i < RAL_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - } -} - -static int -ural_alloc_rx_list(struct ural_softc *sc) -{ - struct ural_rx_data *data; - int i, error; - - for (i = 0; i < RAL_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - data->sc = sc; - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx xfer\n"); - error = ENOMEM; - goto fail; - } - - if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx buffer\n"); - error = ENOMEM; - goto fail; - } - - data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (data->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - - data->buf = mtod(data->m, uint8_t *); - } - - return 0; - -fail: ural_free_rx_list(sc); - return error; -} - -static void -ural_free_rx_list(struct ural_softc *sc) -{ - struct ural_rx_data *data; - int i; - - for (i = 0; i < RAL_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - - if (data->m != NULL) { - m_freem(data->m); - data->m = NULL; - } - } -} - -static void -ural_task(void *xarg) -{ - struct ural_softc *sc = xarg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ural_vap *uvp = URAL_VAP(vap); - const struct ieee80211_txparam *tp; - enum ieee80211_state ostate; - struct ieee80211_node *ni; - struct mbuf *m; - - ostate = vap->iv_state; - - RAL_LOCK(sc); - switch (sc->sc_state) { - case IEEE80211_S_INIT: - if (ostate == IEEE80211_S_RUN) { - /* abort TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - - /* force tx led to stop blinking */ - ural_write(sc, RAL_MAC_CSR20, 0); - } - break; - - case IEEE80211_S_RUN: - ni = vap->iv_bss; - - if (vap->iv_opmode != IEEE80211_M_MONITOR) { - ural_update_slot(ic->ic_ifp); - ural_set_txpreamble(sc); - ural_set_basicrates(sc, ic->ic_bsschan); - ural_set_bssid(sc, ni->ni_bssid); - } - - if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) { - m = ieee80211_beacon_alloc(ni, &uvp->bo); - if (m == NULL) { - device_printf(sc->sc_dev, - "could not allocate beacon\n"); - return; - } - - if (ural_tx_bcn(sc, m, ni) != 0) { - device_printf(sc->sc_dev, - "could not send beacon\n"); - return; - } - } - - /* make tx led blink on tx (controlled by ASIC) */ - ural_write(sc, RAL_MAC_CSR20, 1); - - if (vap->iv_opmode != IEEE80211_M_MONITOR) - ural_enable_tsf_sync(sc); - - /* enable automatic rate adaptation */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - ural_amrr_start(sc, ni); - - break; - - default: - break; - } - - RAL_UNLOCK(sc); - - IEEE80211_LOCK(ic); - uvp->newstate(vap, sc->sc_state, sc->sc_arg); - if (vap->iv_newstate_cb != NULL) - vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); - IEEE80211_UNLOCK(ic); -} - -static void -ural_scantask(void *arg) -{ - struct ural_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - RAL_LOCK(sc); - if (sc->sc_scan_action == URAL_SCAN_START) { - /* abort TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - ural_set_bssid(sc, ifp->if_broadcastaddr); - } else if (sc->sc_scan_action == URAL_SET_CHANNEL) { - mtx_lock(&Giant); - ural_set_chan(sc, ic->ic_curchan); - mtx_unlock(&Giant); - } else { - ural_enable_tsf_sync(sc); - /* XXX keep local copy */ - ural_set_bssid(sc, vap->iv_bss->ni_bssid); - } - RAL_UNLOCK(sc); -} - -static int -ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct ural_vap *uvp = URAL_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ural_softc *sc = ic->ic_ifp->if_softc; - - callout_stop(&uvp->amrr_ch); - - /* do it in a process context */ - sc->sc_state = nstate; - sc->sc_arg = arg; - - usb_rem_task(sc->sc_udev, &sc->sc_task); - if (nstate == IEEE80211_S_INIT) { - uvp->newstate(vap, nstate, arg); - return 0; - } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); - return EINPROGRESS; - } -} - -#define RAL_RXTX_TURNAROUND 5 /* us */ - -static void -ural_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ural_tx_data *data = priv; - struct ural_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - status == USBD_NORMAL_COMPLETION ? 0 : ETIMEDOUT); - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - - ifp->if_oerrors++; - /* XXX mbuf leak? */ - return; - } - - m_freem(data->m); - data->m = NULL; - ieee80211_free_node(data->ni); - data->ni = NULL; - - sc->tx_queued--; - ifp->if_opackets++; - - DPRINTFN(10, ("tx done\n")); - - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ural_start(ifp); -} - -static void -ural_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ural_rx_data *data = priv; - struct ural_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ural_rx_desc *desc; - struct ieee80211_node *ni; - struct mbuf *mnew, *m; - int len, rssi; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh); - goto skip; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); - - if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) { - DPRINTF(("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), - len)); - ifp->if_ierrors++; - goto skip; - } - - /* rx descriptor is located at the end */ - desc = (struct ural_rx_desc *)(data->buf + len - RAL_RX_DESC_SIZE); - - if ((le32toh(desc->flags) & RAL_RX_PHY_ERROR) || - (le32toh(desc->flags) & RAL_RX_CRC_ERROR)) { - /* - * This should not happen since we did not request to receive - * those frames when we filled RAL_TXRX_CSR2. - */ - DPRINTFN(5, ("PHY or CRC error\n")); - ifp->if_ierrors++; - goto skip; - } - - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - ifp->if_ierrors++; - goto skip; - } - - m = data->m; - data->m = mnew; - data->buf = mtod(data->m, uint8_t *); - - /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; - - if (bpf_peers_present(ifp->if_bpf)) { - struct ural_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = IEEE80211_RADIOTAP_F_FCS; - tap->wr_rate = ieee80211_plcp2rate(desc->rate, - (desc->flags & htole32(RAL_RX_OFDM)) ? - IEEE80211_T_OFDM : IEEE80211_T_CCK); - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wr_antenna = sc->rx_ant; - tap->wr_antsignal = URAL_RSSI(desc->rssi); - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); - } - - /* Strip trailing 802.11 MAC FCS. */ - m_adj(m, -IEEE80211_CRC_LEN); - - rssi = URAL_RSSI(desc->rssi); - ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - (void) ieee80211_input(ni, m, rssi, RAL_NOISE_FLOOR, 0); - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, RAL_NOISE_FLOOR, 0); - - DPRINTFN(15, ("rx done\n")); - -skip: /* setup a new transfer */ - usbd_setup_xfer(xfer, sc->sc_rx_pipeh, data, data->buf, MCLBYTES, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ural_rxeof); - usbd_transfer(xfer); -} - -static uint8_t -ural_plcp_signal(int rate) -{ - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: return 0x0; - case 4: return 0x1; - case 11: return 0x2; - case 22: return 0x3; - } - return 0xff; /* XXX unsupported/unknown rate */ -} - -static void -ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, - uint32_t flags, int len, int rate) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t plcp_length; - int remainder; - - desc->flags = htole32(flags); - desc->flags |= htole32(RAL_TX_NEWSEQ); - desc->flags |= htole32(len << 16); - - desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); - desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); - - /* setup PLCP fields */ - desc->plcp_signal = ural_plcp_signal(rate); - desc->plcp_service = 4; - - len += IEEE80211_CRC_LEN; - if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) { - desc->flags |= htole32(RAL_TX_OFDM); - - plcp_length = len & 0xfff; - desc->plcp_length_hi = plcp_length >> 6; - desc->plcp_length_lo = plcp_length & 0x3f; - } else { - plcp_length = (16 * len + rate - 1) / rate; - if (rate == 22) { - remainder = (16 * len) % 22; - if (remainder != 0 && remainder < 7) - desc->plcp_service |= RAL_PLCP_LENGEXT; - } - desc->plcp_length_hi = plcp_length >> 8; - desc->plcp_length_lo = plcp_length & 0xff; - - if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->plcp_signal |= 0x08; - } - - desc->iv = 0; - desc->eiv = 0; -} - -#define RAL_TX_TIMEOUT 5000 - -static int -ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - const struct ieee80211_txparam *tp; - struct ural_tx_desc *desc; - usbd_xfer_handle xfer; - uint8_t cmd; - usbd_status error; - uint8_t *buf; - int xferlen; - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; - - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == NULL) - return ENOMEM; - - /* xfer length needs to be a multiple of two! */ - xferlen = (RAL_TX_DESC_SIZE + m0->m_pkthdr.len + 1) & ~1; - - buf = usbd_alloc_buffer(xfer, xferlen); - if (buf == NULL) { - usbd_free_xfer(xfer); - return ENOMEM; - } - - cmd = 0; - usbd_setup_xfer(xfer, sc->sc_tx_pipeh, NULL, &cmd, sizeof cmd, - USBD_FORCE_SHORT_XFER, RAL_TX_TIMEOUT, NULL); - - error = usbd_sync_transfer(xfer); - if (error != 0) { - usbd_free_xfer(xfer); - return error; - } - - desc = (struct ural_tx_desc *)buf; - - m_copydata(m0, 0, m0->m_pkthdr.len, buf + RAL_TX_DESC_SIZE); - ural_setup_tx_desc(sc, desc, RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, - m0->m_pkthdr.len, tp->mgmtrate); - - DPRINTFN(10, ("sending beacon frame len=%u rate=%u xfer len=%u\n", - m0->m_pkthdr.len, tp->mgmtrate, xferlen)); - - usbd_setup_xfer(xfer, sc->sc_tx_pipeh, NULL, buf, xferlen, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, NULL); - - error = usbd_sync_transfer(xfer); - usbd_free_xfer(xfer); - - return error; -} - -static int -ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = sc->sc_ifp; - const struct ieee80211_txparam *tp; - struct ural_tx_desc *desc; - struct ural_tx_data *data; - struct ieee80211_frame *wh; - struct ieee80211_key *k; - uint32_t flags; - uint16_t dur; - usbd_status error; - int xferlen; - - data = &sc->tx_data[sc->tx_cur]; - desc = (struct ural_tx_desc *)data->buf; - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - - wh = mtod(m0, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - wh = mtod(m0, struct ieee80211_frame *); - } - - data->m = m0; - data->ni = ni; - - flags = 0; - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RAL_TX_ACK; - - dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - - /* tell hardware to add timestamp for probe responses */ - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT && - (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_PROBE_RESP) - flags |= RAL_TX_TIMESTAMP; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct ural_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = tp->mgmtrate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RAL_TX_DESC_SIZE); - ural_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, tp->mgmtrate); - - /* align end on a 2-bytes boundary */ - xferlen = (RAL_TX_DESC_SIZE + m0->m_pkthdr.len + 1) & ~1; - - /* - * No space left in the last URB to store the extra 2 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 2; - - DPRINTFN(10, ("sending mgt frame len=%u rate=%u xfer len=%u\n", - m0->m_pkthdr.len, tp->mgmtrate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, - ural_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - m_freem(m0); - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RAL_TX_LIST_COUNT; - - return 0; -} - -static int -ural_sendprot(struct ural_softc *sc, - const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) -{ - struct ieee80211com *ic = ni->ni_ic; - const struct ieee80211_frame *wh; - struct ural_tx_desc *desc; - struct ural_tx_data *data; - struct mbuf *mprot; - int protrate, ackrate, pktlen, flags, isshort; - uint16_t dur; - usbd_status error; - - KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, - ("protection %d", prot)); - - wh = mtod(m, const struct ieee80211_frame *); - pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; - - protrate = ieee80211_ctl_rate(sc->sc_rates, rate); - ackrate = ieee80211_ack_rate(sc->sc_rates, rate); - - isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; - dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort); - + ieee80211_ack_duration(sc->sc_rates, rate, isshort); - flags = RAL_TX_RETRY(7); - if (prot == IEEE80211_PROT_RTSCTS) { - /* NB: CTS is the same size as an ACK */ - dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort); - flags |= RAL_TX_ACK; - mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); - } else { - mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); - } - if (mprot == NULL) { - /* XXX stat + msg */ - return ENOBUFS; - } - data = &sc->tx_data[sc->tx_cur]; - desc = (struct ural_tx_desc *)data->buf; - - data->m = mprot; - data->ni = ieee80211_ref_node(ni); - m_copydata(mprot, 0, mprot->m_pkthdr.len, data->buf + RAL_TX_DESC_SIZE); - ural_setup_tx_desc(sc, desc, flags, mprot->m_pkthdr.len, protrate); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - /* NB: no roundup necessary */ - RAL_TX_DESC_SIZE + mprot->m_pkthdr.len, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, ural_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RAL_TX_LIST_COUNT; - - return 0; -} - -static int -ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, - const struct ieee80211_bpf_params *params) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ural_tx_desc *desc; - struct ural_tx_data *data; - uint32_t flags; - usbd_status error; - int xferlen, rate; - - KASSERT(params != NULL, ("no raw xmit params")); - - data = &sc->tx_data[sc->tx_cur]; - desc = (struct ural_tx_desc *)data->buf; - - rate = params->ibp_rate0 & IEEE80211_RATE_VAL; - /* XXX validate */ - if (rate == 0) { - m_freem(m0); - return EINVAL; - } - flags = 0; - if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) - flags |= RAL_TX_ACK; - if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { - error = ural_sendprot(sc, m0, ni, - params->ibp_flags & IEEE80211_BPF_RTS ? - IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, - rate); - if (error) { - m_freem(m0); - return error; - } - flags |= RAL_TX_IFS_SIFS; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct ural_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - data->m = m0; - data->ni = ni; - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RAL_TX_DESC_SIZE); - /* XXX need to setup descriptor ourself */ - ural_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate); - - /* align end on a 2-bytes boundary */ - xferlen = (RAL_TX_DESC_SIZE + m0->m_pkthdr.len + 1) & ~1; - - /* - * No space left in the last URB to store the extra 2 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 2; - - DPRINTFN(10, ("sending raw frame len=%u rate=%u xfer len=%u\n", - m0->m_pkthdr.len, rate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, - ural_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - m_freem(m0); - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RAL_TX_LIST_COUNT; - - return 0; -} - -static int -ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = sc->sc_ifp; - struct ural_tx_desc *desc; - struct ural_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - uint32_t flags = 0; - uint16_t dur; - usbd_status error; - int xferlen, rate; - - wh = mtod(m0, struct ieee80211_frame *); - - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else - rate = ni->ni_txrate; - - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - int prot = IEEE80211_PROT_NONE; - if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) - prot = IEEE80211_PROT_RTSCTS; - else if ((ic->ic_flags & IEEE80211_F_USEPROT) && - ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) - prot = ic->ic_protmode; - if (prot != IEEE80211_PROT_NONE) { - error = ural_sendprot(sc, m0, ni, prot, rate); - if (error) { - m_freem(m0); - return error; - } - flags |= RAL_TX_IFS_SIFS; - } - } - - data = &sc->tx_data[sc->tx_cur]; - desc = (struct ural_tx_desc *)data->buf; - - data->m = m0; - data->ni = ni; - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RAL_TX_ACK; - flags |= RAL_TX_RETRY(7); - - dur = ieee80211_ack_duration(sc->sc_rates, rate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct ural_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wt_antenna = sc->tx_ant; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RAL_TX_DESC_SIZE); - ural_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate); - - /* align end on a 2-bytes boundary */ - xferlen = (RAL_TX_DESC_SIZE + m0->m_pkthdr.len + 1) & ~1; - - /* - * No space left in the last URB to store the extra 2 bytes, force - * sending of another URB. - */ - if ((xferlen % 64) == 0) - xferlen += 2; - - DPRINTFN(10, ("sending data frame len=%u rate=%u xfer len=%u\n", - m0->m_pkthdr.len, rate, xferlen)); - - usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf, - xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT, - ural_txeof); - - error = usbd_transfer(data->xfer); - if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) { - m_freem(m0); - data->m = NULL; - data->ni = NULL; - return error; - } - - sc->tx_queued++; - sc->tx_cur = (sc->tx_cur + 1) % RAL_TX_LIST_COUNT; - - return 0; -} - -static void -ural_start(struct ifnet *ifp) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->tx_queued >= RAL_TX_LIST_COUNT-1) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - m = ieee80211_encap(ni, m); - if (m == NULL) { - ieee80211_free_node(ni); - continue; - } - if (ural_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - sc->sc_tx_timer = 5; - callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc); - } -} - -static void -ural_watchdog(void *arg) -{ - struct ural_softc *sc = (struct ural_softc *)arg; - - RAL_LOCK(sc); - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - /*ural_init(sc); XXX needs a process context! */ - sc->sc_ifp->if_oerrors++; - RAL_UNLOCK(sc); - return; - } - callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc); - } - - RAL_UNLOCK(sc); -} - -static int -ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - RAL_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ural_init_locked(sc); - startall = 1; - } else - ural_update_promisc(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ural_stop(sc); - } - RAL_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - default: - error = ether_ioctl(ifp, cmd, data); - break; - } - return error; -} - -static void -ural_set_testmode(struct ural_softc *sc) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_VENDOR_REQUEST; - USETW(req.wValue, 4); - USETW(req.wIndex, 1); - USETW(req.wLength, 0); - - error = usbd_do_request(sc->sc_udev, &req, NULL); - if (error != 0) { - device_printf(sc->sc_dev, "could not set test mode: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_EEPROM; - USETW(req.wValue, 0); - USETW(req.wIndex, addr); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not read EEPROM: %s\n", - usbd_errstr(error)); - } -} - -static uint16_t -ural_read(struct ural_softc *sc, uint16_t reg) -{ - usb_device_request_t req; - usbd_status error; - uint16_t val; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, sizeof (uint16_t)); - - error = usbd_do_request(sc->sc_udev, &req, &val); - if (error != 0) { - device_printf(sc->sc_dev, "could not read MAC register: %s\n", - usbd_errstr(error)); - return 0; - } - - return le16toh(val); -} - -static void -ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not read MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_WRITE_MAC; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - error = usbd_do_request(sc->sc_udev, &req, NULL); - if (error != 0) { - device_printf(sc->sc_dev, "could not write MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_WRITE_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = usbd_do_request(sc->sc_udev, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not write MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val) -{ - uint16_t tmp; - int ntries; - - for (ntries = 0; ntries < 5; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not write to BBP\n"); - return; - } - - tmp = reg << 8 | val; - ural_write(sc, RAL_PHY_CSR7, tmp); -} - -static uint8_t -ural_bbp_read(struct ural_softc *sc, uint8_t reg) -{ - uint16_t val; - int ntries; - - val = RAL_BBP_WRITE | reg << 8; - ural_write(sc, RAL_PHY_CSR7, val); - - for (ntries = 0; ntries < 5; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not read BBP\n"); - return 0; - } - - return ural_read(sc, RAL_PHY_CSR7) & 0xff; -} - -static void -ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val) -{ - uint32_t tmp; - int ntries; - - for (ntries = 0; ntries < 5; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY)) - break; - } - if (ntries == 5) { - device_printf(sc->sc_dev, "could not write to RF\n"); - return; - } - - tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xfffff) << 2 | (reg & 0x3); - ural_write(sc, RAL_PHY_CSR9, tmp & 0xffff); - ural_write(sc, RAL_PHY_CSR10, tmp >> 16); - - /* remember last written value in sc */ - sc->rf_regs[reg] = val; - - DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff)); -} - -/* ARGUSED */ -static struct ieee80211_node * -ural_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct ural_node *un; - - un = malloc(sizeof(struct ural_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return un != NULL ? &un->ni : NULL; -} - -static void -ural_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&URAL_VAP(vap)->amrr, &URAL_NODE(ni)->amn, ni); -} - -static void -ural_scan_start(struct ieee80211com *ic) -{ - struct ural_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = URAL_SCAN_START; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); - -} - -static void -ural_scan_end(struct ieee80211com *ic) -{ - struct ural_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = URAL_SCAN_END; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); - -} - -static void -ural_set_channel(struct ieee80211com *ic) -{ - - struct ural_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = URAL_SET_CHANNEL; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); - - sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); -} - -static void -ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t power, tmp; - u_int i, chan; - - chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) - return; - - if (IEEE80211_IS_CHAN_2GHZ(c)) - power = min(sc->txpow[chan - 1], 31); - else - power = 31; - - /* adjust txpower using ifconfig settings */ - power -= (100 - ic->ic_txpowlimit) / 8; - - DPRINTFN(2, ("setting channel to %u, txpower to %u\n", chan, power)); - - switch (sc->rf_rev) { - case RAL_RF_2522: - ural_rf_write(sc, RAL_RF1, 0x00814); - ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - break; - - case RAL_RF_2523: - ural_rf_write(sc, RAL_RF1, 0x08804); - ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2524: - ural_rf_write(sc, RAL_RF1, 0x0c808); - ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2525: - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2525E: - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); - break; - - case RAL_RF_2526: - ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]); - ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); - ural_rf_write(sc, RAL_RF1, 0x08804); - - ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); - break; - - /* dual-band RF */ - case RAL_RF_5222: - for (i = 0; ural_rf5222[i].chan != chan; i++); - - ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1); - ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4); - break; - } - - if (ic->ic_opmode != IEEE80211_M_MONITOR && - (ic->ic_flags & IEEE80211_F_SCAN) == 0) { - /* set Japan filter bit for channel 14 */ - tmp = ural_bbp_read(sc, 70); - - tmp &= ~RAL_JAPAN_FILTER; - if (chan == 14) - tmp |= RAL_JAPAN_FILTER; - - ural_bbp_write(sc, 70, tmp); - - /* clear CRC errors */ - ural_read(sc, RAL_STA_CSR0); - - DELAY(10000); - ural_disable_rf_tune(sc); - } - - /* XXX doesn't belong here */ - /* update basic rate set */ - ural_set_basicrates(sc, c); -} - -/* - * Disable RF auto-tuning. - */ -static void -ural_disable_rf_tune(struct ural_softc *sc) -{ - uint32_t tmp; - - if (sc->rf_rev != RAL_RF_2523) { - tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE; - ural_rf_write(sc, RAL_RF1, tmp); - } - - tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; - ural_rf_write(sc, RAL_RF3, tmp); - - DPRINTFN(2, ("disabling RF autotune\n")); -} - -/* - * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF - * synchronization. - */ -static void -ural_enable_tsf_sync(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint16_t logcwmin, preload, tmp; - - /* first, disable TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - - tmp = (16 * vap->iv_bss->ni_intval) << 4; - ural_write(sc, RAL_TXRX_CSR18, tmp); - - logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0; - preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6; - tmp = logcwmin << 12 | preload; - ural_write(sc, RAL_TXRX_CSR20, tmp); - - /* finally, enable TSF synchronization */ - tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN; - if (ic->ic_opmode == IEEE80211_M_STA) - tmp |= RAL_ENABLE_TSF_SYNC(1); - else - tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR; - ural_write(sc, RAL_TXRX_CSR19, tmp); - - DPRINTF(("enabling TSF synchronization\n")); -} - -static void -ural_update_slot(struct ifnet *ifp) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t slottime, sifs, eifs; - - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; - - /* - * These settings may sound a bit inconsistent but this is what the - * reference driver does. - */ - if (ic->ic_curmode == IEEE80211_MODE_11B) { - sifs = 16 - RAL_RXTX_TURNAROUND; - eifs = 364; - } else { - sifs = 10 - RAL_RXTX_TURNAROUND; - eifs = 64; - } - - ural_write(sc, RAL_MAC_CSR10, slottime); - ural_write(sc, RAL_MAC_CSR11, sifs); - ural_write(sc, RAL_MAC_CSR12, eifs); -} - -static void -ural_set_txpreamble(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t tmp; - - tmp = ural_read(sc, RAL_TXRX_CSR10); - - tmp &= ~RAL_SHORT_PREAMBLE; - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - tmp |= RAL_SHORT_PREAMBLE; - - ural_write(sc, RAL_TXRX_CSR10, tmp); -} - -static void -ural_set_basicrates(struct ural_softc *sc, const struct ieee80211_channel *c) -{ - /* XXX wrong, take from rate set */ - /* update basic rate set */ - if (IEEE80211_IS_CHAN_5GHZ(c)) { - /* 11a basic rates: 6, 12, 24Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x150); - } else if (IEEE80211_IS_CHAN_ANYG(c)) { - /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x15f); - } else { - /* 11b basic rates: 1, 2Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x3); - } -} - -static void -ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid) -{ - uint16_t tmp; - - tmp = bssid[0] | bssid[1] << 8; - ural_write(sc, RAL_MAC_CSR5, tmp); - - tmp = bssid[2] | bssid[3] << 8; - ural_write(sc, RAL_MAC_CSR6, tmp); - - tmp = bssid[4] | bssid[5] << 8; - ural_write(sc, RAL_MAC_CSR7, tmp); - - DPRINTF(("setting BSSID to %6D\n", bssid, ":")); -} - -static void -ural_set_macaddr(struct ural_softc *sc, uint8_t *addr) -{ - uint16_t tmp; - - tmp = addr[0] | addr[1] << 8; - ural_write(sc, RAL_MAC_CSR2, tmp); - - tmp = addr[2] | addr[3] << 8; - ural_write(sc, RAL_MAC_CSR3, tmp); - - tmp = addr[4] | addr[5] << 8; - ural_write(sc, RAL_MAC_CSR4, tmp); - - DPRINTF(("setting MAC address to %6D\n", addr, ":")); -} - -static void -ural_update_promisc(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - uint32_t tmp; - - tmp = ural_read(sc, RAL_TXRX_CSR2); - - tmp &= ~RAL_DROP_NOT_TO_ME; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RAL_DROP_NOT_TO_ME; - - ural_write(sc, RAL_TXRX_CSR2, tmp); - - DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? - "entering" : "leaving")); -} - -static const char * -ural_get_rf(int rev) -{ - switch (rev) { - case RAL_RF_2522: return "RT2522"; - case RAL_RF_2523: return "RT2523"; - case RAL_RF_2524: return "RT2524"; - case RAL_RF_2525: return "RT2525"; - case RAL_RF_2525E: return "RT2525e"; - case RAL_RF_2526: return "RT2526"; - case RAL_RF_5222: return "RT5222"; - default: return "unknown"; - } -} - -static void -ural_read_eeprom(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t val; - - ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); - val = le16toh(val); - sc->rf_rev = (val >> 11) & 0x7; - sc->hw_radio = (val >> 10) & 0x1; - sc->led_mode = (val >> 6) & 0x7; - sc->rx_ant = (val >> 4) & 0x3; - sc->tx_ant = (val >> 2) & 0x3; - sc->nb_ant = val & 0x3; - - /* read MAC address */ - ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_myaddr, 6); - - /* read default values for BBP registers */ - ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); - - /* read Tx power for all b/g channels */ - ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14); -} - -static int -ural_bbp_init(struct ural_softc *sc) -{ -#define N(a) (sizeof (a) / sizeof ((a)[0])) - int i, ntries; - - /* wait for BBP to be ready */ - for (ntries = 0; ntries < 100; ntries++) { - if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0) - break; - DELAY(1000); - } - if (ntries == 100) { - device_printf(sc->sc_dev, "timeout waiting for BBP\n"); - return EIO; - } - - /* initialize BBP registers to default values */ - for (i = 0; i < N(ural_def_bbp); i++) - ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val); - -#if 0 - /* initialize BBP registers to values stored in EEPROM */ - for (i = 0; i < 16; i++) { - if (sc->bbp_prom[i].reg == 0xff) - continue; - ural_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); - } -#endif - - return 0; -#undef N -} - -static void -ural_set_txantenna(struct ural_softc *sc, int antenna) -{ - uint16_t tmp; - uint8_t tx; - - tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK; - if (antenna == 1) - tx |= RAL_BBP_ANTA; - else if (antenna == 2) - tx |= RAL_BBP_ANTB; - else - tx |= RAL_BBP_DIVERSITY; - - /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ - if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 || - sc->rf_rev == RAL_RF_5222) - tx |= RAL_BBP_FLIPIQ; - - ural_bbp_write(sc, RAL_BBP_TX, tx); - - /* update values in PHY_CSR5 and PHY_CSR6 */ - tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7; - ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7)); - - tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7; - ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7)); -} - -static void -ural_set_rxantenna(struct ural_softc *sc, int antenna) -{ - uint8_t rx; - - rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK; - if (antenna == 1) - rx |= RAL_BBP_ANTA; - else if (antenna == 2) - rx |= RAL_BBP_ANTB; - else - rx |= RAL_BBP_DIVERSITY; - - /* need to force no I/Q flip for RF 2525e and 2526 */ - if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526) - rx &= ~RAL_BBP_FLIPIQ; - - ural_bbp_write(sc, RAL_BBP_RX, rx); -} - -static void -ural_init_locked(struct ural_softc *sc) -{ -#define N(a) (sizeof (a) / sizeof ((a)[0])) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ural_rx_data *data; - uint16_t tmp; - usbd_status error; - int i, ntries; - - ural_set_testmode(sc); - ural_write(sc, 0x308, 0x00f0); /* XXX magic */ - - ural_stop(sc); - - /* initialize MAC registers to default values */ - for (i = 0; i < N(ural_def_mac); i++) - ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val); - - /* wait for BBP and RF to wake up (this can take a long time!) */ - for (ntries = 0; ntries < 100; ntries++) { - tmp = ural_read(sc, RAL_MAC_CSR17); - if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) == - (RAL_BBP_AWAKE | RAL_RF_AWAKE)) - break; - DELAY(1000); - } - if (ntries == 100) { - device_printf(sc->sc_dev, - "timeout waiting for BBP/RF to wakeup\n"); - goto fail; - } - - /* we're ready! */ - ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY); - - /* set basic rate set (will be updated later) */ - ural_write(sc, RAL_TXRX_CSR11, 0x15f); - - if (ural_bbp_init(sc) != 0) - goto fail; - - ural_set_chan(sc, ic->ic_curchan); - - /* clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); - - ural_set_txantenna(sc, sc->tx_ant); - ural_set_rxantenna(sc, sc->rx_ant); - - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - ural_set_macaddr(sc, ic->ic_myaddr); - - /* - * Allocate xfer for AMRR statistics requests. - */ - sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->amrr_xfer == NULL) { - device_printf(sc->sc_dev, "could not allocate AMRR xfer\n"); - goto fail; - } - - /* - * Open Tx and Rx USB bulk pipes. - */ - error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, - &sc->sc_tx_pipeh); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Tx pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - - error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, - &sc->sc_rx_pipeh); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Rx pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - - /* - * Allocate Tx and Rx xfer queues. - */ - error = ural_alloc_tx_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Tx list\n"); - goto fail; - } - - error = ural_alloc_rx_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Rx list\n"); - goto fail; - } - - /* - * Start up the receive pipe. - */ - for (i = 0; i < RAL_RX_LIST_COUNT; i++) { - data = &sc->rx_data[i]; - - usbd_setup_xfer(data->xfer, sc->sc_rx_pipeh, data, data->buf, - MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ural_rxeof); - usbd_transfer(data->xfer); - } - - /* kick Rx */ - tmp = RAL_DROP_PHY | RAL_DROP_CRC; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - tmp |= RAL_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RAL_DROP_NOT_TO_ME; - } - ural_write(sc, RAL_TXRX_CSR2, tmp); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - return; - -fail: ural_stop(sc); -#undef N -} - -static void -ural_init(void *priv) -{ - struct ural_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - RAL_LOCK(sc); - ural_init_locked(sc); - RAL_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -ural_stop(void *priv) -{ - struct ural_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - /* disable Rx */ - ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); - - /* reset ASIC and BBP (but won't reset MAC registers!) */ - ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP); - ural_write(sc, RAL_MAC_CSR1, 0); - - if (sc->amrr_xfer != NULL) { - usbd_free_xfer(sc->amrr_xfer); - sc->amrr_xfer = NULL; - } - - if (sc->sc_rx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_rx_pipeh); - usbd_close_pipe(sc->sc_rx_pipeh); - sc->sc_rx_pipeh = NULL; - } - - if (sc->sc_tx_pipeh != NULL) { - usbd_abort_pipe(sc->sc_tx_pipeh); - usbd_close_pipe(sc->sc_tx_pipeh); - sc->sc_tx_pipeh = NULL; - } - - ural_free_rx_list(sc); - ural_free_tx_list(sc); -} - -static int -ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - if (sc->tx_queued >= RAL_TX_LIST_COUNT) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m); - ieee80211_free_node(ni); - return EIO; - } - - ifp->if_opackets++; - - if (params == NULL) { - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - */ - if (ural_tx_mgt(sc, m, ni) != 0) - goto bad; - } else { - /* - * Caller supplied explicit parameters to use in - * sending the frame. - */ - if (ural_tx_raw(sc, m, ni, params) != 0) - goto bad; - } - sc->sc_tx_timer = 5; - callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc); - - return 0; -bad: - ifp->if_oerrors++; - ieee80211_free_node(ni); - return EIO; /* XXX */ -} - -static void -ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ural_vap *uvp = URAL_VAP(vap); - - /* clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); - - ieee80211_amrr_node_init(&uvp->amrr, &URAL_NODE(ni)->amn, ni); - - callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, vap); -} - -static void -ural_amrr_timeout(void *arg) -{ - struct ieee80211vap *vap = arg; - struct ural_softc *sc = vap->iv_ic->ic_ifp->if_softc; - usb_device_request_t req; - - /* - * Asynchronously read statistic registers (cleared by read). - */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, RAL_STA_CSR0); - USETW(req.wLength, sizeof sc->sta); - - usbd_setup_default_xfer(sc->amrr_xfer, sc->sc_udev, vap, - USBD_DEFAULT_TIMEOUT, &req, sc->sta, sizeof sc->sta, 0, - ural_amrr_update); - (void)usbd_transfer(sc->amrr_xfer); -} - -static void -ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct ieee80211vap *vap = priv; - struct ural_vap *uvp = URAL_VAP(vap); - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; - struct ieee80211_node *ni = vap->iv_bss; - int ok, fail; - - if (status != USBD_NORMAL_COMPLETION) { - device_printf(sc->sc_dev, "could not retrieve Tx statistics - " - "cancelling automatic rate control\n"); - return; - } - - ok = sc->sta[7] + /* TX ok w/o retry */ - sc->sta[8]; /* TX ok w/ retry */ - fail = sc->sta[9]; /* TX retry-fail count */ - - ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn, - ok+fail, ok, sc->sta[8] + fail); - (void) ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn); - - ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ - - callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, vap); -} diff --git a/sys/dev/usb/if_uralreg.h b/sys/dev/usb/if_uralreg.h deleted file mode 100644 index 428089f..0000000 --- a/sys/dev/usb/if_uralreg.h +++ /dev/null @@ -1,210 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 - * Damien Bergamini <damien.bergamini@free.fr> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RAL_NOISE_FLOOR -95 -#define RAL_RSSI_CORR 120 - -#define RAL_RX_DESC_SIZE (sizeof (struct ural_rx_desc)) -#define RAL_TX_DESC_SIZE (sizeof (struct ural_tx_desc)) - -#define RAL_CONFIG_NO 1 -#define RAL_IFACE_INDEX 0 - -#define RAL_VENDOR_REQUEST 0x01 -#define RAL_WRITE_MAC 0x02 -#define RAL_READ_MAC 0x03 -#define RAL_WRITE_MULTI_MAC 0x06 -#define RAL_READ_MULTI_MAC 0x07 -#define RAL_READ_EEPROM 0x09 - -/* - * MAC registers. - */ -#define RAL_MAC_CSR0 0x0400 /* ASIC Version */ -#define RAL_MAC_CSR1 0x0402 /* System control */ -#define RAL_MAC_CSR2 0x0404 /* MAC addr0 */ -#define RAL_MAC_CSR3 0x0406 /* MAC addr1 */ -#define RAL_MAC_CSR4 0x0408 /* MAC addr2 */ -#define RAL_MAC_CSR5 0x040a /* BSSID0 */ -#define RAL_MAC_CSR6 0x040c /* BSSID1 */ -#define RAL_MAC_CSR7 0x040e /* BSSID2 */ -#define RAL_MAC_CSR8 0x0410 /* Max frame length */ -#define RAL_MAC_CSR9 0x0412 /* Timer control */ -#define RAL_MAC_CSR10 0x0414 /* Slot time */ -#define RAL_MAC_CSR11 0x0416 /* IFS */ -#define RAL_MAC_CSR12 0x0418 /* EIFS */ -#define RAL_MAC_CSR13 0x041a /* Power mode0 */ -#define RAL_MAC_CSR14 0x041c /* Power mode1 */ -#define RAL_MAC_CSR15 0x041e /* Power saving transition0 */ -#define RAL_MAC_CSR16 0x0420 /* Power saving transition1 */ -#define RAL_MAC_CSR17 0x0422 /* Power state control */ -#define RAL_MAC_CSR18 0x0424 /* Auto wake-up control */ -#define RAL_MAC_CSR19 0x0426 /* GPIO control */ -#define RAL_MAC_CSR20 0x0428 /* LED control0 */ -#define RAL_MAC_CSR22 0x042c /* XXX not documented */ - -/* - * Tx/Rx Registers. - */ -#define RAL_TXRX_CSR0 0x0440 /* Security control */ -#define RAL_TXRX_CSR2 0x0444 /* Rx control */ -#define RAL_TXRX_CSR5 0x044a /* CCK Tx BBP ID0 */ -#define RAL_TXRX_CSR6 0x044c /* CCK Tx BBP ID1 */ -#define RAL_TXRX_CSR7 0x044e /* OFDM Tx BBP ID0 */ -#define RAL_TXRX_CSR8 0x0450 /* OFDM Tx BBP ID1 */ -#define RAL_TXRX_CSR10 0x0454 /* Auto responder control */ -#define RAL_TXRX_CSR11 0x0456 /* Auto responder basic rate */ -#define RAL_TXRX_CSR18 0x0464 /* Beacon interval */ -#define RAL_TXRX_CSR19 0x0466 /* Beacon/sync control */ -#define RAL_TXRX_CSR20 0x0468 /* Beacon alignment */ -#define RAL_TXRX_CSR21 0x046a /* XXX not documented */ - -/* - * Security registers. - */ -#define RAL_SEC_CSR0 0x0480 /* Shared key 0, word 0 */ - -/* - * PHY registers. - */ -#define RAL_PHY_CSR2 0x04c4 /* Tx MAC configuration */ -#define RAL_PHY_CSR4 0x04c8 /* Interface configuration */ -#define RAL_PHY_CSR5 0x04ca /* BBP Pre-Tx CCK */ -#define RAL_PHY_CSR6 0x04cc /* BBP Pre-Tx OFDM */ -#define RAL_PHY_CSR7 0x04ce /* BBP serial control */ -#define RAL_PHY_CSR8 0x04d0 /* BBP serial status */ -#define RAL_PHY_CSR9 0x04d2 /* RF serial control0 */ -#define RAL_PHY_CSR10 0x04d4 /* RF serial control1 */ - -/* - * Statistics registers. - */ -#define RAL_STA_CSR0 0x04e0 /* FCS error */ - - -#define RAL_DISABLE_RX (1 << 0) -#define RAL_DROP_CRC (1 << 1) -#define RAL_DROP_PHY (1 << 2) -#define RAL_DROP_CTL (1 << 3) -#define RAL_DROP_NOT_TO_ME (1 << 4) -#define RAL_DROP_TODS (1 << 5) -#define RAL_DROP_BAD_VERSION (1 << 6) -#define RAL_DROP_MULTICAST (1 << 9) -#define RAL_DROP_BROADCAST (1 << 10) - -#define RAL_SHORT_PREAMBLE (1 << 2) - -#define RAL_RESET_ASIC (1 << 0) -#define RAL_RESET_BBP (1 << 1) -#define RAL_HOST_READY (1 << 2) - -#define RAL_ENABLE_TSF (1 << 0) -#define RAL_ENABLE_TSF_SYNC(x) (((x) & 0x3) << 1) -#define RAL_ENABLE_TBCN (1 << 3) -#define RAL_ENABLE_BEACON_GENERATOR (1 << 4) - -#define RAL_RF_AWAKE (3 << 7) -#define RAL_BBP_AWAKE (3 << 5) - -#define RAL_BBP_WRITE (1 << 15) -#define RAL_BBP_BUSY (1 << 0) - -#define RAL_RF1_AUTOTUNE 0x08000 -#define RAL_RF3_AUTOTUNE 0x00040 - -#define RAL_RF_2522 0x00 -#define RAL_RF_2523 0x01 -#define RAL_RF_2524 0x02 -#define RAL_RF_2525 0x03 -#define RAL_RF_2525E 0x04 -#define RAL_RF_2526 0x05 -/* dual-band RF */ -#define RAL_RF_5222 0x10 - -#define RAL_BBP_VERSION 0 -#define RAL_BBP_TX 2 -#define RAL_BBP_RX 14 - -#define RAL_BBP_ANTA 0x00 -#define RAL_BBP_DIVERSITY 0x01 -#define RAL_BBP_ANTB 0x02 -#define RAL_BBP_ANTMASK 0x03 -#define RAL_BBP_FLIPIQ 0x04 - -#define RAL_JAPAN_FILTER 0x08 - -struct ural_tx_desc { - uint32_t flags; -#define RAL_TX_RETRY(x) ((x) << 4) -#define RAL_TX_MORE_FRAG (1 << 8) -#define RAL_TX_ACK (1 << 9) -#define RAL_TX_TIMESTAMP (1 << 10) -#define RAL_TX_OFDM (1 << 11) -#define RAL_TX_NEWSEQ (1 << 12) - -#define RAL_TX_IFS_MASK 0x00006000 -#define RAL_TX_IFS_BACKOFF (0 << 13) -#define RAL_TX_IFS_SIFS (1 << 13) -#define RAL_TX_IFS_NEWBACKOFF (2 << 13) -#define RAL_TX_IFS_NONE (3 << 13) - - uint16_t wme; -#define RAL_LOGCWMAX(x) (((x) & 0xf) << 12) -#define RAL_LOGCWMIN(x) (((x) & 0xf) << 8) -#define RAL_AIFSN(x) (((x) & 0x3) << 6) -#define RAL_IVOFFSET(x) (((x) & 0x3f)) - - uint16_t reserved1; - uint8_t plcp_signal; - uint8_t plcp_service; -#define RAL_PLCP_LENGEXT 0x80 - - uint8_t plcp_length_lo; - uint8_t plcp_length_hi; - uint32_t iv; - uint32_t eiv; -} __packed; - -struct ural_rx_desc { - uint32_t flags; -#define RAL_RX_CRC_ERROR (1 << 5) -#define RAL_RX_OFDM (1 << 6) -#define RAL_RX_PHY_ERROR (1 << 7) - - uint8_t rssi; - uint8_t rate; - uint16_t reserved; - - uint32_t iv; - uint32_t eiv; -} __packed; - -#define RAL_RF_LOBUSY (1 << 15) -#define RAL_RF_BUSY (1 << 31) -#define RAL_RF_20BIT (20 << 24) - -#define RAL_RF1 0 -#define RAL_RF2 2 -#define RAL_RF3 1 -#define RAL_RF4 3 - -#define RAL_EEPROM_ADDRESS 0x0004 -#define RAL_EEPROM_TXPOWER 0x003c -#define RAL_EEPROM_CONFIG0 0x0016 -#define RAL_EEPROM_BBP_BASE 0x001c diff --git a/sys/dev/usb/if_uralvar.h b/sys/dev/usb/if_uralvar.h deleted file mode 100644 index 39aef9e..0000000 --- a/sys/dev/usb/if_uralvar.h +++ /dev/null @@ -1,157 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005 - * Damien Bergamini <damien.bergamini@free.fr> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RAL_RX_LIST_COUNT 1 -#define RAL_TX_LIST_COUNT 8 - -#define URAL_SCAN_START 1 -#define URAL_SCAN_END 2 -#define URAL_SET_CHANNEL 3 - - -struct ural_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - uint8_t wr_antenna; - uint8_t wr_antsignal; -}; - -#define RAL_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)) - -struct ural_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; - uint8_t wt_antenna; -}; - -#define RAL_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA)) - -struct ural_softc; - -struct ural_tx_data { - struct ural_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct mbuf *m; - struct ieee80211_node *ni; -}; - -struct ural_rx_data { - struct ural_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct mbuf *m; -}; - -struct ural_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amn; -}; -#define URAL_NODE(ni) ((struct ural_node *)(ni)) - -struct ural_vap { - struct ieee80211vap vap; - struct ieee80211_beacon_offsets bo; - struct ieee80211_amrr amrr; - struct callout amrr_ch; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define URAL_VAP(vap) ((struct ural_vap *)(vap)) - -struct ural_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - const struct ieee80211_rate_table *sc_rates; - - int sc_rx_no; - int sc_tx_no; - - uint32_t asic_rev; - uint8_t rf_rev; - - usbd_xfer_handle amrr_xfer; - - usbd_pipe_handle sc_rx_pipeh; - usbd_pipe_handle sc_tx_pipeh; - - enum ieee80211_state sc_state; - int sc_arg; - int sc_scan_action; /* should be an enum */ - struct usb_task sc_task; - struct usb_task sc_scantask; - - struct ural_rx_data rx_data[RAL_RX_LIST_COUNT]; - struct ural_tx_data tx_data[RAL_TX_LIST_COUNT]; - int tx_queued; - int tx_cur; - - struct mtx sc_mtx; - - struct callout watchdog_ch; - int sc_tx_timer; - - uint16_t sta[11]; - uint32_t rf_regs[4]; - uint8_t txpow[14]; - - struct { - uint8_t val; - uint8_t reg; - } __packed bbp_prom[16]; - - int led_mode; - int hw_radio; - int rx_ant; - int tx_ant; - int nb_ant; - - struct ural_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - - struct ural_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#if 0 -#define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RAL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#else -#define RAL_LOCK(sc) do { ((sc) = (sc)); mtx_lock(&Giant); } while (0) -#define RAL_UNLOCK(sc) mtx_unlock(&Giant) -#endif diff --git a/sys/dev/usb/if_urtw.c b/sys/dev/usb/if_urtw.c deleted file mode 100644 index d1a3a84..0000000 --- a/sys/dev/usb/if_urtw.c +++ /dev/null @@ -1,3324 +0,0 @@ -/*- - * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -#include <sys/param.h> -#include <sys/sockio.h> -#include <sys/sysctl.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/mbuf.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/kdb.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> -#include <netinet/ip.h> -#endif - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_regdomain.h> -#include <net80211/ieee80211_radiotap.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/if_urtwreg.h> -#include <dev/usb/if_urtwvar.h> - -SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L"); -#ifdef URTW_DEBUG -int urtw_debug = 0; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW, &urtw_debug, 0, - "control debugging printfs"); -TUNABLE_INT("hw.usb.urtw.debug", &urtw_debug); -enum { - URTW_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - URTW_DEBUG_RECV = 0x00000002, /* basic recv operation */ - URTW_DEBUG_RESET = 0x00000004, /* reset processing */ - URTW_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */ - URTW_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */ - URTW_DEBUG_STATE = 0x00000020, /* 802.11 state transitions */ - URTW_DEBUG_STAT = 0x00000040, /* statistic */ - URTW_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif -int urtw_preamble_mode = URTW_PREAMBLE_MODE_LONG; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RW, - &urtw_preamble_mode, 0, "set the preable mode (long or short)"); -TUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode); - -/* recognized device vendors/products */ -static const struct usb_devno urtw_devs[] = { -#define URTW_DEV(v,p) { USB_VENDOR_##v, USB_PRODUCT_##v##_##p } - URTW_DEV(REALTEK, RTL8187), - URTW_DEV(NETGEAR, WG111V2) -#undef URTW_DEV -}; - -#define urtw_read8_m(sc, val, data) do { \ - error = urtw_read8_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write8_m(sc, val, data) do { \ - error = urtw_write8_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_read16_m(sc, val, data) do { \ - error = urtw_read16_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write16_m(sc, val, data) do { \ - error = urtw_write16_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_read32_m(sc, val, data) do { \ - error = urtw_read32_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write32_m(sc, val, data) do { \ - error = urtw_write32_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8187_write_phy_ofdm(sc, val, data) do { \ - error = urtw_8187_write_phy_ofdm_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8187_write_phy_cck(sc, val, data) do { \ - error = urtw_8187_write_phy_cck_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8225_write(sc, val, data) do { \ - error = urtw_8225_write_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) - -struct urtw_pair { - uint32_t reg; - uint32_t val; -}; - -static uint8_t urtw_8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, - 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, - 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, - 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, - 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, - 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static uint32_t urtw_8225_channel[] = { - 0x0000, /* dummy channel 0 */ - 0x085c, /* 1 */ - 0x08dc, /* 2 */ - 0x095c, /* 3 */ - 0x09dc, /* 4 */ - 0x0a5c, /* 5 */ - 0x0adc, /* 6 */ - 0x0b5c, /* 7 */ - 0x0bdc, /* 8 */ - 0x0c5c, /* 9 */ - 0x0cdc, /* 10 */ - 0x0d5c, /* 11 */ - 0x0ddc, /* 12 */ - 0x0e5c, /* 13 */ - 0x0f72, /* 14 */ -}; - -static uint8_t urtw_8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ -}; - -static struct urtw_pair urtw_8225_rf_part1[] = { - { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, - { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a }, - { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 }, - { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }, -}; - -static struct urtw_pair urtw_8225_rf_part2[] = { - { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, - { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, - { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 }, - { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 }, - { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 }, - { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef }, - { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 }, - { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 }, - { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 }, - { 0x27, 0x88 } -}; - -static struct urtw_pair urtw_8225_rf_part3[] = { - { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, - { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b }, - { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, - { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d }, - { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e }, - { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a }, - { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 } -}; - -static uint16_t urtw_8225_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static uint8_t urtw_8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, -}; - -static uint8_t urtw_8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static uint8_t urtw_8225_txpwr_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static uint8_t urtw_8225_txpwr_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static uint8_t urtw_8225_txpwr_ofdm[]={ - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static uint8_t urtw_8225v2_gain_bg[]={ - 0x23, 0x15, 0xa5, /* -82-1dbm */ - 0x23, 0x15, 0xb5, /* -82-2dbm */ - 0x23, 0x15, 0xc5, /* -82-3dbm */ - 0x33, 0x15, 0xc5, /* -78dbm */ - 0x43, 0x15, 0xc5, /* -74dbm */ - 0x53, 0x15, 0xc5, /* -70dbm */ - 0x63, 0x15, 0xc5, /* -66dbm */ -}; - -static struct urtw_pair urtw_8225v2_rf_part1[] = { - { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, - { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, - { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, - { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } -}; - -static struct urtw_pair urtw_8225v2_rf_part2[] = { - { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, - { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, - { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 }, - { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, - { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 }, - { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, - { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 }, - { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 }, - { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 }, - { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 } -}; - -static struct urtw_pair urtw_8225v2_rf_part3[] = { - { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, - { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 }, - { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 }, - { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 }, - { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d }, - { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 }, - { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 }, - { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 } -}; - -static uint16_t urtw_8225v2_rxgain[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, - 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, - 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, - 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, - 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, - 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, - 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, -}; - -static uint8_t urtw_8225v2_txpwr_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 -}; - -static uint8_t urtw_8225v2_txpwr_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 -}; - -static struct urtw_pair urtw_ratetable[] = { - { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 }, - { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 }, - { 96, 10 }, { 108, 11 } -}; - -static struct ieee80211vap *urtw_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, int opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void urtw_vap_delete(struct ieee80211vap *); -static void urtw_init(void *); -static void urtw_stop(struct ifnet *, int); -static int urtw_ioctl(struct ifnet *, u_long, caddr_t); -static void urtw_start(struct ifnet *); -static int urtw_alloc_rx_data_list(struct urtw_softc *); -static int urtw_alloc_tx_data_list(struct urtw_softc *); -static void urtw_free_data_list(struct urtw_softc *, - usbd_pipe_handle, usbd_pipe_handle, - struct urtw_data data[], int); -static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void urtw_scan_start(struct ieee80211com *); -static void urtw_scan_end(struct ieee80211com *); -static void urtw_set_channel(struct ieee80211com *); -static void urtw_update_mcast(struct ifnet *); -static void urtw_rxeof(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static int urtw_tx_start(struct urtw_softc *, - struct ieee80211_node *, struct mbuf *, int); -static void urtw_txeof_low(usbd_xfer_handle, usbd_private_handle, - usbd_status); -static void urtw_txeof_normal(usbd_xfer_handle, - usbd_private_handle, usbd_status); -static int urtw_newstate(struct ieee80211vap *, - enum ieee80211_state, int); -static void urtw_ledtask(void *); -static void urtw_ledusbtask(void *); -static void urtw_ctxtask(void *); -static void urtw_task(void *); -static void urtw_watchdog(void *); -static void urtw_set_multi(void *); -static int urtw_isbmode(uint16_t); -static uint16_t urtw_rate2rtl(int); -static uint16_t urtw_rtl2rate(int); -static usbd_status urtw_set_rate(struct urtw_softc *); -static usbd_status urtw_update_msr(struct urtw_softc *); -static usbd_status urtw_read8_c(struct urtw_softc *, int, uint8_t *); -static usbd_status urtw_read16_c(struct urtw_softc *, int, uint16_t *); -static usbd_status urtw_read32_c(struct urtw_softc *, int, uint32_t *); -static usbd_status urtw_write8_c(struct urtw_softc *, int, uint8_t); -static usbd_status urtw_write16_c(struct urtw_softc *, int, uint16_t); -static usbd_status urtw_write32_c(struct urtw_softc *, int, uint32_t); -static usbd_status urtw_eprom_cs(struct urtw_softc *, int); -static usbd_status urtw_eprom_ck(struct urtw_softc *); -static usbd_status urtw_eprom_sendbits(struct urtw_softc *, int16_t *, - int); -static usbd_status urtw_eprom_read32(struct urtw_softc *, uint32_t, - uint32_t *); -static usbd_status urtw_eprom_readbit(struct urtw_softc *, int16_t *); -static usbd_status urtw_eprom_writebit(struct urtw_softc *, int16_t); -static usbd_status urtw_get_macaddr(struct urtw_softc *); -static usbd_status urtw_get_txpwr(struct urtw_softc *); -static usbd_status urtw_get_rfchip(struct urtw_softc *); -static usbd_status urtw_led_init(struct urtw_softc *); -static usbd_status urtw_8185_rf_pins_enable(struct urtw_softc *); -static usbd_status urtw_8185_tx_antenna(struct urtw_softc *, uint8_t); -static usbd_status urtw_8187_write_phy(struct urtw_softc *, uint8_t, - uint32_t); -static usbd_status urtw_8187_write_phy_ofdm_c(struct urtw_softc *, - uint8_t, uint32_t); -static usbd_status urtw_8187_write_phy_cck_c(struct urtw_softc *, uint8_t, - uint32_t); -static usbd_status urtw_8225_setgain(struct urtw_softc *, int16_t); -static usbd_status urtw_8225_usb_init(struct urtw_softc *); -static usbd_status urtw_8225_write_c(struct urtw_softc *, uint8_t, - uint16_t); -static usbd_status urtw_8225_write_s16(struct urtw_softc *, uint8_t, int, - uint16_t *); -static usbd_status urtw_8225_read(struct urtw_softc *, uint8_t, - uint32_t *); -static usbd_status urtw_8225_rf_init(struct urtw_softc *); -static usbd_status urtw_8225_rf_set_chan(struct urtw_softc *, int); -static usbd_status urtw_8225_rf_set_sens(struct urtw_softc *, int); -static usbd_status urtw_8225_set_txpwrlvl(struct urtw_softc *, int); -static usbd_status urtw_8225v2_rf_init(struct urtw_softc *); -static usbd_status urtw_8225v2_rf_set_chan(struct urtw_softc *, int); -static usbd_status urtw_8225v2_set_txpwrlvl(struct urtw_softc *, int); -static usbd_status urtw_8225v2_setgain(struct urtw_softc *, int16_t); -static usbd_status urtw_8225_isv2(struct urtw_softc *, int *); -static usbd_status urtw_read8e(struct urtw_softc *, int, uint8_t *); -static usbd_status urtw_write8e(struct urtw_softc *, int, uint8_t); -static usbd_status urtw_8180_set_anaparam(struct urtw_softc *, uint32_t); -static usbd_status urtw_8185_set_anaparam2(struct urtw_softc *, uint32_t); -static usbd_status urtw_open_pipes(struct urtw_softc *); -static usbd_status urtw_close_pipes(struct urtw_softc *); -static usbd_status urtw_intr_enable(struct urtw_softc *); -static usbd_status urtw_intr_disable(struct urtw_softc *); -static usbd_status urtw_reset(struct urtw_softc *); -static usbd_status urtw_led_on(struct urtw_softc *, int); -static usbd_status urtw_led_ctl(struct urtw_softc *, int); -static usbd_status urtw_led_blink(struct urtw_softc *); -static usbd_status urtw_led_mode0(struct urtw_softc *, int); -static usbd_status urtw_led_mode1(struct urtw_softc *, int); -static usbd_status urtw_led_mode2(struct urtw_softc *, int); -static usbd_status urtw_led_mode3(struct urtw_softc *, int); -static usbd_status urtw_rx_setconf(struct urtw_softc *); -static usbd_status urtw_rx_enable(struct urtw_softc *); -static usbd_status urtw_tx_enable(struct urtw_softc *sc); - -static int -urtw_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - const struct usb_devno *ud; - - if (uaa->iface != NULL) - return UMATCH_NONE; - ud = usb_lookup(urtw_devs, uaa->vendor, uaa->product); - - return (ud != NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -urtw_attach(device_t dev) -{ - int ret = 0; - struct urtw_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct ieee80211com *ic; - struct ifnet *ifp; - uint8_t bands; - uint32_t data; - usbd_status error; - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; -#ifdef URTW_DEBUG - sc->sc_debug = urtw_debug; -#endif - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF); - callout_init(&sc->sc_led_ch, 0); - callout_init(&sc->sc_watchdog_ch, 0); - usb_init_task(&sc->sc_ledtask, urtw_ledusbtask, sc); - usb_init_task(&sc->sc_ctxtask, urtw_ctxtask, sc); - usb_init_task(&sc->sc_task, urtw_task, sc); - - urtw_read32_m(sc, URTW_RX, &data); - sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 : - URTW_EEPROM_93C46; - - error = urtw_get_rfchip(sc); - if (error != 0) - goto fail; - error = urtw_get_macaddr(sc); - if (error != 0) - goto fail; - error = urtw_get_txpwr(sc); - if (error != 0) - goto fail; - error = urtw_led_init(sc); - if (error != 0) - goto fail; - - sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY; - sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY; - sc->sc_currate = 3; - sc->sc_preamble_mode = urtw_preamble_mode; - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not allocate ifnet\n"); - ret = ENXIO; - goto fail; - } - - ifp->if_softc = sc; - if_initname(ifp, "urtw", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ - ifp->if_init = urtw_init; - ifp->if_ioctl = urtw_ioctl; - ifp->if_start = urtw_start; - /* XXX URTW_TX_DATA_LIST_COUNT */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA | /* station mode */ - IEEE80211_C_MONITOR | /* monitor mode supported */ - IEEE80211_C_TXPMGT | /* tx power management */ - IEEE80211_C_SHPREAMBLE | /* short preamble supported */ - IEEE80211_C_SHSLOT | /* short slot time supported */ - IEEE80211_C_BGSCAN | /* capable of bg scanning */ - IEEE80211_C_WPA; /* 802.11i */ - - IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid); - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic); - ic->ic_raw_xmit = urtw_raw_xmit; - ic->ic_scan_start = urtw_scan_start; - ic->ic_scan_end = urtw_scan_end; - ic->ic_set_channel = urtw_set_channel; - - ic->ic_vap_create = urtw_vap_create; - ic->ic_vap_delete = urtw_vap_delete; - ic->ic_update_mcast = urtw_update_mcast; - - bpfattach(ifp, DLT_IEEE802_11_RADIO, - sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap)); - - sc->sc_rxtap_len = sizeof sc->sc_rxtap; - sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); - sc->sc_rxtap.wr_ihdr.it_present = htole32(URTW_RX_RADIOTAP_PRESENT); - - sc->sc_txtap_len = sizeof sc->sc_txtap; - sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); - sc->sc_txtap.wt_ihdr.it_present = htole32(URTW_TX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); -fail: - return (ret); -} - -static usbd_status -urtw_open_pipes(struct urtw_softc *sc) -{ - usbd_status error; - - /* - * NB: there is no way to distinguish each pipes so we need to hardcode - * pipe numbers - */ - - /* tx pipe - low priority packets */ - error = usbd_open_pipe(sc->sc_iface, 0x2, USBD_EXCLUSIVE_USE, - &sc->sc_txpipe_low); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Tx low pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - /* tx pipe - normal priority packets */ - error = usbd_open_pipe(sc->sc_iface, 0x3, USBD_EXCLUSIVE_USE, - &sc->sc_txpipe_normal); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Tx normal pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - /* rx pipe */ - error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE, - &sc->sc_rxpipe); - if (error != 0) { - device_printf(sc->sc_dev, "could not open Rx pipe: %s\n", - usbd_errstr(error)); - goto fail; - } - - return (0); -fail: - (void)urtw_close_pipes(sc); - return (error); -} - -static usbd_status -urtw_close_pipes(struct urtw_softc *sc) -{ - usbd_status error = 0; - - if (sc->sc_rxpipe != NULL) { - error = usbd_close_pipe(sc->sc_rxpipe); - if (error != 0) - goto fail; - sc->sc_rxpipe = NULL; - } - if (sc->sc_txpipe_low != NULL) { - error = usbd_close_pipe(sc->sc_txpipe_low); - if (error != 0) - goto fail; - sc->sc_txpipe_low = NULL; - } - if (sc->sc_txpipe_normal != NULL) { - error = usbd_close_pipe(sc->sc_txpipe_normal); - if (error != 0) - goto fail; - sc->sc_txpipe_normal = NULL; - } -fail: - return (error); -} - -static int -urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[], - int ndata, int maxsz, int fillmbuf) -{ - int i, error; - - for (i = 0; i < ndata; i++) { - struct urtw_data *dp = &data[i]; - - dp->sc = sc; - dp->xfer = usbd_alloc_xfer(sc->sc_udev); - if (dp->xfer == NULL) { - device_printf(sc->sc_dev, "could not allocate xfer\n"); - error = ENOMEM; - goto fail; - } - if (fillmbuf) { - dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (dp->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - dp->buf = mtod(dp->m, uint8_t *); - } else { - dp->m = NULL; - dp->buf = usbd_alloc_buffer(dp->xfer, maxsz); - if (dp->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate buffer\n"); - error = ENOMEM; - goto fail; - } - if (((unsigned long)dp->buf) % 4) - device_printf(sc->sc_dev, - "warn: unaligned buffer %p\n", dp->buf); - } - dp->ni = NULL; - } - - return 0; - -fail: urtw_free_data_list(sc, NULL, NULL, data, ndata); - return error; -} - -static void -urtw_free_data_list(struct urtw_softc *sc, usbd_pipe_handle pipe1, - usbd_pipe_handle pipe2, struct urtw_data data[], int ndata) -{ - int i; - - /* make sure no transfers are pending */ - if (pipe1 != NULL) - usbd_abort_pipe(pipe1); - if (pipe2 != NULL) - usbd_abort_pipe(pipe2); - - for (i = 0; i < ndata; i++) { - struct urtw_data *dp = &data[i]; - - if (dp->xfer != NULL) { - usbd_free_xfer(dp->xfer); - dp->xfer = NULL; - } - if (dp->m != NULL) { - m_freem(dp->m); - dp->m = NULL; - } - if (dp->ni != NULL) { - ieee80211_free_node(dp->ni); - dp->ni = NULL; - } - } -} - -static int -urtw_alloc_rx_data_list(struct urtw_softc *sc) -{ - - return urtw_alloc_data_list(sc, - sc->sc_rxdata, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */); -} - -static void -urtw_free_rx_data_list(struct urtw_softc *sc) -{ - - urtw_free_data_list(sc, sc->sc_rxpipe, NULL, sc->sc_rxdata, - URTW_RX_DATA_LIST_COUNT); -} - -static int -urtw_alloc_tx_data_list(struct urtw_softc *sc) -{ - - return urtw_alloc_data_list(sc, - sc->sc_txdata, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE, - 0 /* no mbufs */); -} - -static void -urtw_free_tx_data_list(struct urtw_softc *sc) -{ - - urtw_free_data_list(sc, sc->sc_txpipe_low, sc->sc_txpipe_normal, - sc->sc_txdata, URTW_TX_DATA_LIST_COUNT); -} - -static usbd_status -urtw_led_init(struct urtw_softc *sc) -{ - uint32_t rev; - usbd_status error; - - urtw_read8_m(sc, URTW_PSR, &sc->sc_psr); - error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev); - if (error != 0) - goto fail; - - switch (rev & URTW_EPROM_CID_MASK) { - case URTW_EPROM_CID_ALPHA0: - sc->sc_strategy = URTW_SW_LED_MODE1; - break; - case URTW_EPROM_CID_SERCOMM_PS: - sc->sc_strategy = URTW_SW_LED_MODE3; - break; - case URTW_EPROM_CID_HW_LED: - sc->sc_strategy = URTW_HW_LED; - break; - case URTW_EPROM_CID_RSVD0: - case URTW_EPROM_CID_RSVD1: - default: - sc->sc_strategy = URTW_SW_LED_MODE0; - break; - } - - sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0; - -fail: - return (error); -} - -/* XXX why we should allocalte memory buffer instead of using memory stack? */ -static usbd_status -urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index, - uint16_t *data) -{ - uint8_t *buf; - uint16_t data16; - usb_device_request_t *req; - usbd_status error = 0; - - data16 = *data; - req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (req == NULL) { - device_printf(sc->sc_dev, "could not allocate a memory\n"); - goto fail0; - } - buf = (uint8_t *)malloc(2, M_80211_VAP, M_NOWAIT | M_ZERO); - if (req == NULL) { - device_printf(sc->sc_dev, "could not allocate a memory\n"); - goto fail1; - } - - req->bmRequestType = UT_WRITE_VENDOR_DEVICE; - req->bRequest = URTW_8187_SETREGS_REQ; - USETW(req->wValue, addr); - USETW(req->wIndex, index); - USETW(req->wLength, sizeof(uint16_t)); - buf[0] = (data16 & 0x00ff); - buf[1] = (data16 & 0xff00) >> 8; - - error = usbd_do_request(sc->sc_udev, req, buf); - - free(buf, M_80211_VAP); -fail1: free(req, M_80211_VAP); -fail0: return (error); -} - -static usbd_status -urtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data) -{ - int i; - int16_t bit; - uint8_t rlen = 12, wlen = 6; - uint16_t o1, o2, o3, tmp; - uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27; - uint32_t mask = 0x80000000, value = 0; - usbd_status error; - - urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &o1); - urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &o2); - urtw_read16_m(sc, URTW_RF_PINS_SELECT, &o3); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2 | URTW_RF_PINS_MAGIC4); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3 | URTW_RF_PINS_MAGIC4); - o1 &= ~URTW_RF_PINS_MAGIC4; - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN); - DELAY(5); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1); - DELAY(5); - - for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) { - bit = ((d2w & mask) != 0) ? 1 : 0; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - mask = mask >> 1; - if (i == 2) - break; - bit = ((d2w & mask) != 0) ? 1 : 0; - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); - DELAY(1); - } - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - - mask = 0x800; - for (i = 0; i < rlen; i++, mask = mask >> 1) { - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - - urtw_read16_m(sc, URTW_RF_PINS_INPUT, &tmp); - value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - } - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN | - URTW_BB_HOST_BANG_RW); - DELAY(2); - - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_OUTPUT_MAGIC1); - - if (data != NULL) - *data = value; -fail: - return (error); -} - -static usbd_status -urtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data) -{ - uint16_t d80, d82, d84; - usbd_status error; - - urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &d80); - d80 &= URTW_RF_PINS_MAGIC1; - urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &d82); - urtw_read16_m(sc, URTW_RF_PINS_SELECT, &d84); - d84 &= URTW_RF_PINS_MAGIC2; - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, d82 | URTW_RF_PINS_MAGIC3); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84 | URTW_RF_PINS_MAGIC3); - DELAY(10); - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80); - DELAY(10); - - error = urtw_8225_write_s16(sc, addr, 0x8225, &data); - if (error != 0) - goto fail; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - DELAY(10); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84); - usbd_delay_ms(sc->sc_udev, 2); -fail: - return (error); -} - -static usbd_status -urtw_8225_isv2(struct urtw_softc *sc, int *ret) -{ - uint32_t data; - usbd_status error; - - *ret = 1; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_MAGIC5); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, URTW_RF_PINS_MAGIC5); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, URTW_RF_PINS_MAGIC5); - usbd_delay_ms(sc->sc_udev, 500); - - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, - URTW_8225_ADDR_0_DATA_MAGIC1); - - error = urtw_8225_read(sc, URTW_8225_ADDR_8_MAGIC, &data); - if (error != 0) - goto fail; - if (data != URTW_8225_ADDR_8_DATA_MAGIC1) - *ret = 0; - else { - error = urtw_8225_read(sc, URTW_8225_ADDR_9_MAGIC, &data); - if (error != 0) - goto fail; - if (data != URTW_8225_ADDR_9_DATA_MAGIC1) - *ret = 0; - } - - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, - URTW_8225_ADDR_0_DATA_MAGIC2); -fail: - return (error); -} - -static usbd_status -urtw_get_rfchip(struct urtw_softc *sc) -{ - int ret; - uint32_t data; - usbd_status error; - - error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); - if (error != 0) - goto fail; - switch (data & 0xff) { - case URTW_EPROM_RFCHIPID_RTL8225U: - error = urtw_8225_isv2(sc, &ret); - if (error != 0) - goto fail; - if (ret == 0) { - sc->sc_rf_init = urtw_8225_rf_init; - sc->sc_rf_set_sens = urtw_8225_rf_set_sens; - sc->sc_rf_set_chan = urtw_8225_rf_set_chan; - } else { - sc->sc_rf_init = urtw_8225v2_rf_init; - sc->sc_rf_set_chan = urtw_8225v2_rf_set_chan; - } - sc->sc_max_sens = URTW_8225_RF_MAX_SENS; - sc->sc_sens = URTW_8225_RF_DEF_SENS; - break; - default: - panic("unsupported RF chip %d\n", data & 0xff); - /* never reach */ - } - -fail: - return (error); -} - -static usbd_status -urtw_get_txpwr(struct urtw_softc *sc) -{ - int i, j; - uint32_t data; - usbd_status error; - - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck_base = data & 0xf; - sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf; - - for (i = 1, j = 0; i < 6; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i] = data & 0xf; - sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12; - } - for (i = 1, j = 0; i < 4; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i + 6] = data & 0xf; - sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; - } - for (i = 1, j = 0; i < 4; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; - sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12; - } -fail: - return (error); -} - -static usbd_status -urtw_get_macaddr(struct urtw_softc *sc) -{ - uint32_t data; - usbd_status error; - - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); - if (error != 0) - goto fail; - sc->sc_bssid[0] = data & 0xff; - sc->sc_bssid[1] = (data & 0xff00) >> 8; - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); - if (error != 0) - goto fail; - sc->sc_bssid[2] = data & 0xff; - sc->sc_bssid[3] = (data & 0xff00) >> 8; - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); - if (error != 0) - goto fail; - sc->sc_bssid[4] = data & 0xff; - sc->sc_bssid[5] = (data & 0xff00) >> 8; -fail: - return (error); -} - -static usbd_status -urtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data) -{ -#define URTW_READCMD_LEN 3 - int addrlen, i; - int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 }; - usbd_status error; - - /* NB: make sure the buffer is initialized */ - *data = 0; - - /* enable EPROM programming */ - urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_PROGRAM_MODE); - DELAY(URTW_EPROM_DELAY); - - error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN); - if (error != 0) - goto fail; - if (sc->sc_epromtype == URTW_EEPROM_93C56) { - addrlen = 8; - addrstr[0] = addr & (1 << 7); - addrstr[1] = addr & (1 << 6); - addrstr[2] = addr & (1 << 5); - addrstr[3] = addr & (1 << 4); - addrstr[4] = addr & (1 << 3); - addrstr[5] = addr & (1 << 2); - addrstr[6] = addr & (1 << 1); - addrstr[7] = addr & (1 << 0); - } else { - addrlen=6; - addrstr[0] = addr & (1 << 5); - addrstr[1] = addr & (1 << 4); - addrstr[2] = addr & (1 << 3); - addrstr[3] = addr & (1 << 2); - addrstr[4] = addr & (1 << 1); - addrstr[5] = addr & (1 << 0); - } - error = urtw_eprom_sendbits(sc, addrstr, addrlen); - if (error != 0) - goto fail; - - error = urtw_eprom_writebit(sc, 0); - if (error != 0) - goto fail; - - for (i = 0; i < 16; i++) { - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - error = urtw_eprom_readbit(sc, &data16); - if (error != 0) - goto fail; - - (*data) |= (data16 << (15 - i)); - } - - error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - - /* now disable EPROM programming */ - urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_NORMAL_MODE); -fail: - return (error); -#undef URTW_READCMD_LEN -} - -static usbd_status -urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data) -{ - uint8_t data8; - usbd_status error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data8); - *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0; - DELAY(URTW_EPROM_DELAY); - -fail: - return (error); -} - -static usbd_status -urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen) -{ - int i = 0; - usbd_status error = 0; - - for (i = 0; i < buflen; i++) { - error = urtw_eprom_writebit(sc, buf[i]); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - } -fail: - return (error); -} - -static usbd_status -urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit) -{ - uint8_t data; - usbd_status error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - if (bit != 0) - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT); - else - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usbd_status -urtw_eprom_ck(struct urtw_softc *sc) -{ - uint8_t data; - usbd_status error; - - /* masking */ - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK); - DELAY(URTW_EPROM_DELAY); - /* unmasking */ - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usbd_status -urtw_eprom_cs(struct urtw_softc *sc, int able) -{ - uint8_t data; - usbd_status error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - if (able == URTW_EPROM_ENABLE) - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS); - else - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usbd_status -urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - error = usbd_do_request(sc->sc_udev, &req, data); - return (error); -} - -static usbd_status -urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, val | 0xfe00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - error = usbd_do_request(sc->sc_udev, &req, data); - return (error); -} - -static usbd_status -urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint16_t)); - - error = usbd_do_request(sc->sc_udev, &req, data); - return (error); -} - -static usbd_status -urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint32_t)); - - error = usbd_do_request(sc->sc_udev, &req, data); - return (error); -} - -static usbd_status -urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - return (usbd_do_request(sc->sc_udev, &req, &data)); -} - -static usbd_status -urtw_write8e(struct urtw_softc *sc, int val, uint8_t data) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, val | 0xfe00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - return (usbd_do_request(sc->sc_udev, &req, &data)); -} - -static usbd_status -urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint16_t)); - - return (usbd_do_request(sc->sc_udev, &req, &data)); -} - -static usbd_status -urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, val | 0xff00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint32_t)); - - return (usbd_do_request(sc->sc_udev, &req, &data)); -} - -static int -urtw_detach(device_t dev) -{ - struct urtw_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return 0; - - urtw_stop(ifp, 1); - - callout_drain(&sc->sc_led_ch); - callout_drain(&sc->sc_watchdog_ch); - usb_rem_task(sc->sc_udev, &sc->sc_ledtask); - usb_rem_task(sc->sc_udev, &sc->sc_ctxtask); - usb_rem_task(sc->sc_udev, &sc->sc_task); - - /* abort and free xfers */ - urtw_free_tx_data_list(sc); - urtw_free_rx_data_list(sc); - urtw_close_pipes(sc); - - bpfdetach(ifp); - ieee80211_ifdetach(ic); - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return (0); -} - -static struct ieee80211vap * -urtw_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, int opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct urtw_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return (NULL); - uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return (NULL); - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = urtw_newstate; - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return (vap); -} - -static void -urtw_vap_delete(struct ieee80211vap *vap) -{ - struct urtw_vap *uvp = URTW_VAP(vap); - - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static usbd_status -urtw_set_mode(struct urtw_softc *sc, uint32_t mode) -{ - uint8_t data; - usbd_status error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT); - data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK); - urtw_write8_m(sc, URTW_EPROM_CMD, data); -fail: - return (error); -} - -static usbd_status -urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val) -{ - uint8_t data; - usbd_status error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); - urtw_write32_m(sc, URTW_ANAPARAM, val); - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; -fail: - return (error); -} - -static usbd_status -urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val) -{ - uint8_t data; - usbd_status error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); - urtw_write32_m(sc, URTW_ANAPARAM2, val); - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; -fail: - return (error); -} - -static usbd_status -urtw_intr_disable(struct urtw_softc *sc) -{ - usbd_status error; - - urtw_write16_m(sc, URTW_INTR_MASK, 0); -fail: - return (error); -} - -static usbd_status -urtw_reset(struct urtw_softc *sc) -{ - uint8_t data; - usbd_status error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - - error = urtw_intr_disable(sc); - if (error) - goto fail; - usbd_delay_ms(sc->sc_udev, 100); - - error = urtw_write8e(sc, 0x18, 0x10); - if (error != 0) - goto fail; - error = urtw_write8e(sc, 0x18, 0x11); - if (error != 0) - goto fail; - error = urtw_write8e(sc, 0x18, 0x00); - if (error != 0) - goto fail; - usbd_delay_ms(sc->sc_udev, 100); - - urtw_read8_m(sc, URTW_CMD, &data); - data = (data & 0x2) | URTW_CMD_RST; - urtw_write8_m(sc, URTW_CMD, data); - usbd_delay_ms(sc->sc_udev, 100); - - urtw_read8_m(sc, URTW_CMD, &data); - if (data & URTW_CMD_RST) { - device_printf(sc->sc_dev, "reset timeout\n"); - goto fail; - } - - error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD); - if (error) - goto fail; - usbd_delay_ms(sc->sc_udev, 100); - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; -fail: - return (error); -} - -static usbd_status -urtw_led_on(struct urtw_softc *sc, int type) -{ - usbd_status error; - - if (type == URTW_LED_GPIO) { - switch (sc->sc_gpio_ledpin) { - case URTW_LED_PIN_GPIO0: - urtw_write8_m(sc, URTW_GPIO, 0x01); - urtw_write8_m(sc, URTW_GP_ENABLE, 0x00); - break; - default: - panic("unsupported LED PIN type 0x%x", - sc->sc_gpio_ledpin); - /* never reach */ - } - } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ - } - - sc->sc_gpio_ledon = 1; -fail: - return (error); -} - -static usbd_status -urtw_led_off(struct urtw_softc *sc, int type) -{ - usbd_status error; - - if (type == URTW_LED_GPIO) { - switch (sc->sc_gpio_ledpin) { - case URTW_LED_PIN_GPIO0: - urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1); - urtw_write8_m(sc, - URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1); - break; - default: - panic("unsupported LED PIN type 0x%x", - sc->sc_gpio_ledpin); - /* never reach */ - } - } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ - } - - sc->sc_gpio_ledon = 0; - -fail: - return (error); -} - -static usbd_status -urtw_led_mode0(struct urtw_softc *sc, int mode) -{ - - switch (mode) { - case URTW_LED_CTL_POWER_ON: - sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK; - break; - case URTW_LED_CTL_TX: - if (sc->sc_gpio_ledinprogress == 1) - return (0); - - sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL; - sc->sc_gpio_blinktime = 2; - break; - case URTW_LED_CTL_LINK: - sc->sc_gpio_ledstate = URTW_LED_ON; - break; - default: - panic("unsupported LED mode 0x%x", mode); - /* never reach */ - } - - switch (sc->sc_gpio_ledstate) { - case URTW_LED_ON: - if (sc->sc_gpio_ledinprogress != 0) - break; - urtw_led_on(sc, URTW_LED_GPIO); - break; - case URTW_LED_BLINK_NORMAL: - if (sc->sc_gpio_ledinprogress != 0) - break; - sc->sc_gpio_ledinprogress = 1; - sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ? - URTW_LED_OFF : URTW_LED_ON; - callout_reset(&sc->sc_led_ch, hz, urtw_ledtask, sc); - break; - case URTW_LED_POWER_ON_BLINK: - urtw_led_on(sc, URTW_LED_GPIO); - usbd_delay_ms(sc->sc_udev, 100); - urtw_led_off(sc, URTW_LED_GPIO); - break; - default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ - } - return (0); -} - -static usbd_status -urtw_led_mode1(struct urtw_softc *sc, int mode) -{ - - return (USBD_INVAL); -} - -static usbd_status -urtw_led_mode2(struct urtw_softc *sc, int mode) -{ - - return (USBD_INVAL); -} - -static usbd_status -urtw_led_mode3(struct urtw_softc *sc, int mode) -{ - - return (USBD_INVAL); -} - -static usbd_status -urtw_led_blink(struct urtw_softc *sc) -{ - uint8_t ing = 0; - usbd_status error; - - if (sc->sc_gpio_blinkstate == URTW_LED_ON) - error = urtw_led_on(sc, URTW_LED_GPIO); - else - error = urtw_led_off(sc, URTW_LED_GPIO); - sc->sc_gpio_blinktime--; - if (sc->sc_gpio_blinktime == 0) - ing = 1; - else { - if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL && - sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY && - sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3) - ing = 1; - } - if (ing == 1) { - if (sc->sc_gpio_ledstate == URTW_LED_ON && - sc->sc_gpio_ledon == 0) - error = urtw_led_on(sc, URTW_LED_GPIO); - else if (sc->sc_gpio_ledstate == URTW_LED_OFF && - sc->sc_gpio_ledon == 1) - error = urtw_led_off(sc, URTW_LED_GPIO); - - sc->sc_gpio_blinktime = 0; - sc->sc_gpio_ledinprogress = 0; - return (0); - } - - sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ? - URTW_LED_ON : URTW_LED_OFF; - - switch (sc->sc_gpio_ledstate) { - case URTW_LED_BLINK_NORMAL: - callout_reset(&sc->sc_led_ch, hz, urtw_ledtask, sc); - break; - default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ - } - return (0); -} - -static void -urtw_ledusbtask(void *arg) -{ - struct urtw_softc *sc = arg; - - if (sc->sc_strategy != URTW_SW_LED_MODE0) - panic("could not process a LED strategy 0x%x", sc->sc_strategy); - - urtw_led_blink(sc); -} - -static void -urtw_ledtask(void *arg) -{ - struct urtw_softc *sc = arg; - - /* - * NB: to change a status of the led we need at least a sleep so we - * can't do it here - */ - usb_add_task(sc->sc_udev, &sc->sc_ledtask, USB_TASKQ_DRIVER); -} - -static usbd_status -urtw_led_ctl(struct urtw_softc *sc, int mode) -{ - usbd_status error = 0; - - switch (sc->sc_strategy) { - case URTW_SW_LED_MODE0: - error = urtw_led_mode0(sc, mode); - break; - case URTW_SW_LED_MODE1: - error = urtw_led_mode1(sc, mode); - break; - case URTW_SW_LED_MODE2: - error = urtw_led_mode2(sc, mode); - break; - case URTW_SW_LED_MODE3: - error = urtw_led_mode3(sc, mode); - break; - default: - panic("unsupported LED mode %d\n", sc->sc_strategy); - /* never reach */ - } - - return (error); -} - -static usbd_status -urtw_update_msr(struct urtw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t data; - usbd_status error; - - urtw_read8_m(sc, URTW_MSR, &data); - data &= ~URTW_MSR_LINK_MASK; - - if (sc->sc_state == IEEE80211_S_RUN) { - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - case IEEE80211_M_MONITOR: - data |= URTW_MSR_LINK_STA; - break; - case IEEE80211_M_IBSS: - data |= URTW_MSR_LINK_ADHOC; - break; - case IEEE80211_M_HOSTAP: - data |= URTW_MSR_LINK_HOSTAP; - break; - default: - panic("unsupported operation mode 0x%x\n", - ic->ic_opmode); - /* never reach */ - } - } else - data |= URTW_MSR_LINK_NONE; - - urtw_write8_m(sc, URTW_MSR, data); -fail: - return (error); -} - -static uint16_t -urtw_rate2rtl(int rate) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int i; - - for (i = 0; i < N(urtw_ratetable); i++) { - if (rate == urtw_ratetable[i].reg) - return urtw_ratetable[i].val; - } - - return (3); -#undef N -} - -static uint16_t -urtw_rtl2rate(int rate) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int i; - - for (i = 0; i < N(urtw_ratetable); i++) { - if (rate == urtw_ratetable[i].val) - return urtw_ratetable[i].reg; - } - - return (0); -#undef N -} - -static usbd_status -urtw_set_rate(struct urtw_softc *sc) -{ - int i, basic_rate, min_rr_rate, max_rr_rate; - uint16_t data; - usbd_status error; - - basic_rate = urtw_rate2rtl(48); - min_rr_rate = urtw_rate2rtl(12); - max_rr_rate = urtw_rate2rtl(48); - - urtw_write8_m(sc, URTW_RESP_RATE, - max_rr_rate << URTW_RESP_MAX_RATE_SHIFT | - min_rr_rate << URTW_RESP_MIN_RATE_SHIFT); - - urtw_read16_m(sc, URTW_BRSR, &data); - data &= ~URTW_BRSR_MBR_8185; - - for (i = 0; i <= basic_rate; i++) - data |= (1 << i); - - urtw_write16_m(sc, URTW_BRSR, data); -fail: - return (error); -} - -static usbd_status -urtw_intr_enable(struct urtw_softc *sc) -{ - usbd_status error; - - urtw_write16_m(sc, URTW_INTR_MASK, 0xffff); -fail: - return (error); -} - -static usbd_status -urtw_adapter_start(struct urtw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - usbd_status error; - - error = urtw_reset(sc); - if (error) - goto fail; - - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 0); - urtw_write8_m(sc, URTW_GPIO, 0); - - /* for led */ - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); - error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON); - if (error != 0) - goto fail; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_myaddr)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_myaddr)[1] & 0xffff); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_update_msr(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_INT_TIMEOUT, 0); - urtw_write8_m(sc, URTW_WPA_CONFIG, 0); - urtw_write8_m(sc, URTW_RATE_FALLBACK, 0x81); - error = urtw_set_rate(sc); - if (error != 0) - goto fail; - - error = sc->sc_rf_init(sc); - if (error != 0) - goto fail; - if (sc->sc_rf_set_sens != NULL) - sc->sc_rf_set_sens(sc, sc->sc_sens); - - /* XXX correct? to call write16 */ - urtw_write16_m(sc, URTW_PSR, 1); - urtw_write16_m(sc, URTW_ADDR_MAGIC2, 0x10); - urtw_write8_m(sc, URTW_TALLY_SEL, 0x80); - urtw_write8_m(sc, URTW_ADDR_MAGIC3, 0x60); - /* XXX correct? to call write16 */ - urtw_write16_m(sc, URTW_PSR, 0); - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); - - error = urtw_intr_enable(sc); - if (error != 0) - goto fail; - -fail: - return (error); -} - -static usbd_status -urtw_rx_setconf(struct urtw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t data; - usbd_status error; - - urtw_read32_m(sc, URTW_RX, &data); - data = data &~ URTW_RX_FILTER_MASK; -#if 0 - data = data | URTW_RX_FILTER_CTL; -#endif - data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA; - data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST; - - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - data = data | URTW_RX_FILTER_ICVERR; - data = data | URTW_RX_FILTER_PWR; - } - if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) - data = data | URTW_RX_FILTER_CRCERR; - - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { - data = data | URTW_RX_FILTER_ALLMAC; - } else { - data = data | URTW_RX_FILTER_NICMAC; - data = data | URTW_RX_CHECK_BSSID; - } - - data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; - data = data | URTW_RX_FIFO_THRESHOLD_NONE | URTW_RX_AUTORESETPHY; - data = data &~ URTW_MAX_RX_DMA_MASK; - data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT; - - urtw_write32_m(sc, URTW_RX, data); -fail: - return (error); -} - -static usbd_status -urtw_rx_enable(struct urtw_softc *sc) -{ - int i; - struct urtw_data *rxdata; - uint8_t data; - usbd_status error; - - /* - * Start up the receive pipe. - */ - for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) { - rxdata = &sc->sc_rxdata[i]; - - usbd_setup_xfer(rxdata->xfer, sc->sc_rxpipe, rxdata, - rxdata->buf, MCLBYTES, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, - urtw_rxeof); - error = usbd_transfer(rxdata->xfer); - if (error != USBD_IN_PROGRESS && error != 0) { - device_printf(sc->sc_dev, - "could not queue Rx transfer\n"); - goto fail; - } - } - - error = urtw_rx_setconf(sc); - if (error != 0) - goto fail; - - urtw_read8_m(sc, URTW_CMD, &data); - urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE); -fail: - return (error); -} - -static usbd_status -urtw_tx_enable(struct urtw_softc *sc) -{ - uint8_t data8; - uint32_t data; - usbd_status error; - - urtw_read8_m(sc, URTW_CW_CONF, &data8); - data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY); - urtw_write8_m(sc, URTW_CW_CONF, data8); - - urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; - data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; - urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); - - urtw_read32_m(sc, URTW_TX_CONF, &data); - data &= ~URTW_TX_LOOPBACK_MASK; - data |= URTW_TX_LOOPBACK_NONE; - data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); - data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; - data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; - data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); - data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; - data &= ~URTW_TX_SWPLCPLEN; - data |= URTW_TX_NOICV; - urtw_write32_m(sc, URTW_TX_CONF, data); - - urtw_read8_m(sc, URTW_CMD, &data8); - urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE); -fail: - return (error); -} - -static void -urtw_init(void *arg) -{ - int ret; - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - usbd_status error; - - urtw_stop(ifp, 0); - - error = urtw_adapter_start(sc); - if (error != 0) - goto fail; - - /* reset softc variables */ - sc->sc_txidx = sc->sc_tx_low_queued = sc->sc_tx_normal_queued = 0; - sc->sc_txtimer = 0; - - if (!(sc->sc_flags & URTW_INIT_ONCE)) { - error = usbd_set_config_no(sc->sc_udev, URTW_CONFIG_NO, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not set configuration no\n"); - goto fail; - } - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, - URTW_IFACE_INDEX, &sc->sc_iface); - if (error != 0) { - device_printf(sc->sc_dev, - "could not get interface handle\n"); - goto fail; - } - error = urtw_open_pipes(sc); - if (error != 0) - goto fail; - ret = urtw_alloc_rx_data_list(sc); - if (error != 0) - goto fail; - ret = urtw_alloc_tx_data_list(sc); - if (error != 0) - goto fail; - sc->sc_flags |= URTW_INIT_ONCE; - } - - error = urtw_rx_enable(sc); - if (error != 0) - goto fail; - error = urtw_tx_enable(sc); - if (error != 0) - goto fail; - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - - callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); -fail: - return; -} - -static void -urtw_set_multi(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (!(ifp->if_flags & IFF_UP)) - return; - - /* - * XXX don't know how to set a device. Lack of docs. Just try to set - * IFF_ALLMULTI flag here. - */ - IF_ADDR_LOCK(ifp); - ifp->if_flags |= IFF_ALLMULTI; - IF_ADDR_UNLOCK(ifp); -} - -static int -urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct urtw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - mtx_lock(&Giant); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & - (IFF_ALLMULTI | IFF_PROMISC)) - urtw_set_multi(sc); - } else { - urtw_init(ifp->if_softc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop(ifp, 1); - } - sc->sc_if_flags = ifp->if_flags; - mtx_unlock(&Giant); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - - return error; -} - -static void -urtw_start(struct ifnet *ifp) -{ - struct urtw_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - URTW_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->sc_tx_low_queued >= URTW_TX_DATA_LIST_COUNT || - sc->sc_tx_normal_queued >= URTW_TX_DATA_LIST_COUNT) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - m = ieee80211_encap(ni, m); - if (m == NULL) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - continue; - } - - if (urtw_tx_start(sc, ni, m, URTW_PRIORITY_NORMAL) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - - sc->sc_txtimer = 5; - } - URTW_UNLOCK(sc); -} - -static void -urtw_txeof_low(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct urtw_data *data = priv; - struct urtw_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_txpipe_low); - - ifp->if_oerrors++; - return; - } - - /* - * Do any tx complete callback. Note this must be done before releasing - * the node reference. - */ - m = data->m; - if (m != NULL && m->m_flags & M_TXCB) { - ieee80211_process_callback(data->ni, m, 0); /* XXX status? */ - m_freem(m); - data->m = NULL; - } - - ieee80211_free_node(data->ni); - data->ni = NULL; - - sc->sc_txtimer = 0; - ifp->if_opackets++; - - URTW_LOCK(sc); - sc->sc_tx_low_queued--; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - URTW_UNLOCK(sc); - - urtw_start(ifp); -} - -static void -urtw_txeof_normal(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct urtw_data *data = priv; - struct urtw_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_txpipe_normal); - - ifp->if_oerrors++; - return; - } - - /* - * Do any tx complete callback. Note this must be done before releasing - * the node reference. - */ - m = data->m; - if (m != NULL && m->m_flags & M_TXCB) { - ieee80211_process_callback(data->ni, m, 0); /* XXX status? */ - m_freem(m); - data->m = NULL; - } - - ieee80211_free_node(data->ni); - data->ni = NULL; - - sc->sc_txtimer = 0; - ifp->if_opackets++; - - URTW_LOCK(sc); - sc->sc_tx_normal_queued--; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - URTW_UNLOCK(sc); - - urtw_start(ifp); -} - -static int -urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, - int prior) -{ - int xferlen; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); - struct ieee80211_key *k; - const struct ieee80211_txparam *tp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = ni->ni_vap; - struct urtw_data *data; - usbd_status error; - - URTW_ASSERT_LOCKED(sc); - - /* - * Software crypto. - */ - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - device_printf(sc->sc_dev, - "ieee80211_crypto_encap returns NULL.\n"); - /* XXX we don't expect the fragmented frames */ - m_freem(m0); - return (ENOBUFS); - } - - /* in case packet header moved, reset pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct urtw_tx_radiotap_header *tap = &sc->sc_txtap; - - /* XXX Are variables correct? */ - tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - xferlen = m0->m_pkthdr.len + 4 * 3; - if((0 == xferlen % 64) || (0 == xferlen % 512)) - xferlen += 1; - - data = &sc->sc_txdata[sc->sc_txidx]; - sc->sc_txidx = (sc->sc_txidx + 1) % URTW_TX_DATA_LIST_COUNT; - - bzero(data->buf, URTW_TX_MAXSIZE); - data->buf[0] = m0->m_pkthdr.len & 0xff; - data->buf[1] = (m0->m_pkthdr.len & 0x0f00) >> 8; - data->buf[1] |= (1 << 7); - - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) && - (sc->sc_preamble_mode == URTW_PREAMBLE_MODE_SHORT) && - (sc->sc_currate != 0)) - data->buf[2] |= 1; - if ((m0->m_pkthdr.len > vap->iv_rtsthreshold) && - prior == URTW_PRIORITY_LOW) - panic("TODO tx."); - if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) - data->buf[2] |= (1 << 1); - /* RTS rate - 10 means we use a basic rate. */ - data->buf[2] |= (urtw_rate2rtl(2) << 3); - /* - * XXX currently TX rate control depends on the rate value of - * RX descriptor because I don't know how to we can control TX rate - * in more smart way. Please fix me you find a thing. - */ - data->buf[3] = sc->sc_currate; - if (prior == URTW_PRIORITY_NORMAL) { - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - data->buf[3] = urtw_rate2rtl(tp->mcastrate); - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - data->buf[3] = urtw_rate2rtl(tp->ucastrate); - } - data->buf[8] = 3; /* CW minimum */ - data->buf[8] |= (7 << 4); /* CW maximum */ - data->buf[9] |= 11; /* retry limitation */ - - m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)&data->buf[12]); - data->ni = ni; - data->m = m0; - - usbd_setup_xfer(data->xfer, - (prior == URTW_PRIORITY_LOW) ? sc->sc_txpipe_low : - sc->sc_txpipe_normal, data, data->buf, xferlen, - USBD_FORCE_SHORT_XFER | USBD_NO_COPY, URTW_DATA_TIMEOUT, - (prior == URTW_PRIORITY_LOW) ? urtw_txeof_low : urtw_txeof_normal); - error = usbd_transfer(data->xfer); - if (error != USBD_IN_PROGRESS && error != USBD_NORMAL_COMPLETION) { - device_printf(sc->sc_dev, "could not send frame: %s\n", - usbd_errstr(error)); - return EIO; - } - - error = urtw_led_ctl(sc, URTW_LED_CTL_TX); - if (error != 0) - device_printf(sc->sc_dev, "could not control LED (%d)\n", error); - - if (prior == URTW_PRIORITY_LOW) - sc->sc_tx_low_queued++; - else - sc->sc_tx_normal_queued++; - - return (0); -} - -static int -urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct urtw_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - URTW_LOCK(sc); - if (sc->sc_tx_low_queued >= URTW_TX_DATA_LIST_COUNT || - sc->sc_tx_normal_queued >= URTW_TX_DATA_LIST_COUNT) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m); - ieee80211_free_node(ni); - URTW_UNLOCK(sc); - return (ENOBUFS); /* XXX */ - } - - ifp->if_opackets++; - if (urtw_tx_start(sc, ni, m, URTW_PRIORITY_LOW) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - URTW_UNLOCK(sc); - return (EIO); - } - - sc->sc_txtimer = 5; - URTW_UNLOCK(sc); - return (0); -} - -static void -urtw_scan_start(struct ieee80211com *ic) -{ - - /* XXX do nothing? */ -} - -static void -urtw_scan_end(struct ieee80211com *ic) -{ - - /* XXX do nothing? */ -} - -static void -urtw_set_channel(struct ieee80211com *ic) -{ - struct urtw_softc *sc = ic->ic_ifp->if_softc; - struct ifnet *ifp = sc->sc_ifp; - - /* - * if the user set a channel explicitly using ifconfig(8) this function - * can be called earlier than we're expected that in some cases the - * initialization would be failed if setting a channel is called before - * the init have done. - */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - return; - - sc->sc_ctxarg = URTW_SET_CHANNEL; - usb_add_task(sc->sc_udev, &sc->sc_ctxtask, USB_TASKQ_DRIVER); -} - -static void -urtw_update_mcast(struct ifnet *ifp) -{ - - /* XXX do nothing? */ -} - -static usbd_status -urtw_8225_usb_init(struct urtw_softc *sc) -{ - uint8_t data; - usbd_status error; - - urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 0); - urtw_write8_m(sc, URTW_GPIO, 0); - error = urtw_read8e(sc, 0x53, &data); - if (error) - goto fail; - error = urtw_write8e(sc, 0x53, data | (1 << 7)); - if (error) - goto fail; - urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 4); - urtw_write8_m(sc, URTW_GPIO, 0x20); - urtw_write8_m(sc, URTW_GP_ENABLE, 0); - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x80); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x80); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x80); - - usbd_delay_ms(sc->sc_udev, 500); -fail: - return (error); -} - -static usbd_status -urtw_8185_rf_pins_enable(struct urtw_softc *sc) -{ - usbd_status error = 0; - - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1ff7); -fail: - return (error); -} - -static usbd_status -urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - uint32_t phyw; - usbd_status error; - - phyw = ((data << 8) | (addr | 0x80)); - urtw_write8_m(sc, URTW_PHY_MAGIC4, ((phyw & 0xff000000) >> 24)); - urtw_write8_m(sc, URTW_PHY_MAGIC3, ((phyw & 0x00ff0000) >> 16)); - urtw_write8_m(sc, URTW_PHY_MAGIC2, ((phyw & 0x0000ff00) >> 8)); - urtw_write8_m(sc, URTW_PHY_MAGIC1, ((phyw & 0x000000ff))); - usbd_delay_ms(sc->sc_udev, 1); -fail: - return (error); -} - -static usbd_status -urtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - - data = data & 0xff; - return urtw_8187_write_phy(sc, addr, data); -} - -static usbd_status -urtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - - data = data & 0xff; - return urtw_8187_write_phy(sc, addr, data | 0x10000); -} - -static usbd_status -urtw_8225_setgain(struct urtw_softc *sc, int16_t gain) -{ - usbd_status error; - - urtw_8187_write_phy_ofdm(sc, 0x0d, urtw_8225_gain[gain * 4]); - urtw_8187_write_phy_ofdm(sc, 0x1b, urtw_8225_gain[gain * 4 + 2]); - urtw_8187_write_phy_ofdm(sc, 0x1d, urtw_8225_gain[gain * 4 + 3]); - urtw_8187_write_phy_ofdm(sc, 0x23, urtw_8225_gain[gain * 4 + 1]); -fail: - return (error); -} - -static usbd_status -urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan) -{ - int i, idx, set; - uint8_t *cck_pwltable; - uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max; - uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; - uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; - usbd_status error; - - cck_pwrlvl_max = 11; - ofdm_pwrlvl_max = 25; /* 12 -> 25 */ - ofdm_pwrlvl_min = 10; - - /* CCK power setting */ - cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; - idx = cck_pwrlvl % 6; - set = cck_pwrlvl / 6; - cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 : - urtw_8225_txpwr_cck; - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, - urtw_8225_tx_gain_cck_ofdm[set] >> 1); - for (i = 0; i < 8; i++) { - urtw_8187_write_phy_cck(sc, 0x44 + i, - cck_pwltable[idx * 8 + i]); - } - usbd_delay_ms(sc->sc_udev, 1); - - /* OFDM power setting */ - ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? - ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; - ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; - - idx = ofdm_pwrlvl % 6; - set = ofdm_pwrlvl / 6; - - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - urtw_8187_write_phy_ofdm(sc, 2, 0x42); - urtw_8187_write_phy_ofdm(sc, 6, 0); - urtw_8187_write_phy_ofdm(sc, 8, 0); - - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, - urtw_8225_tx_gain_cck_ofdm[set] >> 1); - urtw_8187_write_phy_ofdm(sc, 0x5, urtw_8225_txpwr_ofdm[idx]); - urtw_8187_write_phy_ofdm(sc, 0x7, urtw_8225_txpwr_ofdm[idx]); - usbd_delay_ms(sc->sc_udev, 1); -fail: - return (error); -} - -static usbd_status -urtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant) -{ - usbd_status error; - - urtw_write8_m(sc, URTW_TX_ANTENNA, ant); - usbd_delay_ms(sc->sc_udev, 1); -fail: - return (error); -} - -static usbd_status -urtw_8225_rf_init(struct urtw_softc *sc) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int i; - uint16_t data; - usbd_status error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - - error = urtw_8225_usb_init(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); - urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ - urtw_write16_m(sc, URTW_BRSR, 0xffff); - urtw_write32_m(sc, URTW_RF_PARA, 0x100044); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_write8_m(sc, URTW_CONFIG3, 0x44); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_8185_rf_pins_enable(sc); - if (error) - goto fail; - usbd_delay_ms(sc->sc_udev, 1000); - - for (i = 0; i < N(urtw_8225_rf_part1); i++) { - urtw_8225_write(sc, urtw_8225_rf_part1[i].reg, - urtw_8225_rf_part1[i].val); - usbd_delay_ms(sc->sc_udev, 1); - } - usbd_delay_ms(sc->sc_udev, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usbd_delay_ms(sc->sc_udev, 200); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usbd_delay_ms(sc->sc_udev, 200); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3); - - for (i = 0; i < 95; i++) { - urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]); - } - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5); - - for (i = 0; i < 128; i++) { - urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); - usbd_delay_ms(sc->sc_udev, 1); - urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); - usbd_delay_ms(sc->sc_udev, 1); - } - - for (i = 0; i < N(urtw_8225_rf_part2); i++) { - urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg, - urtw_8225_rf_part2[i].val); - usbd_delay_ms(sc->sc_udev, 1); - } - - error = urtw_8225_setgain(sc, 4); - if (error) - goto fail; - - for (i = 0; i < N(urtw_8225_rf_part3); i++) { - urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg, - urtw_8225_rf_part3[i].val); - usbd_delay_ms(sc->sc_udev, 1); - } - - urtw_write8_m(sc, URTW_ADDR_MAGIC4, 0x0d); - - error = urtw_8225_set_txpwrlvl(sc, 1); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x10, 0x9b); - usbd_delay_ms(sc->sc_udev, 1); - urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); - usbd_delay_ms(sc->sc_udev, 1); - - /* TX ant A, 0x0 for B */ - error = urtw_8185_tx_antenna(sc, 0x3); - if (error) - goto fail; - urtw_write32_m(sc, URTW_ADDR_MAGIC5, 0x3dc00002); - - error = urtw_8225_rf_set_chan(sc, 1); -fail: - return (error); -#undef N -} - -static usbd_status -urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211_channel *c = ic->ic_curchan; - usbd_status error; - - error = urtw_8225_set_txpwrlvl(sc, chan); - if (error) - goto fail; - urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); - usbd_delay_ms(sc->sc_udev, 10); - - urtw_write8_m(sc, URTW_SIFS, 0x22); - - if (sc->sc_state == IEEE80211_S_ASSOC && - ic->ic_flags & IEEE80211_F_SHSLOT) - urtw_write8_m(sc, URTW_SLOT, 0x9); - else - urtw_write8_m(sc, URTW_SLOT, 0x14); - - if (IEEE80211_IS_CHAN_G(c)) { - /* for G */ - urtw_write8_m(sc, URTW_DIFS, 0x14); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14); - urtw_write8_m(sc, URTW_CW_VAL, 0x73); - } else { - /* for B */ - urtw_write8_m(sc, URTW_DIFS, 0x24); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24); - urtw_write8_m(sc, URTW_CW_VAL, 0xa5); - } - -fail: - return (error); -} - -static usbd_status -urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens) -{ - usbd_status error; - - if (sens < 0 || sens > 6) - return -1; - - if (sens > 4) - urtw_8225_write(sc, - URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1); - else - urtw_8225_write(sc, - URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2); - - sens = 6 - sens; - error = urtw_8225_setgain(sc, sens); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]); - -fail: - return (error); -} - -static void -urtw_stop(struct ifnet *ifp, int disable) -{ - struct urtw_softc *sc = ifp->if_softc; - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - callout_stop(&sc->sc_led_ch); - callout_stop(&sc->sc_watchdog_ch); - - if (sc->sc_rxpipe != NULL) - usbd_abort_pipe(sc->sc_rxpipe); - if (sc->sc_txpipe_low != NULL) - usbd_abort_pipe(sc->sc_txpipe_low); - if (sc->sc_txpipe_normal != NULL) - usbd_abort_pipe(sc->sc_txpipe_normal); -} - -static int -urtw_isbmode(uint16_t rate) -{ - - rate = urtw_rtl2rate(rate); - - return ((rate <= 22 && rate != 12 && rate != 18) || - rate == 44) ? (1) : (0); -} - -static void -urtw_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - int actlen, flen, len, nf, rssi; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m, *mnew; - struct urtw_data *data = priv; - struct urtw_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t *desc, quality, rate; - usbd_status error; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_rxpipe); - ifp->if_ierrors++; - goto skip; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &actlen, NULL); - if (actlen < URTW_MIN_RXBUFSZ) { - ifp->if_ierrors++; - goto skip; - } - - /* 4 dword and 4 byte CRC */ - len = actlen - (4 * 4); - desc = data->buf + len; - flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff); - if (flen > actlen) { - ifp->if_ierrors++; - goto skip; - } - - rate = (desc[2] & 0xf0) >> 4; - quality = desc[4] & 0xff; - /* XXX correct? */ - rssi = (desc[6] & 0xfe) >> 1; - if (!urtw_isbmode(rate)) { - rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi); - rssi = ((90 - rssi) * 100) / 65; - } else { - rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi); - rssi = ((95 - rssi) * 100) / 65; - } - - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - ifp->if_ierrors++; - goto skip; - } - - m = data->m; - data->m = mnew; - data->buf = mtod(mnew, uint8_t *); - - /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = flen - 4; - - if (bpf_peers_present(ifp->if_bpf)) { - struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap; - - /* XXX Are variables correct? */ - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wr_dbm_antsignal = (int8_t)rssi; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); - } - - wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) - sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; - ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); - /* XXX correct? */ - nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64; - /* send the frame to the 802.11 layer */ - if (ni != NULL) { - (void) ieee80211_input(ni, m, rssi, -nf, 0); - /* node is no longer needed */ - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, -nf, 0); - -skip: /* setup a new transfer */ - usbd_setup_xfer(xfer, sc->sc_rxpipe, data, data->buf, MCLBYTES, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urtw_rxeof); - error = usbd_transfer(xfer); - if (error != USBD_IN_PROGRESS && error != 0) - device_printf(sc->sc_dev, "could not queue Rx transfer\n"); -} - -static int -urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct urtw_vap *rvp = URTW_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct urtw_softc *sc = ic->ic_ifp->if_softc; - - DPRINTF(sc, URTW_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - /* do it in a process context */ - sc->sc_state = nstate; - sc->sc_arg = arg; - - if (nstate == IEEE80211_S_INIT) { - rvp->newstate(vap, nstate, arg); - return (0); - } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); - return (EINPROGRESS); - } -} - -static usbd_status -urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain) -{ - uint8_t *gainp; - usbd_status error; - - /* XXX for A? */ - gainp = urtw_8225v2_gain_bg; - urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]); - usbd_delay_ms(sc->sc_udev, 1); - urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]); - usbd_delay_ms(sc->sc_udev, 1); - urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]); - usbd_delay_ms(sc->sc_udev, 1); - urtw_8187_write_phy_ofdm(sc, 0x21, 0x17); - usbd_delay_ms(sc->sc_udev, 1); -fail: - return (error); -} - -static usbd_status -urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan) -{ - int i; - uint8_t *cck_pwrtable; - uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10; - uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; - uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; - usbd_status error; - - /* CCK power setting */ - cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; - cck_pwrlvl += sc->sc_txpwr_cck_base; - cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; - cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : - urtw_8225v2_txpwr_cck; - - for (i = 0; i < 8; i++) - urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, - urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]); - usbd_delay_ms(sc->sc_udev, 1); - - /* OFDM power setting */ - ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? - ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; - ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; - ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; - - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - - urtw_8187_write_phy_ofdm(sc, 2, 0x42); - urtw_8187_write_phy_ofdm(sc, 5, 0x0); - urtw_8187_write_phy_ofdm(sc, 6, 0x40); - urtw_8187_write_phy_ofdm(sc, 7, 0x0); - urtw_8187_write_phy_ofdm(sc, 8, 0x40); - - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, - urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]); - usbd_delay_ms(sc->sc_udev, 1); -fail: - return (error); -} - -static usbd_status -urtw_8225v2_rf_init(struct urtw_softc *sc) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int i; - uint16_t data; - uint32_t data32; - usbd_status error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - - error = urtw_8225_usb_init(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); - urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ - urtw_write16_m(sc, URTW_BRSR, 0xffff); - urtw_write32_m(sc, URTW_RF_PARA, 0x100044); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_write8_m(sc, URTW_CONFIG3, 0x44); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_8185_rf_pins_enable(sc); - if (error) - goto fail; - - usbd_delay_ms(sc->sc_udev, 500); - - for (i = 0; i < N(urtw_8225v2_rf_part1); i++) { - urtw_8225_write(sc, urtw_8225v2_rf_part1[i].reg, - urtw_8225v2_rf_part1[i].val); - } - usbd_delay_ms(sc->sc_udev, 50); - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1); - - for (i = 0; i < 95; i++) { - urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, - urtw_8225v2_rxgain[i]); - } - - urtw_8225_write(sc, - URTW_8225_ADDR_3_MAGIC, URTW_8225_ADDR_3_DATA_MAGIC1); - urtw_8225_write(sc, - URTW_8225_ADDR_5_MAGIC, URTW_8225_ADDR_5_DATA_MAGIC1); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC2); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usbd_delay_ms(sc->sc_udev, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usbd_delay_ms(sc->sc_udev, 100); - - error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); - if (error != 0) - goto fail; - if (data32 != URTW_8225_ADDR_6_DATA_MAGIC1) - device_printf(sc->sc_dev, "expect 0xe6!! (0x%x)\n", data32); - if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) { - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usbd_delay_ms(sc->sc_udev, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usbd_delay_ms(sc->sc_udev, 50); - error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); - if (error != 0) - goto fail; - if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) - device_printf(sc->sc_dev, "RF calibration failed\n"); - } - usbd_delay_ms(sc->sc_udev, 100); - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC6); - for (i = 0; i < 128; i++) { - urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); - urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); - } - - for (i = 0; i < N(urtw_8225v2_rf_part2); i++) { - urtw_8187_write_phy_ofdm(sc, urtw_8225v2_rf_part2[i].reg, - urtw_8225v2_rf_part2[i].val); - } - - error = urtw_8225v2_setgain(sc, 4); - if (error) - goto fail; - - for (i = 0; i < N(urtw_8225v2_rf_part3); i++) { - urtw_8187_write_phy_cck(sc, urtw_8225v2_rf_part3[i].reg, - urtw_8225v2_rf_part3[i].val); - } - - urtw_write8_m(sc, URTW_ADDR_MAGIC4, 0x0d); - - error = urtw_8225v2_set_txpwrlvl(sc, 1); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x10, 0x9b); - urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); - - /* TX ant A, 0x0 for B */ - error = urtw_8185_tx_antenna(sc, 0x3); - if (error) - goto fail; - urtw_write32_m(sc, URTW_ADDR_MAGIC5, 0x3dc00002); - - error = urtw_8225_rf_set_chan(sc, 1); -fail: - return (error); -#undef N -} - -static usbd_status -urtw_8225v2_rf_set_chan(struct urtw_softc *sc, int chan) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211_channel *c = ic->ic_curchan; - usbd_status error; - - error = urtw_8225v2_set_txpwrlvl(sc, chan); - if (error) - goto fail; - - urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); - usbd_delay_ms(sc->sc_udev, 10); - - urtw_write8_m(sc, URTW_SIFS, 0x22); - - if(sc->sc_state == IEEE80211_S_ASSOC && - ic->ic_flags & IEEE80211_F_SHSLOT) - urtw_write8_m(sc, URTW_SLOT, 0x9); - else - urtw_write8_m(sc, URTW_SLOT, 0x14); - - if (IEEE80211_IS_CHAN_G(c)) { - /* for G */ - urtw_write8_m(sc, URTW_DIFS, 0x14); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14); - urtw_write8_m(sc, URTW_CW_VAL, 0x73); - } else { - /* for B */ - urtw_write8_m(sc, URTW_DIFS, 0x24); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24); - urtw_write8_m(sc, URTW_CW_VAL, 0xa5); - } - -fail: - return (error); -} - -static void -urtw_ctxtask(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t data; - usbd_status error; - - switch (sc->sc_ctxarg) { - case URTW_SET_CHANNEL: - /* - * during changing th channel we need to temporarily be disable - * TX. - */ - urtw_read32_m(sc, URTW_TX_CONF, &data); - data &= ~URTW_TX_LOOPBACK_MASK; - urtw_write32_m(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_MAC); - error = sc->sc_rf_set_chan(sc, - ieee80211_chan2ieee(ic, ic->ic_curchan)); - if (error != 0) - goto fail; - usbd_delay_ms(sc->sc_udev, 10); - urtw_write32_m(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_NONE); - break; - default: - panic("unknown argument.\n"); - } - -fail: - if (error != 0) - device_printf(sc->sc_dev, "could not change the channel\n"); - return; -} - -static void -urtw_task(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - struct urtw_vap *uvp = URTW_VAP(vap); - usbd_status error = 0; - - switch (sc->sc_state) { - case IEEE80211_S_RUN: - /* setting bssid. */ - urtw_write32_m(sc, URTW_BSSID, ((uint32_t *)ni->ni_bssid)[0]); - urtw_write16_m(sc, URTW_BSSID + 4, - ((uint16_t *)ni->ni_bssid)[2]); - urtw_update_msr(sc); - /* XXX maybe the below would be incorrect. */ - urtw_write16_m(sc, URTW_ATIM_WND, 2); - urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); - urtw_write16_m(sc, URTW_BEACON_INTERVAL, 0x64); - urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); - error = urtw_led_ctl(sc, URTW_LED_CTL_LINK); - if (error != 0) - device_printf(sc->sc_dev, - "could not control LED (%d)\n", error); - break; - default: - break; - } - -fail: - if (error != 0) - printf("error duing processing RUN state."); - - IEEE80211_LOCK(ic); - uvp->newstate(vap, sc->sc_state, sc->sc_arg); - if (vap->iv_newstate_cb != NULL) - vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); - IEEE80211_UNLOCK(ic); -} - -static void -urtw_watchdog(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_txtimer > 0) { - if (--sc->sc_txtimer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - ifp->if_oerrors++; - return; - } - callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); - } -} - -static device_method_t urtw_methods[] = { - DEVMETHOD(device_probe, urtw_match), - DEVMETHOD(device_attach, urtw_attach), - DEVMETHOD(device_detach, urtw_detach), - { 0, 0 } -}; -static driver_t urtw_driver = { - "urtw", - urtw_methods, - sizeof(struct urtw_softc) -}; -static devclass_t urtw_devclass; - -DRIVER_MODULE(urtw, uhub, urtw_driver, urtw_devclass, usbd_driver_load, 0); -MODULE_DEPEND(urtw, wlan, 1, 1, 1); -MODULE_DEPEND(urtw, usb, 1, 1, 1); diff --git a/sys/dev/usb/if_urtwreg.h b/sys/dev/usb/if_urtwreg.h deleted file mode 100644 index 7a9baa3..0000000 --- a/sys/dev/usb/if_urtwreg.h +++ /dev/null @@ -1,256 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define URTW_CONFIG_NO 1 -#define URTW_IFACE_INDEX 0 - -/* for 8187 */ -#define URTW_MAC0 0x0000 /* 1 byte */ -#define URTW_MAC1 0x0001 /* 1 byte */ -#define URTW_MAC2 0x0002 /* 1 byte */ -#define URTW_MAC3 0x0003 /* 1 byte */ -#define URTW_MAC4 0x0004 /* 1 byte */ -#define URTW_MAC5 0x0005 /* 1 byte */ -#define URTW_BRSR 0x002c /* 2 byte */ -#define URTW_BRSR_MBR_8185 (0x0fff) -#define URTW_BSSID 0x002e /* 6 byte */ -#define URTW_RESP_RATE 0x0034 /* 1 byte */ -#define URTW_RESP_MAX_RATE_SHIFT (4) -#define URTW_RESP_MIN_RATE_SHIFT (0) -#define URTW_EIFS 0x0035 /* 1 byte */ -#define URTW_INTR_MASK 0x003c /* 2 byte */ -#define URTW_CMD 0x0037 /* 1 byte */ -#define URTW_CMD_TX_ENABLE (0x4) -#define URTW_CMD_RX_ENABLE (0x8) -#define URTW_CMD_RST (0x10) -#define URTW_TX_CONF 0x0040 /* 4 byte */ -#define URTW_TX_LOOPBACK_SHIFT (17) -#define URTW_TX_LOOPBACK_NONE (0 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_MAC (1 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_BASEBAND (2 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_CONTINUE (3 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_MASK (0x60000) -#define URTW_TX_DPRETRY_MASK (0xff00) -#define URTW_TX_RTSRETRY_MASK (0xff) -#define URTW_TX_DPRETRY_SHIFT (0) -#define URTW_TX_RTSRETRY_SHIFT (8) -#define URTW_TX_NOCRC (0x10000) -#define URTW_TX_MXDMA_MASK (0xe00000) -#define URTW_TX_MXDMA_1024 (6 << URTW_TX_MXDMA_SHIFT) -#define URTW_TX_MXDMA_2048 (7 << URTW_TX_MXDMA_SHIFT) -#define URTW_TX_MXDMA_SHIFT (21) -#define URTW_TX_CWMIN (1 << 31) -#define URTW_TX_DISCW (1 << 20) -#define URTW_TX_SWPLCPLEN (1 << 24) -#define URTW_TX_NOICV (0x80000) -#define URTW_RX 0x0044 /* 4 byte */ -#define URTW_RX_9356SEL (1 << 6) -#define URTW_RX_FILTER_MASK \ - (URTW_RX_FILTER_ALLMAC | URTW_RX_FILTER_NICMAC | URTW_RX_FILTER_MCAST | \ - URTW_RX_FILTER_BCAST | URTW_RX_FILTER_CRCERR | URTW_RX_FILTER_ICVERR | \ - URTW_RX_FILTER_DATA | URTW_RX_FILTER_CTL | URTW_RX_FILTER_MNG | \ - (1 << 21) | \ - URTW_RX_FILTER_PWR | URTW_RX_CHECK_BSSID) -#define URTW_RX_FILTER_ALLMAC (0x00000001) -#define URTW_RX_FILTER_NICMAC (0x00000002) -#define URTW_RX_FILTER_MCAST (0x00000004) -#define URTW_RX_FILTER_BCAST (0x00000008) -#define URTW_RX_FILTER_CRCERR (0x00000020) -#define URTW_RX_FILTER_ICVERR (0x00001000) -#define URTW_RX_FILTER_DATA (0x00040000) -#define URTW_RX_FILTER_CTL (0x00080000) -#define URTW_RX_FILTER_MNG (0x00100000) -#define URTW_RX_FILTER_PWR (0x00400000) -#define URTW_RX_CHECK_BSSID (0x00800000) -#define URTW_RX_FIFO_THRESHOLD_MASK ((1 << 13) | (1 << 14) | (1 << 15)) -#define URTW_RX_FIFO_THRESHOLD_SHIFT (13) -#define URTW_RX_FIFO_THRESHOLD_128 (3) -#define URTW_RX_FIFO_THRESHOLD_256 (4) -#define URTW_RX_FIFO_THRESHOLD_512 (5) -#define URTW_RX_FIFO_THRESHOLD_1024 (6) -#define URTW_RX_FIFO_THRESHOLD_NONE (7 << URTW_RX_FIFO_THRESHOLD_SHIFT) -#define URTW_RX_AUTORESETPHY (1 << URTW_RX_AUTORESETPHY_SHIFT) -#define URTW_RX_AUTORESETPHY_SHIFT (28) -#define URTW_MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) -#define URTW_MAX_RX_DMA_2048 (7 << URTW_MAX_RX_DMA_SHIFT) -#define URTW_MAX_RX_DMA_1024 (6) -#define URTW_MAX_RX_DMA_SHIFT (10) -#define URTW_RCR_ONLYERLPKT (1 << 31) -#define URTW_INT_TIMEOUT 0x0048 /* 4 byte */ -#define URTW_EPROM_CMD 0x0050 /* 1 byte */ -#define URTW_EPROM_CMD_NORMAL (0x0) -#define URTW_EPROM_CMD_NORMAL_MODE \ - (URTW_EPROM_CMD_NORMAL << URTW_EPROM_CMD_SHIFT) -#define URTW_EPROM_CMD_LOAD (0x1) -#define URTW_EPROM_CMD_PROGRAM (0x2) -#define URTW_EPROM_CMD_PROGRAM_MODE \ - (URTW_EPROM_CMD_PROGRAM << URTW_EPROM_CMD_SHIFT) -#define URTW_EPROM_CMD_CONFIG (0x3) -#define URTW_EPROM_CMD_SHIFT (6) -#define URTW_EPROM_CMD_MASK ((1 << 7) | (1 << 6)) -#define URTW_EPROM_READBIT (0x1) -#define URTW_EPROM_WRITEBIT (0x2) -#define URTW_EPROM_CK (0x4) -#define URTW_EPROM_CS (0x8) -#define URTW_CONFIG2 0x0053 -#define URTW_ANAPARAM 0x0054 /* 4 byte */ -#define URTW_8225_ANAPARAM_ON (0xa0000a59) -#define URTW_MSR 0x0058 /* 1 byte */ -#define URTW_MSR_LINK_MASK ((1 << 2) | (1 << 3)) -#define URTW_MSR_LINK_SHIFT (2) -#define URTW_MSR_LINK_NONE (0 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_ADHOC (1 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_STA (2 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_HOSTAP (3 << URTW_MSR_LINK_SHIFT) -#define URTW_CONFIG3 0x0059 /* 1 byte */ -#define URTW_CONFIG3_ANAPARAM_WRITE (0x40) -#define URTW_CONFIG3_ANAPARAM_W_SHIFT (6) -#define URTW_ADDR_MAGIC4 0x005b /* 1 byte */ -#define URTW_PSR 0x005e /* 1 byte */ -#define URTW_ANAPARAM2 0x0060 /* 4 byte */ -#define URTW_8225_ANAPARAM2_ON (0x860c7312) -#define URTW_BEACON_INTERVAL 0x0070 /* 2 byte */ -#define URTW_ATIM_WND 0x0072 /* 2 byte */ -#define URTW_BEACON_INTERVAL_TIME 0x0074 /* 2 byte */ -#define URTW_ATIM_TR_ITV 0x0076 /* 2 byte */ -#define URTW_PHY_MAGIC1 0x007c /* 1 byte */ -#define URTW_PHY_MAGIC2 0x007d /* 1 byte */ -#define URTW_PHY_MAGIC3 0x007e /* 1 byte */ -#define URTW_PHY_MAGIC4 0x007f /* 1 byte */ -#define URTW_RF_PINS_OUTPUT 0x0080 /* 2 byte */ -#define URTW_RF_PINS_OUTPUT_MAGIC1 (0x3a0) -#define URTW_BB_HOST_BANG_CLK (1 << 1) -#define URTW_BB_HOST_BANG_EN (1 << 2) -#define URTW_BB_HOST_BANG_RW (1 << 3) -#define URTW_RF_PINS_ENABLE 0x0082 /* 2 byte */ -#define URTW_RF_PINS_SELECT 0x0084 /* 2 byte */ -#define URTW_ADDR_MAGIC1 0x0085 /* broken? */ -#define URTW_RF_PINS_INPUT 0x0086 /* 2 byte */ -#define URTW_RF_PINS_MAGIC1 (0xfff3) -#define URTW_RF_PINS_MAGIC2 (0xfff0) -#define URTW_RF_PINS_MAGIC3 (0x0007) -#define URTW_RF_PINS_MAGIC4 (0xf) -#define URTW_RF_PINS_MAGIC5 (0x0080) -#define URTW_RF_PARA 0x0088 /* 4 byte */ -#define URTW_RF_TIMING 0x008c /* 4 byte */ -#define URTW_GP_ENABLE 0x0090 /* 1 byte */ -#define URTW_GP_ENABLE_DATA_MAGIC1 (0x1) -#define URTW_GPIO 0x0091 /* 1 byte */ -#define URTW_GPIO_DATA_MAGIC1 (0x1) -#define URTW_ADDR_MAGIC5 0x0094 /* 4 byte */ -#define URTW_TX_AGC_CTL 0x009c /* 1 byte */ -#define URTW_TX_AGC_CTL_PERPACKET_GAIN (0x1) -#define URTW_TX_AGC_CTL_PERPACKET_ANTSEL (0x2) -#define URTW_TX_AGC_CTL_FEEDBACK_ANT (0x4) -#define URTW_TX_GAIN_CCK 0x009d /* 1 byte */ -#define URTW_TX_GAIN_OFDM 0x009e /* 1 byte */ -#define URTW_TX_ANTENNA 0x009f /* 1 byte */ -#define URTW_WPA_CONFIG 0x00b0 /* 1 byte */ -#define URTW_SIFS 0x00b4 /* 1 byte */ -#define URTW_DIFS 0x00b5 /* 1 byte */ -#define URTW_SLOT 0x00b6 /* 1 byte */ -#define URTW_CW_CONF 0x00bc /* 1 byte */ -#define URTW_CW_CONF_PERPACKET_RETRY (0x2) -#define URTW_CW_CONF_PERPACKET_CW (0x1) -#define URTW_CW_VAL 0x00bd /* 1 byte */ -#define URTW_RATE_FALLBACK 0x00be /* 1 byte */ -#define URTW_TALLY_SEL 0x00fc /* 1 byte */ -#define URTW_ADDR_MAGIC2 0x00fe /* 2 byte */ -#define URTW_ADDR_MAGIC3 0x00ff /* 1 byte */ - -/* for 8225 */ -#define URTW_8225_ADDR_0_MAGIC 0x0 -#define URTW_8225_ADDR_0_DATA_MAGIC1 (0x1b7) -#define URTW_8225_ADDR_0_DATA_MAGIC2 (0x0b7) -#define URTW_8225_ADDR_0_DATA_MAGIC3 (0x127) -#define URTW_8225_ADDR_0_DATA_MAGIC4 (0x027) -#define URTW_8225_ADDR_0_DATA_MAGIC5 (0x22f) -#define URTW_8225_ADDR_0_DATA_MAGIC6 (0x2bf) -#define URTW_8225_ADDR_1_MAGIC 0x1 -#define URTW_8225_ADDR_2_MAGIC 0x2 -#define URTW_8225_ADDR_2_DATA_MAGIC1 (0xc4d) -#define URTW_8225_ADDR_2_DATA_MAGIC2 (0x44d) -#define URTW_8225_ADDR_3_MAGIC 0x3 -#define URTW_8225_ADDR_3_DATA_MAGIC1 (0x2) -#define URTW_8225_ADDR_5_MAGIC 0x5 -#define URTW_8225_ADDR_5_DATA_MAGIC1 (0x4) -#define URTW_8225_ADDR_6_MAGIC 0x6 -#define URTW_8225_ADDR_6_DATA_MAGIC1 (0xe6) -#define URTW_8225_ADDR_6_DATA_MAGIC2 (0x80) -#define URTW_8225_ADDR_7_MAGIC 0x7 -#define URTW_8225_ADDR_8_MAGIC 0x8 -#define URTW_8225_ADDR_8_DATA_MAGIC1 (0x588) -#define URTW_8225_ADDR_9_MAGIC 0x9 -#define URTW_8225_ADDR_9_DATA_MAGIC1 (0x700) -#define URTW_8225_ADDR_C_MAGIC 0xc -#define URTW_8225_ADDR_C_DATA_MAGIC1 (0x850) -#define URTW_8225_ADDR_C_DATA_MAGIC2 (0x050) - -/* for EEPROM */ -#define URTW_EPROM_TXPW_BASE 0x05 -#define URTW_EPROM_RFCHIPID 0x06 -#define URTW_EPROM_RFCHIPID_RTL8225U (5) -#define URTW_EPROM_MACADDR 0x07 -#define URTW_EPROM_TXPW0 0x16 -#define URTW_EPROM_TXPW2 0x1b -#define URTW_EPROM_TXPW1 0x3d -#define URTW_EPROM_SWREV 0x3f -#define URTW_EPROM_CID_MASK (0xff) -#define URTW_EPROM_CID_RSVD0 (0x00) -#define URTW_EPROM_CID_RSVD1 (0xff) -#define URTW_EPROM_CID_ALPHA0 (0x01) -#define URTW_EPROM_CID_SERCOMM_PS (0x02) -#define URTW_EPROM_CID_HW_LED (0x03) - -/* LED */ -#define URTW_CID_DEFAULT 0 -#define URTW_CID_8187_ALPHA0 1 -#define URTW_CID_8187_SERCOMM_PS 2 -#define URTW_CID_8187_HW_LED 3 -#define URTW_SW_LED_MODE0 0 -#define URTW_SW_LED_MODE1 1 -#define URTW_SW_LED_MODE2 2 -#define URTW_SW_LED_MODE3 3 -#define URTW_HW_LED 4 -#define URTW_LED_CTL_POWER_ON 0 -#define URTW_LED_CTL_LINK 2 -#define URTW_LED_CTL_TX 4 -#define URTW_LED_PIN_GPIO0 0 -#define URTW_LED_PIN_LED0 1 -#define URTW_LED_PIN_LED1 2 -#define URTW_LED_UNKNOWN 0 -#define URTW_LED_ON 1 -#define URTW_LED_OFF 2 -#define URTW_LED_BLINK_NORMAL 3 -#define URTW_LED_BLINK_SLOWLY 4 -#define URTW_LED_POWER_ON_BLINK 5 -#define URTW_LED_SCAN_BLINK 6 -#define URTW_LED_NO_LINK_BLINK 7 -#define URTW_LED_BLINK_CM3 8 - -/* for extra area */ -#define URTW_EPROM_DISABLE 0 -#define URTW_EPROM_ENABLE 1 -#define URTW_EPROM_DELAY 10 -#define URTW_8187_GETREGS_REQ 5 -#define URTW_8187_SETREGS_REQ 5 -#define URTW_8225_RF_MAX_SENS 6 -#define URTW_8225_RF_DEF_SENS 4 -#define URTW_DEFAULT_RTS_RETRY 7 -#define URTW_DEFAULT_TX_RETRY 7 -#define URTW_DEFAULT_RTS_THRESHOLD 2342U diff --git a/sys/dev/usb/if_urtwvar.h b/sys/dev/usb/if_urtwvar.h deleted file mode 100644 index 77c09ef..0000000 --- a/sys/dev/usb/if_urtwvar.h +++ /dev/null @@ -1,151 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* XXX no definition at net80211? */ -#define URTW_MAX_CHANNELS 15 - -struct urtw_data { - struct urtw_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct mbuf *m; - struct ieee80211_node *ni; /* NB: tx only */ -}; - -/* XXX not correct.. */ -#define URTW_MIN_RXBUFSZ \ - (sizeof(struct ieee80211_frame_min)) - -#define URTW_RX_DATA_LIST_COUNT 1 -#define URTW_TX_DATA_LIST_COUNT 16 -#define URTW_RX_MAXSIZE 0x9c4 -#define URTW_TX_MAXSIZE 0x9c4 - -struct urtw_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_dbm_antsignal; -} __packed; - -#define URTW_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)) - -struct urtw_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define URTW_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct urtw_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define URTW_VAP(vap) ((struct urtw_vap *)(vap)) - -struct urtw_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - struct mtx sc_mtx; - - int sc_debug; - int sc_if_flags; - int sc_flags; -#define URTW_INIT_ONCE (1 << 1) - struct usb_task sc_task; - struct usb_task sc_ctxtask; - int sc_ctxarg; -#define URTW_SET_CHANNEL 1 - enum ieee80211_state sc_state; - int sc_arg; - int (*sc_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - - int sc_epromtype; -#define URTW_EEPROM_93C46 0 -#define URTW_EEPROM_93C56 1 - uint8_t sc_crcmon; - uint8_t sc_bssid[IEEE80211_ADDR_LEN]; - - /* for RF */ - usbd_status (*sc_rf_init)(struct urtw_softc *); - usbd_status (*sc_rf_set_chan)(struct urtw_softc *, - int); - usbd_status (*sc_rf_set_sens)(struct urtw_softc *, - int); - uint8_t sc_rfchip; - uint32_t sc_max_sens; - uint32_t sc_sens; - /* for LED */ - struct callout sc_led_ch; - struct usb_task sc_ledtask; - uint8_t sc_psr; - uint8_t sc_strategy; -#define URTW_LED_GPIO 1 - uint8_t sc_gpio_ledon; - uint8_t sc_gpio_ledinprogress; - uint8_t sc_gpio_ledstate; - uint8_t sc_gpio_ledpin; - uint8_t sc_gpio_blinktime; - uint8_t sc_gpio_blinkstate; - /* RX/TX */ - usbd_pipe_handle sc_rxpipe; - usbd_pipe_handle sc_txpipe_low; - usbd_pipe_handle sc_txpipe_normal; -#define URTW_PRIORITY_LOW 0 -#define URTW_PRIORITY_NORMAL 1 -#define URTW_DATA_TIMEOUT 10000 /* 10 sec */ - struct urtw_data sc_rxdata[URTW_RX_DATA_LIST_COUNT]; - struct urtw_data sc_txdata[URTW_TX_DATA_LIST_COUNT]; - uint32_t sc_tx_low_queued; - uint32_t sc_tx_normal_queued; - uint32_t sc_txidx; - uint8_t sc_rts_retry; - uint8_t sc_tx_retry; - uint8_t sc_preamble_mode; -#define URTW_PREAMBLE_MODE_SHORT 1 -#define URTW_PREAMBLE_MODE_LONG 2 - struct callout sc_watchdog_ch; - int sc_txtimer; - int sc_currate; - /* TX power */ - uint8_t sc_txpwr_cck[URTW_MAX_CHANNELS]; - uint8_t sc_txpwr_cck_base; - uint8_t sc_txpwr_ofdm[URTW_MAX_CHANNELS]; - uint8_t sc_txpwr_ofdm_base; - - struct urtw_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct urtw_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define URTW_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define URTW_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define URTW_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) diff --git a/sys/dev/usb/if_zyd.c b/sys/dev/usb/if_zyd.c deleted file mode 100644 index 3a4abce..0000000 --- a/sys/dev/usb/if_zyd.c +++ /dev/null @@ -1,3126 +0,0 @@ -/* $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */ -/* $NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr> - * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * ZyDAS ZD1211/ZD1211B USB WLAN driver. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/endian.h> -#include <sys/linker.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> - -#include <sys/bus.h> -#include <machine/bus.h> - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_amrr.h> -#include <net80211/ieee80211_phy.h> -#include <net80211/ieee80211_radiotap.h> -#include <net80211/ieee80211_regdomain.h> - -#include <net/bpf.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_ethersubr.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <dev/usb/if_zydreg.h> -#include <dev/usb/if_zydfw.h> - -#ifdef ZYD_DEBUG -SYSCTL_NODE(_hw_usb, OID_AUTO, zyd, CTLFLAG_RW, 0, "ZyDAS zd1211/zd1211b"); -int zyd_debug = 0; -SYSCTL_INT(_hw_usb_zyd, OID_AUTO, debug, CTLFLAG_RW, &zyd_debug, 0, - "control debugging printfs"); -TUNABLE_INT("hw.usb.zyd.debug", &zyd_debug); -enum { - ZYD_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - ZYD_DEBUG_RECV = 0x00000002, /* basic recv operation */ - ZYD_DEBUG_RESET = 0x00000004, /* reset processing */ - ZYD_DEBUG_INIT = 0x00000008, /* device init */ - ZYD_DEBUG_TX_PROC = 0x00000010, /* tx ISR proc */ - ZYD_DEBUG_RX_PROC = 0x00000020, /* rx ISR proc */ - ZYD_DEBUG_STATE = 0x00000040, /* 802.11 state transitions */ - ZYD_DEBUG_STAT = 0x00000080, /* statistic */ - ZYD_DEBUG_FW = 0x00000100, /* firmware */ - ZYD_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif - -static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY; -static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; - -/* various supported device vendors/products */ -#define ZYD_ZD1211_DEV(v, p) \ - { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211 } -#define ZYD_ZD1211B_DEV(v, p) \ - { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B } -static const struct zyd_type { - struct usb_devno dev; - uint8_t rev; -#define ZYD_ZD1211 0 -#define ZYD_ZD1211B 1 -} zyd_devs[] = { - ZYD_ZD1211_DEV(3COM2, 3CRUSB10075), - ZYD_ZD1211_DEV(ABOCOM, WL54), - ZYD_ZD1211_DEV(ASUS, WL159G), - ZYD_ZD1211_DEV(CYBERTAN, TG54USB), - ZYD_ZD1211_DEV(DRAYTEK, VIGOR550), - ZYD_ZD1211_DEV(PLANEX2, GWUS54GD), - ZYD_ZD1211_DEV(PLANEX2, GWUS54GZL), - ZYD_ZD1211_DEV(PLANEX3, GWUS54GZ), - ZYD_ZD1211_DEV(PLANEX3, GWUS54MINI), - ZYD_ZD1211_DEV(SAGEM, XG760A), - ZYD_ZD1211_DEV(SENAO, NUB8301), - ZYD_ZD1211_DEV(SITECOMEU, WL113), - ZYD_ZD1211_DEV(SWEEX, ZD1211), - ZYD_ZD1211_DEV(TEKRAM, QUICKWLAN), - ZYD_ZD1211_DEV(TEKRAM, ZD1211_1), - ZYD_ZD1211_DEV(TEKRAM, ZD1211_2), - ZYD_ZD1211_DEV(TWINMOS, G240), - ZYD_ZD1211_DEV(UMEDIA, ALL0298V2), - ZYD_ZD1211_DEV(UMEDIA, TEW429UB_A), - ZYD_ZD1211_DEV(UMEDIA, TEW429UB), - ZYD_ZD1211_DEV(WISTRONNEWEB, UR055G), - ZYD_ZD1211_DEV(ZCOM, ZD1211), - ZYD_ZD1211_DEV(ZYDAS, ZD1211), - ZYD_ZD1211_DEV(ZYXEL, AG225H), - ZYD_ZD1211_DEV(ZYXEL, ZYAIRG220), - ZYD_ZD1211_DEV(ZYXEL, G200V2), - ZYD_ZD1211_DEV(ZYXEL, G202), - - ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG), - ZYD_ZD1211B_DEV(ACCTON, ZD1211B), - ZYD_ZD1211B_DEV(ASUS, A9T_WIFI), - ZYD_ZD1211B_DEV(BELKIN, F5D7050_V4000), - ZYD_ZD1211B_DEV(BELKIN, ZD1211B), - ZYD_ZD1211B_DEV(CISCOLINKSYS, WUSBF54G), - ZYD_ZD1211B_DEV(FIBERLINE, WL430U), - ZYD_ZD1211B_DEV(MELCO, KG54L), - ZYD_ZD1211B_DEV(PHILIPS, SNU5600), - ZYD_ZD1211B_DEV(PLANEX2, GW_US54GXS), - ZYD_ZD1211B_DEV(SAGEM, XG76NA), - ZYD_ZD1211B_DEV(SITECOMEU, ZD1211B), - ZYD_ZD1211B_DEV(UMEDIA, TEW429UBC1), -#if 0 /* Shall we needs? */ - ZYD_ZD1211B_DEV(UNKNOWN1, ZD1211B_1), - ZYD_ZD1211B_DEV(UNKNOWN1, ZD1211B_2), - ZYD_ZD1211B_DEV(UNKNOWN2, ZD1211B), - ZYD_ZD1211B_DEV(UNKNOWN3, ZD1211B), -#endif - ZYD_ZD1211B_DEV(USR, USR5423), - ZYD_ZD1211B_DEV(VTECH, ZD1211B), - ZYD_ZD1211B_DEV(ZCOM, ZD1211B), - ZYD_ZD1211B_DEV(ZYDAS, ZD1211B), - ZYD_ZD1211B_DEV(ZYXEL, M202), - ZYD_ZD1211B_DEV(ZYXEL, G220V2), -}; -#define zyd_lookup(v, p) \ - ((const struct zyd_type *)usb_lookup(zyd_devs, v, p)) -#define zyd_read16_m(sc, val, data) do { \ - error = zyd_read16(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_write16_m(sc, val, data) do { \ - error = zyd_write16(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_read32_m(sc, val, data) do { \ - error = zyd_read32(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_write32_m(sc, val, data) do { \ - error = zyd_write32(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) - -static device_probe_t zyd_match; -static device_attach_t zyd_attach; -static device_detach_t zyd_detach; - -static struct ieee80211vap *zyd_vap_create(struct ieee80211com *, - const char name[IFNAMSIZ], int unit, int opmode, - int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void zyd_vap_delete(struct ieee80211vap *); -static int zyd_open_pipes(struct zyd_softc *); -static void zyd_close_pipes(struct zyd_softc *); -static int zyd_alloc_tx_list(struct zyd_softc *); -static void zyd_free_tx_list(struct zyd_softc *); -static int zyd_alloc_rx_list(struct zyd_softc *); -static void zyd_free_rx_list(struct zyd_softc *); -static struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); -static void zyd_task(void *); -static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static int zyd_cmd(struct zyd_softc *, uint16_t, const void *, int, - void *, int, u_int); -static int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *); -static int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *); -static int zyd_write16(struct zyd_softc *, uint16_t, uint16_t); -static int zyd_write32(struct zyd_softc *, uint16_t, uint32_t); -static int zyd_rfwrite(struct zyd_softc *, uint32_t); -static int zyd_lock_phy(struct zyd_softc *); -static int zyd_unlock_phy(struct zyd_softc *); -static int zyd_rf_attach(struct zyd_softc *, uint8_t); -static const char *zyd_rf_name(uint8_t); -static int zyd_hw_init(struct zyd_softc *); -static int zyd_read_pod(struct zyd_softc *); -static int zyd_read_eeprom(struct zyd_softc *); -static int zyd_get_macaddr(struct zyd_softc *); -static int zyd_set_macaddr(struct zyd_softc *, const uint8_t *); -static int zyd_set_bssid(struct zyd_softc *, const uint8_t *); -static int zyd_switch_radio(struct zyd_softc *, int); -static int zyd_set_led(struct zyd_softc *, int, int); -static void zyd_set_multi(void *); -static void zyd_update_mcast(struct ifnet *); -static int zyd_set_rxfilter(struct zyd_softc *); -static void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *); -static int zyd_set_beacon_interval(struct zyd_softc *, int); -static void zyd_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t); -static void zyd_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void zyd_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); -static int zyd_tx_mgt(struct zyd_softc *, struct mbuf *, - struct ieee80211_node *); -static int zyd_tx_data(struct zyd_softc *, struct mbuf *, - struct ieee80211_node *); -static void zyd_start(struct ifnet *); -static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void zyd_watchdog(void *); -static int zyd_ioctl(struct ifnet *, u_long, caddr_t); -static void zyd_init_locked(struct zyd_softc *); -static void zyd_init(void *); -static void zyd_stop(struct zyd_softc *, int); -static int zyd_loadfirmware(struct zyd_softc *); -static void zyd_newassoc(struct ieee80211_node *, int); -static void zyd_scantask(void *); -static void zyd_scan_start(struct ieee80211com *); -static void zyd_scan_end(struct ieee80211com *); -static void zyd_set_channel(struct ieee80211com *); -static void zyd_wakeup(struct zyd_softc *); -static int zyd_rfmd_init(struct zyd_rf *); -static int zyd_rfmd_switch_radio(struct zyd_rf *, int); -static int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2230_init(struct zyd_rf *); -static int zyd_al2230_switch_radio(struct zyd_rf *, int); -static int zyd_al2230_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2230_set_channel_b(struct zyd_rf *, uint8_t); -static int zyd_al2230_init_b(struct zyd_rf *); -static int zyd_al7230B_init(struct zyd_rf *); -static int zyd_al7230B_switch_radio(struct zyd_rf *, int); -static int zyd_al7230B_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2210_init(struct zyd_rf *); -static int zyd_al2210_switch_radio(struct zyd_rf *, int); -static int zyd_al2210_set_channel(struct zyd_rf *, uint8_t); -static int zyd_gct_init(struct zyd_rf *); -static int zyd_gct_switch_radio(struct zyd_rf *, int); -static int zyd_gct_set_channel(struct zyd_rf *, uint8_t); -static int zyd_maxim_init(struct zyd_rf *); -static int zyd_maxim_switch_radio(struct zyd_rf *, int); -static int zyd_maxim_set_channel(struct zyd_rf *, uint8_t); -static int zyd_maxim2_init(struct zyd_rf *); -static int zyd_maxim2_switch_radio(struct zyd_rf *, int); -static int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t); - -static int -zyd_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (!uaa->iface) - return (UMATCH_NONE); - - return (zyd_lookup(uaa->vendor, uaa->product) != NULL) ? - (UMATCH_VENDOR_PRODUCT) : (UMATCH_NONE); -} - -static int -zyd_attach(device_t dev) -{ - int error = ENXIO; - struct ieee80211com *ic; - struct ifnet *ifp; - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct zyd_softc *sc = device_get_softc(dev); - usb_device_descriptor_t* ddesc; - uint8_t bands; - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; - sc->sc_macrev = zyd_lookup(uaa->vendor, uaa->product)->rev; -#ifdef ZYD_DEBUG - sc->sc_debug = zyd_debug; -#endif - - ddesc = usbd_get_device_descriptor(sc->sc_udev); - if (UGETW(ddesc->bcdDevice) < 0x4330) { - device_printf(dev, "device version mismatch: 0x%x " - "(only >= 43.30 supported)\n", - UGETW(ddesc->bcdDevice)); - return (ENXIO); - } - - if ((error = zyd_get_macaddr(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - return (ENXIO); - } - - mtx_init(&sc->sc_txmtx, device_get_nameunit(sc->sc_dev), - MTX_NETWORK_LOCK, MTX_DEF); - usb_init_task(&sc->sc_mcasttask, zyd_set_multi, sc); - usb_init_task(&sc->sc_scantask, zyd_scantask, sc); - usb_init_task(&sc->sc_task, zyd_task, sc); - callout_init(&sc->sc_watchdog_ch, 0); - STAILQ_INIT(&sc->sc_rqh); - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not if_alloc()\n"); - error = ENXIO; - goto fail0; - } - ifp->if_softc = sc; - if_initname(ifp, "zyd", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; /* USB stack is still under Giant lock */ - ifp->if_init = zyd_init; - ifp->if_ioctl = zyd_ioctl; - ifp->if_start = zyd_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; - IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid); - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode */ - | IEEE80211_C_MONITOR /* monitor mode */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic); - ic->ic_newassoc = zyd_newassoc; - ic->ic_raw_xmit = zyd_raw_xmit; - ic->ic_node_alloc = zyd_node_alloc; - ic->ic_scan_start = zyd_scan_start; - ic->ic_scan_end = zyd_scan_end; - ic->ic_set_channel = zyd_set_channel; - - ic->ic_vap_create = zyd_vap_create; - ic->ic_vap_delete = zyd_vap_delete; - ic->ic_update_mcast = zyd_update_mcast; - - bpfattach(ifp, DLT_IEEE802_11_RADIO, - sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap)); - sc->sc_rxtap_len = sizeof(sc->sc_rxtap); - sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); - sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT); - sc->sc_txtap_len = sizeof(sc->sc_txtap); - sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); - sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); - - return (0); - -fail0: mtx_destroy(&sc->sc_txmtx); - return (error); -} - -static int -zyd_detach(device_t dev) -{ - struct zyd_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return (0); - - /* set a flag to indicate we're detaching. */ - sc->sc_flags |= ZYD_FLAG_DETACHING; - - zyd_stop(sc, 1); - bpfdetach(ifp); - ieee80211_ifdetach(ic); - - zyd_wakeup(sc); - zyd_close_pipes(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_txmtx); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return (0); -} - -static struct ieee80211vap * -zyd_vap_create(struct ieee80211com *ic, - const char name[IFNAMSIZ], int unit, int opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct zyd_vap *zvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return (NULL); - zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (zvp == NULL) - return (NULL); - vap = &zvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - zvp->newstate = vap->iv_newstate; - vap->iv_newstate = zyd_newstate; - - ieee80211_amrr_init(&zvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return (vap); -} - -static void -zyd_vap_delete(struct ieee80211vap *vap) -{ - struct zyd_vap *zvp = ZYD_VAP(vap); - - ieee80211_amrr_cleanup(&zvp->amrr); - ieee80211_vap_detach(vap); - free(zvp, M_80211_VAP); -} - -static int -zyd_open_pipes(struct zyd_softc *sc) -{ - usb_endpoint_descriptor_t *edesc; - int isize; - usbd_status error; - - /* interrupt in */ - edesc = usbd_get_endpoint_descriptor(sc->sc_iface, 0x83); - if (edesc == NULL) - return (EINVAL); - - isize = UGETW(edesc->wMaxPacketSize); - if (isize == 0) /* should not happen */ - return (EINVAL); - - sc->sc_ibuf = malloc(isize, M_USBDEV, M_NOWAIT); - if (sc->sc_ibuf == NULL) - return (ENOMEM); - - error = usbd_open_pipe_intr(sc->sc_iface, 0x83, USBD_SHORT_XFER_OK, - &sc->sc_ep[ZYD_ENDPT_IIN], sc, sc->sc_ibuf, isize, zyd_intr, - USBD_DEFAULT_INTERVAL); - if (error != 0) { - device_printf(sc->sc_dev, "open rx intr pipe failed: %s\n", - usbd_errstr(error)); - goto fail; - } - - /* interrupt out (not necessarily an interrupt pipe) */ - error = usbd_open_pipe(sc->sc_iface, 0x04, USBD_EXCLUSIVE_USE, - &sc->sc_ep[ZYD_ENDPT_IOUT]); - if (error != 0) { - device_printf(sc->sc_dev, "open tx intr pipe failed: %s\n", - usbd_errstr(error)); - goto fail; - } - - /* bulk in */ - error = usbd_open_pipe(sc->sc_iface, 0x82, USBD_EXCLUSIVE_USE, - &sc->sc_ep[ZYD_ENDPT_BIN]); - if (error != 0) { - device_printf(sc->sc_dev, "open rx pipe failed: %s\n", - usbd_errstr(error)); - goto fail; - } - - /* bulk out */ - error = usbd_open_pipe(sc->sc_iface, 0x01, USBD_EXCLUSIVE_USE, - &sc->sc_ep[ZYD_ENDPT_BOUT]); - if (error != 0) { - device_printf(sc->sc_dev, "open tx pipe failed: %s\n", - usbd_errstr(error)); - goto fail; - } - - return (0); - -fail: zyd_close_pipes(sc); - return (ENXIO); -} - -static void -zyd_close_pipes(struct zyd_softc *sc) -{ - int i; - - for (i = 0; i < ZYD_ENDPT_CNT; i++) { - if (sc->sc_ep[i] != NULL) { - usbd_abort_pipe(sc->sc_ep[i]); - usbd_close_pipe(sc->sc_ep[i]); - sc->sc_ep[i] = NULL; - } - } - if (sc->sc_ibuf != NULL) { - free(sc->sc_ibuf, M_USBDEV); - sc->sc_ibuf = NULL; - } -} - -static int -zyd_alloc_tx_list(struct zyd_softc *sc) -{ - int i, error; - - sc->sc_txqueued = 0; - - for (i = 0; i < ZYD_TX_LIST_CNT; i++) { - struct zyd_tx_data *data = &sc->sc_txdata[i]; - - data->sc = sc; /* backpointer for callbacks */ - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx xfer\n"); - error = ENOMEM; - goto fail; - } - data->buf = usbd_alloc_buffer(data->xfer, ZYD_MAX_TXBUFSZ); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate tx buffer\n"); - error = ENOMEM; - goto fail; - } - - /* clear Tx descriptor */ - bzero(data->buf, sizeof(struct zyd_tx_desc)); - } - return (0); - -fail: zyd_free_tx_list(sc); - return (error); -} - -static void -zyd_free_tx_list(struct zyd_softc *sc) -{ - int i; - - for (i = 0; i < ZYD_TX_LIST_CNT; i++) { - struct zyd_tx_data *data = &sc->sc_txdata[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - } -} - -static int -zyd_alloc_rx_list(struct zyd_softc *sc) -{ - int i, error; - - for (i = 0; i < ZYD_RX_LIST_CNT; i++) { - struct zyd_rx_data *data = &sc->sc_rxdata[i]; - - data->sc = sc; /* backpointer for callbacks */ - - data->xfer = usbd_alloc_xfer(sc->sc_udev); - if (data->xfer == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx xfer\n"); - error = ENOMEM; - goto fail; - } - data->buf = usbd_alloc_buffer(data->xfer, ZYX_MAX_RXBUFSZ); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx buffer\n"); - error = ENOMEM; - goto fail; - } - } - return (0); - -fail: zyd_free_rx_list(sc); - return (error); -} - -static void -zyd_free_rx_list(struct zyd_softc *sc) -{ - int i; - - for (i = 0; i < ZYD_RX_LIST_CNT; i++) { - struct zyd_rx_data *data = &sc->sc_rxdata[i]; - - if (data->xfer != NULL) { - usbd_free_xfer(data->xfer); - data->xfer = NULL; - } - } -} - -/* ARGUSED */ -static struct ieee80211_node * -zyd_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct zyd_node *zn; - - zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return (zn != NULL) ? (&zn->ni) : (NULL); -} - -static void -zyd_task(void *arg) -{ - int error; - struct zyd_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - struct zyd_vap *zvp = ZYD_VAP(vap); - - switch (sc->sc_state) { - case IEEE80211_S_AUTH: - zyd_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_RUN: - if (vap->iv_opmode == IEEE80211_M_MONITOR) - break; - - /* turn link LED on */ - error = zyd_set_led(sc, ZYD_LED1, 1); - if (error != 0) - goto fail; - - /* make data LED blink upon Tx */ - zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1); - - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - zyd_set_bssid(sc, sc->sc_bssid); - break; - default: - break; - } - -fail: - IEEE80211_LOCK(ic); - zvp->newstate(vap, sc->sc_state, sc->sc_arg); - if (vap->iv_newstate_cb != NULL) - vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); - IEEE80211_UNLOCK(ic); -} - -static int -zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct zyd_vap *zvp = ZYD_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - usb_rem_task(sc->sc_udev, &sc->sc_task); - callout_stop(&sc->sc_watchdog_ch); - - /* do it in a process context */ - sc->sc_state = nstate; - sc->sc_arg = arg; - - if (nstate == IEEE80211_S_INIT) { - zvp->newstate(vap, nstate, arg); - return (0); - } else { - usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); - return (EINPROGRESS); - } -} - -static int -zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, - void *odata, int olen, u_int flags) -{ - usbd_xfer_handle xfer; - struct zyd_cmd cmd; - struct zyd_rq rq; - uint16_t xferflags; - usbd_status error; - - if (sc->sc_flags & ZYD_FLAG_DETACHING) - return (ENXIO); - - if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) - return (ENOMEM); - - cmd.code = htole16(code); - bcopy(idata, cmd.data, ilen); - - xferflags = USBD_FORCE_SHORT_XFER; - if (!(flags & ZYD_CMD_FLAG_READ)) - xferflags |= USBD_SYNCHRONOUS; - else { - rq.idata = idata; - rq.odata = odata; - rq.len = olen / sizeof(struct zyd_pair); - STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq); - } - - usbd_setup_xfer(xfer, sc->sc_ep[ZYD_ENDPT_IOUT], 0, &cmd, - sizeof(uint16_t) + ilen, xferflags, ZYD_INTR_TIMEOUT, NULL); - error = usbd_transfer(xfer); - if (error != USBD_IN_PROGRESS && error != 0) { - device_printf(sc->sc_dev, "could not send command (error=%s)\n", - usbd_errstr(error)); - (void)usbd_free_xfer(xfer); - return (EIO); - } - if (!(flags & ZYD_CMD_FLAG_READ)) { - (void)usbd_free_xfer(xfer); - return (0); /* write: don't wait for reply */ - } - /* wait at most one second for command reply */ - error = tsleep(odata, PCATCH, "zydcmd", hz); - if (error == EWOULDBLOCK) - device_printf(sc->sc_dev, "zyd_read sleep timeout\n"); - STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq); - - (void)usbd_free_xfer(xfer); - return (error); -} - -static int -zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val) -{ - struct zyd_pair tmp; - int error; - - reg = htole16(reg); - error = zyd_cmd(sc, ZYD_CMD_IORD, ®, sizeof(reg), &tmp, sizeof(tmp), - ZYD_CMD_FLAG_READ); - if (error == 0) - *val = le16toh(tmp.val); - return (error); -} - -static int -zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val) -{ - struct zyd_pair tmp[2]; - uint16_t regs[2]; - int error; - - regs[0] = htole16(ZYD_REG32_HI(reg)); - regs[1] = htole16(ZYD_REG32_LO(reg)); - error = zyd_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), tmp, sizeof(tmp), - ZYD_CMD_FLAG_READ); - if (error == 0) - *val = le16toh(tmp[0].val) << 16 | le16toh(tmp[1].val); - return (error); -} - -static int -zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val) -{ - struct zyd_pair pair; - - pair.reg = htole16(reg); - pair.val = htole16(val); - - return zyd_cmd(sc, ZYD_CMD_IOWR, &pair, sizeof(pair), NULL, 0, 0); -} - -static int -zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val) -{ - struct zyd_pair pair[2]; - - pair[0].reg = htole16(ZYD_REG32_HI(reg)); - pair[0].val = htole16(val >> 16); - pair[1].reg = htole16(ZYD_REG32_LO(reg)); - pair[1].val = htole16(val & 0xffff); - - return zyd_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); -} - -static int -zyd_rfwrite(struct zyd_softc *sc, uint32_t val) -{ - struct zyd_rf *rf = &sc->sc_rf; - struct zyd_rfwrite_cmd req; - uint16_t cr203; - int error, i; - - zyd_read16_m(sc, ZYD_CR203, &cr203); - cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA); - - req.code = htole16(2); - req.width = htole16(rf->width); - for (i = 0; i < rf->width; i++) { - req.bit[i] = htole16(cr203); - if (val & (1 << (rf->width - 1 - i))) - req.bit[i] |= htole16(ZYD_RF_DATA); - } - error = zyd_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width, NULL, 0, 0); -fail: - return (error); -} - -static int -zyd_rfwrite_cr(struct zyd_softc *sc, uint32_t val) -{ - int error; - - zyd_write16_m(sc, ZYD_CR244, (val >> 16) & 0xff); - zyd_write16_m(sc, ZYD_CR243, (val >> 8) & 0xff); - zyd_write16_m(sc, ZYD_CR242, (val >> 0) & 0xff); -fail: - return (error); -} - -static int -zyd_lock_phy(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); - tmp &= ~ZYD_UNLOCK_PHY_REGS; - zyd_write32_m(sc, ZYD_MAC_MISC, tmp); -fail: - return (error); -} - -static int -zyd_unlock_phy(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); - tmp |= ZYD_UNLOCK_PHY_REGS; - zyd_write32_m(sc, ZYD_MAC_MISC, tmp); -fail: - return (error); -} - -/* - * RFMD RF methods. - */ -static int -zyd_rfmd_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY; - static const uint32_t rfini[] = ZYD_RFMD_RF; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) { - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - } - - /* init RFMD radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } -fail: - return (error); -#undef N -} - -static int -zyd_rfmd_switch_radio(struct zyd_rf *rf, int on) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - - zyd_write16_m(sc, ZYD_CR10, on ? 0x89 : 0x15); - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x81); -fail: - return (error); -} - -static int -zyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_RFMD_CHANTABLE; - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - -fail: - return (error); -} - -/* - * AL2230 RF methods. - */ -static int -zyd_al2230_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY; - static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; - static const struct zyd_phy_pair phypll[] = { - { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } - }; - static const uint32_t rfini1[] = ZYD_AL2230_RF_PART1; - static const uint32_t rfini2[] = ZYD_AL2230_RF_PART2; - static const uint32_t rfini3[] = ZYD_AL2230_RF_PART3; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { - for (i = 0; i < N(phy2230s); i++) - zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); - } - - /* init AL2230 radio */ - for (i = 0; i < N(rfini1); i++) { - error = zyd_rfwrite(sc, rfini1[i]); - if (error != 0) - goto fail; - } - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) - error = zyd_rfwrite(sc, 0x000824); - else - error = zyd_rfwrite(sc, 0x0005a4); - if (error != 0) - goto fail; - - for (i = 0; i < N(rfini2); i++) { - error = zyd_rfwrite(sc, rfini2[i]); - if (error != 0) - goto fail; - } - - for (i = 0; i < N(phypll); i++) - zyd_write16_m(sc, phypll[i].reg, phypll[i].val); - - for (i = 0; i < N(rfini3); i++) { - error = zyd_rfwrite(sc, rfini3[i]); - if (error != 0) - goto fail; - } -fail: - return (error); -#undef N -} - -static int -zyd_al2230_fini(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy[] = ZYD_AL2230_PHY_FINI_PART1; - - for (i = 0; i < N(phy); i++) - zyd_write16_m(sc, phy[i].reg, phy[i].val); - - if (sc->sc_newphy != 0) - zyd_write16_m(sc, ZYD_CR9, 0xe1); - - zyd_write16_m(sc, ZYD_CR203, 0x6); -fail: - return (error); -#undef N -} - -static int -zyd_al2230_init_b(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; - static const struct zyd_phy_pair phy2[] = ZYD_AL2230_PHY_PART2; - static const struct zyd_phy_pair phy3[] = ZYD_AL2230_PHY_PART3; - static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; - static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B; - static const uint32_t rfini_part1[] = ZYD_AL2230_RF_B_PART1; - static const uint32_t rfini_part2[] = ZYD_AL2230_RF_B_PART2; - static const uint32_t rfini_part3[] = ZYD_AL2230_RF_B_PART3; - static const uint32_t zyd_al2230_chtable[][3] = ZYD_AL2230_CHANTABLE; - int i, error; - - for (i = 0; i < N(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { - for (i = 0; i < N(phy2230s); i++) - zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); - } - - for (i = 0; i < 3; i++) { - error = zyd_rfwrite_cr(sc, zyd_al2230_chtable[0][i]); - if (error != 0) - return (error); - } - - for (i = 0; i < N(rfini_part1); i++) { - error = zyd_rfwrite_cr(sc, rfini_part1[i]); - if (error != 0) - return (error); - } - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) - error = zyd_rfwrite(sc, 0x241000); - else - error = zyd_rfwrite(sc, 0x25a000); - if (error != 0) - goto fail; - - for (i = 0; i < N(rfini_part2); i++) { - error = zyd_rfwrite_cr(sc, rfini_part2[i]); - if (error != 0) - return (error); - } - - for (i = 0; i < N(phy2); i++) - zyd_write16_m(sc, phy2[i].reg, phy2[i].val); - - for (i = 0; i < N(rfini_part3); i++) { - error = zyd_rfwrite_cr(sc, rfini_part3[i]); - if (error != 0) - return (error); - } - - for (i = 0; i < N(phy3); i++) - zyd_write16_m(sc, phy3[i].reg, phy3[i].val); - - error = zyd_al2230_fini(rf); -fail: - return (error); -#undef N -} - -static int -zyd_al2230_switch_radio(struct zyd_rf *rf, int on) -{ - struct zyd_softc *sc = rf->rf_sc; - int error, on251 = (sc->sc_macrev == ZYD_ZD1211) ? 0x3f : 0x7f; - - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); - zyd_write16_m(sc, ZYD_CR251, on ? on251 : 0x2f); -fail: - return (error); -} - -static int -zyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = { - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 }, - }; - static const struct { - uint32_t r1, r2, r3; - } rfprog[] = ZYD_AL2230_CHANTABLE; - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r3); - if (error != 0) - goto fail; - - for (i = 0; i < N(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); -fail: - return (error); -#undef N -} - -static int -zyd_al2230_set_channel_b(struct zyd_rf *rf, uint8_t chan) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; - static const struct { - uint32_t r1, r2, r3; - } rfprog[] = ZYD_AL2230_CHANTABLE_B; - - for (i = 0; i < N(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); - - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r3); - if (error != 0) - goto fail; - error = zyd_al2230_fini(rf); -fail: - return (error); -#undef N -} - -#define ZYD_AL2230_PHY_BANDEDGE6 \ -{ \ - { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ - { ZYD_CR47, 0x1e } \ -} - -static int -zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - int error = 0, i; - struct zyd_softc *sc = rf->rf_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6; - u_int chan = ieee80211_chan2ieee(ic, c); - - if (chan == 1 || chan == 11) - r[0].val = 0x12; - - for (i = 0; i < N(r); i++) - zyd_write16_m(sc, r[i].reg, r[i].val); -fail: - return (error); -#undef N -} - -/* - * AL7230B RF methods. - */ -static int -zyd_al7230B_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1; - static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2; - static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3; - static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1; - static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2; - int i, error; - - /* for AL7230B, PHY and RF need to be initialized in "phases" */ - - /* init RF-dependent PHY registers, part one */ - for (i = 0; i < N(phyini_1); i++) - zyd_write16_m(sc, phyini_1[i].reg, phyini_1[i].val); - - /* init AL7230B radio, part one */ - for (i = 0; i < N(rfini_1); i++) { - if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0) - return (error); - } - /* init RF-dependent PHY registers, part two */ - for (i = 0; i < N(phyini_2); i++) - zyd_write16_m(sc, phyini_2[i].reg, phyini_2[i].val); - - /* init AL7230B radio, part two */ - for (i = 0; i < N(rfini_2); i++) { - if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0) - return (error); - } - /* init RF-dependent PHY registers, part three */ - for (i = 0; i < N(phyini_3); i++) - zyd_write16_m(sc, phyini_3[i].reg, phyini_3[i].val); -fail: - return (error); -#undef N -} - -static int -zyd_al7230B_switch_radio(struct zyd_rf *rf, int on) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); - zyd_write16_m(sc, ZYD_CR251, on ? 0x3f : 0x2f); -fail: - return (error); -} - -static int -zyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_AL7230B_CHANTABLE; - static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL; - int i, error; - - zyd_write16_m(sc, ZYD_CR240, 0x57); - zyd_write16_m(sc, ZYD_CR251, 0x2f); - - for (i = 0; i < N(rfsc); i++) { - if ((error = zyd_rfwrite(sc, rfsc[i])) != 0) - return (error); - } - - zyd_write16_m(sc, ZYD_CR128, 0x14); - zyd_write16_m(sc, ZYD_CR129, 0x12); - zyd_write16_m(sc, ZYD_CR130, 0x10); - zyd_write16_m(sc, ZYD_CR38, 0x38); - zyd_write16_m(sc, ZYD_CR136, 0xdf); - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, 0x3c9000); - if (error != 0) - goto fail; - - zyd_write16_m(sc, ZYD_CR251, 0x3f); - zyd_write16_m(sc, ZYD_CR203, 0x06); - zyd_write16_m(sc, ZYD_CR240, 0x08); -fail: - return (error); -#undef N -} - -/* - * AL2210 RF methods. - */ -static int -zyd_al2210_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY; - static const uint32_t rfini[] = ZYD_AL2210_RF; - uint32_t tmp; - int i, error; - - zyd_write32_m(sc, ZYD_CR18, 2); - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - /* init AL2210 radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_write32_m(sc, ZYD_CR18, 3); -fail: - return (error); -#undef N -} - -static int -zyd_al2210_switch_radio(struct zyd_rf *rf, int on) -{ - /* vendor driver does nothing for this RF chip */ - - return (0); -} - -static int -zyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE; - uint32_t tmp; - - zyd_write32_m(sc, ZYD_CR18, 2); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - - /* actually set the channel */ - error = zyd_rfwrite(sc, rfprog[chan - 1]); - if (error != 0) - goto fail; - - zyd_write32_m(sc, ZYD_CR18, 3); -fail: - return (error); -} - -/* - * GCT RF methods. - */ -static int -zyd_gct_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; - static const uint32_t rfini[] = ZYD_GCT_RF; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - /* init cgt radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } -fail: - return (error); -#undef N -} - -static int -zyd_gct_switch_radio(struct zyd_rf *rf, int on) -{ - /* vendor driver does nothing for this RF chip */ - - return (0); -} - -static int -zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE; - - error = zyd_rfwrite(sc, 0x1c0000); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1]); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, 0x1c0008); -fail: - return (error); -} - -/* - * Maxim RF methods. - */ -static int -zyd_maxim_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; - static const uint32_t rfini[] = ZYD_MAXIM_RF; - uint16_t tmp; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* init maxim radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -#undef N -} - -static int -zyd_maxim_switch_radio(struct zyd_rf *rf, int on) -{ - - /* vendor driver does nothing for this RF chip */ - return (0); -} - -static int -zyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; - static const uint32_t rfini[] = ZYD_MAXIM_RF; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_MAXIM_CHANTABLE; - uint16_t tmp; - int i, error; - - /* - * Do the same as we do when initializing it, except for the channel - * values coming from the two channel tables. - */ - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* first two values taken from the chantables */ - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - - /* init maxim radio - skipping the two first values */ - for (i = 2; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -#undef N -} - -/* - * Maxim2 RF methods. - */ -static int -zyd_maxim2_init(struct zyd_rf *rf) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; - static const uint32_t rfini[] = ZYD_MAXIM2_RF; - uint16_t tmp; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* init maxim2 radio */ - for (i = 0; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -#undef N -} - -static int -zyd_maxim2_switch_radio(struct zyd_rf *rf, int on) -{ - - /* vendor driver does nothing for this RF chip */ - return (0); -} - -static int -zyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan) -{ -#define N(a) (sizeof(a) / sizeof((a)[0])) - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; - static const uint32_t rfini[] = ZYD_MAXIM2_RF; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_MAXIM2_CHANTABLE; - uint16_t tmp; - int i, error; - - /* - * Do the same as we do when initializing it, except for the channel - * values coming from the two channel tables. - */ - - /* init RF-dependent PHY registers */ - for (i = 0; i < N(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* first two values taken from the chantables */ - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - - /* init maxim2 radio - skipping the two first values */ - for (i = 2; i < N(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -#undef N -} - -static int -zyd_rf_attach(struct zyd_softc *sc, uint8_t type) -{ - struct zyd_rf *rf = &sc->sc_rf; - - rf->rf_sc = sc; - - switch (type) { - case ZYD_RF_RFMD: - rf->init = zyd_rfmd_init; - rf->switch_radio = zyd_rfmd_switch_radio; - rf->set_channel = zyd_rfmd_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL2230: - case ZYD_RF_AL2230S: - if (sc->sc_macrev == ZYD_ZD1211B) { - rf->init = zyd_al2230_init_b; - rf->set_channel = zyd_al2230_set_channel_b; - } else { - rf->init = zyd_al2230_init; - rf->set_channel = zyd_al2230_set_channel; - } - rf->switch_radio = zyd_al2230_switch_radio; - rf->bandedge6 = zyd_al2230_bandedge6; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL7230B: - rf->init = zyd_al7230B_init; - rf->switch_radio = zyd_al7230B_switch_radio; - rf->set_channel = zyd_al7230B_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL2210: - rf->init = zyd_al2210_init; - rf->switch_radio = zyd_al2210_switch_radio; - rf->set_channel = zyd_al2210_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_GCT: - rf->init = zyd_gct_init; - rf->switch_radio = zyd_gct_switch_radio; - rf->set_channel = zyd_gct_set_channel; - rf->width = 21; /* 21-bit RF values */ - break; - case ZYD_RF_MAXIM_NEW: - rf->init = zyd_maxim_init; - rf->switch_radio = zyd_maxim_switch_radio; - rf->set_channel = zyd_maxim_set_channel; - rf->width = 18; /* 18-bit RF values */ - break; - case ZYD_RF_MAXIM_NEW2: - rf->init = zyd_maxim2_init; - rf->switch_radio = zyd_maxim2_switch_radio; - rf->set_channel = zyd_maxim2_set_channel; - rf->width = 18; /* 18-bit RF values */ - break; - default: - device_printf(sc->sc_dev, - "sorry, radio \"%s\" is not supported yet\n", - zyd_rf_name(type)); - return (EINVAL); - } - return (0); -} - -static const char * -zyd_rf_name(uint8_t type) -{ - static const char * const zyd_rfs[] = { - "unknown", "unknown", "UW2451", "UCHIP", "AL2230", - "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT", - "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2", - "PHILIPS" - }; - - return zyd_rfs[(type > 15) ? 0 : type]; -} - -static int -zyd_hw_init(struct zyd_softc *sc) -{ - int error; - const struct zyd_phy_pair *phyp; - struct zyd_rf *rf = &sc->sc_rf; - uint16_t val; - - /* specify that the plug and play is finished */ - zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); - zyd_read16_m(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->sc_fwbase); - DPRINTF(sc, ZYD_DEBUG_FW, "firmware base address=0x%04x\n", - sc->sc_fwbase); - - /* retrieve firmware revision number */ - zyd_read16_m(sc, sc->sc_fwbase + ZYD_FW_FIRMWARE_REV, &sc->sc_fwrev); - zyd_write32_m(sc, ZYD_CR_GPI_EN, 0); - zyd_write32_m(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f); - /* set mandatory rates - XXX assumes 802.11b/g */ - zyd_write32_m(sc, ZYD_MAC_MAN_RATE, 0x150f); - - /* disable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); - - if ((error = zyd_read_pod(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - goto fail; - } - - /* PHY init (resetting) */ - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - phyp = (sc->sc_macrev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy; - for (; phyp->reg != 0; phyp++) - zyd_write16_m(sc, phyp->reg, phyp->val); - if (sc->sc_macrev == ZYD_ZD1211 && sc->sc_fix_cr157 != 0) { - zyd_read16_m(sc, ZYD_EEPROM_PHY_REG, &val); - zyd_write32_m(sc, ZYD_CR157, val >> 8); - } - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - /* HMAC init */ - zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000020); - zyd_write32_m(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808); - zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_GHTBL, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_GHTBH, 0x80000000); - zyd_write32_m(sc, ZYD_MAC_MISC, 0x000000a4); - zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f); - zyd_write32_m(sc, ZYD_MAC_BCNCFG, 0x00f00401); - zyd_write32_m(sc, ZYD_MAC_PHY_DELAY2, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000080); - zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100); - zyd_write32_m(sc, ZYD_CR_RX_PE_DELAY, 0x00000070); - zyd_write32_m(sc, ZYD_CR_PS_CTRL, 0x10000000); - zyd_write32_m(sc, ZYD_MAC_RTSCTSRATE, 0x02030203); - zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); - zyd_write32_m(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114); - zyd_write32_m(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0a47c032); - zyd_write32_m(sc, ZYD_MAC_CAM_MODE, 0x3); - - if (sc->sc_macrev == ZYD_ZD1211) { - zyd_write32_m(sc, ZYD_MAC_RETRY, 0x00000002); - zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640); - } else { - zyd_write32_m(sc, ZYD_MACB_MAX_RETRY, 0x02020202); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); - zyd_write32_m(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); - zyd_write32_m(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); - zyd_write32_m(sc, ZYD_MACB_TXOP, 0x01800824); - zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0eff); - } - - /* init beacon interval to 100ms */ - if ((error = zyd_set_beacon_interval(sc, 100)) != 0) - goto fail; - - if ((error = zyd_rf_attach(sc, sc->sc_rfrev)) != 0) { - device_printf(sc->sc_dev, "could not attach RF, rev 0x%x\n", - sc->sc_rfrev); - goto fail; - } - - /* RF chip init */ - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - error = (*rf->init)(rf); - if (error != 0) { - device_printf(sc->sc_dev, - "radio initialization failed, error %d\n", error); - goto fail; - } - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - if ((error = zyd_read_eeprom(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - goto fail; - } - -fail: return (error); -} - -static int -zyd_read_pod(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_EEPROM_POD, &tmp); - sc->sc_rfrev = tmp & 0x0f; - sc->sc_ledtype = (tmp >> 4) & 0x01; - sc->sc_al2230s = (tmp >> 7) & 0x01; - sc->sc_cckgain = (tmp >> 8) & 0x01; - sc->sc_fix_cr157 = (tmp >> 13) & 0x01; - sc->sc_parev = (tmp >> 16) & 0x0f; - sc->sc_bandedge6 = (tmp >> 21) & 0x01; - sc->sc_newphy = (tmp >> 31) & 0x01; - sc->sc_txled = ((tmp & (1 << 24)) && (tmp & (1 << 29))) ? 0 : 1; -fail: - return (error); -} - -static int -zyd_read_eeprom(struct zyd_softc *sc) -{ - uint16_t val; - int error, i; - - /* read Tx power calibration tables */ - for (i = 0; i < 7; i++) { - zyd_read16_m(sc, ZYD_EEPROM_PWR_CAL + i, &val); - sc->sc_pwrcal[i * 2] = val >> 8; - sc->sc_pwrcal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_PWR_INT + i, &val); - sc->sc_pwrint[i * 2] = val >> 8; - sc->sc_pwrint[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_36M_CAL + i, &val); - sc->sc_ofdm36_cal[i * 2] = val >> 8; - sc->sc_ofdm36_cal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_48M_CAL + i, &val); - sc->sc_ofdm48_cal[i * 2] = val >> 8; - sc->sc_ofdm48_cal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_54M_CAL + i, &val); - sc->sc_ofdm54_cal[i * 2] = val >> 8; - sc->sc_ofdm54_cal[i * 2 + 1] = val & 0xff; - } -fail: - return (error); -} - -static int -zyd_get_macaddr(struct zyd_softc *sc) -{ - usb_device_request_t req; - usbd_status error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = ZYD_READFWDATAREQ; - USETW(req.wValue, ZYD_EEPROM_MAC_ADDR_P1); - USETW(req.wIndex, 0); - USETW(req.wLength, IEEE80211_ADDR_LEN); - - error = usbd_do_request(sc->sc_udev, &req, sc->sc_bssid); - if (error != 0) { - device_printf(sc->sc_dev, "could not read EEPROM: %s\n", - usbd_errstr(error)); - } - - return (error); -} - -static int -zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr) -{ - int error; - uint32_t tmp; - - tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; - zyd_write32_m(sc, ZYD_MAC_MACADRL, tmp); - tmp = addr[5] << 8 | addr[4]; - zyd_write32_m(sc, ZYD_MAC_MACADRH, tmp); -fail: - return (error); -} - -static int -zyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr) -{ - int error; - uint32_t tmp; - - tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; - zyd_write32_m(sc, ZYD_MAC_BSSADRL, tmp); - tmp = addr[5] << 8 | addr[4]; - zyd_write32_m(sc, ZYD_MAC_BSSADRH, tmp); -fail: - return (error); -} - -static int -zyd_switch_radio(struct zyd_softc *sc, int on) -{ - struct zyd_rf *rf = &sc->sc_rf; - int error; - - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - error = (*rf->switch_radio)(rf, on); - if (error != 0) - goto fail; - error = zyd_unlock_phy(sc); -fail: - return (error); -} - -static int -zyd_set_led(struct zyd_softc *sc, int which, int on) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_TX_PE_CONTROL, &tmp); - tmp &= ~which; - if (on) - tmp |= which; - zyd_write32_m(sc, ZYD_MAC_TX_PE_CONTROL, tmp); -fail: - return (error); -} - -static void -zyd_set_multi(void *arg) -{ - int error; - struct zyd_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ifmultiaddr *ifma; - uint32_t low, high; - uint8_t v; - - if (!(ifp->if_flags & IFF_UP)) - return; - - low = 0x00000000; - high = 0x80000000; - - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { - low = 0xffffffff; - high = 0xffffffff; - } else { - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - v = ((uint8_t *)LLADDR((struct sockaddr_dl *) - ifma->ifma_addr))[5] >> 2; - if (v < 32) - low |= 1 << v; - else - high |= 1 << (v - 32); - } - IF_ADDR_UNLOCK(ifp); - } - - /* reprogram multicast global hash table */ - zyd_write32_m(sc, ZYD_MAC_GHTBL, low); - zyd_write32_m(sc, ZYD_MAC_GHTBH, high); -fail: - if (error != 0) - device_printf(sc->sc_dev, - "could not set multicast hash table\n"); -} - -static void -zyd_update_mcast(struct ifnet *ifp) -{ - struct zyd_softc *sc = ifp->if_softc; - - if (!(sc->sc_flags & ZYD_FLAG_INITDONE)) - return; - - usb_add_task(sc->sc_udev, &sc->sc_mcasttask, USB_TASKQ_DRIVER); -} - -static int -zyd_set_rxfilter(struct zyd_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t rxfilter; - - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - rxfilter = ZYD_FILTER_BSS; - break; - case IEEE80211_M_IBSS: - case IEEE80211_M_HOSTAP: - rxfilter = ZYD_FILTER_HOSTAP; - break; - case IEEE80211_M_MONITOR: - rxfilter = ZYD_FILTER_MONITOR; - break; - default: - /* should not get there */ - return (EINVAL); - } - return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter); -} - -static void -zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) -{ - int error; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct zyd_rf *rf = &sc->sc_rf; - uint32_t tmp; - u_int chan; - - chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) { - /* XXX should NEVER happen */ - device_printf(sc->sc_dev, - "%s: invalid channel %x\n", __func__, chan); - return; - } - - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - - error = (*rf->set_channel)(rf, chan); - if (error != 0) - goto fail; - - /* update Tx power */ - zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); - - if (sc->sc_macrev == ZYD_ZD1211B) { - zyd_write16_m(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); - zyd_write16_m(sc, ZYD_CR69, 0x28); - zyd_write16_m(sc, ZYD_CR69, 0x2a); - } - if (sc->sc_cckgain) { - /* set CCK baseband gain from EEPROM */ - if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) - zyd_write16_m(sc, ZYD_CR47, tmp & 0xff); - } - if (sc->sc_bandedge6 && rf->bandedge6 != NULL) { - error = (*rf->bandedge6)(rf, c); - if (error != 0) - goto fail; - } - zyd_write32_m(sc, ZYD_CR_CONFIG_PHILIPS, 0); - - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq = - htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = sc->sc_txtap.wt_chan_flags = - htole16(c->ic_flags); -fail: - return; -} - -static int -zyd_set_beacon_interval(struct zyd_softc *sc, int bintval) -{ - int error; - uint32_t val; - - zyd_read32_m(sc, ZYD_CR_ATIM_WND_PERIOD, &val); - sc->sc_atim_wnd = val; - zyd_read32_m(sc, ZYD_CR_PRE_TBTT, &val); - sc->sc_pre_tbtt = val; - sc->sc_bcn_int = bintval; - - if (sc->sc_bcn_int <= 5) - sc->sc_bcn_int = 5; - if (sc->sc_pre_tbtt < 4 || sc->sc_pre_tbtt >= sc->sc_bcn_int) - sc->sc_pre_tbtt = sc->sc_bcn_int - 1; - if (sc->sc_atim_wnd >= sc->sc_pre_tbtt) - sc->sc_atim_wnd = sc->sc_pre_tbtt - 1; - - zyd_write32_m(sc, ZYD_CR_ATIM_WND_PERIOD, sc->sc_atim_wnd); - zyd_write32_m(sc, ZYD_CR_PRE_TBTT, sc->sc_pre_tbtt); - zyd_write32_m(sc, ZYD_CR_BCN_INTERVAL, sc->sc_bcn_int); -fail: - return (error); -} - -static void -zyd_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct zyd_softc *sc = (struct zyd_softc *)priv; - struct zyd_cmd *cmd; - uint32_t datalen; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - if (status == USBD_STALLED) { - usbd_clear_endpoint_stall_async( - sc->sc_ep[ZYD_ENDPT_IIN]); - } - return; - } - - cmd = (struct zyd_cmd *)sc->sc_ibuf; - - if (le16toh(cmd->code) == ZYD_NOTIF_RETRYSTATUS) { - struct zyd_notif_retry *retry = - (struct zyd_notif_retry *)cmd->data; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni; - - DPRINTF(sc, ZYD_DEBUG_TX_PROC, - "retry intr: rate=0x%x addr=%s count=%d (0x%x)\n", - le16toh(retry->rate), ether_sprintf(retry->macaddr), - le16toh(retry->count) & 0xff, le16toh(retry->count)); - - /* - * Find the node to which the packet was sent and update its - * retry statistics. In BSS mode, this node is the AP we're - * associated to so no lookup is actually needed. - */ - ni = ieee80211_find_txnode(vap, retry->macaddr); - if (ni != NULL) { - ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, - IEEE80211_AMRR_FAILURE, 1); - ieee80211_free_node(ni); - } - if (le16toh(retry->count) & 0x100) - ifp->if_oerrors++; /* too many retries */ - } else if (le16toh(cmd->code) == ZYD_NOTIF_IORD) { - struct zyd_rq *rqp; - - if (le16toh(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT) - return; /* HMAC interrupt */ - - usbd_get_xfer_status(xfer, NULL, NULL, &datalen, NULL); - datalen -= sizeof(cmd->code); - datalen -= 2; /* XXX: padding? */ - - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { - int i; - - if (sizeof(struct zyd_pair) * rqp->len != datalen) - continue; - for (i = 0; i < rqp->len; i++) { - if (*(((const uint16_t *)rqp->idata) + i) != - (((struct zyd_pair *)cmd->data) + i)->reg) - break; - } - if (i != rqp->len) - continue; - - /* copy answer into caller-supplied buffer */ - bcopy(cmd->data, rqp->odata, - sizeof(struct zyd_pair) * rqp->len); - wakeup(rqp->odata); /* wakeup caller */ - - return; - } - return; /* unexpected IORD notification */ - } else { - device_printf(sc->sc_dev, "unknown notification %x\n", - le16toh(cmd->code)); - } -} - -static void -zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_node *ni; - const struct zyd_plcphdr *plcp; - const struct zyd_rx_stat *stat; - struct mbuf *m; - int rlen, rssi, nf; - - if (len < ZYD_MIN_FRAGSZ) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", - device_get_nameunit(sc->sc_dev), len); - ifp->if_ierrors++; - return; - } - - plcp = (const struct zyd_plcphdr *)buf; - stat = (const struct zyd_rx_stat *) - (buf + len - sizeof(struct zyd_rx_stat)); - - if (stat->flags & ZYD_RX_ERROR) { - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: RX status indicated error (%x)\n", - device_get_nameunit(sc->sc_dev), stat->flags); - ifp->if_ierrors++; - return; - } - - /* compute actual frame length */ - rlen = len - sizeof(struct zyd_plcphdr) - - sizeof(struct zyd_rx_stat) - IEEE80211_CRC_LEN; - - /* allocate a mbuf to store the frame */ - if (rlen > MHLEN) - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - else - m = m_gethdr(M_DONTWAIT, MT_DATA); - if (m == NULL) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", - device_get_nameunit(sc->sc_dev)); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = rlen; - bcopy((const uint8_t *)(plcp + 1), mtod(m, uint8_t *), rlen); - - if (bpf_peers_present(ifp->if_bpf)) { - struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - if (stat->flags & (ZYD_RX_BADCRC16 | ZYD_RX_BADCRC32)) - tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - /* XXX toss, no way to express errors */ - if (stat->flags & ZYD_RX_DECRYPTERR) - tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - tap->wr_rate = ieee80211_plcp2rate(plcp->signal, - (stat->flags & ZYD_RX_OFDM) ? - IEEE80211_T_OFDM : IEEE80211_T_CCK); - tap->wr_antsignal = stat->rssi + -95; - tap->wr_antnoise = -95; /* XXX */ - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); - } - - rssi = stat->rssi > 63 ? 127 : 2 * stat->rssi; - nf = -95; /* XXX */ - - ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - (void)ieee80211_input(ni, m, rssi, nf, 0); - ieee80211_free_node(ni); - } else - (void)ieee80211_input_all(ic, m, rssi, nf, 0); -} - -static void -zyd_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct zyd_rx_data *data = priv; - struct zyd_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - const struct zyd_rx_desc *desc; - int len; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - if (status == USBD_STALLED) - usbd_clear_endpoint_stall(sc->sc_ep[ZYD_ENDPT_BIN]); - - goto skip; - } - usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); - - if (len < ZYD_MIN_RXBUFSZ) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: xfer too short (length=%d)\n", - device_get_nameunit(sc->sc_dev), len); - ifp->if_ierrors++; /* XXX not really errors */ - goto skip; - } - - desc = (const struct zyd_rx_desc *) - (data->buf + len - sizeof(struct zyd_rx_desc)); - - if (UGETW(desc->tag) == ZYD_TAG_MULTIFRAME) { - const uint8_t *p = data->buf, *end = p + len; - int i; - - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: received multi-frame transfer\n", __func__); - - for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) { - const uint16_t len16 = UGETW(desc->len[i]); - - if (len16 == 0 || p + len16 > end) - break; - - zyd_rx_data(sc, p, len16); - /* next frame is aligned on a 32-bit boundary */ - p += (len16 + 3) & ~3; - } - } else { - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: received single-frame transfer\n", __func__); - - zyd_rx_data(sc, data->buf, len); - } - -skip: /* setup a new transfer */ - usbd_setup_xfer(xfer, sc->sc_ep[ZYD_ENDPT_BIN], data, NULL, - ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, zyd_rxeof); - (void)usbd_transfer(xfer); -} - -static uint8_t -zyd_plcp_signal(int rate) -{ - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: - return (0xb); - case 18: - return (0xf); - case 24: - return (0xa); - case 36: - return (0xe); - case 48: - return (0x9); - case 72: - return (0xd); - case 96: - return (0x8); - case 108: - return (0xc); - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: - return (0x0); - case 4: - return (0x1); - case 11: - return (0x2); - case 22: - return (0x3); - } - return (0xff); /* XXX unsupported/unknown rate */ -} - -static int -zyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = sc->sc_ifp; - struct zyd_tx_desc *desc; - struct zyd_tx_data *data; - struct ieee80211_frame *wh; - struct ieee80211_key *k; - int data_idx, rate, totlen, xferlen; - uint16_t pktlen; - usbd_status error; - - data_idx = sc->sc_txidx; - sc->sc_txidx = (sc->sc_txidx + 1) % ZYD_TX_LIST_CNT; - - data = &sc->sc_txdata[data_idx]; - desc = (struct zyd_tx_desc *)data->buf; - - rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; - - wh = mtod(m0, struct ieee80211_frame *); - - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return (ENOBUFS); - } - } - - data->ni = ni; - data->m = m0; - - wh = mtod(m0, struct ieee80211_frame *); - - xferlen = sizeof(struct zyd_tx_desc) + m0->m_pkthdr.len; - totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; - - /* fill Tx descriptor */ - desc->len = htole16(totlen); - - desc->flags = ZYD_TX_FLAG_BACKOFF; - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - /* multicast frames are not sent at OFDM rates in 802.11b/g */ - if (totlen > vap->iv_rtsthreshold) { - desc->flags |= ZYD_TX_FLAG_RTS; - } else if (ZYD_RATE_IS_OFDM(rate) && - (ic->ic_flags & IEEE80211_F_USEPROT)) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) - desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; - else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) - desc->flags |= ZYD_TX_FLAG_RTS; - } - } else - desc->flags |= ZYD_TX_FLAG_MULTICAST; - - if ((wh->i_fc[0] & - (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == - (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) - desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); - - desc->phy = zyd_plcp_signal(rate); - if (ZYD_RATE_IS_OFDM(rate)) { - desc->phy |= ZYD_TX_PHY_OFDM; - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - desc->phy |= ZYD_TX_PHY_5GHZ; - } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->phy |= ZYD_TX_PHY_SHPREAMBLE; - - /* actual transmit length (XXX why +10?) */ - pktlen = sizeof(struct zyd_tx_desc) + 10; - if (sc->sc_macrev == ZYD_ZD1211) - pktlen += totlen; - desc->pktlen = htole16(pktlen); - - desc->plcp_length = (16 * totlen + rate - 1) / rate; - desc->plcp_service = 0; - if (rate == 22) { - const int remainder = (16 * totlen) % 22; - if (remainder != 0 && remainder < 7) - desc->plcp_service |= ZYD_PLCP_LENGEXT; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, - data->buf + sizeof(struct zyd_tx_desc)); - - DPRINTF(sc, ZYD_DEBUG_XMIT, - "%s: sending mgt frame len=%zu rate=%u xferlen=%u\n", - device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, - rate, xferlen); - - usbd_setup_xfer(data->xfer, sc->sc_ep[ZYD_ENDPT_BOUT], data, - data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, - ZYD_TX_TIMEOUT, zyd_txeof); - error = usbd_transfer(data->xfer); - if (error != USBD_IN_PROGRESS && error != 0) { - ifp->if_oerrors++; - return (EIO); - } - sc->sc_txqueued++; - - return (0); -} - -static void -zyd_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct zyd_tx_data *data = priv; - struct zyd_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211_node *ni; - struct mbuf *m; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_dev, "could not transmit buffer: %s\n", - usbd_errstr(status)); - - if (status == USBD_STALLED) { - usbd_clear_endpoint_stall_async( - sc->sc_ep[ZYD_ENDPT_BOUT]); - } - ifp->if_oerrors++; - return; - } - - ni = data->ni; - /* update rate control statistics */ - ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, - IEEE80211_AMRR_SUCCESS, 0); - - /* - * Do any tx complete callback. Note this must - * be done before releasing the node reference. - */ - m = data->m; - if (m != NULL && m->m_flags & M_TXCB) { - ieee80211_process_callback(ni, m, 0); /* XXX status? */ - m_freem(m); - data->m = NULL; - } - - ieee80211_free_node(ni); - data->ni = NULL; - - ZYD_TX_LOCK(sc); - sc->sc_txqueued--; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ZYD_TX_UNLOCK(sc); - - ifp->if_opackets++; - sc->sc_txtimer = 0; - zyd_start(ifp); -} - -static int -zyd_tx_data(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = sc->sc_ifp; - struct zyd_tx_desc *desc; - struct zyd_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - int data_idx, rate, totlen, xferlen; - uint16_t pktlen; - usbd_status error; - - data_idx = sc->sc_txidx; - sc->sc_txidx = (sc->sc_txidx + 1) % ZYD_TX_LIST_CNT; - - wh = mtod(m0, struct ieee80211_frame *); - data = &sc->sc_txdata[data_idx]; - desc = (struct zyd_tx_desc *)data->buf; - - desc->flags = ZYD_TX_FLAG_BACKOFF; - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { - rate = tp->mcastrate; - desc->flags |= ZYD_TX_FLAG_MULTICAST; - } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { - rate = tp->ucastrate; - } else { - (void) ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn); - rate = ni->ni_txrate; - } - - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return (ENOBUFS); - } - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - data->ni = ni; - data->m = NULL; - - xferlen = sizeof(struct zyd_tx_desc) + m0->m_pkthdr.len; - totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; - - /* fill Tx descriptor */ - desc->len = htole16(totlen); - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - /* multicast frames are not sent at OFDM rates in 802.11b/g */ - if (totlen > vap->iv_rtsthreshold) { - desc->flags |= ZYD_TX_FLAG_RTS; - } else if (ZYD_RATE_IS_OFDM(rate) && - (ic->ic_flags & IEEE80211_F_USEPROT)) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) - desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; - else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) - desc->flags |= ZYD_TX_FLAG_RTS; - } - } - - if ((wh->i_fc[0] & - (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == - (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) - desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); - - desc->phy = zyd_plcp_signal(rate); - if (ZYD_RATE_IS_OFDM(rate)) { - desc->phy |= ZYD_TX_PHY_OFDM; - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - desc->phy |= ZYD_TX_PHY_5GHZ; - } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->phy |= ZYD_TX_PHY_SHPREAMBLE; - - /* actual transmit length (XXX why +10?) */ - pktlen = sizeof(struct zyd_tx_desc) + 10; - if (sc->sc_macrev == ZYD_ZD1211) - pktlen += totlen; - desc->pktlen = htole16(pktlen); - - desc->plcp_length = (16 * totlen + rate - 1) / rate; - desc->plcp_service = 0; - if (rate == 22) { - const int remainder = (16 * totlen) % 22; - if (remainder != 0 && remainder < 7) - desc->plcp_service |= ZYD_PLCP_LENGEXT; - } - - if (bpf_peers_present(ifp->if_bpf)) { - struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); - } - - m_copydata(m0, 0, m0->m_pkthdr.len, - data->buf + sizeof(struct zyd_tx_desc)); - - DPRINTF(sc, ZYD_DEBUG_XMIT, - "%s: sending data frame len=%zu rate=%u xferlen=%u\n", - device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, - rate, xferlen); - - m_freem(m0); /* mbuf no longer needed */ - - usbd_setup_xfer(data->xfer, sc->sc_ep[ZYD_ENDPT_BOUT], data, - data->buf, xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, - ZYD_TX_TIMEOUT, zyd_txeof); - error = usbd_transfer(data->xfer); - if (error != USBD_IN_PROGRESS && error != 0) { - ifp->if_oerrors++; - return (EIO); - } - sc->sc_txqueued++; - - return (0); -} - -static void -zyd_start(struct ifnet *ifp) -{ - struct zyd_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - ZYD_TX_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->sc_txqueued >= ZYD_TX_LIST_CNT) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m = ieee80211_encap(ni, m); - if (m == NULL) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - continue; - } - if (zyd_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - - sc->sc_txtimer = 5; - } - ZYD_TX_UNLOCK(sc); -} - -static int -zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct zyd_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return (ENETDOWN); - } - ZYD_TX_LOCK(sc); - if (sc->sc_txqueued >= ZYD_TX_LIST_CNT) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m); - ieee80211_free_node(ni); - return (ENOBUFS); /* XXX */ - } - - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - * XXX raw path - */ - if (zyd_tx_mgt(sc, m, ni) != 0) { - ZYD_TX_UNLOCK(sc); - ifp->if_oerrors++; - ieee80211_free_node(ni); - return (EIO); - } - - ZYD_TX_UNLOCK(sc); - ifp->if_opackets++; - sc->sc_txtimer = 5; - return (0); -} - -static void -zyd_watchdog(void *arg) -{ - struct zyd_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_txtimer > 0) { - if (--sc->sc_txtimer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - /* zyd_init(ifp); XXX needs a process context ? */ - ifp->if_oerrors++; - return; - } - callout_reset(&sc->sc_watchdog_ch, hz, zyd_watchdog, sc); - } -} - -static int -zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct zyd_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - ZYD_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & - (IFF_ALLMULTI | IFF_PROMISC)) - zyd_set_multi(sc); - } else { - zyd_init_locked(sc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - zyd_stop(sc, 1); - } - sc->sc_if_flags = ifp->if_flags; - ZYD_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - return (error); -} - -static void -zyd_init_locked(struct zyd_softc *sc) -{ - int error, i; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t val; - - if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) { - error = zyd_loadfirmware(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "could not load firmware (error=%d)\n", error); - goto fail; - } - - error = usbd_set_config_no(sc->sc_udev, ZYD_CONFIG_NO, 1); - if (error != 0) { - device_printf(sc->sc_dev, "setting config no failed\n"); - goto fail; - } - error = usbd_device2interface_handle(sc->sc_udev, - ZYD_IFACE_INDEX, &sc->sc_iface); - if (error != 0) { - device_printf(sc->sc_dev, - "getting interface handle failed\n"); - goto fail; - } - - if ((error = zyd_open_pipes(sc)) != 0) { - device_printf(sc->sc_dev, "could not open pipes\n"); - goto fail; - } - if ((error = zyd_hw_init(sc)) != 0) { - device_printf(sc->sc_dev, - "hardware initialization failed\n"); - goto fail; - } - - device_printf(sc->sc_dev, - "HMAC ZD1211%s, FW %02x.%02x, RF %s S%x, PA%x LED %x " - "BE%x NP%x Gain%x F%x\n", - (sc->sc_macrev == ZYD_ZD1211) ? "": "B", - sc->sc_fwrev >> 8, sc->sc_fwrev & 0xff, - zyd_rf_name(sc->sc_rfrev), sc->sc_al2230s, sc->sc_parev, - sc->sc_ledtype, sc->sc_bandedge6, sc->sc_newphy, - sc->sc_cckgain, sc->sc_fix_cr157); - - /* read regulatory domain (currently unused) */ - zyd_read32_m(sc, ZYD_EEPROM_SUBID, &val); - sc->sc_regdomain = val >> 16; - DPRINTF(sc, ZYD_DEBUG_INIT, "regulatory domain %x\n", - sc->sc_regdomain); - - /* we'll do software WEP decryption for now */ - DPRINTF(sc, ZYD_DEBUG_INIT, "%s: setting encryption type\n", - __func__); - zyd_write32_m(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER); - - sc->sc_flags |= ZYD_FLAG_INITONCE; - } - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - zyd_stop(sc, 0); - - /* reset softc variables. */ - sc->sc_txidx = 0; - - IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); - DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %s\n", - ether_sprintf(ic->ic_myaddr)); - error = zyd_set_macaddr(sc, ic->ic_myaddr); - if (error != 0) - return; - - /* set basic rates */ - if (ic->ic_curmode == IEEE80211_MODE_11B) - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x0003); - else if (ic->ic_curmode == IEEE80211_MODE_11A) - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x1500); - else /* assumes 802.11b/g */ - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0xff0f); - - /* promiscuous mode */ - zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0); - /* multicast setup */ - zyd_set_multi(sc); - /* set RX filter */ - error = zyd_set_rxfilter(sc); - if (error != 0) - goto fail; - - /* switch radio transmitter ON */ - error = zyd_switch_radio(sc, 1); - if (error != 0) - goto fail; - /* set default BSS channel */ - zyd_set_chan(sc, ic->ic_curchan); - - /* - * Allocate Tx and Rx xfer queues. - */ - if ((error = zyd_alloc_tx_list(sc)) != 0) { - device_printf(sc->sc_dev, "could not allocate Tx list\n"); - goto fail; - } - if ((error = zyd_alloc_rx_list(sc)) != 0) { - device_printf(sc->sc_dev, "could not allocate Rx list\n"); - goto fail; - } - - /* - * Start up the receive pipe. - */ - for (i = 0; i < ZYD_RX_LIST_CNT; i++) { - struct zyd_rx_data *data = &sc->sc_rxdata[i]; - - usbd_setup_xfer(data->xfer, sc->sc_ep[ZYD_ENDPT_BIN], data, - NULL, ZYX_MAX_RXBUFSZ, USBD_NO_COPY | USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, zyd_rxeof); - error = usbd_transfer(data->xfer); - if (error != USBD_IN_PROGRESS && error != 0) { - device_printf(sc->sc_dev, - "could not queue Rx transfer\n"); - goto fail; - } - } - - /* enable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->sc_flags |= ZYD_FLAG_INITDONE; - - callout_reset(&sc->sc_watchdog_ch, hz, zyd_watchdog, sc); - return; - -fail: zyd_stop(sc, 1); - return; -} - -static void -zyd_init(void *priv) -{ - struct zyd_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ZYD_LOCK(sc); - zyd_init_locked(sc); - ZYD_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -zyd_stop(struct zyd_softc *sc, int disable) -{ - int error; - struct ifnet *ifp = sc->sc_ifp; - - sc->sc_txtimer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - /* switch radio transmitter OFF */ - error = zyd_switch_radio(sc, 0); - if (error != 0) - goto fail; - /* disable Rx */ - zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0); - /* disable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - usb_rem_task(sc->sc_udev, &sc->sc_task); - callout_stop(&sc->sc_watchdog_ch); - - usbd_abort_pipe(sc->sc_ep[ZYD_ENDPT_BIN]); - usbd_abort_pipe(sc->sc_ep[ZYD_ENDPT_BOUT]); - - zyd_free_rx_list(sc); - zyd_free_tx_list(sc); -fail: - return; -} - -static int -zyd_loadfirmware(struct zyd_softc *sc) -{ - usb_device_request_t req; - size_t size; - u_char *fw; - uint8_t stat; - uint16_t addr; - - if (sc->sc_flags & ZYD_FLAG_FWLOADED) - return (0); - - if (sc->sc_macrev == ZYD_ZD1211) { - fw = (u_char *)zd1211_firmware; - size = sizeof(zd1211_firmware); - } else { - fw = (u_char *)zd1211b_firmware; - size = sizeof(zd1211b_firmware); - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = ZYD_DOWNLOADREQ; - USETW(req.wIndex, 0); - - addr = ZYD_FIRMWARE_START_ADDR; - while (size > 0) { - /* - * When the transfer size is 4096 bytes, it is not - * likely to be able to transfer it. - * The cause is port or machine or chip? - */ - const int mlen = min(size, 64); - - DPRINTF(sc, ZYD_DEBUG_FW, - "loading firmware block: len=%d, addr=0x%x\n", mlen, addr); - - USETW(req.wValue, addr); - USETW(req.wLength, mlen); - if (usbd_do_request(sc->sc_udev, &req, fw) != 0) - return (EIO); - - addr += mlen / 2; - fw += mlen; - size -= mlen; - } - - /* check whether the upload succeeded */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = ZYD_DOWNLOADSTS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(stat)); - if (usbd_do_request(sc->sc_udev, &req, &stat) != 0) - return (EIO); - - sc->sc_flags |= ZYD_FLAG_FWLOADED; - - return (stat & 0x80) ? (EIO) : (0); -} - -static void -zyd_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); -} - -static void -zyd_scan_start(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = ZYD_SCAN_START; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -zyd_scan_end(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - - /* do it in a process context */ - sc->sc_scan_action = ZYD_SCAN_END; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -zyd_set_channel(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - usb_rem_task(sc->sc_udev, &sc->sc_scantask); - /* do it in a process context */ - sc->sc_scan_action = ZYD_SET_CHANNEL; - usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER); -} - -static void -zyd_scantask(void *arg) -{ - struct zyd_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ZYD_LOCK(sc); - - switch (sc->sc_scan_action) { - case ZYD_SCAN_START: - /* want broadcast address while scanning */ - zyd_set_bssid(sc, ifp->if_broadcastaddr); - break; - case ZYD_SCAN_END: - /* restore previous bssid */ - zyd_set_bssid(sc, sc->sc_bssid); - break; - case ZYD_SET_CHANNEL: - zyd_set_chan(sc, ic->ic_curchan); - break; - default: - device_printf(sc->sc_dev, "unknown scan action %d\n", - sc->sc_scan_action); - break; - } - - ZYD_UNLOCK(sc); -} - -static void -zyd_wakeup(struct zyd_softc *sc) -{ - struct zyd_rq *rqp; - - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) - wakeup(rqp->odata); /* wakeup sleeping caller */ -} - -static device_method_t zyd_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, zyd_match), - DEVMETHOD(device_attach, zyd_attach), - DEVMETHOD(device_detach, zyd_detach), - - { 0, 0 } -}; - -static driver_t zyd_driver = { - "zyd", - zyd_methods, - sizeof(struct zyd_softc) -}; - -static devclass_t zyd_devclass; - -DRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, usbd_driver_load, 0); -MODULE_DEPEND(zyd, wlan, 1, 1, 1); -MODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1); -MODULE_DEPEND(zyd, usb, 1, 1, 1); diff --git a/sys/dev/usb/if_zydfw.h b/sys/dev/usb/if_zydfw.h deleted file mode 100644 index 46f5c2a..0000000 --- a/sys/dev/usb/if_zydfw.h +++ /dev/null @@ -1,1144 +0,0 @@ -/* - * Copyright (C) 2001, 2002, 2003,2004 ZyDAS Technology Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted provided - * that the following conditions are met: - * 1. Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistribution 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. 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. - */ - -/* $FreeBSD$ */ - -uint8_t zd1211_firmware[] = { - 0x08, 0x91, 0xFF, 0xED, 0x09, 0x93, 0x1E, 0xEE, - 0xD1, 0x94, 0x11, 0xEE, 0x88, 0xD4, 0xD1, 0x96, - 0xD1, 0x98, 0x5C, 0x99, 0x5C, 0x99, 0x4C, 0x99, - 0x04, 0x9D, 0xD1, 0x98, 0xD1, 0x9A, 0x03, 0xEE, - 0xF4, 0x94, 0xD3, 0xD4, 0x41, 0x2A, 0x40, 0x4A, - 0x45, 0xBE, 0x88, 0x92, 0x41, 0x24, 0x40, 0x44, - 0x53, 0xBE, 0x40, 0xF0, 0x93, 0xEE, 0x41, 0xEE, - 0x98, 0x9A, 0xD4, 0xF7, 0x02, 0x00, 0x1F, 0xEC, - 0x00, 0x00, 0xB2, 0xF8, 0x4D, 0x00, 0xA1, 0xEC, - 0x00, 0x00, 0xA6, 0xF7, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xD8, - 0xA0, 0x90, 0x98, 0x9A, 0x98, 0x9A, 0xA0, 0xD8, - 0x40, 0xF0, 0xB4, 0xF0, 0xA0, 0x90, 0x98, 0x9A, - 0xA0, 0xD8, 0x40, 0xF0, 0x64, 0xEF, 0xA0, 0x90, - 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, 0xF6, 0xF0, - 0xA0, 0x90, 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, - 0xF7, 0xF6, 0xA0, 0x90, 0x98, 0x9A, 0xA0, 0xD8, - 0x40, 0xF0, 0xF8, 0xF5, 0xA0, 0x90, 0x98, 0x9A, - 0xA0, 0xD8, 0x40, 0xF0, 0xF1, 0xF0, 0xA0, 0x90, - 0x98, 0x9A, 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, - 0x97, 0xF7, 0xA0, 0x90, 0x98, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x0D, 0x03, 0x03, 0x00, - 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, 0x42, 0x02, - 0xC1, 0x92, 0x03, 0x96, 0x1B, 0xD7, 0x2A, 0x86, - 0x1A, 0xD5, 0x2B, 0x86, 0x09, 0xA3, 0x00, 0x80, - 0x19, 0xD3, 0x2C, 0x86, 0x00, 0xEE, 0x0A, 0x65, - 0xC0, 0x7A, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xFE, 0xFF, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x0D, 0x03, 0x05, 0x00, 0x05, 0x94, 0xC5, 0xD4, - 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, 0x01, 0xD4, - 0x42, 0x02, 0xC1, 0x96, 0x0A, 0x65, 0xC0, 0x7A, - 0x02, 0x99, 0xC4, 0x92, 0x41, 0xA2, 0xC4, 0xD2, - 0xC5, 0x98, 0x1C, 0xD9, 0x2A, 0x86, 0x01, 0x98, - 0x1C, 0xD9, 0x2B, 0x86, 0x1B, 0xD7, 0x2C, 0x86, - 0x00, 0xEE, 0x09, 0xB3, 0xFE, 0xFF, 0xC2, 0xD2, - 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x41, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0xE5, 0xEE, 0x11, 0x93, 0xD8, 0xF7, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xAE, 0xEE, 0x40, 0xF1, - 0x40, 0x92, 0x19, 0xD3, 0xD8, 0xF7, 0xC5, 0x92, - 0x41, 0x92, 0x19, 0xD3, 0x00, 0x83, 0x40, 0x92, - 0x19, 0xD3, 0x00, 0x83, 0x0F, 0x9F, 0x95, 0xF8, - 0x0F, 0x9F, 0x99, 0xEE, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x99, 0xEE, 0x40, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x09, 0x93, 0xC7, 0xF7, 0x19, 0xD3, - 0x91, 0xEC, 0x40, 0xF0, 0x5F, 0xF2, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, 0x0F, 0x9F, - 0x99, 0xEE, 0x41, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0x92, - 0x19, 0xD3, 0x12, 0x95, 0x19, 0xD3, 0x10, 0x95, - 0x19, 0xD3, 0x02, 0x80, 0x19, 0xD3, 0x03, 0x82, - 0x09, 0x93, 0xC7, 0xF7, 0x19, 0xD3, 0x91, 0xEC, - 0x40, 0xF0, 0x5F, 0xF2, 0x40, 0xF0, 0xDE, 0xF3, - 0x11, 0x93, 0x04, 0xEC, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xE3, 0xEE, 0x40, 0x92, 0x19, 0xD3, - 0x04, 0xEC, 0x40, 0xF0, 0x38, 0xF2, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x11, 0x93, 0x44, 0x96, 0x09, 0xB3, 0xFF, 0xFD, - 0x19, 0xD3, 0x44, 0x96, 0x40, 0xF0, 0x90, 0xF7, - 0x6E, 0x92, 0x19, 0xD3, 0x05, 0x84, 0x40, 0xF0, - 0xC4, 0xEE, 0x4B, 0x62, 0x0A, 0x95, 0x2E, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x2B, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x00, 0xEE, 0xD1, 0xD4, 0x0B, 0x97, - 0x2F, 0xEE, 0xD1, 0xD6, 0x0A, 0x95, 0x34, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x39, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x3E, 0xEE, 0xD1, 0xD4, 0x0B, 0x97, - 0x43, 0xEE, 0xD1, 0xD6, 0x0A, 0x95, 0x48, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x4D, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x4E, 0xEE, 0xC1, 0xD4, 0x0A, 0x65, - 0x00, 0x44, 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, - 0xC2, 0xD2, 0x43, 0xF1, 0x09, 0x93, 0x01, 0x3F, - 0x19, 0xD3, 0xC0, 0x85, 0x11, 0x93, 0x44, 0x96, - 0x09, 0xB3, 0xFF, 0xFC, 0x19, 0xD3, 0x44, 0x96, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x03, 0x00, 0x03, 0x96, - 0x41, 0x02, 0x03, 0x99, 0xC4, 0x94, 0x42, 0x04, - 0xC1, 0x04, 0xC2, 0x94, 0xC3, 0xD4, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x40, 0x92, 0x19, 0xD3, 0x94, 0xEC, 0x13, 0x97, - 0x95, 0xEC, 0x1B, 0xD7, 0x02, 0x80, 0x11, 0x93, - 0x99, 0xEC, 0x19, 0xD3, 0x7C, 0x96, 0x0B, 0x97, - 0xA0, 0x00, 0x1B, 0xD7, 0x6E, 0xEC, 0x0A, 0x65, - 0x0E, 0x42, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xFF, 0xBF, 0x11, 0xA3, 0x9A, 0xEC, 0xC2, 0xD2, - 0x0A, 0x65, 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xA3, 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, - 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xBF, 0xFF, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x47, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x14, 0x99, 0x03, 0x80, 0x0C, 0xB3, 0x00, 0x10, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x97, 0xF0, - 0x11, 0x93, 0x9F, 0xEC, 0x41, 0x02, 0x19, 0xD3, - 0x9F, 0xEC, 0x11, 0x93, 0xD6, 0xF7, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x84, 0xEF, 0x0A, 0x65, - 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0x00, 0x04, 0xC2, 0xD2, 0x0F, 0x9F, 0xB1, 0xF0, - 0x11, 0x93, 0x94, 0xEC, 0x02, 0xD2, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xD0, 0xEF, 0x41, 0x92, - 0x19, 0xD3, 0x94, 0xEC, 0x19, 0xD3, 0x9F, 0xEC, - 0x12, 0x95, 0x02, 0x80, 0x1A, 0xD5, 0x95, 0xEC, - 0x13, 0x97, 0x7C, 0x96, 0x1B, 0xD7, 0x99, 0xEC, - 0x0A, 0x65, 0x0E, 0x42, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0x00, 0x40, 0x19, 0xD3, 0x9A, 0xEC, - 0x09, 0x63, 0x00, 0x40, 0xC2, 0xD2, 0x02, 0x94, - 0x1A, 0xD5, 0x7C, 0x96, 0x0C, 0xB3, 0x00, 0x08, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xB0, 0xEF, - 0x0C, 0xB3, 0xFF, 0x07, 0x0F, 0x9F, 0xB4, 0xEF, - 0x11, 0x93, 0x06, 0x80, 0x09, 0xB3, 0xFF, 0x07, - 0x09, 0x03, 0x00, 0xA0, 0x19, 0xD3, 0x97, 0xEC, - 0x40, 0x98, 0x0B, 0x97, 0x9C, 0xEC, 0x04, 0x95, - 0x03, 0x05, 0x14, 0x03, 0x97, 0xEC, 0x46, 0x02, - 0xC1, 0x92, 0xC2, 0xD2, 0x41, 0x08, 0x42, 0x48, - 0x02, 0x9E, 0x0F, 0x9F, 0xBB, 0xEF, 0x11, 0x93, - 0x97, 0xEC, 0xC1, 0x92, 0xC5, 0xD2, 0x5F, 0xB2, - 0x19, 0xD3, 0x9B, 0xEC, 0x0F, 0x9F, 0xD3, 0xEF, - 0x13, 0x97, 0x98, 0xEC, 0xC5, 0xD6, 0x11, 0x93, - 0x03, 0x80, 0x09, 0xB3, 0x00, 0x08, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xE9, 0xEF, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x10, - 0x19, 0xD3, 0xDB, 0xF7, 0x40, 0x98, 0x1C, 0xD9, - 0x9B, 0xEC, 0x12, 0x95, 0x9B, 0xEC, 0x40, 0x44, - 0x02, 0x4E, 0x0F, 0x9F, 0x86, 0xF0, 0x0A, 0xB3, - 0x08, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x07, 0xF0, 0x0A, 0xB3, 0x07, 0x00, 0x09, 0x05, - 0xA9, 0xEC, 0xC2, 0x94, 0x01, 0xD4, 0x09, 0x03, - 0xA1, 0xEC, 0xC1, 0x92, 0x19, 0xD3, 0x9B, 0xEC, - 0xC5, 0x94, 0x0A, 0xB5, 0x00, 0xFF, 0x01, 0xA5, - 0xC5, 0xD4, 0x0F, 0x9F, 0x13, 0xF0, 0x0A, 0x05, - 0xFF, 0xFF, 0x0A, 0x03, 0xB1, 0xEC, 0xC1, 0x92, - 0x01, 0xD2, 0x1A, 0xD5, 0x9B, 0xEC, 0xC5, 0x96, - 0x0B, 0x07, 0xFF, 0xFF, 0xC5, 0xD6, 0x11, 0x93, - 0x97, 0xEC, 0xC5, 0x98, 0xC1, 0xD8, 0x11, 0x93, - 0x97, 0xEC, 0x09, 0x05, 0x0B, 0x00, 0x03, 0xD4, - 0xC2, 0x96, 0x06, 0xD6, 0x7B, 0x95, 0x7A, 0x95, - 0x4C, 0x02, 0xC1, 0x92, 0x59, 0x93, 0x59, 0x93, - 0x01, 0xA5, 0x01, 0x98, 0x0C, 0xF5, 0x7B, 0x93, - 0x09, 0x09, 0x01, 0x00, 0x06, 0x92, 0x09, 0xB3, - 0xFF, 0x00, 0x04, 0xD2, 0x5C, 0x93, 0x59, 0x93, - 0x04, 0x94, 0x01, 0xA5, 0x03, 0x96, 0xC3, 0xD4, - 0x11, 0x93, 0x97, 0xEC, 0x4C, 0x02, 0x05, 0xD2, - 0xC1, 0x92, 0x09, 0xB3, 0x00, 0xFF, 0x7C, 0x95, - 0x7A, 0x95, 0x02, 0xA3, 0x05, 0x98, 0xC4, 0xD2, - 0x12, 0x95, 0x97, 0xEC, 0x45, 0x04, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x00, 0x01, 0xC2, 0xD2, - 0x12, 0x95, 0x9B, 0xEC, 0x0A, 0xB3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x5B, 0xF0, - 0x12, 0x95, 0x97, 0xEC, 0x4A, 0x04, 0x02, 0x99, - 0xC4, 0x92, 0x01, 0x98, 0x0C, 0xF3, 0x7B, 0x93, - 0x41, 0x02, 0x0F, 0x9F, 0x7C, 0xF0, 0x43, 0x44, - 0x02, 0x8E, 0x0F, 0x9F, 0x7D, 0xF0, 0x11, 0x93, - 0x97, 0xEC, 0x42, 0x02, 0x0A, 0x05, 0xFF, 0xFF, - 0xC1, 0xD4, 0x11, 0x93, 0x97, 0xEC, 0x4A, 0x02, - 0x12, 0x95, 0x60, 0x96, 0xC1, 0xD4, 0x12, 0x95, - 0x97, 0xEC, 0x4B, 0x04, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0x1F, 0xFF, 0xC2, 0xD2, 0x12, 0x95, - 0x97, 0xEC, 0x4B, 0x04, 0x11, 0x93, 0x62, 0x96, - 0x41, 0x93, 0x59, 0x93, 0x02, 0x99, 0xC4, 0xA2, - 0xC2, 0xD2, 0xC5, 0x92, 0x19, 0xD3, 0x98, 0xEC, - 0x0A, 0x95, 0x0C, 0x02, 0x1A, 0xD5, 0x02, 0x80, - 0x0F, 0x9F, 0xB1, 0xF0, 0x09, 0x63, 0xFE, 0x7F, - 0x01, 0x97, 0xC3, 0x94, 0x0A, 0xA5, 0x00, 0x04, - 0xC1, 0xD4, 0x11, 0x93, 0x9F, 0xEC, 0x09, 0xA3, - 0x00, 0x01, 0x19, 0xD3, 0x9F, 0xEC, 0x40, 0xF0, - 0x39, 0xEF, 0x0F, 0x9F, 0xB1, 0xF0, 0x11, 0x93, - 0x94, 0xEC, 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0xA6, 0xF0, 0x40, 0xF0, 0x39, 0xEF, 0x11, 0x93, - 0x95, 0xEC, 0x44, 0xB2, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xB1, 0xF0, 0x48, 0x98, 0x1C, 0xD9, - 0x02, 0x80, 0x11, 0x93, 0x91, 0xEC, 0x41, 0x22, - 0x0A, 0x95, 0xB1, 0xF0, 0x88, 0xD4, 0x88, 0xDC, - 0x91, 0x9A, 0x47, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0x04, 0x82, 0x48, 0xB2, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xC8, 0xF0, 0x0A, 0x65, 0xFD, 0x7D, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xFF, 0xFE, - 0xC2, 0xD2, 0x41, 0x92, 0x19, 0xD3, 0xBF, 0xEC, - 0x11, 0x93, 0x04, 0x82, 0x43, 0xB2, 0x12, 0x95, - 0x03, 0x82, 0x02, 0xB3, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xEF, 0xF0, 0x0A, 0xB3, 0x00, 0xFF, - 0x48, 0xA2, 0x19, 0xD3, 0x03, 0x82, 0x40, 0xF0, - 0xEB, 0xF3, 0x11, 0x93, 0xBF, 0xEC, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xEF, 0xF0, 0x11, 0x93, - 0x07, 0x82, 0x11, 0x43, 0x03, 0xEC, 0x02, 0x0E, - 0x0F, 0x9F, 0xEF, 0xF0, 0x11, 0x93, 0x03, 0x82, - 0x09, 0xA3, 0x00, 0x01, 0x19, 0xD3, 0x03, 0x82, - 0x40, 0x96, 0x1B, 0xD7, 0xBF, 0xEC, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x11, 0x93, 0x20, 0xBC, 0xC8, 0xD2, - 0x40, 0xF0, 0x48, 0xF1, 0x41, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x05, 0x00, 0x05, 0x94, - 0x41, 0x02, 0xC1, 0x92, 0x01, 0x97, 0xC3, 0x96, - 0xC2, 0xD6, 0x0A, 0x45, 0x00, 0x95, 0x02, 0x5E, - 0x0F, 0x9F, 0x45, 0xF1, 0xC1, 0x92, 0x41, 0xB2, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x45, 0xF1, - 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x45, 0xF1, 0x41, 0x98, 0x1C, 0xD9, - 0xC0, 0xEC, 0x12, 0x95, 0x02, 0x80, 0x01, 0xD4, - 0x40, 0xF0, 0x56, 0xF2, 0x0B, 0x67, 0xFD, 0x7D, - 0x03, 0x99, 0xC4, 0x92, 0x0C, 0x99, 0x96, 0x03, - 0x1C, 0xD9, 0x06, 0x82, 0x41, 0x98, 0x1C, 0xD9, - 0x02, 0x82, 0x42, 0x98, 0x1C, 0xD9, 0x05, 0x82, - 0x0C, 0x69, 0x80, 0x7F, 0x1C, 0xD9, 0x00, 0xB0, - 0x09, 0xA3, 0x00, 0x01, 0xC3, 0xD2, 0x01, 0x94, - 0x0A, 0xB3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x43, 0xF1, 0x42, 0xA4, 0x1A, 0xD5, - 0x02, 0x80, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x05, 0x92, 0xC5, 0xD2, 0x60, 0xB2, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x55, 0xF1, 0x40, 0xF0, - 0x35, 0xF7, 0xC5, 0x94, 0x0A, 0xB3, 0x10, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x5E, 0xF1, - 0x40, 0xF0, 0x23, 0xF6, 0xC5, 0x96, 0x0B, 0xB3, - 0x40, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x67, 0xF1, 0x40, 0xF0, 0x5D, 0xF5, 0xC5, 0x94, - 0x0A, 0xB3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xC8, 0xF1, 0x13, 0x97, 0x21, 0xBC, - 0x01, 0xD6, 0x0B, 0xB3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x79, 0xF1, 0x40, 0xF0, - 0x62, 0xFB, 0x01, 0x94, 0x0A, 0xB3, 0x04, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x82, 0xF1, - 0x40, 0xF0, 0x6C, 0xFB, 0x01, 0x96, 0x0B, 0xB3, - 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xA2, 0xF1, 0x40, 0xF0, 0xB0, 0xFA, 0x41, 0x92, - 0x19, 0xD3, 0xD5, 0xF7, 0x11, 0x93, 0x03, 0xEC, - 0x09, 0x43, 0x40, 0x00, 0x02, 0x5E, 0x0F, 0x9F, - 0x98, 0xF1, 0x40, 0x94, 0x1A, 0xD5, 0xD5, 0xF7, - 0x11, 0x93, 0x00, 0xEC, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xAB, 0xF1, 0x40, 0xF0, 0x38, 0xF2, - 0x0F, 0x9F, 0xAB, 0xF1, 0x01, 0x96, 0x0B, 0xB3, - 0x08, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xAB, 0xF1, 0x40, 0xF0, 0x7C, 0xFB, 0x01, 0x94, - 0x0A, 0xB3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xB4, 0xF1, 0x40, 0xF0, 0x87, 0xFB, - 0x11, 0x93, 0x10, 0xEC, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xBF, 0xF1, 0x44, 0x96, 0x1B, 0xD7, - 0x0B, 0xBC, 0x0F, 0x9F, 0xC5, 0xF1, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xC5, 0xF1, 0x19, 0xD3, - 0x0B, 0xBC, 0x40, 0x92, 0x19, 0xD3, 0x10, 0xEC, - 0xC5, 0x94, 0x0A, 0xB3, 0x80, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x12, 0xF2, 0x13, 0x97, - 0x28, 0xBC, 0x01, 0xD6, 0x0B, 0xB3, 0x40, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0xDA, 0xF1, - 0x40, 0xF0, 0x18, 0xF7, 0x01, 0x94, 0x0A, 0xB3, - 0x02, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xED, 0xF1, 0x40, 0xF0, 0xC4, 0xEE, 0x40, 0xF0, - 0x8F, 0xFB, 0x40, 0xF0, 0x1B, 0xF2, 0x40, 0x96, - 0x1B, 0xD7, 0x00, 0xEC, 0x41, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x01, 0x94, 0x0A, 0xB3, 0x04, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x09, 0xF2, - 0x40, 0xF0, 0x9E, 0xFB, 0x09, 0x63, 0x00, 0x44, - 0x01, 0x97, 0xC3, 0x94, 0x48, 0xA4, 0xC1, 0xD4, - 0x00, 0xEE, 0x40, 0x92, 0x19, 0xD3, 0x12, 0x95, - 0x19, 0xD3, 0x10, 0x95, 0x19, 0xD3, 0x02, 0x80, - 0x19, 0xD3, 0x03, 0x82, 0x41, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x01, 0x94, 0x0A, 0xB3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x12, 0xF2, - 0x40, 0xF0, 0xAE, 0xFB, 0x0A, 0x65, 0x00, 0x44, - 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, - 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xD3, 0xF2, 0xBD, 0x0A, 0x65, 0xEA, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, - 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xA3, 0x40, 0x00, 0xC2, 0xD2, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, 0x0A, 0x65, - 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xEB, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xBF, 0xFF, - 0xC2, 0xD2, 0x0A, 0x65, 0xEA, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, 0xC2, 0xD2, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x09, 0x93, 0x00, 0x01, 0x19, 0xD3, - 0x02, 0x80, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x93, 0x00, 0x09, - 0x19, 0xD3, 0x02, 0x80, 0x40, 0xF0, 0x56, 0xF2, - 0x40, 0x92, 0x19, 0xD3, 0x94, 0xEC, 0xC8, 0xD2, - 0x09, 0x93, 0x91, 0xEC, 0xC8, 0xD2, 0x40, 0xF0, - 0x2A, 0xEF, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0x3B, 0xF5, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x85, 0xF2, 0x0A, 0x65, 0xFE, 0x7F, 0x02, 0x97, - 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, 0x0F, 0x9F, - 0x92, 0xF2, 0x40, 0xF0, 0x94, 0xF2, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0x92, 0xF2, 0xC8, 0xD2, - 0x09, 0x93, 0x91, 0xEC, 0xC8, 0xD2, 0x40, 0xF0, - 0x2A, 0xEF, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0xF1, 0xBD, 0x19, 0xD3, 0xB6, 0xEC, 0x11, 0x93, - 0xB4, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0xAC, 0xF2, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xC3, 0x94, 0x0A, 0x07, 0x07, 0x00, 0xC1, 0xD6, - 0x0A, 0x05, 0x00, 0xA0, 0x1A, 0xD5, 0x96, 0xEC, - 0x11, 0x93, 0xB6, 0xEC, 0x19, 0xD3, 0x01, 0x80, - 0x0A, 0x65, 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, - 0x41, 0xA2, 0xC2, 0xD2, 0x40, 0x92, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x41, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x13, 0x97, 0xB4, 0xEC, 0x40, 0x46, - 0x02, 0x5E, 0x0F, 0x9F, 0x2C, 0xF3, 0x12, 0x95, - 0x96, 0xEC, 0x0A, 0x03, 0x07, 0x00, 0xC1, 0x92, - 0xC2, 0xD2, 0x11, 0x93, 0x96, 0xEC, 0x09, 0x05, - 0x01, 0x00, 0x48, 0x02, 0xC1, 0x92, 0xC2, 0xD2, - 0x11, 0x93, 0x96, 0xEC, 0x4E, 0x02, 0xC1, 0x94, - 0xC5, 0xD6, 0xC5, 0x92, 0x11, 0x07, 0x96, 0xEC, - 0x0B, 0x03, 0x0F, 0x00, 0xC1, 0x98, 0x46, 0x06, - 0x7A, 0x93, 0x79, 0x93, 0x5C, 0x95, 0x5A, 0x95, - 0x02, 0xA3, 0xC3, 0xD2, 0x04, 0x95, 0xC5, 0x96, - 0x41, 0x06, 0xC5, 0xD6, 0x42, 0x46, 0x02, 0x9E, - 0x0F, 0x9F, 0xD5, 0xF2, 0x11, 0x93, 0x96, 0xEC, - 0x09, 0x05, 0x05, 0x00, 0x41, 0x02, 0xC1, 0x92, - 0xC2, 0xD2, 0x11, 0x93, 0x96, 0xEC, 0xC1, 0x92, - 0x09, 0xB5, 0x1F, 0x00, 0x43, 0x44, 0x02, 0x8E, - 0x0F, 0x9F, 0x02, 0xF3, 0x40, 0x44, 0x02, 0x4E, - 0x0F, 0x9F, 0x03, 0xF3, 0x0A, 0x05, 0xFF, 0xFF, - 0x0F, 0x9F, 0x03, 0xF3, 0x43, 0x94, 0x11, 0x93, - 0x96, 0xEC, 0x42, 0x02, 0xC1, 0xD4, 0x11, 0x93, - 0x96, 0xEC, 0x49, 0x02, 0xC1, 0x92, 0x19, 0xD3, - 0xB4, 0xEC, 0x09, 0x05, 0xF2, 0xFF, 0x1A, 0xD5, - 0x92, 0xEC, 0x09, 0x43, 0xD0, 0x07, 0x02, 0x9E, - 0x0F, 0x9F, 0x2C, 0xF3, 0x11, 0x93, 0xDC, 0xF7, - 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, 0x11, 0x93, - 0xDB, 0xF7, 0x09, 0xA3, 0x40, 0x00, 0x19, 0xD3, - 0xDB, 0xF7, 0x09, 0x63, 0x00, 0x80, 0x01, 0x95, - 0xC2, 0x94, 0x1A, 0xD5, 0xB5, 0xEC, 0x40, 0x96, - 0x1B, 0xD7, 0xB4, 0xEC, 0x0F, 0x9F, 0x92, 0xF3, - 0x11, 0x93, 0x92, 0xEC, 0x12, 0x95, 0xB6, 0xEC, - 0x02, 0x43, 0x02, 0x8E, 0x0F, 0x9F, 0x7A, 0xF3, - 0x02, 0x0E, 0x0F, 0x9F, 0x4D, 0xF3, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x80, 0x00, - 0x19, 0xD3, 0xDB, 0xF7, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x95, 0xC2, 0x94, 0x1A, 0xD5, 0xB5, 0xEC, - 0x40, 0x96, 0x1B, 0xD7, 0xB4, 0xEC, 0x0F, 0x9F, - 0x92, 0xF3, 0x11, 0x93, 0x03, 0x80, 0x09, 0xB3, - 0x00, 0x40, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x5F, 0xF3, 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0x5F, 0xF3, 0x40, 0xF0, - 0xA6, 0xF3, 0x0F, 0x9F, 0x94, 0xF3, 0x41, 0x92, - 0xC8, 0xD2, 0x0A, 0x95, 0x91, 0xEC, 0xC8, 0xD4, - 0x40, 0xF0, 0x2A, 0xEF, 0x42, 0x00, 0x11, 0x93, - 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x72, 0xF3, 0x42, 0x96, 0x1B, 0xD7, 0xC0, 0xEC, - 0x0F, 0x9F, 0x94, 0xF3, 0x0A, 0x65, 0xFE, 0x7F, - 0x02, 0x97, 0xC3, 0x92, 0x42, 0xA2, 0xC2, 0xD2, - 0x0F, 0x9F, 0x94, 0xF3, 0x12, 0x45, 0x03, 0xEC, - 0x02, 0x4E, 0x0F, 0x9F, 0x8C, 0xF3, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x08, - 0x19, 0xD3, 0xDB, 0xF7, 0x1A, 0xD5, 0x92, 0xEC, - 0x11, 0x93, 0x92, 0xEC, 0x19, 0x25, 0x92, 0xEC, - 0x09, 0x63, 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, - 0x41, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, 0xA6, 0xF3, - 0x40, 0x92, 0xC8, 0xD2, 0x09, 0x93, 0x91, 0xEC, - 0xC8, 0xD2, 0x40, 0xF0, 0x2A, 0xEF, 0x42, 0x00, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x11, 0x93, 0xD7, 0xF7, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xB6, 0xF3, 0x0A, 0x65, - 0xBC, 0x69, 0x02, 0x97, 0xC3, 0x92, 0x09, 0x83, - 0x00, 0x02, 0xC2, 0xD2, 0x11, 0x93, 0x03, 0x80, - 0x09, 0xB3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xC9, 0xF3, 0x11, 0x93, 0xDC, 0xF7, - 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, 0x11, 0x93, - 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x20, 0x19, 0xD3, - 0xDB, 0xF7, 0x11, 0x93, 0xB5, 0xEC, 0x19, 0xD3, - 0x04, 0x80, 0x12, 0x95, 0xB4, 0xEC, 0x1A, 0xD5, - 0x05, 0x80, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xC3, 0x96, 0x1B, 0xD7, 0xB5, 0xEC, 0x40, 0x94, - 0x1A, 0xD5, 0xB4, 0xEC, 0x19, 0xD3, 0xF2, 0xBD, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x09, 0x93, 0x96, 0x03, 0x19, 0xD3, - 0x06, 0x82, 0x09, 0x93, 0x00, 0x01, 0x19, 0xD3, - 0x03, 0x82, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x47, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0x01, 0x82, 0xC5, 0xD2, 0x40, 0x94, 0x01, 0xD4, - 0x13, 0x97, 0xB8, 0xEC, 0x02, 0xD6, 0x03, 0x95, - 0x0C, 0x99, 0xBB, 0xEC, 0x04, 0x05, 0x13, 0x97, - 0x03, 0xEC, 0x01, 0x27, 0x02, 0x99, 0xC4, 0x92, - 0x03, 0x03, 0xC2, 0xD2, 0x14, 0x99, 0xBA, 0xEC, - 0x03, 0x09, 0x1C, 0xD9, 0xBA, 0xEC, 0x12, 0x95, - 0x04, 0x82, 0x0A, 0xB3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x29, 0xF5, 0x01, 0x92, - 0x03, 0xD2, 0x0A, 0xA3, 0x02, 0x00, 0x19, 0xD3, - 0x04, 0x82, 0x02, 0x96, 0x0B, 0x05, 0x01, 0x00, - 0x1A, 0xD5, 0xB8, 0xEC, 0xC5, 0x92, 0x43, 0x42, - 0x02, 0x9E, 0x0F, 0x9F, 0x37, 0xF4, 0x42, 0x44, - 0x02, 0x8E, 0x0F, 0x9F, 0x37, 0xF4, 0x11, 0x93, - 0xBF, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x37, 0xF4, 0x0C, 0x49, 0xD3, 0x08, 0x02, 0x8E, - 0x0F, 0x9F, 0x37, 0xF4, 0x11, 0x63, 0x07, 0x82, - 0x11, 0xA3, 0x07, 0x82, 0x71, 0x93, 0x79, 0x93, - 0x79, 0x93, 0x79, 0x93, 0x03, 0xD2, 0xC5, 0x94, - 0x0A, 0xB5, 0xFC, 0xFF, 0x04, 0xD4, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x46, 0xF4, - 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, 0x02, 0x8E, - 0x0F, 0x9F, 0x4D, 0xF4, 0xC5, 0x98, 0x0C, 0x03, - 0xFF, 0xFF, 0x42, 0x42, 0x02, 0x8E, 0x0F, 0x9F, - 0x74, 0xF4, 0x0A, 0x95, 0xBB, 0xEC, 0x42, 0x92, - 0x19, 0xD3, 0xB9, 0xEC, 0xC5, 0x96, 0x43, 0x46, - 0x02, 0x9E, 0x0F, 0x9F, 0x66, 0xF4, 0x0B, 0x07, - 0xFC, 0xFF, 0xC5, 0xD6, 0xD2, 0x98, 0x1C, 0xD9, - 0xC8, 0xBC, 0xD2, 0x96, 0x1B, 0xD7, 0xCA, 0xBC, - 0x09, 0x03, 0xFF, 0xFF, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x52, 0xF4, 0x19, 0xD3, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x72, 0xF4, - 0x0A, 0x05, 0xFE, 0xFF, 0xCA, 0xD2, 0xC2, 0xD2, - 0x0F, 0x9F, 0x74, 0xF4, 0x1A, 0xD5, 0x93, 0xEC, - 0x03, 0x98, 0x40, 0x48, 0x02, 0x5E, 0x0F, 0x9F, - 0xA1, 0xF4, 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, - 0x02, 0x9E, 0x0F, 0x9F, 0x84, 0xF4, 0x04, 0x94, - 0x48, 0x44, 0x02, 0x4E, 0x0F, 0x9F, 0x8F, 0xF4, - 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xA1, 0xF4, - 0x11, 0x93, 0x04, 0x82, 0x41, 0xB2, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xA1, 0xF4, 0x41, 0x96, - 0x01, 0xD6, 0x0A, 0x65, 0xBD, 0x43, 0x02, 0x99, - 0xC4, 0x92, 0x09, 0xA3, 0x80, 0x00, 0xC2, 0xD2, - 0x0A, 0x65, 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x0F, 0x9F, - 0xFA, 0xF4, 0xC5, 0x98, 0x43, 0x48, 0x02, 0x9E, - 0x0F, 0x9F, 0xFA, 0xF4, 0x4F, 0x96, 0x0C, 0xB3, - 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xAE, 0xF4, 0x47, 0x96, 0x11, 0x93, 0xB7, 0xEC, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0xD6, 0xF4, - 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xD6, 0xF4, 0x12, 0x95, 0x00, 0x82, - 0x0A, 0x05, 0xFF, 0xAF, 0x05, 0xD4, 0xC8, 0xD6, - 0xC8, 0xD2, 0x40, 0xF0, 0x7B, 0xF7, 0x42, 0x00, - 0x05, 0x96, 0xC3, 0x94, 0x01, 0xB5, 0x40, 0x44, - 0x02, 0x4E, 0x0F, 0x9F, 0xD6, 0xF4, 0x06, 0x98, - 0x50, 0x98, 0x1C, 0xD9, 0xA2, 0xBC, 0x40, 0x98, - 0x1C, 0xD9, 0xA2, 0xBC, 0x40, 0x92, 0x03, 0xD2, - 0x0F, 0x9F, 0xFF, 0xF4, 0x03, 0x94, 0x40, 0x44, - 0x02, 0x5E, 0x0F, 0x9F, 0xE3, 0xF4, 0x0A, 0x65, - 0x5E, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x48, 0xA2, - 0xC2, 0xD2, 0x0F, 0x9F, 0xFF, 0xF4, 0x11, 0x93, - 0xB8, 0xEC, 0x0C, 0x99, 0xBB, 0xEC, 0x04, 0x03, - 0x04, 0x96, 0x13, 0x25, 0x03, 0xEC, 0xC1, 0xD4, - 0x11, 0x93, 0xBA, 0xEC, 0x19, 0x05, 0xBA, 0xEC, - 0x1B, 0xD7, 0x01, 0x82, 0x0A, 0x65, 0xFD, 0x7D, - 0x02, 0x99, 0xC4, 0x92, 0x43, 0xA2, 0xC2, 0xD2, - 0x41, 0x92, 0x01, 0xD2, 0x03, 0x94, 0x40, 0x44, - 0x02, 0x5E, 0x0F, 0x9F, 0x13, 0xF5, 0x11, 0x93, - 0xB9, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x0B, 0xF5, 0x19, 0xD3, 0xB8, 0xEC, 0x19, 0xD3, - 0xBA, 0xEC, 0x19, 0xD3, 0xBB, 0xEC, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x13, 0xF5, - 0x41, 0x98, 0x1C, 0xD9, 0xB7, 0xEC, 0x11, 0x93, - 0xBF, 0xEC, 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x24, 0xF5, 0x11, 0x93, 0x00, 0x82, 0x19, 0xD3, - 0x02, 0x82, 0x0A, 0x65, 0xFD, 0x7D, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x00, 0x01, 0xC2, 0xD2, - 0x40, 0x98, 0x1C, 0xD9, 0xBF, 0xEC, 0x0F, 0x9F, - 0x2C, 0xF5, 0x01, 0x92, 0x19, 0xD3, 0xB7, 0xEC, - 0x01, 0x94, 0x40, 0x44, 0x02, 0x5E, 0x0F, 0x9F, - 0x38, 0xF5, 0x0A, 0x65, 0xEA, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, 0xC2, 0xD2, - 0x47, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x12, 0x95, 0x03, 0x80, - 0x0A, 0xB3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x57, 0xF5, 0x0A, 0xB7, 0x00, 0x08, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x5A, 0xF5, - 0x11, 0x93, 0x03, 0xEC, 0x41, 0x02, 0x09, 0xB3, - 0xFE, 0xFF, 0x12, 0x95, 0x07, 0x80, 0x01, 0x45, - 0x02, 0x8E, 0x0F, 0x9F, 0x5A, 0xF5, 0x41, 0x92, - 0x0F, 0x9F, 0x5B, 0xF5, 0x40, 0x92, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x41, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x40, 0x00, 0xC2, 0xD2, - 0x13, 0x97, 0x6E, 0xEC, 0x0B, 0x47, 0xA0, 0x00, - 0x02, 0x5E, 0x0F, 0x9F, 0x86, 0xF5, 0x09, 0x63, - 0x08, 0x43, 0x0A, 0x65, 0xFF, 0x5F, 0x01, 0x99, - 0xC4, 0xD4, 0x0A, 0x95, 0x9B, 0xEC, 0xD2, 0x96, - 0x1B, 0xD7, 0xFA, 0xBC, 0xD2, 0x96, 0xC4, 0xD6, - 0xD2, 0x98, 0x1C, 0xD9, 0xFA, 0xBC, 0xD2, 0x96, - 0xC1, 0xD6, 0xC2, 0x94, 0x1A, 0xD5, 0xFA, 0xBC, - 0x0F, 0x9F, 0xC4, 0xF5, 0x0C, 0x69, 0xFF, 0x6F, - 0x1C, 0xD9, 0xF8, 0xBC, 0x0B, 0x47, 0x10, 0x95, - 0x02, 0x5E, 0x0F, 0x9F, 0x9E, 0xF5, 0x0A, 0x95, - 0x6F, 0xEC, 0x09, 0x63, 0x06, 0x43, 0x01, 0x99, - 0xC4, 0xD6, 0xD2, 0x96, 0x1B, 0xD7, 0xF8, 0xBC, - 0x0C, 0x69, 0xEE, 0x6A, 0xC1, 0xD8, 0xC2, 0x94, - 0x1A, 0xD5, 0xF8, 0xBC, 0x40, 0x92, 0xC5, 0xD2, - 0x11, 0x43, 0xC1, 0xEC, 0x02, 0x0E, 0x0F, 0x9F, - 0xC1, 0xF5, 0xC5, 0x94, 0x0A, 0x03, 0x71, 0xEC, - 0xC1, 0x94, 0x1A, 0xD5, 0xFA, 0xBC, 0x11, 0x93, - 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xB3, 0xF5, 0x0A, 0x95, 0x6F, 0xEC, 0xC8, 0xD4, - 0x40, 0xF0, 0x9C, 0xF7, 0x19, 0xD3, 0xF8, 0xBC, - 0x41, 0x00, 0xC5, 0x96, 0x41, 0x06, 0xC5, 0xD6, - 0x13, 0x47, 0xC1, 0xEC, 0x02, 0x1E, 0x0F, 0x9F, - 0xA5, 0xF5, 0x40, 0x98, 0x1C, 0xD9, 0xFA, 0xBC, - 0x40, 0x92, 0x19, 0xD3, 0x6E, 0xEC, 0x19, 0xD3, - 0xC1, 0xEC, 0x0A, 0x65, 0x52, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x48, 0xA2, 0xC2, 0xD2, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x99, 0xC4, 0x92, 0x09, 0xB3, - 0xBF, 0xFF, 0xC2, 0xD2, 0x41, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x43, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x06, 0x92, 0x01, 0xD2, 0x0A, 0x65, - 0xF0, 0x6A, 0x0B, 0x97, 0x6F, 0xEC, 0x02, 0x99, - 0xC4, 0x98, 0xD3, 0xD8, 0x02, 0xD6, 0x0A, 0x03, - 0x02, 0x00, 0x01, 0x97, 0xC3, 0x98, 0x02, 0x96, - 0xC3, 0xD8, 0x01, 0x96, 0xC1, 0xD6, 0x1A, 0xD5, - 0x6E, 0xEC, 0xC5, 0x98, 0x14, 0x99, 0x6F, 0xEC, - 0xC2, 0xD8, 0x43, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0x92, - 0xC8, 0xD2, 0x40, 0xF0, 0xD9, 0xF5, 0x41, 0x00, - 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x13, 0xF6, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x10, 0xF6, 0x0A, 0x65, 0xFE, 0x7F, - 0x02, 0x97, 0xC3, 0x92, 0x42, 0xA2, 0xC2, 0xD2, - 0x40, 0x92, 0x19, 0xD3, 0xC0, 0xEC, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xE9, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xBF, 0xFF, - 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x63, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0xAF, 0xBC, 0x47, 0xB2, 0x59, 0x95, 0x5A, 0x95, - 0x12, 0xA5, 0xBF, 0xBC, 0x0A, 0xB3, 0x01, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x35, 0xF6, - 0x41, 0x04, 0x05, 0x93, 0x40, 0x96, 0x20, 0xD6, - 0x62, 0x97, 0x0F, 0x9F, 0x44, 0xF6, 0x14, 0x99, - 0xFC, 0xBC, 0xD1, 0xD8, 0x14, 0x99, 0xFE, 0xBC, - 0xD1, 0xD8, 0x20, 0x98, 0x42, 0x08, 0x20, 0xD8, - 0x20, 0x98, 0x03, 0x49, 0x02, 0x1E, 0x0F, 0x9F, - 0x3B, 0xF6, 0xC5, 0x92, 0x62, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x5D, 0xF6, 0x02, 0x8E, 0x0F, 0x9F, - 0x57, 0xF6, 0x61, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x81, 0xF6, 0x0F, 0x9F, 0xAE, 0xF6, 0x63, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xA4, 0xF6, 0x0F, 0x9F, - 0xAE, 0xF6, 0x0D, 0x03, 0x01, 0x00, 0x0C, 0x99, - 0x71, 0xEC, 0x0B, 0x05, 0xFF, 0xFF, 0x40, 0x96, - 0x0F, 0x9F, 0x6A, 0xF6, 0xD1, 0x96, 0xD4, 0xD6, - 0x20, 0x96, 0x41, 0x06, 0x20, 0xD6, 0x02, 0x47, - 0x02, 0x1E, 0x0F, 0x9F, 0x66, 0xF6, 0x1A, 0xD5, - 0xC1, 0xEC, 0x0A, 0x65, 0xEB, 0x43, 0x02, 0x99, - 0xC4, 0x92, 0x09, 0xA3, 0xC0, 0x00, 0xC2, 0xD2, - 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x0F, 0x9F, - 0xAE, 0xF6, 0x0A, 0x03, 0xFE, 0xFF, 0x61, 0x95, - 0x40, 0x98, 0x20, 0xD8, 0x02, 0x49, 0x02, 0x0E, - 0x0F, 0x9F, 0xAE, 0xF6, 0x0D, 0x03, 0x01, 0x00, - 0x21, 0xD2, 0x20, 0x92, 0x05, 0x03, 0x42, 0x02, - 0xC8, 0xD2, 0x21, 0x96, 0xC3, 0x92, 0x42, 0x06, - 0x21, 0xD6, 0xC8, 0xD2, 0x22, 0xD4, 0x40, 0xF0, - 0x01, 0xF1, 0x42, 0x00, 0x20, 0x98, 0x42, 0x08, - 0x20, 0xD8, 0x22, 0x94, 0x02, 0x49, 0x02, 0x1E, - 0x0F, 0x9F, 0x8D, 0xF6, 0x0F, 0x9F, 0xAE, 0xF6, - 0x0D, 0x03, 0x03, 0x00, 0xC8, 0xD2, 0x02, 0x92, - 0xC8, 0xD2, 0x01, 0x96, 0xC8, 0xD6, 0x40, 0xF0, - 0xB1, 0xF6, 0x43, 0x00, 0x63, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x45, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x08, 0x00, 0x08, 0x94, - 0xC5, 0xD4, 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, - 0x03, 0xD4, 0x42, 0x02, 0xC1, 0x92, 0x01, 0xD2, - 0x02, 0x97, 0xC5, 0x94, 0x0A, 0x83, 0xFF, 0xFF, - 0x11, 0xB3, 0x2C, 0x93, 0x09, 0xB3, 0xFB, 0xFF, - 0x19, 0xD3, 0x2C, 0x93, 0x03, 0x92, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xE4, 0xF6, 0x01, 0x94, - 0xD2, 0x92, 0x19, 0xD3, 0x2C, 0x93, 0x01, 0xD4, - 0x02, 0x94, 0x12, 0x95, 0x2C, 0x93, 0x44, 0xA4, - 0x1A, 0xD5, 0x2C, 0x93, 0x0A, 0xB5, 0xFB, 0xFF, - 0x1A, 0xD5, 0x2C, 0x93, 0x0B, 0x07, 0xFF, 0xFF, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0xCF, 0xF6, - 0x09, 0x63, 0xD4, 0x6C, 0x01, 0x95, 0xC2, 0x96, - 0xC5, 0x94, 0x02, 0xA7, 0xC1, 0xD6, 0x03, 0x92, - 0x54, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xF4, 0xF6, - 0x0A, 0x83, 0xFF, 0xFF, 0x1B, 0xB3, 0x2C, 0x93, - 0x45, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xD3, 0xF2, 0xBD, 0x40, 0xF0, 0x3B, 0xF5, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x08, 0xF7, - 0x40, 0xF0, 0x94, 0xF2, 0x0F, 0x9F, 0x16, 0xF7, - 0x40, 0x96, 0xC8, 0xD6, 0x09, 0x93, 0x91, 0xEC, - 0xC8, 0xD2, 0x40, 0xF0, 0x2A, 0xEF, 0x0A, 0x65, - 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, - 0xC2, 0xD2, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x0A, 0x65, - 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0x40, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xEA, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, - 0xC2, 0xD2, 0x40, 0x92, 0x19, 0xD3, 0x2D, 0xBC, - 0x0A, 0x65, 0xD8, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x09, 0x63, 0xEA, 0x43, 0x01, 0x97, 0xC3, 0x94, - 0x44, 0xA4, 0xC1, 0xD4, 0x11, 0x93, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x6F, 0xF7, - 0x12, 0x95, 0x93, 0xEC, 0x0B, 0x67, 0x36, 0x43, - 0xD2, 0x98, 0x1C, 0xD9, 0xC8, 0xBC, 0xD2, 0x98, - 0x03, 0x93, 0xC1, 0xD8, 0x11, 0x93, 0xB9, 0xEC, - 0x09, 0x03, 0xFF, 0xFF, 0x19, 0xD3, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x48, 0xF7, - 0x19, 0xD3, 0xB8, 0xEC, 0x19, 0xD3, 0xBA, 0xEC, - 0x0A, 0x05, 0xFE, 0xFF, 0xCA, 0xD2, 0xCA, 0xD2, - 0xC2, 0xD2, 0x0A, 0x65, 0x5E, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x48, 0xA2, 0xC2, 0xD2, 0x0A, 0x65, - 0xEA, 0x43, 0x02, 0x99, 0xC4, 0x92, 0x09, 0xB3, - 0xFB, 0xFF, 0x0F, 0x9F, 0x78, 0xF7, 0x11, 0x93, - 0x03, 0xEC, 0x19, 0xD3, 0x01, 0x82, 0x0A, 0x65, - 0xFD, 0x7D, 0x02, 0x97, 0xC3, 0x92, 0x43, 0xA2, - 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x03, 0x92, 0x04, 0x96, - 0x0D, 0x5E, 0x50, 0x46, 0x02, 0x0E, 0x40, 0x92, - 0x09, 0xEE, 0x44, 0x46, 0x04, 0x0E, 0x59, 0x93, - 0x44, 0x26, 0x04, 0x5E, 0x46, 0xEE, 0x41, 0x93, - 0x41, 0x26, 0x43, 0x4E, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0xB1, 0xFE, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x03, 0x94, - 0x1A, 0xD5, 0xA3, 0xF7, 0x11, 0x93, 0x00, 0x90, - 0x88, 0x98, 0x90, 0x9A, 0x1D, 0x00, 0x1A, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x18, 0x00, 0x19, 0x00, - 0x1A, 0x00, 0x1B, 0x00, 0x16, 0x00, 0x21, 0x00, - 0x12, 0x00, 0x09, 0x00, 0x13, 0x00, 0x19, 0x00, - 0x19, 0x00, 0x19, 0x00, 0x21, 0x00, 0x2D, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x69, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5F, 0xF2, 0xCD, 0xF7, 0x00, 0x00, 0x74, 0xF2, - 0xCD, 0xF7, 0x00, 0x00, 0xB9, 0xF2, 0xCA, 0xF7, - 0xD1, 0xF7, 0x00, 0x00, 0x97, 0xF3, 0xCD, 0xF7, - 0x05, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * current zd1211b firmware version. - */ -#define ZD1211B_FIRMWARE_VER 4705 - -uint8_t zd1211b_firmware[] = { - 0x08, 0x91, 0xff, 0xed, 0x09, 0x93, 0x1e, 0xee, 0xd1, 0x94, 0x11, - 0xee, 0x88, 0xd4, 0xd1, 0x96, 0xd1, 0x98, 0x5c, 0x99, 0x5c, 0x99, - 0x4c, 0x99, 0x04, 0x9d, 0xd1, 0x98, 0xd1, 0x9a, 0x03, 0xee, 0xf4, - 0x94, 0xd3, 0xd4, 0x41, 0x2a, 0x40, 0x4a, 0x45, 0xbe, 0x88, 0x92, - 0x41, 0x24, 0x40, 0x44, 0x53, 0xbe, 0x40, 0xf0, 0x4e, 0xee, 0x41, - 0xee, 0x98, 0x9a, 0x72, 0xf7, 0x02, 0x00, 0x1f, 0xec, 0x00, 0x00, - 0xb2, 0xf8, 0x4d, 0x00, 0xa1, 0xec, 0x00, 0x00, 0x43, 0xf7, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xd8, - 0xa0, 0x90, 0x98, 0x9a, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x5a, - 0xf0, 0xa0, 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x0a, 0xef, - 0xa0, 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x97, 0xf0, 0xa0, - 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x94, 0xf6, 0xa0, 0x90, - 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x95, 0xf5, 0xa0, 0x90, 0x98, - 0x9a, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x34, 0xf7, 0xa0, 0x90, - 0x98, 0x9a, 0x88, 0xda, 0x41, 0x20, 0x08, 0x0b, 0x01, 0x00, 0x40, - 0xf0, 0x8e, 0xee, 0x40, 0x96, 0x0a, 0x65, 0x00, 0x7d, 0x11, 0x93, - 0x76, 0xf7, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x57, 0xee, 0x40, - 0xf1, 0x1b, 0xd7, 0x76, 0xf7, 0xc5, 0x92, 0x02, 0x99, 0x41, 0x92, - 0xc4, 0xd2, 0x40, 0x92, 0xc4, 0xd2, 0x0f, 0x9f, 0x95, 0xf8, 0x0f, - 0x9f, 0x57, 0xee, 0x41, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x40, 0x92, 0x19, 0xd3, 0x12, 0x95, 0x19, - 0xd3, 0x10, 0x95, 0x19, 0xd3, 0x02, 0x80, 0x19, 0xd3, 0x03, 0x82, - 0x09, 0x93, 0x65, 0xf7, 0x19, 0xd3, 0x91, 0xec, 0x40, 0xf0, 0x07, - 0xf2, 0x40, 0xf0, 0x75, 0xf3, 0x11, 0x93, 0x04, 0xec, 0x42, 0x42, - 0x02, 0x5e, 0x0f, 0x9f, 0x8c, 0xee, 0x40, 0x92, 0x19, 0xd3, 0x04, - 0xec, 0x40, 0xf0, 0xe0, 0xf1, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0x44, 0x96, 0x09, 0xb3, 0xff, - 0xfd, 0x19, 0xd3, 0x44, 0x96, 0x40, 0xf0, 0x2d, 0xf7, 0x40, 0xf0, - 0x6d, 0xee, 0x4b, 0x62, 0x0a, 0x95, 0x2e, 0xee, 0xd1, 0xd4, 0x0b, - 0x97, 0x2b, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x00, 0xee, 0xd1, 0xd4, - 0x0b, 0x97, 0x2f, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x34, 0xee, 0xd1, - 0xd4, 0x0b, 0x97, 0x39, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x3e, 0xee, - 0xd1, 0xd4, 0x0b, 0x97, 0x43, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x2e, - 0xee, 0xd1, 0xd4, 0x0b, 0x97, 0x48, 0xee, 0xd1, 0xd6, 0x0a, 0x95, - 0x49, 0xee, 0xc1, 0xd4, 0x0a, 0x65, 0x00, 0x44, 0x02, 0x97, 0xc3, - 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x43, 0xf1, 0x09, 0x93, 0x01, 0x3f, - 0x19, 0xd3, 0xc0, 0x85, 0x11, 0x93, 0x44, 0x96, 0x09, 0xb3, 0xff, - 0xfc, 0x19, 0xd3, 0x44, 0x96, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x03, 0x00, 0x03, 0x96, 0x41, - 0x02, 0x03, 0x99, 0xc4, 0x94, 0x42, 0x04, 0xc1, 0x04, 0xc2, 0x94, - 0xc3, 0xd4, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x40, 0x92, 0x19, 0xd3, 0x94, 0xec, 0x13, 0x97, 0x95, 0xec, - 0x1b, 0xd7, 0x02, 0x80, 0x11, 0x93, 0x99, 0xec, 0x19, 0xd3, 0x7c, - 0x96, 0x0b, 0x97, 0xa0, 0x00, 0x1b, 0xd7, 0x6e, 0xec, 0x0a, 0x65, - 0x0e, 0x42, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xff, 0xbf, 0x11, - 0xa3, 0x9a, 0xec, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, 0x0a, 0x65, 0xe9, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, 0xd2, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x47, 0x20, 0x08, 0x0b, 0x01, - 0x00, 0x14, 0x99, 0x03, 0x80, 0x0c, 0xb3, 0x00, 0x10, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x3d, 0xf0, 0x11, 0x93, 0x9f, 0xec, 0x41, - 0x02, 0x19, 0xd3, 0x9f, 0xec, 0x11, 0x93, 0x74, 0xf7, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x2a, 0xef, 0x0a, 0x65, 0xfe, 0x7f, 0x02, - 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x00, 0x04, 0xc2, 0xd2, 0x0f, 0x9f, - 0x57, 0xf0, 0x11, 0x93, 0x94, 0xec, 0x02, 0xd2, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x76, 0xef, 0x41, 0x92, 0x19, 0xd3, 0x94, 0xec, - 0x19, 0xd3, 0x9f, 0xec, 0x12, 0x95, 0x02, 0x80, 0x1a, 0xd5, 0x95, - 0xec, 0x13, 0x97, 0x7c, 0x96, 0x1b, 0xd7, 0x99, 0xec, 0x0a, 0x65, - 0x0e, 0x42, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0x00, 0x40, 0x19, - 0xd3, 0x9a, 0xec, 0x09, 0x63, 0x00, 0x40, 0xc2, 0xd2, 0x02, 0x94, - 0x1a, 0xd5, 0x7c, 0x96, 0x0c, 0xb3, 0x00, 0x08, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x56, 0xef, 0x0c, 0xb3, 0xff, 0x07, 0x0f, 0x9f, - 0x5a, 0xef, 0x11, 0x93, 0x06, 0x80, 0x09, 0xb3, 0xff, 0x07, 0x09, - 0x03, 0x00, 0xa0, 0x19, 0xd3, 0x97, 0xec, 0x40, 0x98, 0x0b, 0x97, - 0x9c, 0xec, 0x04, 0x95, 0x03, 0x05, 0x14, 0x03, 0x97, 0xec, 0x46, - 0x02, 0xc1, 0x92, 0xc2, 0xd2, 0x41, 0x08, 0x42, 0x48, 0x02, 0x9e, - 0x0f, 0x9f, 0x61, 0xef, 0x11, 0x93, 0x97, 0xec, 0xc1, 0x92, 0xc5, - 0xd2, 0x5f, 0xb2, 0x19, 0xd3, 0x9b, 0xec, 0x0f, 0x9f, 0x79, 0xef, - 0x13, 0x97, 0x98, 0xec, 0xc5, 0xd6, 0x11, 0x93, 0x03, 0x80, 0x09, - 0xb3, 0x00, 0x08, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x8f, 0xef, - 0x11, 0x93, 0x7a, 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, - 0x93, 0x79, 0xf7, 0x09, 0xa3, 0x00, 0x10, 0x19, 0xd3, 0x79, 0xf7, - 0x40, 0x98, 0x1c, 0xd9, 0x9b, 0xec, 0x12, 0x95, 0x9b, 0xec, 0x40, - 0x44, 0x02, 0x4e, 0x0f, 0x9f, 0x2c, 0xf0, 0x0a, 0xb3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xad, 0xef, 0x0a, 0xb3, 0x07, - 0x00, 0x09, 0x05, 0xa9, 0xec, 0xc2, 0x94, 0x01, 0xd4, 0x09, 0x03, - 0xa1, 0xec, 0xc1, 0x92, 0x19, 0xd3, 0x9b, 0xec, 0xc5, 0x94, 0x0a, - 0xb5, 0x00, 0xff, 0x01, 0xa5, 0xc5, 0xd4, 0x0f, 0x9f, 0xb9, 0xef, - 0x0a, 0x05, 0xff, 0xff, 0x0a, 0x03, 0xb1, 0xec, 0xc1, 0x92, 0x01, - 0xd2, 0x1a, 0xd5, 0x9b, 0xec, 0xc5, 0x96, 0x0b, 0x07, 0xff, 0xff, - 0xc5, 0xd6, 0x11, 0x93, 0x97, 0xec, 0xc5, 0x98, 0xc1, 0xd8, 0x11, - 0x93, 0x97, 0xec, 0x09, 0x05, 0x0b, 0x00, 0x03, 0xd4, 0xc2, 0x96, - 0x06, 0xd6, 0x7b, 0x95, 0x7a, 0x95, 0x4c, 0x02, 0xc1, 0x92, 0x59, - 0x93, 0x59, 0x93, 0x01, 0xa5, 0x01, 0x98, 0x0c, 0xf5, 0x7b, 0x93, - 0x09, 0x09, 0x01, 0x00, 0x06, 0x92, 0x09, 0xb3, 0xff, 0x00, 0x04, - 0xd2, 0x5c, 0x93, 0x59, 0x93, 0x04, 0x94, 0x01, 0xa5, 0x03, 0x96, - 0xc3, 0xd4, 0x11, 0x93, 0x97, 0xec, 0x4c, 0x02, 0x05, 0xd2, 0xc1, - 0x92, 0x09, 0xb3, 0x00, 0xff, 0x7c, 0x95, 0x7a, 0x95, 0x02, 0xa3, - 0x05, 0x98, 0xc4, 0xd2, 0x12, 0x95, 0x97, 0xec, 0x45, 0x04, 0x02, - 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x00, 0x01, 0xc2, 0xd2, 0x12, 0x95, - 0x9b, 0xec, 0x0a, 0xb3, 0x08, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x01, 0xf0, 0x12, 0x95, 0x97, 0xec, 0x4a, 0x04, 0x02, 0x99, - 0xc4, 0x92, 0x01, 0x98, 0x0c, 0xf3, 0x7b, 0x93, 0x41, 0x02, 0x0f, - 0x9f, 0x22, 0xf0, 0x43, 0x44, 0x02, 0x8e, 0x0f, 0x9f, 0x23, 0xf0, - 0x11, 0x93, 0x97, 0xec, 0x42, 0x02, 0x0a, 0x05, 0xff, 0xff, 0xc1, - 0xd4, 0x11, 0x93, 0x97, 0xec, 0x4a, 0x02, 0x12, 0x95, 0x60, 0x96, - 0xc1, 0xd4, 0x12, 0x95, 0x97, 0xec, 0x4b, 0x04, 0x02, 0x97, 0xc3, - 0x92, 0x09, 0xb3, 0x1f, 0xff, 0xc2, 0xd2, 0x12, 0x95, 0x97, 0xec, - 0x4b, 0x04, 0x11, 0x93, 0x62, 0x96, 0x41, 0x93, 0x59, 0x93, 0x02, - 0x99, 0xc4, 0xa2, 0xc2, 0xd2, 0xc5, 0x92, 0x19, 0xd3, 0x98, 0xec, - 0x0a, 0x95, 0x0c, 0x02, 0x1a, 0xd5, 0x02, 0x80, 0x0f, 0x9f, 0x57, - 0xf0, 0x09, 0x63, 0xfe, 0x7f, 0x01, 0x97, 0xc3, 0x94, 0x0a, 0xa5, - 0x00, 0x04, 0xc1, 0xd4, 0x11, 0x93, 0x9f, 0xec, 0x09, 0xa3, 0x00, - 0x01, 0x19, 0xd3, 0x9f, 0xec, 0x40, 0xf0, 0xdf, 0xee, 0x0f, 0x9f, - 0x57, 0xf0, 0x11, 0x93, 0x94, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, - 0x9f, 0x4c, 0xf0, 0x40, 0xf0, 0xdf, 0xee, 0x11, 0x93, 0x95, 0xec, - 0x44, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x57, 0xf0, 0x48, - 0x98, 0x1c, 0xd9, 0x02, 0x80, 0x11, 0x93, 0x91, 0xec, 0x41, 0x22, - 0x0a, 0x95, 0x57, 0xf0, 0x88, 0xd4, 0x88, 0xdc, 0x91, 0x9a, 0x47, - 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, - 0x11, 0x93, 0x04, 0x82, 0x48, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x6e, 0xf0, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, - 0x09, 0xb3, 0xff, 0xfe, 0xc2, 0xd2, 0x41, 0x92, 0x19, 0xd3, 0xbf, - 0xec, 0x11, 0x93, 0x04, 0x82, 0x43, 0xb2, 0x12, 0x95, 0x03, 0x82, - 0x02, 0xb3, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x95, 0xf0, 0x0a, - 0xb3, 0x00, 0xff, 0x48, 0xa2, 0x19, 0xd3, 0x03, 0x82, 0x40, 0xf0, - 0x82, 0xf3, 0x11, 0x93, 0xbf, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, - 0x9f, 0x95, 0xf0, 0x11, 0x93, 0x07, 0x82, 0x11, 0x43, 0x03, 0xec, - 0x02, 0x0e, 0x0f, 0x9f, 0x95, 0xf0, 0x11, 0x93, 0x03, 0x82, 0x09, - 0xa3, 0x00, 0x01, 0x19, 0xd3, 0x03, 0x82, 0x40, 0x96, 0x1b, 0xd7, - 0xbf, 0xec, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x11, 0x93, 0x20, 0xbc, 0xc8, 0xd2, 0x40, 0xf0, 0xe9, 0xf0, - 0x41, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x42, 0x20, 0x08, - 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x05, 0x00, 0x05, 0x94, 0x41, 0x02, - 0xc1, 0x92, 0x01, 0x97, 0xc3, 0x96, 0xc2, 0xd6, 0x0a, 0x45, 0x00, - 0x95, 0x02, 0x5e, 0x0f, 0x9f, 0xe6, 0xf0, 0xc1, 0x92, 0x41, 0xb2, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xe6, 0xf0, 0x11, 0x93, 0xc0, - 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe6, 0xf0, 0x41, 0x98, - 0x1c, 0xd9, 0xc0, 0xec, 0x12, 0x95, 0x02, 0x80, 0x01, 0xd4, 0x40, - 0xf0, 0xfe, 0xf1, 0x0b, 0x67, 0xfd, 0x7d, 0x03, 0x99, 0xc4, 0x92, - 0x0c, 0x99, 0x96, 0x03, 0x1c, 0xd9, 0x06, 0x82, 0x41, 0x98, 0x1c, - 0xd9, 0x02, 0x82, 0x42, 0x98, 0x1c, 0xd9, 0x05, 0x82, 0x0c, 0x69, - 0x80, 0x7f, 0x1c, 0xd9, 0x00, 0xb0, 0x09, 0xa3, 0x00, 0x01, 0xc3, - 0xd2, 0x01, 0x94, 0x0a, 0xb3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0xe4, 0xf0, 0x42, 0xa4, 0x1a, 0xd5, 0x02, 0x80, 0x42, - 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x42, 0x20, 0x08, 0x0b, - 0x01, 0x00, 0x05, 0x92, 0xc5, 0xd2, 0x60, 0xb2, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0xf6, 0xf0, 0x40, 0xf0, 0xd2, 0xf6, 0xc5, 0x94, - 0x0a, 0xb3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xff, - 0xf0, 0x40, 0xf0, 0xc0, 0xf5, 0xc5, 0x96, 0x0b, 0xb3, 0x40, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x08, 0xf1, 0x40, 0xf0, 0xfa, - 0xf4, 0xc5, 0x94, 0x0a, 0xb3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0x70, 0xf1, 0x13, 0x97, 0x21, 0xbc, 0x01, 0xd6, 0x0b, - 0xb3, 0x02, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x1a, 0xf1, - 0x40, 0xf0, 0x62, 0xfb, 0x01, 0x94, 0x0a, 0xb3, 0x04, 0x00, 0x40, - 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x23, 0xf1, 0x40, 0xf0, 0x6c, 0xfb, - 0x01, 0x96, 0x0b, 0xb3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x4c, 0xf1, 0x40, 0xf0, 0xb0, 0xfa, 0x41, 0x92, 0x19, 0xd3, - 0x73, 0xf7, 0x11, 0x93, 0x03, 0xec, 0x09, 0x43, 0x40, 0x00, 0x02, - 0x5e, 0x0f, 0x9f, 0x39, 0xf1, 0x40, 0x94, 0x1a, 0xd5, 0x73, 0xf7, - 0x11, 0x93, 0x00, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x55, - 0xf1, 0x11, 0x93, 0xc1, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0x55, 0xf1, 0x40, 0xf0, 0xe0, 0xf1, 0x41, 0x96, 0x1b, 0xd7, 0xc1, - 0xec, 0x0f, 0x9f, 0x55, 0xf1, 0x01, 0x94, 0x0a, 0xb3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x55, 0xf1, 0x40, 0xf0, 0x7c, - 0xfb, 0x01, 0x96, 0x0b, 0xb3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0x5e, 0xf1, 0x40, 0xf0, 0x87, 0xfb, 0x11, 0x93, 0x10, - 0xec, 0x42, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x67, 0xf1, 0x44, 0x92, - 0x0f, 0x9f, 0x6b, 0xf1, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x6d, - 0xf1, 0x19, 0xd3, 0x0b, 0xbc, 0x40, 0x94, 0x1a, 0xd5, 0x10, 0xec, - 0xc5, 0x96, 0x0b, 0xb3, 0x80, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0xba, 0xf1, 0x11, 0x93, 0x28, 0xbc, 0x01, 0xd2, 0x09, 0xb3, - 0x40, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x82, 0xf1, 0x40, - 0xf0, 0xb5, 0xf6, 0x01, 0x94, 0x0a, 0xb3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x95, 0xf1, 0x40, 0xf0, 0x6d, 0xee, 0x40, - 0xf0, 0x8f, 0xfb, 0x40, 0xf0, 0xc3, 0xf1, 0x40, 0x96, 0x1b, 0xd7, - 0x00, 0xec, 0x41, 0x92, 0x19, 0xd3, 0x76, 0xf7, 0x01, 0x94, 0x0a, - 0xb3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xb1, 0xf1, - 0x40, 0xf0, 0x9e, 0xfb, 0x09, 0x63, 0x00, 0x44, 0x01, 0x97, 0xc3, - 0x94, 0x48, 0xa4, 0xc1, 0xd4, 0x00, 0xee, 0x40, 0x92, 0x19, 0xd3, - 0x12, 0x95, 0x19, 0xd3, 0x10, 0x95, 0x19, 0xd3, 0x02, 0x80, 0x19, - 0xd3, 0x03, 0x82, 0x41, 0x92, 0x19, 0xd3, 0x76, 0xf7, 0x01, 0x94, - 0x0a, 0xb3, 0x08, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xba, - 0xf1, 0x40, 0xf0, 0xae, 0xfb, 0x0a, 0x65, 0x00, 0x44, 0x02, 0x97, - 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x42, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xd3, 0xf2, 0xbd, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, - 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, - 0x63, 0x00, 0x80, 0x19, 0xd3, 0xf2, 0xbd, 0x0a, 0x65, 0xe8, 0x43, - 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, 0x0a, - 0x65, 0xeb, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, - 0xc2, 0xd2, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, - 0xb3, 0xfb, 0xff, 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x09, 0x93, 0x00, 0x01, 0x19, 0xd3, 0x02, - 0x80, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, - 0x09, 0x93, 0x00, 0x09, 0x19, 0xd3, 0x02, 0x80, 0x40, 0xf0, 0xfe, - 0xf1, 0x40, 0x92, 0x19, 0xd3, 0x94, 0xec, 0xc8, 0xd2, 0x09, 0x93, - 0x91, 0xec, 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, - 0xd8, 0xf4, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x2d, 0xf2, 0x0a, - 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, - 0x0f, 0x9f, 0x3a, 0xf2, 0x40, 0xf0, 0x3c, 0xf2, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x3a, 0xf2, 0xc8, 0xd2, 0x09, 0x93, 0x91, 0xec, - 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0xf1, 0xbd, - 0x19, 0xd3, 0xb6, 0xec, 0x11, 0x93, 0xb4, 0xec, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x54, 0xf2, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xc3, 0x94, 0x0a, 0x07, 0x07, 0x00, 0xc1, 0xd6, 0x0a, 0x05, 0x00, - 0xa0, 0x1a, 0xd5, 0x96, 0xec, 0x11, 0x93, 0xb6, 0xec, 0x19, 0xd3, - 0x01, 0x80, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x41, - 0xa2, 0xc2, 0xd2, 0x40, 0x92, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x41, 0x20, 0x08, 0x0b, 0x01, 0x00, 0x13, 0x97, 0xb4, 0xec, 0x40, - 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xc3, 0xf2, 0x12, 0x95, 0x96, 0xec, - 0x0a, 0x03, 0x07, 0x00, 0xc1, 0x92, 0xc2, 0xd2, 0x11, 0x93, 0x96, - 0xec, 0x09, 0x05, 0x01, 0x00, 0x48, 0x02, 0xc1, 0x92, 0xc2, 0xd2, - 0x11, 0x93, 0x96, 0xec, 0x4e, 0x02, 0xc1, 0x94, 0xc5, 0xd6, 0xc5, - 0x92, 0x11, 0x07, 0x96, 0xec, 0x0b, 0x03, 0x0f, 0x00, 0xc1, 0x98, - 0x46, 0x06, 0x7a, 0x93, 0x79, 0x93, 0x5c, 0x95, 0x5a, 0x95, 0x02, - 0xa3, 0xc3, 0xd2, 0x04, 0x95, 0xc5, 0x96, 0x41, 0x06, 0xc5, 0xd6, - 0x42, 0x46, 0x02, 0x9e, 0x0f, 0x9f, 0x7d, 0xf2, 0x11, 0x93, 0x96, - 0xec, 0x09, 0x05, 0x05, 0x00, 0x41, 0x02, 0xc1, 0x92, 0xc2, 0xd2, - 0x11, 0x93, 0x96, 0xec, 0xc1, 0x92, 0x09, 0xb5, 0x1f, 0x00, 0x43, - 0x44, 0x02, 0x8e, 0x0f, 0x9f, 0xaa, 0xf2, 0x40, 0x44, 0x02, 0x4e, - 0x0f, 0x9f, 0xab, 0xf2, 0x0a, 0x05, 0xff, 0xff, 0x0f, 0x9f, 0xab, - 0xf2, 0x43, 0x94, 0x11, 0x93, 0x96, 0xec, 0x42, 0x02, 0xc1, 0xd4, - 0x13, 0x97, 0x96, 0xec, 0x03, 0x93, 0xd1, 0x94, 0x7a, 0x95, 0x7a, - 0x95, 0xc1, 0x92, 0x59, 0x93, 0x59, 0x93, 0x01, 0x05, 0x49, 0x06, - 0xc3, 0x92, 0x7f, 0xb2, 0x01, 0x05, 0x1a, 0xd5, 0xb4, 0xec, 0x0a, - 0x05, 0xf2, 0xff, 0x1a, 0xd5, 0x92, 0xec, 0x11, 0x93, 0x92, 0xec, - 0x12, 0x95, 0xb6, 0xec, 0x02, 0x43, 0x02, 0x8e, 0x0f, 0x9f, 0x11, - 0xf3, 0x02, 0x0e, 0x0f, 0x9f, 0xe4, 0xf2, 0x11, 0x93, 0x7a, 0xf7, - 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, 0x93, 0x79, 0xf7, 0x09, - 0xa3, 0x80, 0x00, 0x19, 0xd3, 0x79, 0xf7, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x95, 0xc2, 0x94, 0x1a, 0xd5, 0xb5, 0xec, 0x40, 0x96, 0x1b, - 0xd7, 0xb4, 0xec, 0x0f, 0x9f, 0x29, 0xf3, 0x11, 0x93, 0x03, 0x80, - 0x09, 0xb3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xf6, - 0xf2, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0xf6, 0xf2, 0x40, 0xf0, 0x3d, 0xf3, 0x0f, 0x9f, 0x2b, 0xf3, 0x41, - 0x92, 0xc8, 0xd2, 0x0a, 0x95, 0x91, 0xec, 0xc8, 0xd4, 0x40, 0xf0, - 0xd0, 0xee, 0x42, 0x00, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0x09, 0xf3, 0x42, 0x96, 0x1b, 0xd7, 0xc0, 0xec, - 0x0f, 0x9f, 0x2b, 0xf3, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, - 0x92, 0x42, 0xa2, 0xc2, 0xd2, 0x0f, 0x9f, 0x2b, 0xf3, 0x12, 0x45, - 0x03, 0xec, 0x02, 0x4e, 0x0f, 0x9f, 0x23, 0xf3, 0x11, 0x93, 0x7a, - 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, 0x93, 0x79, 0xf7, - 0x09, 0xa3, 0x00, 0x08, 0x19, 0xd3, 0x79, 0xf7, 0x1a, 0xd5, 0x92, - 0xec, 0x11, 0x93, 0x92, 0xec, 0x19, 0x25, 0x92, 0xec, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xd3, 0xf2, 0xbd, 0x41, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, 0x3d, 0xf3, - 0x40, 0x92, 0xc8, 0xd2, 0x09, 0x93, 0x91, 0xec, 0xc8, 0xd2, 0x40, - 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0x75, 0xf7, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0x4d, 0xf3, 0x0a, 0x65, 0xbc, 0x69, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0x83, 0x00, 0x02, 0xc2, 0xd2, 0x11, 0x93, 0x03, - 0x80, 0x09, 0xb3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0x60, 0xf3, 0x11, 0x93, 0x7a, 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, - 0xf7, 0x11, 0x93, 0x79, 0xf7, 0x09, 0xa3, 0x00, 0x20, 0x19, 0xd3, - 0x79, 0xf7, 0x11, 0x93, 0xb5, 0xec, 0x19, 0xd3, 0x04, 0x80, 0x12, - 0x95, 0xb4, 0xec, 0x1a, 0xd5, 0x05, 0x80, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x97, 0xc3, 0x96, 0x1b, 0xd7, 0xb5, 0xec, 0x40, 0x94, 0x1a, - 0xd5, 0xb4, 0xec, 0x19, 0xd3, 0xf2, 0xbd, 0x88, 0x98, 0x90, 0x9a, - 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x93, 0x96, 0x03, 0x19, - 0xd3, 0x06, 0x82, 0x09, 0x93, 0x00, 0x01, 0x19, 0xd3, 0x03, 0x82, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x47, 0x20, 0x08, 0x0b, 0x01, - 0x00, 0x11, 0x93, 0x01, 0x82, 0xc5, 0xd2, 0x40, 0x94, 0x01, 0xd4, - 0x13, 0x97, 0xb8, 0xec, 0x02, 0xd6, 0x03, 0x95, 0x0c, 0x99, 0xbb, - 0xec, 0x04, 0x05, 0x13, 0x97, 0x03, 0xec, 0x01, 0x27, 0x02, 0x99, - 0xc4, 0x92, 0x03, 0x03, 0xc2, 0xd2, 0x14, 0x99, 0xba, 0xec, 0x03, - 0x09, 0x1c, 0xd9, 0xba, 0xec, 0x12, 0x95, 0x04, 0x82, 0x0a, 0xb3, - 0x02, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xc6, 0xf4, 0x01, - 0x92, 0x03, 0xd2, 0x0a, 0xa3, 0x02, 0x00, 0x19, 0xd3, 0x04, 0x82, - 0x02, 0x96, 0x0b, 0x05, 0x01, 0x00, 0x1a, 0xd5, 0xb8, 0xec, 0xc5, - 0x92, 0x43, 0x42, 0x02, 0x9e, 0x0f, 0x9f, 0xce, 0xf3, 0x42, 0x44, - 0x02, 0x8e, 0x0f, 0x9f, 0xce, 0xf3, 0x11, 0x93, 0xbf, 0xec, 0x40, - 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xce, 0xf3, 0x0c, 0x49, 0xd3, 0x08, - 0x02, 0x8e, 0x0f, 0x9f, 0xce, 0xf3, 0x11, 0x63, 0x07, 0x82, 0x11, - 0xa3, 0x07, 0x82, 0x71, 0x93, 0x79, 0x93, 0x79, 0x93, 0x79, 0x93, - 0x03, 0xd2, 0xc5, 0x94, 0x0a, 0xb5, 0xfc, 0xff, 0x04, 0xd4, 0x03, - 0x96, 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xdd, 0xf3, 0x11, 0x93, - 0xb8, 0xec, 0x41, 0x42, 0x02, 0x8e, 0x0f, 0x9f, 0xe4, 0xf3, 0xc5, - 0x98, 0x0c, 0x03, 0xff, 0xff, 0x42, 0x42, 0x02, 0x8e, 0x0f, 0x9f, - 0x0b, 0xf4, 0x0a, 0x95, 0xbb, 0xec, 0x42, 0x92, 0x19, 0xd3, 0xb9, - 0xec, 0xc5, 0x96, 0x43, 0x46, 0x02, 0x9e, 0x0f, 0x9f, 0xfd, 0xf3, - 0x0b, 0x07, 0xfc, 0xff, 0xc5, 0xd6, 0xd2, 0x98, 0x1c, 0xd9, 0xc8, - 0xbc, 0xd2, 0x96, 0x1b, 0xd7, 0xca, 0xbc, 0x09, 0x03, 0xff, 0xff, - 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe9, 0xf3, 0x19, 0xd3, 0xb9, - 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x09, 0xf4, 0x0a, 0x05, - 0xfe, 0xff, 0xca, 0xd2, 0xc2, 0xd2, 0x0f, 0x9f, 0x0b, 0xf4, 0x1a, - 0xd5, 0x93, 0xec, 0x03, 0x98, 0x40, 0x48, 0x02, 0x5e, 0x0f, 0x9f, - 0x38, 0xf4, 0x11, 0x93, 0xb8, 0xec, 0x41, 0x42, 0x02, 0x9e, 0x0f, - 0x9f, 0x1b, 0xf4, 0x04, 0x94, 0x48, 0x44, 0x02, 0x4e, 0x0f, 0x9f, - 0x26, 0xf4, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x38, 0xf4, 0x11, - 0x93, 0x04, 0x82, 0x41, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, - 0x38, 0xf4, 0x41, 0x96, 0x01, 0xd6, 0x0a, 0x65, 0xbd, 0x43, 0x02, - 0x99, 0xc4, 0x92, 0x09, 0xa3, 0x80, 0x00, 0xc2, 0xd2, 0x0a, 0x65, - 0xe8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, - 0xd2, 0x0f, 0x9f, 0x97, 0xf4, 0xc5, 0x98, 0x43, 0x48, 0x02, 0x9e, - 0x0f, 0x9f, 0x97, 0xf4, 0x4f, 0x96, 0x0c, 0xb3, 0x01, 0x00, 0x40, - 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x45, 0xf4, 0x47, 0x96, 0x11, 0x93, - 0xb7, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x73, 0xf4, 0x11, - 0x93, 0xb8, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x73, 0xf4, - 0x12, 0x95, 0x00, 0x82, 0x0a, 0x05, 0xff, 0xaf, 0x05, 0xd4, 0xc8, - 0xd6, 0xc8, 0xd2, 0x40, 0xf0, 0x18, 0xf7, 0x42, 0x00, 0x05, 0x96, - 0xc3, 0x94, 0x01, 0xb5, 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0x68, - 0xf4, 0x11, 0x93, 0xba, 0xec, 0x4d, 0x42, 0x02, 0x8e, 0x0f, 0x9f, - 0x73, 0xf4, 0x06, 0x98, 0x50, 0x98, 0x1c, 0xd9, 0xa2, 0xbc, 0x40, - 0x98, 0x1c, 0xd9, 0xa2, 0xbc, 0x40, 0x92, 0x03, 0xd2, 0x0f, 0x9f, - 0x9c, 0xf4, 0x03, 0x94, 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0x80, - 0xf4, 0x0a, 0x65, 0x5e, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x48, 0xa2, - 0xc2, 0xd2, 0x0f, 0x9f, 0x9c, 0xf4, 0x11, 0x93, 0xb8, 0xec, 0x0c, - 0x99, 0xbb, 0xec, 0x04, 0x03, 0x04, 0x96, 0x13, 0x25, 0x03, 0xec, - 0xc1, 0xd4, 0x11, 0x93, 0xba, 0xec, 0x19, 0x05, 0xba, 0xec, 0x1b, - 0xd7, 0x01, 0x82, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x99, 0xc4, 0x92, - 0x43, 0xa2, 0xc2, 0xd2, 0x41, 0x92, 0x01, 0xd2, 0x03, 0x94, 0x40, - 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0xb0, 0xf4, 0x11, 0x93, 0xb9, 0xec, - 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xa8, 0xf4, 0x19, 0xd3, 0xb8, - 0xec, 0x19, 0xd3, 0xba, 0xec, 0x19, 0xd3, 0xbb, 0xec, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xb0, 0xf4, 0x41, 0x98, 0x1c, - 0xd9, 0xb7, 0xec, 0x11, 0x93, 0xbf, 0xec, 0x41, 0x42, 0x02, 0x5e, - 0x0f, 0x9f, 0xc1, 0xf4, 0x11, 0x93, 0x00, 0x82, 0x19, 0xd3, 0x02, - 0x82, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, - 0x00, 0x01, 0xc2, 0xd2, 0x40, 0x98, 0x1c, 0xd9, 0xbf, 0xec, 0x0f, - 0x9f, 0xc9, 0xf4, 0x01, 0x92, 0x19, 0xd3, 0xb7, 0xec, 0x01, 0x94, - 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0xd5, 0xf4, 0x0a, 0x65, 0xea, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xfb, 0xff, 0xc2, 0xd2, - 0x47, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x12, 0x95, 0x03, 0x80, 0x0a, 0xb3, 0x00, 0x40, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0xf4, 0xf4, 0x0a, 0xb7, 0x00, 0x08, 0x40, - 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xf7, 0xf4, 0x11, 0x93, 0x03, 0xec, - 0x41, 0x02, 0x09, 0xb3, 0xfe, 0xff, 0x12, 0x95, 0x07, 0x80, 0x01, - 0x45, 0x02, 0x8e, 0x0f, 0x9f, 0xf7, 0xf4, 0x41, 0x92, 0x0f, 0x9f, - 0xf8, 0xf4, 0x40, 0x92, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x41, - 0x20, 0x08, 0x0b, 0x01, 0x00, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, 0xd2, 0x13, 0x97, 0x6e, - 0xec, 0x0b, 0x47, 0xa0, 0x00, 0x02, 0x5e, 0x0f, 0x9f, 0x23, 0xf5, - 0x09, 0x63, 0x08, 0x43, 0x0a, 0x65, 0xff, 0x5f, 0x01, 0x99, 0xc4, - 0xd4, 0x0a, 0x95, 0x9b, 0xec, 0xd2, 0x96, 0x1b, 0xd7, 0xfa, 0xbc, - 0xd2, 0x96, 0xc4, 0xd6, 0xd2, 0x98, 0x1c, 0xd9, 0xfa, 0xbc, 0xd2, - 0x96, 0xc1, 0xd6, 0xc2, 0x94, 0x1a, 0xd5, 0xfa, 0xbc, 0x0f, 0x9f, - 0x61, 0xf5, 0x0c, 0x69, 0xff, 0x6f, 0x1c, 0xd9, 0xf8, 0xbc, 0x0b, - 0x47, 0x10, 0x95, 0x02, 0x5e, 0x0f, 0x9f, 0x3b, 0xf5, 0x0a, 0x95, - 0x6f, 0xec, 0x09, 0x63, 0x06, 0x43, 0x01, 0x99, 0xc4, 0xd6, 0xd2, - 0x96, 0x1b, 0xd7, 0xf8, 0xbc, 0x0c, 0x69, 0xee, 0x6a, 0xc1, 0xd8, - 0xc2, 0x94, 0x1a, 0xd5, 0xf8, 0xbc, 0x40, 0x92, 0xc5, 0xd2, 0x11, - 0x43, 0xc2, 0xec, 0x02, 0x0e, 0x0f, 0x9f, 0x5e, 0xf5, 0xc5, 0x94, - 0x0a, 0x03, 0x71, 0xec, 0xc1, 0x94, 0x1a, 0xd5, 0xfa, 0xbc, 0x11, - 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x50, 0xf5, - 0x0a, 0x95, 0x6f, 0xec, 0xc8, 0xd4, 0x40, 0xf0, 0x39, 0xf7, 0x19, - 0xd3, 0xf8, 0xbc, 0x41, 0x00, 0xc5, 0x96, 0x41, 0x06, 0xc5, 0xd6, - 0x13, 0x47, 0xc2, 0xec, 0x02, 0x1e, 0x0f, 0x9f, 0x42, 0xf5, 0x40, - 0x98, 0x1c, 0xd9, 0xfa, 0xbc, 0x40, 0x92, 0x19, 0xd3, 0x6e, 0xec, - 0x19, 0xd3, 0xc2, 0xec, 0x0a, 0x65, 0x52, 0x43, 0x02, 0x97, 0xc3, - 0x92, 0x48, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, 0x43, 0x02, 0x99, - 0xc4, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, 0xd2, 0x41, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x43, 0x20, 0x08, 0x0b, 0x01, 0x00, - 0x06, 0x92, 0x01, 0xd2, 0x0a, 0x65, 0xf0, 0x6a, 0x0b, 0x97, 0x6f, - 0xec, 0x02, 0x99, 0xc4, 0x98, 0xd3, 0xd8, 0x02, 0xd6, 0x0a, 0x03, - 0x02, 0x00, 0x01, 0x97, 0xc3, 0x98, 0x02, 0x96, 0xc3, 0xd8, 0x01, - 0x96, 0xc1, 0xd6, 0x1a, 0xd5, 0x6e, 0xec, 0xc5, 0x98, 0x14, 0x99, - 0x6f, 0xec, 0xc2, 0xd8, 0x43, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, - 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0x92, 0xc8, 0xd2, 0x40, 0xf0, - 0x76, 0xf5, 0x41, 0x00, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0xb0, 0xf5, 0x42, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0xad, 0xf5, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x42, - 0xa2, 0xc2, 0xd2, 0x40, 0x92, 0x19, 0xd3, 0xc0, 0xec, 0x0a, 0x65, - 0xeb, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, - 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, - 0xbf, 0xff, 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x63, - 0x20, 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0xaf, 0xbc, 0x47, 0xb2, - 0x59, 0x95, 0x5a, 0x95, 0x12, 0xa5, 0xbf, 0xbc, 0x0a, 0xb3, 0x01, - 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xd2, 0xf5, 0x41, 0x04, - 0x05, 0x93, 0x40, 0x96, 0x20, 0xd6, 0x62, 0x97, 0x0f, 0x9f, 0xe1, - 0xf5, 0x14, 0x99, 0xfc, 0xbc, 0xd1, 0xd8, 0x14, 0x99, 0xfe, 0xbc, - 0xd1, 0xd8, 0x20, 0x98, 0x42, 0x08, 0x20, 0xd8, 0x20, 0x98, 0x03, - 0x49, 0x02, 0x1e, 0x0f, 0x9f, 0xd8, 0xf5, 0xc5, 0x92, 0x62, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0xfa, 0xf5, 0x02, 0x8e, 0x0f, 0x9f, 0xf4, - 0xf5, 0x61, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x1e, 0xf6, 0x0f, 0x9f, - 0x4b, 0xf6, 0x63, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x41, 0xf6, 0x0f, - 0x9f, 0x4b, 0xf6, 0x0d, 0x03, 0x01, 0x00, 0x0c, 0x99, 0x71, 0xec, - 0x0b, 0x05, 0xff, 0xff, 0x40, 0x96, 0x0f, 0x9f, 0x07, 0xf6, 0xd1, - 0x96, 0xd4, 0xd6, 0x20, 0x96, 0x41, 0x06, 0x20, 0xd6, 0x02, 0x47, - 0x02, 0x1e, 0x0f, 0x9f, 0x03, 0xf6, 0x1a, 0xd5, 0xc2, 0xec, 0x0a, - 0x65, 0xeb, 0x43, 0x02, 0x99, 0xc4, 0x92, 0x09, 0xa3, 0xc0, 0x00, - 0xc2, 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, - 0xb3, 0xbf, 0xff, 0xc2, 0xd2, 0x0f, 0x9f, 0x4b, 0xf6, 0x0a, 0x03, - 0xfe, 0xff, 0x61, 0x95, 0x40, 0x98, 0x20, 0xd8, 0x02, 0x49, 0x02, - 0x0e, 0x0f, 0x9f, 0x4b, 0xf6, 0x0d, 0x03, 0x01, 0x00, 0x21, 0xd2, - 0x20, 0x92, 0x05, 0x03, 0x42, 0x02, 0xc8, 0xd2, 0x21, 0x96, 0xc3, - 0x92, 0x42, 0x06, 0x21, 0xd6, 0xc8, 0xd2, 0x22, 0xd4, 0x40, 0xf0, - 0xa2, 0xf0, 0x42, 0x00, 0x20, 0x98, 0x42, 0x08, 0x20, 0xd8, 0x22, - 0x94, 0x02, 0x49, 0x02, 0x1e, 0x0f, 0x9f, 0x2a, 0xf6, 0x0f, 0x9f, - 0x4b, 0xf6, 0x0d, 0x03, 0x03, 0x00, 0xc8, 0xd2, 0x02, 0x92, 0xc8, - 0xd2, 0x01, 0x96, 0xc8, 0xd6, 0x40, 0xf0, 0x4e, 0xf6, 0x43, 0x00, - 0x63, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x45, 0x20, 0x08, - 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x08, 0x00, 0x08, 0x94, 0xc5, 0xd4, - 0x09, 0x05, 0x01, 0x00, 0xc2, 0x94, 0x03, 0xd4, 0x42, 0x02, 0xc1, - 0x92, 0x01, 0xd2, 0x02, 0x97, 0xc5, 0x94, 0x0a, 0x83, 0xff, 0xff, - 0x11, 0xb3, 0x2c, 0x93, 0x09, 0xb3, 0xfb, 0xff, 0x19, 0xd3, 0x2c, - 0x93, 0x03, 0x92, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x81, 0xf6, - 0x01, 0x94, 0xd2, 0x92, 0x19, 0xd3, 0x2c, 0x93, 0x01, 0xd4, 0x02, - 0x94, 0x12, 0x95, 0x2c, 0x93, 0x44, 0xa4, 0x1a, 0xd5, 0x2c, 0x93, - 0x0a, 0xb5, 0xfb, 0xff, 0x1a, 0xd5, 0x2c, 0x93, 0x0b, 0x07, 0xff, - 0xff, 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0x6c, 0xf6, 0x09, 0x63, - 0xd4, 0x6c, 0x01, 0x95, 0xc2, 0x96, 0xc5, 0x94, 0x02, 0xa7, 0xc1, - 0xd6, 0x03, 0x92, 0x54, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x91, 0xf6, - 0x0a, 0x83, 0xff, 0xff, 0x1b, 0xb3, 0x2c, 0x93, 0x45, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x63, - 0x00, 0x40, 0x19, 0xd3, 0xf2, 0xbd, 0x40, 0xf0, 0xd8, 0xf4, 0x40, - 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xa5, 0xf6, 0x40, 0xf0, 0x3c, 0xf2, - 0x0f, 0x9f, 0xb3, 0xf6, 0x40, 0x96, 0xc8, 0xd6, 0x09, 0x93, 0x91, - 0xec, 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x0a, 0x65, 0xfe, 0x7f, - 0x02, 0x97, 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x42, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x0a, 0x65, - 0xe8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, - 0xd2, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, - 0xfb, 0xff, 0xc2, 0xd2, 0x40, 0x92, 0x19, 0xd3, 0x2d, 0xbc, 0x0a, - 0x65, 0xd8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, - 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x09, 0x63, 0xea, 0x43, 0x01, 0x97, 0xc3, 0x94, 0x44, 0xa4, - 0xc1, 0xd4, 0x11, 0x93, 0xb9, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x0c, 0xf7, 0x12, 0x95, 0x93, 0xec, 0x0b, 0x67, 0x36, 0x43, - 0xd2, 0x98, 0x1c, 0xd9, 0xc8, 0xbc, 0xd2, 0x98, 0x03, 0x93, 0xc1, - 0xd8, 0x11, 0x93, 0xb9, 0xec, 0x09, 0x03, 0xff, 0xff, 0x19, 0xd3, - 0xb9, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe5, 0xf6, 0x19, - 0xd3, 0xb8, 0xec, 0x19, 0xd3, 0xba, 0xec, 0x0a, 0x05, 0xfe, 0xff, - 0xca, 0xd2, 0xca, 0xd2, 0xc2, 0xd2, 0x0a, 0x65, 0x5e, 0x43, 0x02, - 0x97, 0xc3, 0x92, 0x48, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xea, 0x43, - 0x02, 0x99, 0xc4, 0x92, 0x09, 0xb3, 0xfb, 0xff, 0x0f, 0x9f, 0x15, - 0xf7, 0x11, 0x93, 0x03, 0xec, 0x19, 0xd3, 0x01, 0x82, 0x0a, 0x65, - 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, 0x43, 0xa2, 0xc2, 0xd2, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x03, 0x92, - 0x04, 0x96, 0x0d, 0x5e, 0x50, 0x46, 0x02, 0x0e, 0x40, 0x92, 0x09, - 0xee, 0x44, 0x46, 0x04, 0x0e, 0x59, 0x93, 0x44, 0x26, 0x04, 0x5e, - 0x46, 0xee, 0x41, 0x93, 0x41, 0x26, 0x43, 0x4e, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, 0xb1, 0xfe, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x03, 0x94, - 0x1a, 0xd5, 0x40, 0xf7, 0x11, 0x93, 0x00, 0x90, 0x88, 0x98, 0x90, - 0x9a, 0x1d, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x03, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x16, 0x00, 0x21, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x13, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, - 0x21, 0x00, 0x2d, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf2, 0x6b, 0xf7, 0x00, 0x00, - 0x1c, 0xf2, 0x6b, 0xf7, 0x00, 0x00, 0x61, 0xf2, 0x68, 0xf7, 0x6f, - 0xf7, 0x00, 0x00, 0x2e, 0xf3, 0x6b, 0xf7, 0x25, 0x47, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/sys/dev/usb/if_zydreg.h b/sys/dev/usb/if_zydreg.h deleted file mode 100644 index feae22f..0000000 --- a/sys/dev/usb/if_zydreg.h +++ /dev/null @@ -1,1322 +0,0 @@ -/* $OpenBSD: if_zydreg.h,v 1.19 2006/11/30 19:28:07 damien Exp $ */ -/* $NetBSD: if_zydreg.h,v 1.2 2007/06/16 11:18:45 kiyohara Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr> - * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * ZyDAS ZD1211/ZD1211B USB WLAN driver. - */ - -#define ZYD_CR_GPI_EN 0x9418 -#define ZYD_CR_RADIO_PD 0x942c -#define ZYD_CR_RF2948_PD 0x942c -#define ZYD_CR_EN_PS_MANUAL_AGC 0x943c -#define ZYD_CR_CONFIG_PHILIPS 0x9440 -#define ZYD_CR_I2C_WRITE 0x9444 -#define ZYD_CR_SA2400_SER_RP 0x9448 -#define ZYD_CR_RADIO_PE 0x9458 -#define ZYD_CR_RST_BUS_MASTER 0x945c -#define ZYD_CR_RFCFG 0x9464 -#define ZYD_CR_HSTSCHG 0x946c -#define ZYD_CR_PHY_ON 0x9474 -#define ZYD_CR_RX_DELAY 0x9478 -#define ZYD_CR_RX_PE_DELAY 0x947c -#define ZYD_CR_GPIO_1 0x9490 -#define ZYD_CR_GPIO_2 0x9494 -#define ZYD_CR_EnZYD_CRyBufMux 0x94a8 -#define ZYD_CR_PS_CTRL 0x9500 -#define ZYD_CR_ADDA_PWR_DWN 0x9504 -#define ZYD_CR_ADDA_MBIAS_WT 0x9508 -#define ZYD_CR_INTERRUPT 0x9510 -#define ZYD_CR_MAC_PS_STATE 0x950c -#define ZYD_CR_ATIM_WND_PERIOD 0x951c -#define ZYD_CR_BCN_INTERVAL 0x9520 -#define ZYD_CR_PRE_TBTT 0x9524 - -/* - * MAC registers. - */ -#define ZYD_MAC_MACADRL 0x9610 /* MAC address (low) */ -#define ZYD_MAC_MACADRH 0x9614 /* MAC address (high) */ -#define ZYD_MAC_BSSADRL 0x9618 /* BSS address (low) */ -#define ZYD_MAC_BSSADRH 0x961c /* BSS address (high) */ -#define ZYD_MAC_BCNCFG 0x9620 /* BCN configuration */ -#define ZYD_MAC_GHTBL 0x9624 /* Group hash table (low) */ -#define ZYD_MAC_GHTBH 0x9628 /* Group hash table (high) */ -#define ZYD_MAC_RX_TIMEOUT 0x962c /* Rx timeout value */ -#define ZYD_MAC_BAS_RATE 0x9630 /* Basic rate setting */ -#define ZYD_MAC_MAN_RATE 0x9634 /* Mandatory rate setting */ -#define ZYD_MAC_RTSCTSRATE 0x9638 /* RTS CTS rate */ -#define ZYD_MAC_BACKOFF_PROTECT 0x963c /* Backoff protection */ -#define ZYD_MAC_RX_THRESHOLD 0x9640 /* Rx threshold */ -#define ZYD_MAC_TX_PE_CONTROL 0x9644 /* Tx_PE control */ -#define ZYD_MAC_AFTER_PNP 0x9648 /* After PnP */ -#define ZYD_MAC_RX_PE_DELAY 0x964c /* Rx_pe delay */ -#define ZYD_MAC_RX_ADDR2_L 0x9650 /* RX address2 (low) */ -#define ZYD_MAC_RX_ADDR2_H 0x9654 /* RX address2 (high) */ -#define ZYD_MAC_SIFS_ACK_TIME 0x9658 /* Dynamic SIFS ack time */ -#define ZYD_MAC_PHY_DELAY 0x9660 /* PHY delay */ -#define ZYD_MAC_PHY_DELAY2 0x966c /* PHY delay */ -#define ZYD_MAC_BCNFIFO 0x9670 /* Beacon FIFO I/O port */ -#define ZYD_MAC_SNIFFER 0x9674 /* Sniffer on/off */ -#define ZYD_MAC_ENCRYPTION_TYPE 0x9678 /* Encryption type */ -#define ZYD_MAC_RETRY 0x967c /* Retry time */ -#define ZYD_MAC_MISC 0x9680 /* Misc */ -#define ZYD_MAC_STMACHINESTAT 0x9684 /* State machine status */ -#define ZYD_MAC_TX_UNDERRUN_CNT 0x9688 /* TX underrun counter */ -#define ZYD_MAC_RXFILTER 0x968c /* Send to host settings */ -#define ZYD_MAC_ACK_EXT 0x9690 /* Acknowledge extension */ -#define ZYD_MAC_BCNFIFOST 0x9694 /* BCN FIFO set and status */ -#define ZYD_MAC_DIFS_EIFS_SIFS 0x9698 /* DIFS, EIFS & SIFS settings */ -#define ZYD_MAC_RX_TIMEOUT_CNT 0x969c /* RX timeout count */ -#define ZYD_MAC_RX_TOTAL_FRAME 0x96a0 /* RX total frame count */ -#define ZYD_MAC_RX_CRC32_CNT 0x96a4 /* RX CRC32 frame count */ -#define ZYD_MAC_RX_CRC16_CNT 0x96a8 /* RX CRC16 frame count */ -#define ZYD_MAC_RX_UDEC 0x96ac /* RX unicast decr. error count */ -#define ZYD_MAC_RX_OVERRUN_CNT 0x96b0 /* RX FIFO overrun count */ -#define ZYD_MAC_RX_MDEC 0x96bc /* RX multicast decr. err. cnt. */ -#define ZYD_MAC_NAV_TCR 0x96c4 /* NAV timer count read */ -#define ZYD_MAC_BACKOFF_ST_RD 0x96c8 /* Backoff status read */ -#define ZYD_MAC_DM_RETRY_CNT_RD 0x96cc /* DM retry count read */ -#define ZYD_MAC_RX_ACR 0x96d0 /* RX arbitration count read */ -#define ZYD_MAC_TX_CCR 0x96d4 /* Tx complete count read */ -#define ZYD_MAC_TCB_ADDR 0x96e8 /* Current PCI process TCP addr */ -#define ZYD_MAC_RCB_ADDR 0x96ec /* Next RCB address */ -#define ZYD_MAC_CONT_WIN_LIMIT 0x96f0 /* Contention window limit */ -#define ZYD_MAC_TX_PKT 0x96f4 /* Tx total packet count read */ -#define ZYD_MAC_DL_CTRL 0x96f8 /* Download control */ -#define ZYD_MAC_CAM_MODE 0x9700 /* CAM: Continuous Access Mode */ -#define ZYD_MACB_TXPWR_CTL1 0x9b00 -#define ZYD_MACB_TXPWR_CTL2 0x9b04 -#define ZYD_MACB_TXPWR_CTL3 0x9b08 -#define ZYD_MACB_TXPWR_CTL4 0x9b0c -#define ZYD_MACB_AIFS_CTL1 0x9b10 -#define ZYD_MACB_AIFS_CTL2 0x9b14 -#define ZYD_MACB_TXOP 0x9b20 -#define ZYD_MACB_MAX_RETRY 0x9b28 - -/* - * Miscellanous registers. - */ -#define ZYD_FIRMWARE_START_ADDR 0xee00 -#define ZYD_FIRMWARE_BASE_ADDR 0xee1d /* Firmware base address */ - -/* - * EEPROM registers. - */ -#define ZYD_EEPROM_START_HEAD 0xf800 /* EEPROM start */ -#define ZYD_EEPROM_SUBID 0xf817 -#define ZYD_EEPROM_POD 0xf819 -#define ZYD_EEPROM_MAC_ADDR_P1 0xf81b /* Part 1 of the MAC address */ -#define ZYD_EEPROM_MAC_ADDR_P2 0xf81d /* Part 2 of the MAC address */ -#define ZYD_EEPROM_PWR_CAL 0xf81f /* Calibration */ -#define ZYD_EEPROM_PWR_INT 0xf827 /* Calibration */ -#define ZYD_EEPROM_ALLOWEDCHAN 0xf82f /* Allowed CH mask, 1 bit each */ -#define ZYD_EEPROM_DEVICE_VER 0xf837 /* Device version */ -#define ZYD_EEPROM_PHY_REG 0xf83c /* PHY registers */ -#define ZYD_EEPROM_36M_CAL 0xf83f /* Calibration */ -#define ZYD_EEPROM_11A_INT 0xf847 /* Interpolation */ -#define ZYD_EEPROM_48M_CAL 0xf84f /* Calibration */ -#define ZYD_EEPROM_48M_INT 0xf857 /* Interpolation */ -#define ZYD_EEPROM_54M_CAL 0xf85f /* Calibration */ -#define ZYD_EEPROM_54M_INT 0xf867 /* Interpolation */ - -/* - * Firmware registers offsets (relative to fwbase). - */ -#define ZYD_FW_FIRMWARE_REV 0x0000 /* Firmware version */ -#define ZYD_FW_USB_SPEED 0x0001 /* USB speed (!=0 if highspeed) */ -#define ZYD_FW_FIX_TX_RATE 0x0002 /* Fixed TX rate */ -#define ZYD_FW_LINK_STATUS 0x0003 -#define ZYD_FW_SOFT_RESET 0x0004 -#define ZYD_FW_FLASH_CHK 0x0005 - -/* possible flags for register ZYD_FW_LINK_STATUS */ -#define ZYD_LED1 (1 << 8) -#define ZYD_LED2 (1 << 9) - -/* - * RF IDs. - */ -#define ZYD_RF_UW2451 0x2 /* not supported yet */ -#define ZYD_RF_UCHIP 0x3 /* not supported yet */ -#define ZYD_RF_AL2230 0x4 -#define ZYD_RF_AL7230B 0x5 -#define ZYD_RF_THETA 0x6 /* not supported yet */ -#define ZYD_RF_AL2210 0x7 -#define ZYD_RF_MAXIM_NEW 0x8 -#define ZYD_RF_GCT 0x9 -#define ZYD_RF_AL2230S 0xa /* not supported yet */ -#define ZYD_RF_RALINK 0xb /* not supported yet */ -#define ZYD_RF_INTERSIL 0xc /* not supported yet */ -#define ZYD_RF_RFMD 0xd -#define ZYD_RF_MAXIM_NEW2 0xe -#define ZYD_RF_PHILIPS 0xf /* not supported yet */ - -/* - * PHY registers (8 bits, not documented). - */ -#define ZYD_CR0 0x9000 -#define ZYD_CR1 0x9004 -#define ZYD_CR2 0x9008 -#define ZYD_CR3 0x900c -#define ZYD_CR5 0x9010 -#define ZYD_CR6 0x9014 -#define ZYD_CR7 0x9018 -#define ZYD_CR8 0x901c -#define ZYD_CR4 0x9020 -#define ZYD_CR9 0x9024 -#define ZYD_CR10 0x9028 -#define ZYD_CR11 0x902c -#define ZYD_CR12 0x9030 -#define ZYD_CR13 0x9034 -#define ZYD_CR14 0x9038 -#define ZYD_CR15 0x903c -#define ZYD_CR16 0x9040 -#define ZYD_CR17 0x9044 -#define ZYD_CR18 0x9048 -#define ZYD_CR19 0x904c -#define ZYD_CR20 0x9050 -#define ZYD_CR21 0x9054 -#define ZYD_CR22 0x9058 -#define ZYD_CR23 0x905c -#define ZYD_CR24 0x9060 -#define ZYD_CR25 0x9064 -#define ZYD_CR26 0x9068 -#define ZYD_CR27 0x906c -#define ZYD_CR28 0x9070 -#define ZYD_CR29 0x9074 -#define ZYD_CR30 0x9078 -#define ZYD_CR31 0x907c -#define ZYD_CR32 0x9080 -#define ZYD_CR33 0x9084 -#define ZYD_CR34 0x9088 -#define ZYD_CR35 0x908c -#define ZYD_CR36 0x9090 -#define ZYD_CR37 0x9094 -#define ZYD_CR38 0x9098 -#define ZYD_CR39 0x909c -#define ZYD_CR40 0x90a0 -#define ZYD_CR41 0x90a4 -#define ZYD_CR42 0x90a8 -#define ZYD_CR43 0x90ac -#define ZYD_CR44 0x90b0 -#define ZYD_CR45 0x90b4 -#define ZYD_CR46 0x90b8 -#define ZYD_CR47 0x90bc -#define ZYD_CR48 0x90c0 -#define ZYD_CR49 0x90c4 -#define ZYD_CR50 0x90c8 -#define ZYD_CR51 0x90cc -#define ZYD_CR52 0x90d0 -#define ZYD_CR53 0x90d4 -#define ZYD_CR54 0x90d8 -#define ZYD_CR55 0x90dc -#define ZYD_CR56 0x90e0 -#define ZYD_CR57 0x90e4 -#define ZYD_CR58 0x90e8 -#define ZYD_CR59 0x90ec -#define ZYD_CR60 0x90f0 -#define ZYD_CR61 0x90f4 -#define ZYD_CR62 0x90f8 -#define ZYD_CR63 0x90fc -#define ZYD_CR64 0x9100 -#define ZYD_CR65 0x9104 -#define ZYD_CR66 0x9108 -#define ZYD_CR67 0x910c -#define ZYD_CR68 0x9110 -#define ZYD_CR69 0x9114 -#define ZYD_CR70 0x9118 -#define ZYD_CR71 0x911c -#define ZYD_CR72 0x9120 -#define ZYD_CR73 0x9124 -#define ZYD_CR74 0x9128 -#define ZYD_CR75 0x912c -#define ZYD_CR76 0x9130 -#define ZYD_CR77 0x9134 -#define ZYD_CR78 0x9138 -#define ZYD_CR79 0x913c -#define ZYD_CR80 0x9140 -#define ZYD_CR81 0x9144 -#define ZYD_CR82 0x9148 -#define ZYD_CR83 0x914c -#define ZYD_CR84 0x9150 -#define ZYD_CR85 0x9154 -#define ZYD_CR86 0x9158 -#define ZYD_CR87 0x915c -#define ZYD_CR88 0x9160 -#define ZYD_CR89 0x9164 -#define ZYD_CR90 0x9168 -#define ZYD_CR91 0x916c -#define ZYD_CR92 0x9170 -#define ZYD_CR93 0x9174 -#define ZYD_CR94 0x9178 -#define ZYD_CR95 0x917c -#define ZYD_CR96 0x9180 -#define ZYD_CR97 0x9184 -#define ZYD_CR98 0x9188 -#define ZYD_CR99 0x918c -#define ZYD_CR100 0x9190 -#define ZYD_CR101 0x9194 -#define ZYD_CR102 0x9198 -#define ZYD_CR103 0x919c -#define ZYD_CR104 0x91a0 -#define ZYD_CR105 0x91a4 -#define ZYD_CR106 0x91a8 -#define ZYD_CR107 0x91ac -#define ZYD_CR108 0x91b0 -#define ZYD_CR109 0x91b4 -#define ZYD_CR110 0x91b8 -#define ZYD_CR111 0x91bc -#define ZYD_CR112 0x91c0 -#define ZYD_CR113 0x91c4 -#define ZYD_CR114 0x91c8 -#define ZYD_CR115 0x91cc -#define ZYD_CR116 0x91d0 -#define ZYD_CR117 0x91d4 -#define ZYD_CR118 0x91d8 -#define ZYD_CR119 0x91dc -#define ZYD_CR120 0x91e0 -#define ZYD_CR121 0x91e4 -#define ZYD_CR122 0x91e8 -#define ZYD_CR123 0x91ec -#define ZYD_CR124 0x91f0 -#define ZYD_CR125 0x91f4 -#define ZYD_CR126 0x91f8 -#define ZYD_CR127 0x91fc -#define ZYD_CR128 0x9200 -#define ZYD_CR129 0x9204 -#define ZYD_CR130 0x9208 -#define ZYD_CR131 0x920c -#define ZYD_CR132 0x9210 -#define ZYD_CR133 0x9214 -#define ZYD_CR134 0x9218 -#define ZYD_CR135 0x921c -#define ZYD_CR136 0x9220 -#define ZYD_CR137 0x9224 -#define ZYD_CR138 0x9228 -#define ZYD_CR139 0x922c -#define ZYD_CR140 0x9230 -#define ZYD_CR141 0x9234 -#define ZYD_CR142 0x9238 -#define ZYD_CR143 0x923c -#define ZYD_CR144 0x9240 -#define ZYD_CR145 0x9244 -#define ZYD_CR146 0x9248 -#define ZYD_CR147 0x924c -#define ZYD_CR148 0x9250 -#define ZYD_CR149 0x9254 -#define ZYD_CR150 0x9258 -#define ZYD_CR151 0x925c -#define ZYD_CR152 0x9260 -#define ZYD_CR153 0x9264 -#define ZYD_CR154 0x9268 -#define ZYD_CR155 0x926c -#define ZYD_CR156 0x9270 -#define ZYD_CR157 0x9274 -#define ZYD_CR158 0x9278 -#define ZYD_CR159 0x927c -#define ZYD_CR160 0x9280 -#define ZYD_CR161 0x9284 -#define ZYD_CR162 0x9288 -#define ZYD_CR163 0x928c -#define ZYD_CR164 0x9290 -#define ZYD_CR165 0x9294 -#define ZYD_CR166 0x9298 -#define ZYD_CR167 0x929c -#define ZYD_CR168 0x92a0 -#define ZYD_CR169 0x92a4 -#define ZYD_CR170 0x92a8 -#define ZYD_CR171 0x92ac -#define ZYD_CR172 0x92b0 -#define ZYD_CR173 0x92b4 -#define ZYD_CR174 0x92b8 -#define ZYD_CR175 0x92bc -#define ZYD_CR176 0x92c0 -#define ZYD_CR177 0x92c4 -#define ZYD_CR178 0x92c8 -#define ZYD_CR179 0x92cc -#define ZYD_CR180 0x92d0 -#define ZYD_CR181 0x92d4 -#define ZYD_CR182 0x92d8 -#define ZYD_CR183 0x92dc -#define ZYD_CR184 0x92e0 -#define ZYD_CR185 0x92e4 -#define ZYD_CR186 0x92e8 -#define ZYD_CR187 0x92ec -#define ZYD_CR188 0x92f0 -#define ZYD_CR189 0x92f4 -#define ZYD_CR190 0x92f8 -#define ZYD_CR191 0x92fc -#define ZYD_CR192 0x9300 -#define ZYD_CR193 0x9304 -#define ZYD_CR194 0x9308 -#define ZYD_CR195 0x930c -#define ZYD_CR196 0x9310 -#define ZYD_CR197 0x9314 -#define ZYD_CR198 0x9318 -#define ZYD_CR199 0x931c -#define ZYD_CR200 0x9320 -#define ZYD_CR201 0x9324 -#define ZYD_CR202 0x9328 -#define ZYD_CR203 0x932c -#define ZYD_CR204 0x9330 -#define ZYD_CR205 0x9334 -#define ZYD_CR206 0x9338 -#define ZYD_CR207 0x933c -#define ZYD_CR208 0x9340 -#define ZYD_CR209 0x9344 -#define ZYD_CR210 0x9348 -#define ZYD_CR211 0x934c -#define ZYD_CR212 0x9350 -#define ZYD_CR213 0x9354 -#define ZYD_CR214 0x9358 -#define ZYD_CR215 0x935c -#define ZYD_CR216 0x9360 -#define ZYD_CR217 0x9364 -#define ZYD_CR218 0x9368 -#define ZYD_CR219 0x936c -#define ZYD_CR220 0x9370 -#define ZYD_CR221 0x9374 -#define ZYD_CR222 0x9378 -#define ZYD_CR223 0x937c -#define ZYD_CR224 0x9380 -#define ZYD_CR225 0x9384 -#define ZYD_CR226 0x9388 -#define ZYD_CR227 0x938c -#define ZYD_CR228 0x9390 -#define ZYD_CR229 0x9394 -#define ZYD_CR230 0x9398 -#define ZYD_CR231 0x939c -#define ZYD_CR232 0x93a0 -#define ZYD_CR233 0x93a4 -#define ZYD_CR234 0x93a8 -#define ZYD_CR235 0x93ac -#define ZYD_CR236 0x93b0 -#define ZYD_CR240 0x93c0 -#define ZYD_CR241 0x93c4 -#define ZYD_CR242 0x93c8 -#define ZYD_CR243 0x93cc -#define ZYD_CR244 0x93d0 -#define ZYD_CR245 0x93d4 -#define ZYD_CR251 0x93ec -#define ZYD_CR252 0x93f0 -#define ZYD_CR253 0x93f4 -#define ZYD_CR254 0x93f8 -#define ZYD_CR255 0x93fc - -/* copied nearly verbatim from the Linux driver rewrite */ -#define ZYD_DEF_PHY \ -{ \ - { ZYD_CR0, 0x0a }, { ZYD_CR1, 0x06 }, { ZYD_CR2, 0x26 }, \ - { ZYD_CR3, 0x38 }, { ZYD_CR4, 0x80 }, { ZYD_CR9, 0xa0 }, \ - { ZYD_CR10, 0x81 }, { ZYD_CR11, 0x00 }, { ZYD_CR12, 0x7f }, \ - { ZYD_CR13, 0x8c }, { ZYD_CR14, 0x80 }, { ZYD_CR15, 0x3d }, \ - { ZYD_CR16, 0x20 }, { ZYD_CR17, 0x1e }, { ZYD_CR18, 0x0a }, \ - { ZYD_CR19, 0x48 }, { ZYD_CR20, 0x0c }, { ZYD_CR21, 0x0c }, \ - { ZYD_CR22, 0x23 }, { ZYD_CR23, 0x90 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR25, 0x40 }, { ZYD_CR26, 0x10 }, { ZYD_CR27, 0x19 }, \ - { ZYD_CR28, 0x7f }, { ZYD_CR29, 0x80 }, { ZYD_CR30, 0x4b }, \ - { ZYD_CR31, 0x60 }, { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x08 }, \ - { ZYD_CR34, 0x06 }, { ZYD_CR35, 0x0a }, { ZYD_CR36, 0x00 }, \ - { ZYD_CR37, 0x00 }, { ZYD_CR38, 0x38 }, { ZYD_CR39, 0x0c }, \ - { ZYD_CR40, 0x84 }, { ZYD_CR41, 0x2a }, { ZYD_CR42, 0x80 }, \ - { ZYD_CR43, 0x10 }, { ZYD_CR44, 0x12 }, { ZYD_CR46, 0xff }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \ - { ZYD_CR64, 0xd0 }, { ZYD_CR65, 0x04 }, { ZYD_CR66, 0x58 }, \ - { ZYD_CR67, 0xc9 }, { ZYD_CR68, 0x88 }, { ZYD_CR69, 0x41 }, \ - { ZYD_CR70, 0x23 }, { ZYD_CR71, 0x10 }, { ZYD_CR72, 0xff }, \ - { ZYD_CR73, 0x32 }, { ZYD_CR74, 0x30 }, { ZYD_CR75, 0x65 }, \ - { ZYD_CR76, 0x41 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x30 }, \ - { ZYD_CR79, 0x68 }, { ZYD_CR80, 0x64 }, { ZYD_CR81, 0x64 }, \ - { ZYD_CR82, 0x00 }, { ZYD_CR83, 0x00 }, { ZYD_CR84, 0x00 }, \ - { ZYD_CR85, 0x02 }, { ZYD_CR86, 0x00 }, { ZYD_CR87, 0x00 }, \ - { ZYD_CR88, 0xff }, { ZYD_CR89, 0xfc }, { ZYD_CR90, 0x00 }, \ - { ZYD_CR91, 0x00 }, { ZYD_CR92, 0x00 }, { ZYD_CR93, 0x08 }, \ - { ZYD_CR94, 0x00 }, { ZYD_CR95, 0x00 }, { ZYD_CR96, 0xff }, \ - { ZYD_CR97, 0xe7 }, { ZYD_CR98, 0x00 }, { ZYD_CR99, 0x00 }, \ - { ZYD_CR100, 0x00 }, { ZYD_CR101, 0xae }, { ZYD_CR102, 0x02 }, \ - { ZYD_CR103, 0x00 }, { ZYD_CR104, 0x03 }, { ZYD_CR105, 0x65 }, \ - { ZYD_CR106, 0x04 }, { ZYD_CR107, 0x00 }, { ZYD_CR108, 0x0a }, \ - { ZYD_CR109, 0xaa }, { ZYD_CR110, 0xaa }, { ZYD_CR111, 0x25 }, \ - { ZYD_CR112, 0x25 }, { ZYD_CR113, 0x00 }, { ZYD_CR119, 0x1e }, \ - { ZYD_CR125, 0x90 }, { ZYD_CR126, 0x00 }, { ZYD_CR127, 0x00 }, \ - { ZYD_CR5, 0x00 }, { ZYD_CR6, 0x00 }, { ZYD_CR7, 0x00 }, \ - { ZYD_CR8, 0x00 }, { ZYD_CR9, 0x20 }, { ZYD_CR12, 0xf0 }, \ - { ZYD_CR20, 0x0e }, { ZYD_CR21, 0x0e }, { ZYD_CR27, 0x10 }, \ - { ZYD_CR44, 0x33 }, { ZYD_CR47, 0x1E }, { ZYD_CR83, 0x24 }, \ - { ZYD_CR84, 0x04 }, { ZYD_CR85, 0x00 }, { ZYD_CR86, 0x0C }, \ - { ZYD_CR87, 0x12 }, { ZYD_CR88, 0x0C }, { ZYD_CR89, 0x00 }, \ - { ZYD_CR90, 0x10 }, { ZYD_CR91, 0x08 }, { ZYD_CR93, 0x00 }, \ - { ZYD_CR94, 0x01 }, { ZYD_CR95, 0x00 }, { ZYD_CR96, 0x50 }, \ - { ZYD_CR97, 0x37 }, { ZYD_CR98, 0x35 }, { ZYD_CR101, 0x13 }, \ - { ZYD_CR102, 0x27 }, { ZYD_CR103, 0x27 }, { ZYD_CR104, 0x18 }, \ - { ZYD_CR105, 0x12 }, { ZYD_CR109, 0x27 }, { ZYD_CR110, 0x27 }, \ - { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x27 }, { ZYD_CR113, 0x27 }, \ - { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, { ZYD_CR116, 0x24 }, \ - { ZYD_CR117, 0xfc }, { ZYD_CR118, 0xfa }, { ZYD_CR120, 0x4f }, \ - { ZYD_CR125, 0xaa }, { ZYD_CR127, 0x03 }, { ZYD_CR128, 0x14 }, \ - { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR131, 0x0C }, \ - { ZYD_CR136, 0xdf }, { ZYD_CR137, 0x40 }, { ZYD_CR138, 0xa0 }, \ - { ZYD_CR139, 0xb0 }, { ZYD_CR140, 0x99 }, { ZYD_CR141, 0x82 }, \ - { ZYD_CR142, 0x54 }, { ZYD_CR143, 0x1c }, { ZYD_CR144, 0x6c }, \ - { ZYD_CR147, 0x07 }, { ZYD_CR148, 0x4c }, { ZYD_CR149, 0x50 }, \ - { ZYD_CR150, 0x0e }, { ZYD_CR151, 0x18 }, { ZYD_CR160, 0xfe }, \ - { ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, { ZYD_CR163, 0xfa }, \ - { ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, { ZYD_CR166, 0xbe }, \ - { ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, { ZYD_CR169, 0xba }, \ - { ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, { ZYD_CR204, 0x7d }, \ - { ZYD_CR203, 0x30 }, { 0, 0} \ -} - -#define ZYD_DEF_PHYB \ -{ \ - { ZYD_CR0, 0x14 }, { ZYD_CR1, 0x06 }, { ZYD_CR2, 0x26 }, \ - { ZYD_CR3, 0x38 }, { ZYD_CR4, 0x80 }, { ZYD_CR9, 0xe0 }, \ - { ZYD_CR10, 0x81 }, { ZYD_CR11, 0x00 }, { ZYD_CR12, 0xf0 }, \ - { ZYD_CR13, 0x8c }, { ZYD_CR14, 0x80 }, { ZYD_CR15, 0x3d }, \ - { ZYD_CR16, 0x20 }, { ZYD_CR17, 0x1e }, { ZYD_CR18, 0x0a }, \ - { ZYD_CR19, 0x48 }, { ZYD_CR20, 0x10 }, { ZYD_CR21, 0x0e }, \ - { ZYD_CR22, 0x23 }, { ZYD_CR23, 0x90 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR25, 0x40 }, { ZYD_CR26, 0x10 }, { ZYD_CR27, 0x10 }, \ - { ZYD_CR28, 0x7f }, { ZYD_CR29, 0x80 }, { ZYD_CR30, 0x4b }, \ - { ZYD_CR31, 0x60 }, { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x08 }, \ - { ZYD_CR34, 0x06 }, { ZYD_CR35, 0x0a }, { ZYD_CR36, 0x00 }, \ - { ZYD_CR37, 0x00 }, { ZYD_CR38, 0x38 }, { ZYD_CR39, 0x0c }, \ - { ZYD_CR40, 0x84 }, { ZYD_CR41, 0x2a }, { ZYD_CR42, 0x80 }, \ - { ZYD_CR43, 0x10 }, { ZYD_CR44, 0x33 }, { ZYD_CR46, 0xff }, \ - { ZYD_CR47, 0x1E }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \ - { ZYD_CR64, 0xd0 }, { ZYD_CR65, 0x04 }, { ZYD_CR66, 0x58 }, \ - { ZYD_CR67, 0xc9 }, { ZYD_CR68, 0x88 }, { ZYD_CR69, 0x41 }, \ - { ZYD_CR70, 0x23 }, { ZYD_CR71, 0x10 }, { ZYD_CR72, 0xff }, \ - { ZYD_CR73, 0x32 }, { ZYD_CR74, 0x30 }, { ZYD_CR75, 0x65 }, \ - { ZYD_CR76, 0x41 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x30 }, \ - { ZYD_CR79, 0xf0 }, { ZYD_CR80, 0x64 }, { ZYD_CR81, 0x64 }, \ - { ZYD_CR82, 0x00 }, { ZYD_CR83, 0x24 }, { ZYD_CR84, 0x04 }, \ - { ZYD_CR85, 0x00 }, { ZYD_CR86, 0x0c }, { ZYD_CR87, 0x12 }, \ - { ZYD_CR88, 0x0c }, { ZYD_CR89, 0x00 }, { ZYD_CR90, 0x58 }, \ - { ZYD_CR91, 0x04 }, { ZYD_CR92, 0x00 }, { ZYD_CR93, 0x00 }, \ - { ZYD_CR94, 0x01 }, { ZYD_CR95, 0x20 }, { ZYD_CR96, 0x50 }, \ - { ZYD_CR97, 0x37 }, { ZYD_CR98, 0x35 }, { ZYD_CR99, 0x00 }, \ - { ZYD_CR100, 0x01 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR103, 0x27 }, { ZYD_CR104, 0x18 }, { ZYD_CR105, 0x12 }, \ - { ZYD_CR106, 0x04 }, { ZYD_CR107, 0x00 }, { ZYD_CR108, 0x0a }, \ - { ZYD_CR109, 0x27 }, { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x27 }, \ - { ZYD_CR112, 0x27 }, { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, \ - { ZYD_CR115, 0x26 }, { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfc }, \ - { ZYD_CR118, 0xfa }, { ZYD_CR119, 0x1e }, { ZYD_CR125, 0x90 }, \ - { ZYD_CR126, 0x00 }, { ZYD_CR127, 0x00 }, { ZYD_CR128, 0x14 }, \ - { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR131, 0x0c }, \ - { ZYD_CR136, 0xdf }, { ZYD_CR137, 0xa0 }, { ZYD_CR138, 0xa8 }, \ - { ZYD_CR139, 0xb4 }, { ZYD_CR140, 0x98 }, { ZYD_CR141, 0x82 }, \ - { ZYD_CR142, 0x53 }, { ZYD_CR143, 0x1c }, { ZYD_CR144, 0x6c }, \ - { ZYD_CR147, 0x07 }, { ZYD_CR148, 0x40 }, { ZYD_CR149, 0x40 }, \ - { ZYD_CR150, 0x14 }, { ZYD_CR151, 0x18 }, { ZYD_CR159, 0x70 }, \ - { ZYD_CR160, 0xfe }, { ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, \ - { ZYD_CR163, 0xfa }, { ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, \ - { ZYD_CR166, 0xbe }, { ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, \ - { ZYD_CR169, 0xba }, { ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, \ - { ZYD_CR204, 0x7d }, { ZYD_CR203, 0x30 }, \ - { 0, 0 } \ -} - -#define ZYD_RFMD_PHY \ -{ \ - { ZYD_CR2, 0x1e }, { ZYD_CR9, 0x20 }, { ZYD_CR10, 0x89 }, \ - { ZYD_CR11, 0x00 }, { ZYD_CR15, 0xd0 }, { ZYD_CR17, 0x68 }, \ - { ZYD_CR19, 0x4a }, { ZYD_CR20, 0x0c }, { ZYD_CR21, 0x0e }, \ - { ZYD_CR23, 0x48 }, { ZYD_CR24, 0x14 }, { ZYD_CR26, 0x90 }, \ - { ZYD_CR27, 0x30 }, { ZYD_CR29, 0x20 }, { ZYD_CR31, 0xb2 }, \ - { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x28 }, { ZYD_CR38, 0x30 }, \ - { ZYD_CR34, 0x0f }, { ZYD_CR35, 0xf0 }, { ZYD_CR41, 0x2a }, \ - { ZYD_CR46, 0x7f }, { ZYD_CR47, 0x1e }, { ZYD_CR51, 0xc5 }, \ - { ZYD_CR52, 0xc5 }, { ZYD_CR53, 0xc5 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR82, 0x00 }, \ - { ZYD_CR83, 0x24 }, { ZYD_CR84, 0x04 }, { ZYD_CR85, 0x00 }, \ - { ZYD_CR86, 0x10 }, { ZYD_CR87, 0x2a }, { ZYD_CR88, 0x10 }, \ - { ZYD_CR89, 0x24 }, { ZYD_CR90, 0x18 }, { ZYD_CR91, 0x00 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR93, 0x00 }, { ZYD_CR94, 0x01 }, \ - { ZYD_CR95, 0x00 }, { ZYD_CR96, 0x40 }, { ZYD_CR97, 0x37 }, \ - { ZYD_CR98, 0x05 }, { ZYD_CR99, 0x28 }, { ZYD_CR100, 0x00 }, \ - { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, { ZYD_CR103, 0x27 }, \ - { ZYD_CR104, 0x18 }, { ZYD_CR105, 0x12 }, { ZYD_CR106, 0x1a }, \ - { ZYD_CR107, 0x24 }, { ZYD_CR108, 0x0a }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x2f }, { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x27 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x40 }, \ - { ZYD_CR116, 0x40 }, { ZYD_CR117, 0xf0 }, { ZYD_CR118, 0xf0 }, \ - { ZYD_CR119, 0x16 }, { ZYD_CR122, 0x00 }, { ZYD_CR127, 0x03 }, \ - { ZYD_CR131, 0x08 }, { ZYD_CR138, 0x28 }, { ZYD_CR148, 0x44 }, \ - { ZYD_CR150, 0x10 }, { ZYD_CR169, 0xbb }, { ZYD_CR170, 0xbb } \ -} - -#define ZYD_RFMD_RF \ -{ \ - 0x000007, 0x07dd43, 0x080959, 0x0e6666, 0x116a57, 0x17dd43, \ - 0x1819f9, 0x1e6666, 0x214554, 0x25e7fa, 0x27fffa, 0x294128, \ - 0x2c0000, 0x300000, 0x340000, 0x381e0f, 0x6c180f \ -} - -#define ZYD_RFMD_CHANTABLE \ -{ \ - { 0x181979, 0x1e6666 }, \ - { 0x181989, 0x1e6666 }, \ - { 0x181999, 0x1e6666 }, \ - { 0x1819a9, 0x1e6666 }, \ - { 0x1819b9, 0x1e6666 }, \ - { 0x1819c9, 0x1e6666 }, \ - { 0x1819d9, 0x1e6666 }, \ - { 0x1819e9, 0x1e6666 }, \ - { 0x1819f9, 0x1e6666 }, \ - { 0x181a09, 0x1e6666 }, \ - { 0x181a19, 0x1e6666 }, \ - { 0x181a29, 0x1e6666 }, \ - { 0x181a39, 0x1e6666 }, \ - { 0x181a60, 0x1c0000 } \ -} - -#define ZYD_AL2230_PHY \ -{ \ - { ZYD_CR15, 0x20 }, { ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, \ - { ZYD_CR26, 0x11 }, { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, \ - { ZYD_CR44, 0x33 }, { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, \ - { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x2b }, \ - { ZYD_CR112, 0x2b }, { ZYD_CR119, 0x0a }, { ZYD_CR10, 0x89 }, \ - { ZYD_CR17, 0x28 }, { ZYD_CR26, 0x93 }, { ZYD_CR34, 0x30 }, \ - { ZYD_CR35, 0x3e }, { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, \ - { ZYD_CR46, 0x96 }, { ZYD_CR47, 0x1e }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, \ - { ZYD_CR89, 0x04 }, { ZYD_CR92, 0x0a }, { ZYD_CR99, 0x28 }, \ - { ZYD_CR100, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x24 }, { ZYD_CR107, 0x2a }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfc }, \ - { ZYD_CR119, 0x10 }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, \ - { ZYD_CR122, 0xe0 }, { ZYD_CR137, 0x88 }, { ZYD_CR252, 0xff }, \ - { ZYD_CR253, 0xff }, { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, \ - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } \ -} - -#define ZYD_AL2230_PHY_B \ -{ \ - { ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x2B }, \ - { ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, { ZYD_CR33, 0x28 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x3e }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x99 }, { ZYD_CR47, 0x1e }, \ - { ZYD_CR48, 0x06 }, { ZYD_CR49, 0xf9 }, { ZYD_CR51, 0x01 }, \ - { ZYD_CR52, 0x80 }, { ZYD_CR53, 0x7e }, { ZYD_CR65, 0x00 }, \ - { ZYD_CR66, 0x00 }, { ZYD_CR67, 0x00 }, { ZYD_CR68, 0x00 }, \ - { ZYD_CR69, 0x28 }, { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, \ - { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, \ - { ZYD_CR91, 0x00 }, { ZYD_CR92, 0x0a }, { ZYD_CR98, 0x8d }, \ - { ZYD_CR99, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x24 }, { ZYD_CR107, 0x2a }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x1f }, { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR119, 0x10 }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x6c }, \ - { ZYD_CR122, 0xfc }, { ZYD_CR123, 0x57 }, { ZYD_CR125, 0xad }, \ - { ZYD_CR126, 0x6c }, { ZYD_CR127, 0x03 }, { ZYD_CR137, 0x50 }, \ - { ZYD_CR138, 0xa8 }, { ZYD_CR144, 0xac }, { ZYD_CR150, 0x0d }, \ - { ZYD_CR252, 0x34 }, { ZYD_CR253, 0x34 } \ -} - -#define ZYD_AL2230_PHY_PART1 \ -{ \ - { ZYD_CR240, 0x57 }, { ZYD_CR9, 0xe0 } \ -} - -#define ZYD_AL2230_PHY_PART2 \ -{ \ - { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x7f }, \ -} - -#define ZYD_AL2230_PHY_PART3 \ -{ \ - { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ -} - -#define ZYD_AL2230S_PHY_INIT \ -{ \ - { ZYD_CR47, 0x1e }, { ZYD_CR106, 0x22 }, { ZYD_CR107, 0x2a }, \ - { ZYD_CR109, 0x13 }, { ZYD_CR118, 0xf8 }, { ZYD_CR119, 0x12 }, \ - { ZYD_CR122, 0xe0 }, { ZYD_CR128, 0x10 }, { ZYD_CR129, 0x0e }, \ - { ZYD_CR130, 0x10 } \ -} - -#define ZYD_AL2230_PHY_FINI_PART1 \ -{ \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR12, 0xf0 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x58 }, \ - { ZYD_CR203, 0x06 }, { ZYD_CR240, 0x80 }, \ -} - -#define ZYD_AL2230_RF_PART1 \ -{ \ - 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3 \ -} - -#define ZYD_AL2230_RF_PART2 \ -{ \ - 0x000da4, 0x0f4dc5, 0x0805b6, 0x011687, 0x000688, 0x0403b9, \ - 0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00500f \ -} - -#define ZYD_AL2230_RF_PART3 \ -{ \ - 0x00d00f, 0x004c0f, 0x00540f, 0x00700f, 0x00500f \ -} - -#define ZYD_AL2230_RF_B \ -{ \ - 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3, \ - 0x0005a4, 0x0f4dc5, 0x0805b6, 0x0146c7, 0x000688, 0x0403b9, \ - 0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00580f \ -} - -#define ZYD_AL2230_RF_B_PART1 \ -{ \ - 0x8cccd0, 0x481dc0, 0xcfff00, 0x25a000 \ -} - -#define ZYD_AL2230_RF_B_PART2 \ -{ \ - 0x25a000, 0xa3b2f0, 0x6da010, 0xe36280, 0x116000, 0x9dc020, \ - 0x5ddb00, 0xd99000, 0x3ffbd0, 0xb00000, 0xf01a00 \ -} - -#define ZYD_AL2230_RF_B_PART3 \ -{ \ - 0xf01b00, 0xf01e00, 0xf01a00 \ -} - -#define ZYD_AL2230_CHANTABLE \ -{ \ - { 0x03f790, 0x033331, 0x00000d }, \ - { 0x03f790, 0x0b3331, 0x00000d }, \ - { 0x03e790, 0x033331, 0x00000d }, \ - { 0x03e790, 0x0b3331, 0x00000d }, \ - { 0x03f7a0, 0x033331, 0x00000d }, \ - { 0x03f7a0, 0x0b3331, 0x00000d }, \ - { 0x03e7a0, 0x033331, 0x00000d }, \ - { 0x03e7a0, 0x0b3331, 0x00000d }, \ - { 0x03f7b0, 0x033331, 0x00000d }, \ - { 0x03f7b0, 0x0b3331, 0x00000d }, \ - { 0x03e7b0, 0x033331, 0x00000d }, \ - { 0x03e7b0, 0x0b3331, 0x00000d }, \ - { 0x03f7c0, 0x033331, 0x00000d }, \ - { 0x03e7c0, 0x066661, 0x00000d } \ -} - -#define ZYD_AL2230_CHANTABLE_B \ -{ \ - { 0x09efc0, 0x8cccc0, 0xb00000 }, \ - { 0x09efc0, 0x8cccd0, 0xb00000 }, \ - { 0x09e7c0, 0x8cccc0, 0xb00000 }, \ - { 0x09e7c0, 0x8cccd0, 0xb00000 }, \ - { 0x05efc0, 0x8cccc0, 0xb00000 }, \ - { 0x05efc0, 0x8cccd0, 0xb00000 }, \ - { 0x05e7c0, 0x8cccc0, 0xb00000 }, \ - { 0x05e7c0, 0x8cccd0, 0xb00000 }, \ - { 0x0defc0, 0x8cccc0, 0xb00000 }, \ - { 0x0defc0, 0x8cccd0, 0xb00000 }, \ - { 0x0de7c0, 0x8cccc0, 0xb00000 }, \ - { 0x0de7c0, 0x8cccd0, 0xb00000 }, \ - { 0x03efc0, 0x8cccc0, 0xb00000 }, \ - { 0x03e7c0, 0x866660, 0xb00000 } \ -} - -#define ZYD_AL7230B_PHY_1 \ -{ \ - { ZYD_CR240, 0x57 }, { ZYD_CR15, 0x20 }, { ZYD_CR23, 0x40 }, \ - { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x11 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR44, 0x33 }, { ZYD_CR106, 0x22 }, \ - { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x27 }, \ - { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, { ZYD_CR119, 0x0a }, \ - { ZYD_CR122, 0xfc }, { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x28 }, \ - { ZYD_CR26, 0x93 }, { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x3e }, \ - { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x96 }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, \ - { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR99, 0x28 }, { ZYD_CR100, 0x02 }, \ - { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, { ZYD_CR106, 0x22 }, \ - { ZYD_CR107, 0x3f }, { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x1f }, \ - { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, { ZYD_CR113, 0x27 }, \ - { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, { ZYD_CR116, 0x3f }, \ - { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xfc }, { ZYD_CR119, 0x10 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR137, 0x88 }, \ - { ZYD_CR138, 0xa8 }, { ZYD_CR252, 0x34 }, { ZYD_CR253, 0x34 }, \ - { ZYD_CR251, 0x2f } \ -} - -#define ZYD_AL7230B_PHY_2 \ -{ \ - { ZYD_CR251, 0x3f }, { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, \ - { ZYD_CR130, 0x10 }, { ZYD_CR38, 0x38 }, { ZYD_CR136, 0xdf } \ -} - -#define ZYD_AL7230B_PHY_3 \ -{ \ - { ZYD_CR203, 0x06 }, { ZYD_CR240, 0x80 } \ -} - -#define ZYD_AL7230B_RF_1 \ -{ \ - 0x09ec04, 0x8cccc8, 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401, \ - 0x6cf56a, 0xe04073, 0x193d76, 0x9dd844, 0x500007, 0xd8c010, \ - 0x3c9000, 0xbfffff, 0x700000, 0xf15d58 \ -} - -#define ZYD_AL7230B_RF_2 \ -{ \ - 0xf15d59, 0xf15d5c, 0xf15d58 \ -} - -#define ZYD_AL7230B_RF_SETCHANNEL \ -{ \ - 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401, 0x6cf56a, 0xe04073, \ - 0x193d76, 0x9dd844, 0x500007, 0xd8c010, 0x3c9000, 0xf15d58 \ -} - -#define ZYD_AL7230B_CHANTABLE \ -{ \ - { 0x09ec00, 0x8cccc8 }, \ - { 0x09ec00, 0x8cccd8 }, \ - { 0x09ec00, 0x8cccc0 }, \ - { 0x09ec00, 0x8cccd0 }, \ - { 0x05ec00, 0x8cccc8 }, \ - { 0x05ec00, 0x8cccd8 }, \ - { 0x05ec00, 0x8cccc0 }, \ - { 0x05ec00, 0x8cccd0 }, \ - { 0x0dec00, 0x8cccc8 }, \ - { 0x0dec00, 0x8cccd8 }, \ - { 0x0dec00, 0x8cccc0 }, \ - { 0x0dec00, 0x8cccd0 }, \ - { 0x03ec00, 0x8cccc8 }, \ - { 0x03ec00, 0x866660 } \ -} - -#define ZYD_AL2210_PHY \ -{ \ - { ZYD_CR9, 0xe0 }, { ZYD_CR10, 0x91 }, { ZYD_CR12, 0x90 }, \ - { ZYD_CR15, 0xd0 }, { ZYD_CR16, 0x40 }, { ZYD_CR17, 0x58 }, \ - { ZYD_CR18, 0x04 }, { ZYD_CR23, 0x66 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR26, 0x90 }, { ZYD_CR31, 0x80 }, { ZYD_CR34, 0x06 }, \ - { ZYD_CR35, 0x3e }, { ZYD_CR38, 0x38 }, { ZYD_CR46, 0x90 }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR64, 0x64 }, { ZYD_CR79, 0xb5 }, \ - { ZYD_CR80, 0x38 }, { ZYD_CR81, 0x30 }, { ZYD_CR113, 0xc0 }, \ - { ZYD_CR127, 0x03 } \ -} - -#define ZYD_AL2210_RF \ -{ \ - 0x2396c0, 0x00fcb1, 0x358132, 0x0108b3, 0xc77804, 0x456415, \ - 0xff2226, 0x806667, 0x7860f8, 0xbb01c9, 0x00000a, 0x00000b \ -} - -#define ZYD_AL2210_CHANTABLE \ -{ \ - 0x0196c0, 0x019710, 0x019760, 0x0197b0, 0x019800, 0x019850, \ - 0x0198a0, 0x0198f0, 0x019940, 0x019990, 0x0199e0, 0x019a30, \ - 0x019a80, 0x019b40 \ -} - -#define ZYD_GCT_PHY \ -{ \ - { ZYD_CR47, 0x1e }, { ZYD_CR15, 0xdc }, { ZYD_CR113, 0xc0 }, \ - { ZYD_CR20, 0x0c }, { ZYD_CR17, 0x65 }, { ZYD_CR34, 0x04 }, \ - { ZYD_CR35, 0x35 }, { ZYD_CR24, 0x20 }, { ZYD_CR9, 0xe0 }, \ - { ZYD_CR127, 0x02 }, { ZYD_CR10, 0x91 }, { ZYD_CR23, 0x7f }, \ - { ZYD_CR27, 0x10 }, { ZYD_CR28, 0x7a }, { ZYD_CR79, 0xb5 }, \ - { ZYD_CR64, 0x80 }, { ZYD_CR33, 0x28 }, { ZYD_CR38, 0x30 } \ -} - -#define ZYD_GCT_RF \ -{ \ - 0x1f0000, 0x1f0000, 0x1f0200, 0x1f0600, 0x1f8600, 0x1f8600, \ - 0x002050, 0x1f8000, 0x1f8200, 0x1f8600, 0x1c0000, 0x10c458, \ - 0x088e92, 0x187b82, 0x0401b4, 0x140816, 0x0c7000, 0x1c0000, \ - 0x02ccae, 0x128023, 0x0a0000, 0x1a0000, 0x06e380, 0x16cb94, \ - 0x0e1740, 0x014980, 0x116240, 0x090000, 0x192304, 0x05112f, \ - 0x0d54a8, 0x0f8000, 0x1c0008, 0x1c0000, 0x1a0000, 0x1c0008, \ - 0x150000, 0x0c7000, 0x150800, 0x150000 \ -} - -#define ZYD_GCT_CHANTABLE \ -{ \ - 0x1a0000, 0x1a8000, 0x1a4000, 0x1ac000, 0x1a2000, 0x1aa000, \ - 0x1a6000, 0x1ae000, 0x1a1000, 0x1a9000, 0x1a5000, 0x1ad000, \ - 0x1a3000, 0x1ab000 \ -} - -#define ZYD_MAXIM_PHY \ -{ \ - { ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR26, 0x11 }, { ZYD_CR44, 0x33 }, \ - { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x2b }, \ - { ZYD_CR110, 0x2b }, { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0x00 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x06 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR150, 0x0d } \ -} - -#define ZYD_MAXIM_RF \ -{ \ - 0x00ccd4, 0x030a03, 0x000400, 0x000ca1, 0x010072, 0x018645, \ - 0x004006, 0x0000a7, 0x008258, 0x003fc9, 0x00040a, 0x00000b, \ - 0x00026c \ -} - -#define ZYD_MAXIM_CHANTABLE \ -{ \ - { 0x0ccd4, 0x30a03 }, \ - { 0x22224, 0x00a13 }, \ - { 0x37774, 0x10a13 }, \ - { 0x0ccd4, 0x30a13 }, \ - { 0x22224, 0x00a23 }, \ - { 0x37774, 0x10a23 }, \ - { 0x0ccd4, 0x30a23 }, \ - { 0x22224, 0x00a33 }, \ - { 0x37774, 0x10a33 }, \ - { 0x0ccd4, 0x30a33 }, \ - { 0x22224, 0x00a43 }, \ - { 0x37774, 0x10a43 }, \ - { 0x0ccd4, 0x30a43 }, \ - { 0x199a4, 0x20a53 } \ -} - -#define ZYD_MAXIM2_PHY \ -{ \ - { ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR26, 0x11 }, { ZYD_CR44, 0x33 }, \ - { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x2b }, \ - { ZYD_CR110, 0x2b }, { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0x00 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x06 }, { ZYD_CR122, 0xfe } \ -} - -#define ZYD_MAXIM2_RF \ -{ \ - 0x33334, 0x10a03, 0x00400, 0x00ca1, 0x10072, 0x18645, 0x04006, \ - 0x000a7, 0x08258, 0x03fc9, 0x0040a, 0x0000b, 0x0026c \ -} - -#define ZYD_MAXIM2_CHANTABLE_F \ -{ \ - 0x33334, 0x08884, 0x1ddd4, 0x33334, 0x08884, 0x1ddd4, 0x33334, \ - 0x08884, 0x1ddd4, 0x33334, 0x08884, 0x1ddd4, 0x33334, 0x26664 \ -} - -#define ZYD_MAXIM2_CHANTABLE \ -{ \ - { 0x33334, 0x10a03 }, \ - { 0x08884, 0x20a13 }, \ - { 0x1ddd4, 0x30a13 }, \ - { 0x33334, 0x10a13 }, \ - { 0x08884, 0x20a23 }, \ - { 0x1ddd4, 0x30a23 }, \ - { 0x33334, 0x10a23 }, \ - { 0x08884, 0x20a33 }, \ - { 0x1ddd4, 0x30a33 }, \ - { 0x33334, 0x10a33 }, \ - { 0x08884, 0x20a43 }, \ - { 0x1ddd4, 0x30a43 }, \ - { 0x33334, 0x10a43 }, \ - { 0x26664, 0x20a53 } \ -} - -/* - * Control pipe requests. - */ -#define ZYD_DOWNLOADREQ 0x30 -#define ZYD_DOWNLOADSTS 0x31 -#define ZYD_READFWDATAREQ 0x32 - -/* possible values for register ZYD_CR_INTERRUPT */ -#define ZYD_HWINT_MASK 0x004f0000 - -/* possible values for register ZYD_MAC_MISC */ -#define ZYD_UNLOCK_PHY_REGS 0x80 - -/* possible values for register ZYD_MAC_ENCRYPTION_TYPE */ -#define ZYD_ENC_SNIFFER 8 - -/* flags for register ZYD_MAC_RXFILTER */ -#define ZYD_FILTER_ASS_REQ (1 << 0) -#define ZYD_FILTER_ASS_RSP (1 << 1) -#define ZYD_FILTER_REASS_REQ (1 << 2) -#define ZYD_FILTER_REASS_RSP (1 << 3) -#define ZYD_FILTER_PRB_REQ (1 << 4) -#define ZYD_FILTER_PRB_RSP (1 << 5) -#define ZYD_FILTER_BCN (1 << 8) -#define ZYD_FILTER_ATIM (1 << 9) -#define ZYD_FILTER_DEASS (1 << 10) -#define ZYD_FILTER_AUTH (1 << 11) -#define ZYD_FILTER_DEAUTH (1 << 12) -#define ZYD_FILTER_PS_POLL (1 << 26) -#define ZYD_FILTER_RTS (1 << 27) -#define ZYD_FILTER_CTS (1 << 28) -#define ZYD_FILTER_ACK (1 << 29) -#define ZYD_FILTER_CFE (1 << 30) -#define ZYD_FILTER_CFE_A (1 << 31) - -/* helpers for register ZYD_MAC_RXFILTER */ -#define ZYD_FILTER_MONITOR 0xffffffff -#define ZYD_FILTER_BSS \ - (ZYD_FILTER_ASS_REQ | ZYD_FILTER_ASS_RSP | \ - ZYD_FILTER_REASS_REQ | ZYD_FILTER_REASS_RSP | \ - ZYD_FILTER_PRB_REQ | ZYD_FILTER_PRB_RSP | \ - (0x3 << 6) | \ - ZYD_FILTER_BCN | ZYD_FILTER_ATIM | ZYD_FILTER_DEASS | \ - ZYD_FILTER_AUTH | ZYD_FILTER_DEAUTH | \ - (0x7 << 13) | \ - ZYD_FILTER_PS_POLL | ZYD_FILTER_ACK) -#define ZYD_FILTER_HOSTAP \ - (ZYD_FILTER_ASS_REQ | ZYD_FILTER_REASS_REQ | \ - ZYD_FILTER_PRB_REQ | ZYD_FILTER_DEASS | ZYD_FILTER_AUTH | \ - ZYD_FILTER_DEAUTH | ZYD_FILTER_PS_POLL) - -struct zyd_tx_desc { - uint8_t phy; -#define ZYD_TX_PHY_SIGNAL(x) ((x) & 0xf) -#define ZYD_TX_PHY_OFDM (1 << 4) -#define ZYD_TX_PHY_SHPREAMBLE (1 << 5) /* CCK */ -#define ZYD_TX_PHY_5GHZ (1 << 5) /* OFDM */ - uint16_t len; - uint8_t flags; -#define ZYD_TX_FLAG_BACKOFF (1 << 0) -#define ZYD_TX_FLAG_MULTICAST (1 << 1) -#define ZYD_TX_FLAG_TYPE(x) (((x) & 0x3) << 2) -#define ZYD_TX_TYPE_DATA 0 -#define ZYD_TX_TYPE_PS_POLL 1 -#define ZYD_TX_TYPE_MGMT 2 -#define ZYD_TX_TYPE_CTL 3 -#define ZYD_TX_FLAG_WAKEUP (1 << 4) -#define ZYD_TX_FLAG_RTS (1 << 5) -#define ZYD_TX_FLAG_ENCRYPT (1 << 6) -#define ZYD_TX_FLAG_CTS_TO_SELF (1 << 7) - uint16_t pktlen; - uint16_t plcp_length; - uint8_t plcp_service; -#define ZYD_PLCP_LENGEXT 0x80 - uint16_t nextlen; -} __packed; - -struct zyd_plcphdr { - uint8_t signal; - uint8_t reserved[2]; - uint16_t service; /* unaligned! */ -} __packed; - -struct zyd_rx_stat { - uint8_t signal_cck; - uint8_t rssi; - uint8_t signal_ofdm; - uint8_t cipher; -#define ZYD_RX_CIPHER_WEP64 1 -#define ZYD_RX_CIPHER_TKIP 2 -#define ZYD_RX_CIPHER_AES 4 -#define ZYD_RX_CIPHER_WEP128 5 -#define ZYD_RX_CIPHER_WEP256 6 -#define ZYD_RX_CIPHER_WEP \ - (ZYD_RX_CIPHER_WEP64 | ZYD_RX_CIPHER_WEP128 | ZYD_RX_CIPHER_WEP256) - uint8_t flags; -#define ZYD_RX_OFDM (1 << 0) -#define ZYD_RX_TIMEOUT (1 << 1) -#define ZYD_RX_OVERRUN (1 << 2) -#define ZYD_RX_DECRYPTERR (1 << 3) -#define ZYD_RX_BADCRC32 (1 << 4) -#define ZYD_RX_NOT2ME (1 << 5) -#define ZYD_RX_BADCRC16 (1 << 6) -#define ZYD_RX_ERROR (1 << 7) -} __packed; - -/* this structure may be unaligned */ -struct zyd_rx_desc { -#define ZYD_MAX_RXFRAMECNT 3 - uWord len[ZYD_MAX_RXFRAMECNT]; - uWord tag; -#define ZYD_TAG_MULTIFRAME 0x697e -} __packed; - -/* I2C bus alike */ -struct zyd_rfwrite_cmd { - uint16_t code; - uint16_t width; - uint16_t bit[32]; -#define ZYD_RF_IF_LE (1 << 1) -#define ZYD_RF_CLK (1 << 2) -#define ZYD_RF_DATA (1 << 3) -} __packed; - -struct zyd_cmd { - uint16_t code; -#define ZYD_CMD_IOWR 0x0021 /* write HMAC or PHY register */ -#define ZYD_CMD_IORD 0x0022 /* read HMAC or PHY register */ -#define ZYD_CMD_RFCFG 0x0023 /* write RF register */ -#define ZYD_NOTIF_IORD 0x9001 /* response for ZYD_CMD_IORD */ -#define ZYD_NOTIF_MACINTR 0x9001 /* interrupt notification */ -#define ZYD_NOTIF_RETRYSTATUS 0xa001 /* Tx retry notification */ - uint8_t data[64]; -} __packed; - -/* structure for command ZYD_CMD_IOWR */ -struct zyd_pair { - uint16_t reg; -/* helpers macros to read/write 32-bit registers */ -#define ZYD_REG32_LO(reg) (reg) -#define ZYD_REG32_HI(reg) \ - ((reg) + ((((reg) & 0xf000) == 0x9000) ? 2 : 1)) - uint16_t val; -} __packed; - -/* structure for notification ZYD_NOTIF_RETRYSTATUS */ -struct zyd_notif_retry { - uint16_t rate; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - uint16_t count; -} __packed; - -#define ZYD_CONFIG_NO 1 -#define ZYD_IFACE_INDEX 0 - -#define ZYD_INTR_TIMEOUT 1000 -#define ZYD_TX_TIMEOUT 10000 - -#define ZYD_MAX_TXBUFSZ \ - (sizeof(struct zyd_tx_desc) + MCLBYTES) -#define ZYD_MIN_FRAGSZ \ - (sizeof(struct zyd_plcphdr) + IEEE80211_MIN_LEN + \ - sizeof(struct zyd_rx_stat)) -#define ZYD_MIN_RXBUFSZ ZYD_MIN_FRAGSZ -#define ZYX_MAX_RXBUFSZ \ - ((sizeof (struct zyd_plcphdr) + IEEE80211_MAX_LEN + \ - sizeof (struct zyd_rx_stat)) * ZYD_MAX_RXFRAMECNT + \ - sizeof (struct zyd_rx_desc)) - -#define ZYD_RX_LIST_CNT 1 -#define ZYD_TX_LIST_CNT 5 -#define ZYD_CMD_FLAG_READ (1 << 0) - -/* quickly determine if a given rate is CCK or OFDM */ -#define ZYD_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) - -struct zyd_phy_pair { - uint16_t reg; - uint8_t val; -}; - -struct zyd_mac_pair { - uint16_t reg; - uint32_t val; -}; - -struct zyd_tx_data { - struct zyd_softc *sc; - usbd_xfer_handle xfer; - uint8_t *buf; - struct ieee80211_node *ni; - struct mbuf *m; -}; - -struct zyd_rx_data { - struct zyd_softc *sc; - usbd_xfer_handle xfer; - const uint8_t *buf; -}; - -struct zyd_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define ZYD_NODE(ni) ((struct zyd_node *)(ni)) - -struct zyd_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; -} __packed; - -#define ZYD_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct zyd_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define ZYD_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct zyd_softc; /* forward declaration */ - -struct zyd_rf { - /* RF methods */ - int (*init)(struct zyd_rf *); - int (*switch_radio)(struct zyd_rf *, int); - int (*set_channel)(struct zyd_rf *, uint8_t); - int (*bandedge6)(struct zyd_rf *, - struct ieee80211_channel *); - /* RF attributes */ - struct zyd_softc *rf_sc; /* back-pointer */ - int width; -}; - -struct zyd_rq { - const uint16_t *idata; - struct zyd_pair *odata; - int len; - STAILQ_ENTRY(zyd_rq) rq; -}; - -struct zyd_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); - struct callout amrr_ch; - struct ieee80211_amrr amrr; -}; -#define ZYD_VAP(vap) ((struct zyd_vap *)(vap)) - -struct zyd_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - struct ifnet *sc_ifp; - - enum ieee80211_state sc_state; - int sc_arg; - int sc_flags; -#define ZYD_FLAG_FWLOADED (1 << 0) -#define ZYD_FLAG_DETACHING (1 << 1) -#define ZYD_FLAG_INITONCE (1 << 2) -#define ZYD_FLAG_INITDONE (1 << 3) - int sc_if_flags; - uint32_t sc_debug; - - struct usb_task sc_mcasttask; - struct usb_task sc_scantask; - int sc_scan_action; -#define ZYD_SCAN_START 0 -#define ZYD_SCAN_END 1 -#define ZYD_SET_CHANNEL 2 - struct usb_task sc_task; - struct callout sc_watchdog_ch; - - struct zyd_rf sc_rf; - - STAILQ_HEAD(, zyd_rq) sc_rqh; - - uint8_t sc_bssid[IEEE80211_ADDR_LEN]; - uint16_t sc_fwbase; - uint8_t sc_regdomain; - uint8_t sc_macrev; - uint16_t sc_fwrev; - uint8_t sc_rfrev; - uint8_t sc_parev; - uint8_t sc_al2230s; - uint8_t sc_bandedge6; - uint8_t sc_newphy; - uint8_t sc_cckgain; - uint8_t sc_fix_cr157; - uint8_t sc_ledtype; - uint8_t sc_txled; - - uint32_t sc_atim_wnd; - uint32_t sc_pre_tbtt; - uint32_t sc_bcn_int; - - uint8_t sc_pwrcal[14]; - uint8_t sc_pwrint[14]; - uint8_t sc_ofdm36_cal[14]; - uint8_t sc_ofdm48_cal[14]; - uint8_t sc_ofdm54_cal[14]; -#define ZYD_ENDPT_BOUT 0 -#define ZYD_ENDPT_BIN 1 -#define ZYD_ENDPT_IIN 2 -#define ZYD_ENDPT_IOUT 3 -#define ZYD_ENDPT_CNT 4 - usbd_pipe_handle sc_ep[ZYD_ENDPT_CNT]; - uint8_t *sc_ibuf; - - struct mtx sc_txmtx; - struct zyd_rx_data sc_rxdata[ZYD_RX_LIST_CNT]; - struct zyd_tx_data sc_txdata[ZYD_TX_LIST_CNT]; - int sc_txidx; - int sc_txqueued; - int sc_txtimer; - - struct zyd_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct zyd_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define ZYD_LOCK(sc) do { ((sc) = (sc)); mtx_lock(&Giant); } while (0) -#define ZYD_UNLOCK(sc) mtx_unlock(&Giant) -#define ZYD_TX_LOCK(sc) mtx_lock(&(sc)->sc_txmtx) -#define ZYD_TX_UNLOCK(sc) mtx_unlock(&(sc)->sc_txmtx) - diff --git a/sys/dev/usb/kue_fw.h b/sys/dev/usb/kue_fw.h deleted file mode 100644 index 8934465..0000000 --- a/sys/dev/usb/kue_fw.h +++ /dev/null @@ -1,685 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -/* - * This file contains the firmware needed to make the KLSI chip work, - * along with a few constants related to the QT Engine microcontroller - * embedded in the KLSI part. - * - * Firmware is loaded using the vendor-specific 'send scan data' - * command (0xFF). The basic operation is that we must load the - * firmware, then issue some trigger commands to fix it up and start - * it running. There are three transfers: load the binary code, - * load the 'fixup' (data segment?), then issue a command to - * start the code firmware running. The data itself is prefixed by - * a 16-bit signature word, a 16-bit length value, a type byte - * and an interrupt (command) byte. The code segment is of type - * 0x02 (replacement interrupt vector data) and the fixup segment - * is of type 0x03 (replacement interrupt fixup data). The interrupt - * code is 0x64 (load new code). The length word is the total length - * of the segment minus 7. I precomputed the values and stuck them - * into the appropriate locations within the segments to save some - * work in the driver. - */ - -/* QT controller data block types. */ -/* Write data into specific memory location. */ -#define KUE_QTBTYPE_WRITE_DATA 0x00 -/* Write data into interrupt vector location */ -#define KUE_QTBTYPE_WRITE_INTVEC 0x01 -/* Replace interrupt vector with this data */ -#define KUE_QTBTYPE_REPL_INTVEC 0x02 -/* Fixup interrupt vector code with this data */ -#define KUE_QTBTYPE_FIXUP_INTVEC 0x03 -/* Force jump to location */ -#define KUE_QTBTYPE_JUMP 0x04 -/* Force call to location */ -#define KUE_QTBTYPE_CALL 0x05 -/* Force interrupt call */ -#define KUE_QTBTYPE_CALLINTR 0x06 -/* - * Cause data to be written using the specified QT engine - * interrupt, from starting location in memory for a specified - * number of bytes. - */ -#define KUE_QTBTYPE_WRITE_WITH_INTR 0x07 -/* Cause data from stream to be written using specified QT interrupt. */ -#define KUE_QTBTYPE_WRITE_STR_WITH_INTR 0x08 -/* Cause data to be written to config locations. */ -/* Addresses assume 0xc000 offset. */ -#define KUE_QTBTYPE_WRITE_CONFIG 0x09 - -#define KUE_QTINTR_LOAD_CODE 0x64 -#define KUE_QTINTR_TRIGGER_CODE 0x3B -#define KUE_QTINTR_LOAD_CODE_HIGH 0x9C - -/* Firmware code segment */ -static unsigned char kue_code_seg[] = -{ - /******************************************/ - /* NOTE: B6/C3 is data header signature */ - /* 0xAA/0xBB is data length = total */ - /* bytes - 7, 0xCC is type, 0xDD is */ - /* interrupt to use. */ - /******************************************/ - 0xB6, 0xC3, 0xf7, 0x0e, 0x02, 0x64, - 0x9f, 0xcf, 0xbc, 0x08, 0xe7, 0x57, 0x00, 0x00, - 0x9a, 0x08, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f, - 0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0, - 0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf, - 0xe7, 0x09, 0xa2, 0xc0, 0x94, 0x08, 0xd7, 0x09, - 0x00, 0xc0, 0xe7, 0x59, 0xba, 0x08, 0x94, 0x08, - 0x03, 0xc1, 0xe7, 0x67, 0xff, 0xf7, 0x24, 0xc0, - 0xe7, 0x05, 0x00, 0xc0, 0xa7, 0xcf, 0x92, 0x08, - 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x08, 0xa7, 0xa1, - 0x8e, 0x08, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0xf2, 0x09, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00, - 0xa4, 0xc0, 0xa7, 0xc0, 0x56, 0x08, 0x9f, 0xaf, - 0x70, 0x09, 0xe7, 0x07, 0x00, 0x00, 0xf2, 0x09, - 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, 0x9f, 0xa0, - 0x40, 0x00, 0xe7, 0x59, 0x90, 0x08, 0x94, 0x08, - 0x9f, 0xa0, 0x40, 0x00, 0xc8, 0x09, 0xa2, 0x08, - 0x08, 0x62, 0x9f, 0xa1, 0x14, 0x0a, 0xe7, 0x57, - 0x00, 0x00, 0x52, 0x08, 0xa7, 0xc0, 0x56, 0x08, - 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, - 0x8e, 0x08, 0xa7, 0xc1, 0x56, 0x08, 0xc0, 0x09, - 0xa8, 0x08, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59, - 0x94, 0x08, 0x02, 0xc0, 0x9f, 0xaf, 0xee, 0x00, - 0xe7, 0x59, 0xae, 0x08, 0x94, 0x08, 0x02, 0xc1, - 0x9f, 0xaf, 0xf6, 0x00, 0x9f, 0xaf, 0x9e, 0x03, - 0xef, 0x57, 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xa1, - 0xde, 0x01, 0xe7, 0x57, 0x00, 0x00, 0x78, 0x08, - 0x9f, 0xa0, 0xe4, 0x03, 0x9f, 0xaf, 0x2c, 0x04, - 0xa7, 0xcf, 0x56, 0x08, 0x48, 0x02, 0xe7, 0x09, - 0x94, 0x08, 0xa8, 0x08, 0xc8, 0x37, 0x04, 0x00, - 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, 0xe7, 0x57, - 0x00, 0x00, 0xa6, 0x08, 0x97, 0xc0, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, 0x9c, 0x08, - 0x08, 0x62, 0x1d, 0xc0, 0x27, 0x04, 0x9c, 0x08, - 0x10, 0x94, 0xf0, 0x07, 0xee, 0x09, 0x02, 0x00, - 0xc1, 0x07, 0x01, 0x00, 0x70, 0x00, 0x04, 0x00, - 0xf0, 0x07, 0x44, 0x01, 0x06, 0x00, 0x50, 0xaf, - 0xe7, 0x09, 0x94, 0x08, 0xae, 0x08, 0xe7, 0x17, - 0x14, 0x00, 0xae, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xae, 0x08, 0xe7, 0x07, 0xff, 0xff, 0xa8, 0x08, - 0xe7, 0x07, 0x00, 0x00, 0xa6, 0x08, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0x48, 0x02, 0xd0, 0x09, 0x9c, 0x08, - 0x27, 0x02, 0x9c, 0x08, 0xe7, 0x09, 0x20, 0xc0, - 0xee, 0x09, 0xe7, 0xd0, 0xee, 0x09, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02, 0xc8, 0x37, - 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x60, - 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00, 0x23, 0xc9, - 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8, 0xc0, 0x17, - 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, - 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0xbe, 0x01, 0x0a, 0x00, - 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, - 0x9f, 0xaf, 0xe4, 0x03, 0x97, 0xcf, 0x9f, 0xaf, - 0xe4, 0x03, 0xc9, 0x37, 0x04, 0x00, 0xc1, 0xdf, - 0xc8, 0x09, 0x70, 0x08, 0x50, 0x02, 0x67, 0x02, - 0x70, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc0, 0xdf, - 0x9f, 0xaf, 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x57, - 0x00, 0x00, 0xaa, 0x08, 0x97, 0xc1, 0xe7, 0x57, - 0x01, 0x00, 0x7a, 0x08, 0x97, 0xc0, 0xc8, 0x09, - 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, - 0xc0, 0x17, 0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, - 0x27, 0x0c, 0x0c, 0x00, 0x36, 0x01, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xc0, 0xbe, 0x02, - 0xe7, 0x57, 0x00, 0x00, 0xb0, 0x08, 0x97, 0xc1, - 0xe7, 0x07, 0x09, 0x00, 0x12, 0xc0, 0xe7, 0x77, - 0x00, 0x08, 0x20, 0xc0, 0x9f, 0xc1, 0xb6, 0x02, - 0xe7, 0x57, 0x09, 0x00, 0x12, 0xc0, 0x77, 0xc9, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x77, - 0x00, 0x08, 0x20, 0xc0, 0x2f, 0xc1, 0xe7, 0x07, - 0x00, 0x00, 0x42, 0xc0, 0xe7, 0x07, 0x05, 0x00, - 0x90, 0xc0, 0xc8, 0x07, 0x0a, 0x00, 0xe7, 0x77, - 0x04, 0x00, 0x20, 0xc0, 0x09, 0xc1, 0x08, 0xda, - 0x7a, 0xc1, 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, - 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, 0x1a, 0xcf, - 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, 0x00, 0xd8, - 0x27, 0x50, 0x34, 0x01, 0x17, 0xc1, 0xe7, 0x77, - 0x02, 0x00, 0x20, 0xc0, 0x79, 0xc1, 0x27, 0x50, - 0x34, 0x01, 0x10, 0xc1, 0xe7, 0x77, 0x02, 0x00, - 0x20, 0xc0, 0x79, 0xc0, 0x9f, 0xaf, 0xd8, 0x02, - 0xe7, 0x05, 0x00, 0xc0, 0x00, 0x60, 0x9f, 0xc0, - 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, - 0xb8, 0x08, 0x06, 0xcf, 0xe7, 0x07, 0x30, 0x0e, - 0x02, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x12, 0xc0, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xe7, 0x07, - 0x01, 0x00, 0xb8, 0x08, 0x97, 0xcf, 0xe7, 0x07, - 0x50, 0xc3, 0x12, 0xc0, 0xe7, 0x07, 0x30, 0x0e, - 0x02, 0x00, 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, - 0xe7, 0x07, 0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, - 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, 0xe7, 0x07, - 0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x7a, 0x08, 0xe7, 0x57, 0x0f, 0x00, 0xb2, 0x08, - 0x13, 0xc1, 0x9f, 0xaf, 0x2e, 0x08, 0xca, 0x09, - 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, 0x5c, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, 0xe7, 0x07, - 0x00, 0x00, 0xb2, 0x08, 0xe7, 0x07, 0x01, 0x00, - 0xb4, 0x08, 0xc0, 0x07, 0xff, 0xff, 0x97, 0xcf, - 0x9f, 0xaf, 0x4c, 0x03, 0xc0, 0x69, 0xb4, 0x08, - 0x57, 0x00, 0x9f, 0xde, 0x33, 0x00, 0xc1, 0x05, - 0x27, 0xd8, 0xb2, 0x08, 0x27, 0xd2, 0xb4, 0x08, - 0xe7, 0x87, 0x01, 0x00, 0xb4, 0x08, 0xe7, 0x67, - 0xff, 0x03, 0xb4, 0x08, 0x00, 0x60, 0x97, 0xc0, - 0xe7, 0x07, 0x01, 0x00, 0xb0, 0x08, 0x27, 0x00, - 0x12, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0xb6, 0x08, - 0x00, 0xd2, 0x02, 0xc3, 0xc0, 0x97, 0x05, 0x80, - 0x27, 0x00, 0xb6, 0x08, 0xc0, 0x99, 0x82, 0x08, - 0xc0, 0x99, 0xa2, 0xc0, 0x97, 0xcf, 0xe7, 0x07, - 0x00, 0x00, 0xb0, 0x08, 0xc0, 0xdf, 0x97, 0xcf, - 0xc8, 0x09, 0x72, 0x08, 0x08, 0x62, 0x02, 0xc0, - 0x10, 0x64, 0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, - 0x64, 0x08, 0xe7, 0x07, 0xc8, 0x05, 0x24, 0x00, - 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, 0xc8, 0x17, - 0x0e, 0x00, 0x27, 0x02, 0x64, 0x08, 0xe7, 0x07, - 0xd6, 0x05, 0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, - 0x62, 0x08, 0x13, 0xc1, 0x9f, 0xaf, 0x70, 0x03, - 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, 0x13, 0xc0, - 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, 0xe7, 0x07, - 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, - 0x96, 0xc0, 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, - 0x04, 0xcf, 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, - 0x02, 0xc1, 0x9f, 0xaf, 0x70, 0x03, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0xc8, 0x09, 0x72, 0x08, 0x27, 0x02, - 0x78, 0x08, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, - 0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00, - 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0x64, 0x01, 0x0a, 0x00, - 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00, - 0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0x6a, 0x08, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, - 0x6a, 0x08, 0x27, 0x04, 0x6a, 0x08, 0x27, 0x52, - 0x6c, 0x08, 0x03, 0xc1, 0xe7, 0x07, 0x6a, 0x08, - 0x6c, 0x08, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17, - 0x0e, 0x00, 0x9f, 0xaf, 0x16, 0x05, 0xc8, 0x05, - 0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x80, 0x04, - 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, - 0x1c, 0xc0, 0xd0, 0x09, 0x72, 0x08, 0x27, 0x02, - 0x72, 0x08, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, - 0x01, 0x00, 0x04, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x06, 0x00, 0xca, 0x17, 0x2c, 0x00, 0xf8, 0x77, - 0x01, 0x00, 0x0e, 0x00, 0x06, 0xc0, 0xca, 0xd9, - 0xf8, 0x57, 0xff, 0x00, 0x0e, 0x00, 0x01, 0xc1, - 0xca, 0xd9, 0x22, 0x1c, 0x0c, 0x00, 0xe2, 0x27, - 0x00, 0x00, 0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, - 0x00, 0x00, 0xca, 0x05, 0x00, 0x0c, 0x0c, 0x00, - 0xc0, 0x17, 0x41, 0x00, 0xc0, 0x67, 0xc0, 0xff, - 0x30, 0x00, 0x08, 0x00, 0x00, 0x02, 0xc0, 0x17, - 0x0c, 0x00, 0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, - 0xdc, 0x00, 0x0a, 0x00, 0xf0, 0x07, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x40, 0xd1, - 0x01, 0x00, 0xc0, 0x19, 0xa6, 0x08, 0xc0, 0x59, - 0x98, 0x08, 0x04, 0xc9, 0x49, 0xaf, 0x9f, 0xaf, - 0xee, 0x00, 0x4a, 0xaf, 0x67, 0x10, 0xa6, 0x08, - 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x01, 0x00, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x50, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xc0, 0x07, - 0x01, 0x00, 0xc1, 0x09, 0x7c, 0x08, 0xc1, 0x77, - 0x01, 0x00, 0x97, 0xc1, 0xd8, 0x77, 0x01, 0x00, - 0x12, 0xc0, 0xc9, 0x07, 0x4c, 0x08, 0x9f, 0xaf, - 0x64, 0x05, 0x04, 0xc1, 0xc1, 0x77, 0x08, 0x00, - 0x13, 0xc0, 0x97, 0xcf, 0xc1, 0x77, 0x02, 0x00, - 0x97, 0xc1, 0xc1, 0x77, 0x10, 0x00, 0x0c, 0xc0, - 0x9f, 0xaf, 0x86, 0x05, 0x97, 0xcf, 0xc1, 0x77, - 0x04, 0x00, 0x06, 0xc0, 0xc9, 0x07, 0x7e, 0x08, - 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x00, 0xcf, - 0x00, 0x90, 0x97, 0xcf, 0x50, 0x54, 0x97, 0xc1, - 0x70, 0x5c, 0x02, 0x00, 0x02, 0x00, 0x97, 0xc1, - 0x70, 0x5c, 0x04, 0x00, 0x04, 0x00, 0x97, 0xcf, - 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, - 0x0c, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, - 0x88, 0x08, 0xcc, 0x09, 0x8a, 0x08, 0x0b, 0x53, - 0x11, 0xc0, 0xc9, 0x02, 0xca, 0x07, 0x78, 0x05, - 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x0a, 0xc8, - 0x82, 0x08, 0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, - 0x64, 0x05, 0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, - 0x82, 0x60, 0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, - 0x89, 0x10, 0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, - 0x82, 0x08, 0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, - 0xe7, 0x09, 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, - 0x98, 0xc0, 0x68, 0x08, 0x0f, 0xcf, 0xe7, 0x09, - 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, 0x98, 0xc0, - 0x68, 0x08, 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, - 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, - 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09, 0x00, 0xc0, - 0x17, 0x02, 0xc8, 0x09, 0x62, 0x08, 0xc8, 0x37, - 0x0e, 0x00, 0xe7, 0x57, 0x04, 0x00, 0x68, 0x08, - 0x3d, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, - 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, - 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xba, 0x08, 0xe7, 0x77, 0x2a, 0x00, 0x66, 0x08, - 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, - 0xe7, 0x77, 0x20, 0x00, 0x66, 0x08, 0x0e, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77, 0x0a, 0x00, - 0x66, 0x08, 0xca, 0x05, 0x1e, 0xc0, 0x97, 0x02, - 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, - 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x0e, 0x00, - 0xe7, 0x77, 0x02, 0x00, 0x66, 0x08, 0x07, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf, 0xf2, 0x17, - 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf, 0x68, 0x04, - 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02, 0xf1, 0x09, - 0x68, 0x08, 0x0c, 0x00, 0xf1, 0xda, 0x0c, 0x00, - 0xc8, 0x09, 0x6c, 0x08, 0x50, 0x02, 0x67, 0x02, - 0x6c, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc9, 0x05, - 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, 0xe7, 0x57, - 0x00, 0x00, 0x62, 0x08, 0x02, 0xc0, 0x9f, 0xaf, - 0x70, 0x03, 0xc8, 0x05, 0xe7, 0x05, 0x00, 0xc0, - 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xc0, 0x09, - 0x92, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, - 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, - 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, - 0xba, 0x08, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, - 0xca, 0x09, 0xac, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0x7a, 0x08, 0xe7, 0x07, 0x66, 0x03, 0x02, 0x00, - 0xc0, 0x77, 0x02, 0x00, 0x10, 0xc0, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x04, 0xc0, 0x9f, 0xaf, - 0xd8, 0x02, 0x9f, 0xcf, 0x12, 0x08, 0xf2, 0x17, - 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x52, 0x00, 0x9f, 0xcf, 0x12, 0x08, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x08, 0xc0, 0xe7, 0x57, - 0x00, 0x00, 0xb8, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0xb8, 0x08, 0x0a, 0xc0, 0x03, 0xcf, 0xc0, 0x77, - 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, - 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5a, 0x00, - 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0, 0xf2, 0x17, - 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00, 0x1d, 0xc1, - 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77, 0x00, 0x02, - 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x64, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00, 0xc0, 0x77, - 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, - 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, - 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0, 0x37, 0xcf, - 0x36, 0xcf, 0xf2, 0x17, 0x01, 0x00, 0x00, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00, 0xef, 0x57, - 0x00, 0x00, 0xf0, 0x09, 0x18, 0xc0, 0xe7, 0x57, - 0x01, 0x00, 0xb2, 0x08, 0x0e, 0xc2, 0x07, 0xc8, - 0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x52, 0x00, 0x06, 0xcf, 0xf2, 0x17, - 0x01, 0x00, 0x54, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x56, 0x00, 0xe7, 0x07, 0x00, 0x00, 0xb2, 0x08, - 0xe7, 0x07, 0x01, 0x00, 0xb4, 0x08, 0xc8, 0x09, - 0x34, 0x01, 0xca, 0x17, 0x14, 0x00, 0xd8, 0x77, - 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9, 0xd8, 0x57, - 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9, 0xe2, 0x19, - 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17, - 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0x9f, 0xaf, - 0x2e, 0x08, 0x9f, 0xaf, 0xde, 0x01, 0xe7, 0x57, - 0x00, 0x00, 0xaa, 0x08, 0x9f, 0xa1, 0xf0, 0x0b, - 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05, 0xe7, 0x05, - 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xc8, 0x09, - 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x27, 0x04, - 0x6e, 0x08, 0x27, 0x52, 0x70, 0x08, 0x03, 0xc1, - 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x9f, 0xaf, - 0x68, 0x04, 0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0xcc, - 0x00, 0x00, 0x00, 0x00, 0xe7, 0x57, 0x00, 0x80, - 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07, 0x52, 0x0e, - 0x12, 0x00, 0xe7, 0x07, 0x98, 0x0e, 0xb2, 0x00, - 0xe7, 0x07, 0xa4, 0x09, 0xf2, 0x02, 0xc8, 0x09, - 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00, 0x0d, 0x00, - 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x0e, 0xc0, 0xc8, 0x09, 0xdc, 0x00, 0xf0, 0x07, - 0xff, 0xff, 0x09, 0x00, 0xf0, 0x07, 0xfb, 0x13, - 0x0b, 0x00, 0xe7, 0x09, 0xc0, 0x00, 0x58, 0x08, - 0xe7, 0x09, 0xbe, 0x00, 0x54, 0x08, 0xe7, 0x09, - 0x10, 0x00, 0x92, 0x08, 0xc8, 0x07, 0xb4, 0x09, - 0x9f, 0xaf, 0x8c, 0x09, 0x9f, 0xaf, 0xe2, 0x0b, - 0xc0, 0x07, 0x80, 0x01, 0x44, 0xaf, 0x27, 0x00, - 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0x27, 0x00, - 0x8c, 0x08, 0xc0, 0x07, 0x74, 0x00, 0x44, 0xaf, - 0x27, 0x00, 0xac, 0x08, 0x08, 0x00, 0x00, 0x90, - 0xc1, 0x07, 0x1d, 0x00, 0x20, 0x00, 0x20, 0x00, - 0x01, 0xda, 0x7c, 0xc1, 0x9f, 0xaf, 0x8a, 0x0b, - 0xc0, 0x07, 0x4c, 0x00, 0x48, 0xaf, 0x27, 0x00, - 0x56, 0x08, 0x9f, 0xaf, 0x72, 0x0c, 0xe7, 0x07, - 0x00, 0x80, 0x96, 0x08, 0xef, 0x57, 0x00, 0x00, - 0xf0, 0x09, 0x03, 0xc0, 0xe7, 0x07, 0x01, 0x00, - 0x1c, 0xc0, 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, - 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00, 0x0e, 0xc0, - 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, - 0x8a, 0x0c, 0xc0, 0x07, 0x01, 0x00, 0x60, 0xaf, - 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08, 0x09, 0x08, - 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1, 0x97, 0xcf, - 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf, 0x51, 0x94, - 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf, 0xc9, 0x09, - 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1, 0xc0, 0xdf, - 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00, 0x24, 0x00, - 0xd6, 0x05, 0x22, 0x00, 0xc4, 0x06, 0xd0, 0x00, - 0xf0, 0x0b, 0xaa, 0x00, 0x0e, 0x0a, 0xbe, 0x00, - 0x2c, 0x0c, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, - 0xc4, 0x05, 0x02, 0x00, 0x66, 0x03, 0x06, 0x00, - 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04, 0x28, 0xc0, - 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04, 0x22, 0xc0, - 0xff, 0xf0, 0xc0, 0x00, 0x60, 0x0b, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x34, 0x0a, 0x3e, 0x0a, - 0x9e, 0x0a, 0xa8, 0x0a, 0xce, 0x0a, 0xd2, 0x0a, - 0xd6, 0x0a, 0x00, 0x0b, 0x10, 0x0b, 0x1e, 0x0b, - 0x20, 0x0b, 0x28, 0x0b, 0x28, 0x0b, 0x27, 0x02, - 0xa2, 0x08, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00, - 0xa2, 0x08, 0x0a, 0x0e, 0x01, 0x00, 0xca, 0x57, - 0x0e, 0x00, 0x9f, 0xc3, 0x2a, 0x0b, 0xca, 0x37, - 0x00, 0x00, 0x9f, 0xc2, 0x2a, 0x0b, 0x0a, 0xd2, - 0xb2, 0xcf, 0xf4, 0x09, 0xc8, 0x09, 0xde, 0x00, - 0x07, 0x06, 0x9f, 0xcf, 0x3c, 0x0b, 0xf0, 0x57, - 0x80, 0x01, 0x06, 0x00, 0x9f, 0xc8, 0x2a, 0x0b, - 0x27, 0x0c, 0x02, 0x00, 0x86, 0x08, 0xc0, 0x09, - 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0xe7, 0x07, - 0x00, 0x00, 0x84, 0x08, 0x27, 0x00, 0x5c, 0x08, - 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00, 0x8c, 0x08, - 0x41, 0x90, 0x67, 0x50, 0x86, 0x08, 0x0d, 0xc0, - 0x67, 0x00, 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, - 0x5e, 0x08, 0xe7, 0x07, 0x8a, 0x0a, 0x60, 0x08, - 0xc8, 0x07, 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, - 0x97, 0xcf, 0x9f, 0xaf, 0xac, 0x0e, 0xe7, 0x09, - 0x8c, 0x08, 0x8a, 0x08, 0xe7, 0x09, 0x86, 0x08, - 0x84, 0x08, 0x59, 0xaf, 0x97, 0xcf, 0x27, 0x0c, - 0x02, 0x00, 0x7c, 0x08, 0x59, 0xaf, 0x97, 0xcf, - 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda, 0x49, 0xd2, - 0xc9, 0x19, 0xac, 0x08, 0xc8, 0x07, 0x5a, 0x08, - 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02, 0xe0, 0x07, - 0x04, 0x00, 0xd0, 0x07, 0x9a, 0x0a, 0x48, 0xdb, - 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, - 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, 0xf0, 0x57, - 0x06, 0x00, 0x06, 0x00, 0x26, 0xc1, 0xe7, 0x07, - 0x7e, 0x08, 0x5c, 0x08, 0x41, 0x90, 0x67, 0x00, - 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, 0x5e, 0x08, - 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, 0xc8, 0x07, - 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, 0x97, 0xcf, - 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57, 0x06, 0x00, - 0x10, 0xc1, 0xc8, 0x07, 0x7e, 0x08, 0x16, 0xcf, - 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda, 0x40, 0xd1, - 0x27, 0x00, 0x98, 0x08, 0x1f, 0xcf, 0x1e, 0xcf, - 0x27, 0x0c, 0x02, 0x00, 0xa4, 0x08, 0x1a, 0xcf, - 0x00, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07, - 0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00, - 0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00, - 0x5a, 0x08, 0xe7, 0x01, 0x5e, 0x08, 0x27, 0x02, - 0x5c, 0x08, 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, - 0xc8, 0x07, 0x5a, 0x08, 0xc1, 0x07, 0x00, 0x80, - 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, - 0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x9a, 0x08, 0xa7, 0xcf, 0x58, 0x08, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x07, 0x01, 0x00, 0x9a, 0x08, - 0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf, - 0x58, 0x08, 0xc0, 0x07, 0x40, 0x00, 0x44, 0xaf, - 0x27, 0x00, 0xa0, 0x08, 0x08, 0x00, 0xc0, 0x07, - 0x20, 0x00, 0x20, 0x94, 0x00, 0xda, 0x7d, 0xc1, - 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf, 0x40, 0x00, - 0x41, 0x90, 0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, - 0x50, 0x06, 0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, - 0xc0, 0x07, 0x10, 0x00, 0x27, 0x00, 0x76, 0x08, - 0x41, 0x90, 0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, - 0x27, 0x00, 0x74, 0x08, 0xc0, 0x09, 0x76, 0x08, - 0x41, 0x90, 0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, - 0x08, 0x00, 0x44, 0xaf, 0x27, 0x00, 0x9e, 0x08, - 0x97, 0xcf, 0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, - 0xe7, 0x67, 0xff, 0xf3, 0x24, 0xc0, 0x97, 0xcf, - 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0xe7, 0x57, - 0x00, 0x00, 0x7a, 0x08, 0x97, 0xc1, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, - 0xe7, 0x07, 0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, - 0xfe, 0xff, 0x3e, 0xc0, 0xe7, 0x07, 0x2e, 0x00, - 0x0a, 0xc0, 0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, - 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, - 0xf0, 0x0c, 0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, - 0x54, 0x08, 0xc0, 0x05, 0x27, 0x00, 0x52, 0x08, - 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0x9f, 0xaf, - 0xe2, 0x0b, 0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, - 0x9f, 0xaf, 0xf0, 0x0c, 0xe7, 0x07, 0x00, 0x00, - 0x78, 0x08, 0x00, 0x90, 0xe7, 0x09, 0x88, 0x08, - 0x8a, 0x08, 0x27, 0x00, 0x84, 0x08, 0x27, 0x00, - 0x7c, 0x08, 0x9f, 0xaf, 0x8a, 0x0c, 0xe7, 0x07, - 0x00, 0x00, 0xb2, 0x02, 0xe7, 0x07, 0x00, 0x00, - 0xb4, 0x02, 0xc0, 0x07, 0x06, 0x00, 0xc8, 0x09, - 0xde, 0x00, 0xc8, 0x17, 0x03, 0x00, 0xc9, 0x07, - 0x7e, 0x08, 0x29, 0x0a, 0x00, 0xda, 0x7d, 0xc1, - 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, - 0x00, 0x90, 0x27, 0x00, 0x6a, 0x08, 0xe7, 0x07, - 0x6a, 0x08, 0x6c, 0x08, 0x27, 0x00, 0x6e, 0x08, - 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x27, 0x00, - 0x78, 0x08, 0x27, 0x00, 0x62, 0x08, 0x27, 0x00, - 0x64, 0x08, 0xc8, 0x09, 0x74, 0x08, 0xc1, 0x09, - 0x76, 0x08, 0xc9, 0x07, 0x72, 0x08, 0x11, 0x02, - 0x09, 0x02, 0xc8, 0x17, 0x40, 0x06, 0x01, 0xda, - 0x7a, 0xc1, 0x51, 0x94, 0xc8, 0x09, 0x9e, 0x08, - 0xc9, 0x07, 0x9c, 0x08, 0xc1, 0x09, 0x76, 0x08, - 0x01, 0xd2, 0x01, 0xd8, 0x11, 0x02, 0x09, 0x02, - 0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1, - 0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0xe7, 0x57, 0x00, 0x00, 0x52, 0x08, 0x97, 0xc0, - 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0x94, 0x08, - 0x90, 0x08, 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, - 0x04, 0xc1, 0xe7, 0x07, 0xf0, 0x0c, 0x8e, 0x08, - 0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0x90, 0x08, - 0xe7, 0x67, 0xff, 0x07, 0x90, 0x08, 0xe7, 0x07, - 0x26, 0x0d, 0x8e, 0x08, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, - 0x96, 0x08, 0x23, 0xc0, 0xe7, 0x07, 0x00, 0x80, - 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, - 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, - 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07, 0x00, 0x00, - 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, - 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, - 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07, 0x00, 0x80, - 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00, 0xe7, 0x07, - 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0x80, 0xc0, 0xef, 0x57, 0x00, 0x00, 0xf1, 0x09, - 0x9f, 0xa0, 0xc0, 0x0d, 0xe7, 0x07, 0x04, 0x00, - 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0, - 0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x96, 0x08, 0xe7, 0x07, 0x00, 0x00, - 0x8e, 0x08, 0xe7, 0x07, 0x00, 0x00, 0xaa, 0x08, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf, - 0x9e, 0x03, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf, - 0xde, 0x01, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0x9f, 0xaf, 0xde, 0x0d, 0xef, 0x77, 0x00, 0x00, - 0xf1, 0x09, 0x97, 0xc1, 0x9f, 0xaf, 0xde, 0x0d, - 0xef, 0x77, 0x00, 0x00, 0xf1, 0x09, 0x97, 0xc1, - 0xef, 0x07, 0x01, 0x00, 0xf1, 0x09, 0xe7, 0x87, - 0x00, 0x08, 0x1e, 0xc0, 0xe7, 0x87, 0x00, 0x08, - 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, 0x22, 0xc0, - 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, 0x11, 0xc0, - 0xe7, 0x67, 0xff, 0xf7, 0x1e, 0xc0, 0xe7, 0x87, - 0x00, 0x08, 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, - 0x22, 0xc0, 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, - 0x04, 0xc1, 0xe7, 0x87, 0x00, 0x08, 0x22, 0xc0, - 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x01, 0xf0, 0x09, - 0xef, 0x57, 0x18, 0x00, 0xfe, 0xff, 0x97, 0xc2, - 0xef, 0x07, 0x00, 0x00, 0xf0, 0x09, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, - 0x97, 0x02, 0xe7, 0x57, 0x00, 0x00, 0x7a, 0x08, - 0x06, 0xc0, 0xc0, 0x09, 0x92, 0xc0, 0xc0, 0x77, - 0x09, 0x02, 0x9f, 0xc1, 0xea, 0x06, 0x9f, 0xcf, - 0x20, 0x08, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x0e, 0xc0, 0x9f, 0xaf, 0x66, 0x0e, - 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0xb0, 0xc0, - 0xe7, 0x67, 0xfe, 0x7f, 0xb0, 0xc0, 0xc8, 0x77, - 0x00, 0x20, 0x9f, 0xc1, 0x64, 0xeb, 0xe7, 0x57, - 0x00, 0x00, 0xc8, 0x02, 0x9f, 0xc1, 0x80, 0xeb, - 0xc8, 0x99, 0xca, 0x02, 0xc8, 0x67, 0x04, 0x00, - 0x9f, 0xc1, 0x96, 0xeb, 0x9f, 0xcf, 0x4c, 0xeb, - 0xe7, 0x07, 0x00, 0x00, 0xa6, 0xc0, 0xe7, 0x09, - 0xb0, 0xc0, 0xc8, 0x02, 0xe7, 0x07, 0x03, 0x00, - 0xb0, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0x86, 0x08, - 0xc0, 0x37, 0x01, 0x00, 0x97, 0xc9, 0xc9, 0x09, - 0x88, 0x08, 0x02, 0x00, 0x41, 0x90, 0x48, 0x02, - 0xc9, 0x17, 0x06, 0x00, 0x9f, 0xaf, 0x64, 0x05, - 0x9f, 0xa2, 0xd6, 0x0e, 0x02, 0xda, 0x77, 0xc1, - 0x41, 0x60, 0x71, 0xc1, 0x97, 0xcf, 0x17, 0x02, - 0x57, 0x02, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, - 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, - 0x21, 0x04, 0xe0, 0x00, 0xc1, 0x07, 0x01, 0x00, - 0xc9, 0x05, 0xc8, 0x05, 0x97, 0xcf, - 0, 0 -}; - -/* Firmware fixup (data?) segment */ -static unsigned char kue_fix_seg[] = -{ - /******************************************/ - /* NOTE: B6/C3 is data header signature */ - /* 0xAA/0xBB is data length = total */ - /* bytes - 7, 0xCC is type, 0xDD is */ - /* interrupt to use. */ - /******************************************/ - 0xB6, 0xC3, 0xc9, 0x02, 0x03, 0x64, - 0x02, 0x00, 0x08, 0x00, 0x24, 0x00, 0x2e, 0x00, - 0x2c, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x48, 0x00, - 0x50, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x66, 0x00, - 0x6c, 0x00, 0x70, 0x00, 0x76, 0x00, 0x74, 0x00, - 0x7a, 0x00, 0x7e, 0x00, 0x84, 0x00, 0x8a, 0x00, - 0x8e, 0x00, 0x92, 0x00, 0x98, 0x00, 0x9c, 0x00, - 0xa0, 0x00, 0xa8, 0x00, 0xae, 0x00, 0xb4, 0x00, - 0xb2, 0x00, 0xba, 0x00, 0xbe, 0x00, 0xc4, 0x00, - 0xc8, 0x00, 0xce, 0x00, 0xd2, 0x00, 0xd6, 0x00, - 0xda, 0x00, 0xe2, 0x00, 0xe0, 0x00, 0xea, 0x00, - 0xf2, 0x00, 0xfe, 0x00, 0x06, 0x01, 0x0c, 0x01, - 0x1a, 0x01, 0x24, 0x01, 0x22, 0x01, 0x2a, 0x01, - 0x30, 0x01, 0x36, 0x01, 0x3c, 0x01, 0x4e, 0x01, - 0x52, 0x01, 0x58, 0x01, 0x5c, 0x01, 0x9c, 0x01, - 0xb6, 0x01, 0xba, 0x01, 0xc0, 0x01, 0xca, 0x01, - 0xd0, 0x01, 0xda, 0x01, 0xe2, 0x01, 0xea, 0x01, - 0xf0, 0x01, 0x0a, 0x02, 0x0e, 0x02, 0x14, 0x02, - 0x26, 0x02, 0x6c, 0x02, 0x8e, 0x02, 0x98, 0x02, - 0xa0, 0x02, 0xa6, 0x02, 0xba, 0x02, 0xc6, 0x02, - 0xce, 0x02, 0xe8, 0x02, 0xee, 0x02, 0xf4, 0x02, - 0xf8, 0x02, 0x0a, 0x03, 0x10, 0x03, 0x1a, 0x03, - 0x1e, 0x03, 0x2a, 0x03, 0x2e, 0x03, 0x34, 0x03, - 0x3a, 0x03, 0x44, 0x03, 0x4e, 0x03, 0x5a, 0x03, - 0x5e, 0x03, 0x6a, 0x03, 0x72, 0x03, 0x80, 0x03, - 0x84, 0x03, 0x8c, 0x03, 0x94, 0x03, 0x98, 0x03, - 0xa8, 0x03, 0xae, 0x03, 0xb4, 0x03, 0xba, 0x03, - 0xce, 0x03, 0xcc, 0x03, 0xd6, 0x03, 0xdc, 0x03, - 0xec, 0x03, 0xf0, 0x03, 0xfe, 0x03, 0x1c, 0x04, - 0x30, 0x04, 0x38, 0x04, 0x3c, 0x04, 0x40, 0x04, - 0x48, 0x04, 0x46, 0x04, 0x54, 0x04, 0x5e, 0x04, - 0x64, 0x04, 0x74, 0x04, 0x78, 0x04, 0x84, 0x04, - 0xd8, 0x04, 0xec, 0x04, 0xf0, 0x04, 0xf8, 0x04, - 0xfe, 0x04, 0x1c, 0x05, 0x2c, 0x05, 0x30, 0x05, - 0x4a, 0x05, 0x56, 0x05, 0x5a, 0x05, 0x88, 0x05, - 0x8c, 0x05, 0x96, 0x05, 0x9a, 0x05, 0xa8, 0x05, - 0xcc, 0x05, 0xd2, 0x05, 0xda, 0x05, 0xe0, 0x05, - 0xe4, 0x05, 0xfc, 0x05, 0x06, 0x06, 0x14, 0x06, - 0x12, 0x06, 0x1a, 0x06, 0x20, 0x06, 0x26, 0x06, - 0x2e, 0x06, 0x34, 0x06, 0x48, 0x06, 0x52, 0x06, - 0x64, 0x06, 0x86, 0x06, 0x90, 0x06, 0x9a, 0x06, - 0xa0, 0x06, 0xac, 0x06, 0xaa, 0x06, 0xb2, 0x06, - 0xb8, 0x06, 0xdc, 0x06, 0xda, 0x06, 0xe2, 0x06, - 0xe8, 0x06, 0xf2, 0x06, 0xf8, 0x06, 0xfc, 0x06, - 0x0a, 0x07, 0x10, 0x07, 0x14, 0x07, 0x24, 0x07, - 0x2a, 0x07, 0x32, 0x07, 0x38, 0x07, 0xb2, 0x07, - 0xba, 0x07, 0xde, 0x07, 0xe4, 0x07, 0x10, 0x08, - 0x14, 0x08, 0x1a, 0x08, 0x1e, 0x08, 0x30, 0x08, - 0x38, 0x08, 0x3c, 0x08, 0x44, 0x08, 0x42, 0x08, - 0x48, 0x08, 0xc6, 0x08, 0xcc, 0x08, 0xd2, 0x08, - 0xfe, 0x08, 0x04, 0x09, 0x0a, 0x09, 0x0e, 0x09, - 0x12, 0x09, 0x16, 0x09, 0x20, 0x09, 0x24, 0x09, - 0x28, 0x09, 0x32, 0x09, 0x46, 0x09, 0x4a, 0x09, - 0x50, 0x09, 0x54, 0x09, 0x5a, 0x09, 0x60, 0x09, - 0x7c, 0x09, 0x80, 0x09, 0xb8, 0x09, 0xbc, 0x09, - 0xc0, 0x09, 0xc4, 0x09, 0xc8, 0x09, 0xcc, 0x09, - 0xd0, 0x09, 0xd4, 0x09, 0xec, 0x09, 0xf4, 0x09, - 0xf6, 0x09, 0xf8, 0x09, 0xfa, 0x09, 0xfc, 0x09, - 0xfe, 0x09, 0x00, 0x0a, 0x02, 0x0a, 0x04, 0x0a, - 0x06, 0x0a, 0x08, 0x0a, 0x0a, 0x0a, 0x0c, 0x0a, - 0x10, 0x0a, 0x18, 0x0a, 0x24, 0x0a, 0x2c, 0x0a, - 0x32, 0x0a, 0x3c, 0x0a, 0x46, 0x0a, 0x4c, 0x0a, - 0x50, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a, - 0x66, 0x0a, 0x6c, 0x0a, 0x72, 0x0a, 0x78, 0x0a, - 0x7e, 0x0a, 0x7c, 0x0a, 0x82, 0x0a, 0x8c, 0x0a, - 0x92, 0x0a, 0x90, 0x0a, 0x98, 0x0a, 0x96, 0x0a, - 0xa2, 0x0a, 0xb2, 0x0a, 0xb6, 0x0a, 0xc4, 0x0a, - 0xe2, 0x0a, 0xe0, 0x0a, 0xe8, 0x0a, 0xee, 0x0a, - 0xf4, 0x0a, 0xf2, 0x0a, 0xf8, 0x0a, 0x0c, 0x0b, - 0x1a, 0x0b, 0x24, 0x0b, 0x40, 0x0b, 0x44, 0x0b, - 0x48, 0x0b, 0x4e, 0x0b, 0x4c, 0x0b, 0x52, 0x0b, - 0x68, 0x0b, 0x6c, 0x0b, 0x70, 0x0b, 0x76, 0x0b, - 0x88, 0x0b, 0x92, 0x0b, 0xbe, 0x0b, 0xca, 0x0b, - 0xce, 0x0b, 0xde, 0x0b, 0xf4, 0x0b, 0xfa, 0x0b, - 0x00, 0x0c, 0x24, 0x0c, 0x28, 0x0c, 0x30, 0x0c, - 0x36, 0x0c, 0x3c, 0x0c, 0x40, 0x0c, 0x4a, 0x0c, - 0x50, 0x0c, 0x58, 0x0c, 0x56, 0x0c, 0x5c, 0x0c, - 0x60, 0x0c, 0x64, 0x0c, 0x80, 0x0c, 0x94, 0x0c, - 0x9a, 0x0c, 0x98, 0x0c, 0x9e, 0x0c, 0xa4, 0x0c, - 0xa2, 0x0c, 0xa8, 0x0c, 0xac, 0x0c, 0xb0, 0x0c, - 0xb4, 0x0c, 0xb8, 0x0c, 0xbc, 0x0c, 0xce, 0x0c, - 0xd2, 0x0c, 0xd6, 0x0c, 0xf4, 0x0c, 0xfa, 0x0c, - 0x00, 0x0d, 0xfe, 0x0c, 0x06, 0x0d, 0x0e, 0x0d, - 0x0c, 0x0d, 0x16, 0x0d, 0x1c, 0x0d, 0x22, 0x0d, - 0x20, 0x0d, 0x30, 0x0d, 0x7e, 0x0d, 0x82, 0x0d, - 0x9a, 0x0d, 0xa0, 0x0d, 0xa6, 0x0d, 0xb0, 0x0d, - 0xb8, 0x0d, 0xc2, 0x0d, 0xc8, 0x0d, 0xce, 0x0d, - 0xd4, 0x0d, 0xdc, 0x0d, 0x1e, 0x0e, 0x2c, 0x0e, - 0x3e, 0x0e, 0x4c, 0x0e, 0x50, 0x0e, 0x5e, 0x0e, - 0xae, 0x0e, 0xb8, 0x0e, 0xc6, 0x0e, 0xca, 0x0e, - 0, 0 -}; - -/* Fixup command. */ -#define KUE_TRIGCMD_OFFSET 5 -static unsigned char kue_trig_seg[] = { -0xb6, 0xc3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 -}; diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c deleted file mode 100644 index efa6e7e..0000000 --- a/sys/dev/usb/ohci.c +++ /dev/null @@ -1,3638 +0,0 @@ -/* $NetBSD: ohci.c,v 1.138 2003/02/08 03:32:50 ichiro Exp $ */ - -/* Also, already ported: - * $NetBSD: ohci.c,v 1.140 2003/05/13 04:42:00 gson Exp $ - * $NetBSD: ohci.c,v 1.141 2003/09/10 20:08:29 mycroft Exp $ - * $NetBSD: ohci.c,v 1.142 2003/10/11 03:04:26 toshii Exp $ - * $NetBSD: ohci.c,v 1.143 2003/10/18 04:50:35 simonb Exp $ - * $NetBSD: ohci.c,v 1.144 2003/11/23 19:18:06 augustss Exp $ - * $NetBSD: ohci.c,v 1.145 2003/11/23 19:20:25 augustss Exp $ - * $NetBSD: ohci.c,v 1.146 2003/12/29 08:17:10 toshii Exp $ - * $NetBSD: ohci.c,v 1.147 2004/06/22 07:20:35 mycroft Exp $ - * $NetBSD: ohci.c,v 1.148 2004/06/22 18:27:46 mycroft Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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. - */ - -/* - * USB Open Host Controller driver. - * - * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/endian.h> -#include <sys/module.h> -#include <sys/bus.h> -#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__) -#include <machine/cpu.h> -#endif -#include <sys/proc.h> -#include <sys/queue.h> -#include <sys/sysctl.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/ohcireg.h> -#include <dev/usb/ohcivar.h> - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ohcidebug) printf x -#define DPRINTFN(n,x) if (ohcidebug>(n)) printf x -int ohcidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci"); -SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW, - &ohcidebug, 0, "ohci debug level"); -#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f)) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct ohci_pipe; - -static ohci_soft_ed_t *ohci_alloc_sed(ohci_softc_t *); -static void ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *); - -static ohci_soft_td_t *ohci_alloc_std(ohci_softc_t *); -static void ohci_free_std(ohci_softc_t *, ohci_soft_td_t *); - -static ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *); -static void ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *); - -#if 0 -static void ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *, - ohci_soft_td_t *); -#endif -static usbd_status ohci_alloc_std_chain(struct ohci_pipe *, - ohci_softc_t *, int, int, usbd_xfer_handle, - ohci_soft_td_t *, ohci_soft_td_t **); - -#if defined(__NetBSD__) || defined(__OpenBSD__) -static void ohci_shutdown(void *v); -static void ohci_power(int, void *); -#endif -static usbd_status ohci_open(usbd_pipe_handle); -static void ohci_poll(struct usbd_bus *); -static void ohci_softintr(void *); -static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); -static void ohci_add_done(ohci_softc_t *, ohci_physaddr_t); -static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); - -static usbd_status ohci_device_request(usbd_xfer_handle xfer); -static void ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); -static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); -static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); -static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); -static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); -static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); -static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); -static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); - -static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); -static void ohci_device_isoc_enter(usbd_xfer_handle); - -static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void ohci_freem(struct usbd_bus *, usb_dma_t *); - -static usbd_xfer_handle ohci_allocx(struct usbd_bus *); -static void ohci_freex(struct usbd_bus *, usbd_xfer_handle); - -static usbd_status ohci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status ohci_root_ctrl_start(usbd_xfer_handle); -static void ohci_root_ctrl_abort(usbd_xfer_handle); -static void ohci_root_ctrl_close(usbd_pipe_handle); -static void ohci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status ohci_root_intr_transfer(usbd_xfer_handle); -static usbd_status ohci_root_intr_start(usbd_xfer_handle); -static void ohci_root_intr_abort(usbd_xfer_handle); -static void ohci_root_intr_close(usbd_pipe_handle); -static void ohci_root_intr_done(usbd_xfer_handle); - -static usbd_status ohci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status ohci_device_ctrl_start(usbd_xfer_handle); -static void ohci_device_ctrl_abort(usbd_xfer_handle); -static void ohci_device_ctrl_close(usbd_pipe_handle); -static void ohci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status ohci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status ohci_device_bulk_start(usbd_xfer_handle); -static void ohci_device_bulk_abort(usbd_xfer_handle); -static void ohci_device_bulk_close(usbd_pipe_handle); -static void ohci_device_bulk_done(usbd_xfer_handle); - -static usbd_status ohci_device_intr_transfer(usbd_xfer_handle); -static usbd_status ohci_device_intr_start(usbd_xfer_handle); -static void ohci_device_intr_abort(usbd_xfer_handle); -static void ohci_device_intr_close(usbd_pipe_handle); -static void ohci_device_intr_done(usbd_xfer_handle); - -static usbd_status ohci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status ohci_device_isoc_start(usbd_xfer_handle); -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, - struct ohci_pipe *pipe, int ival); -static usbd_status ohci_device_intr_insert(ohci_softc_t *sc, - usbd_xfer_handle xfer); - -static int ohci_str(usb_string_descriptor_t *, int, const 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_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *); -static void ohci_abort_xfer(usbd_xfer_handle, usbd_status); - -static void ohci_device_clear_toggle(usbd_pipe_handle pipe); -static void ohci_noop(usbd_pipe_handle pipe); - -static usbd_status ohci_controller_init(ohci_softc_t *sc); - -#ifdef USB_DEBUG -static void ohci_dumpregs(ohci_softc_t *); -static void ohci_dump_tds(ohci_soft_td_t *); -static void ohci_dump_td(ohci_soft_td_t *); -static void ohci_dump_ed(ohci_soft_ed_t *); -static void ohci_dump_itd(ohci_soft_itd_t *); -static void ohci_dump_itds(ohci_soft_itd_t *); -#endif - -#define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \ - BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) -#define OWRITE1(sc, r, x) \ - do { OBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OWRITE2(sc, r, x) \ - do { OBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OWRITE4(sc, r, x) \ - do { OBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); } while (0) -#define OREAD1(sc, r) (OBARR(sc), bus_space_read_1((sc)->iot, (sc)->ioh, (r))) -#define OREAD2(sc, r) (OBARR(sc), bus_space_read_2((sc)->iot, (sc)->ioh, (r))) -#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] = - { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, - 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, - 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, - 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f }; - -struct ohci_pipe { - struct usbd_pipe pipe; - ohci_soft_ed_t *sed; - u_int32_t aborting; - union { - ohci_soft_td_t *td; - ohci_soft_itd_t *itd; - } tail; - /* Info needed for different pipe kinds. */ - union { - /* Control pipe */ - struct { - usb_dma_t reqdma; - u_int length; - ohci_soft_td_t *setup, *data, *stat; - } ctl; - /* Interrupt pipe */ - struct { - int nslots; - int pos; - } intr; - /* Bulk pipe */ - struct { - u_int length; - int isread; - } bulk; - /* Iso pipe */ - struct iso { - int next, inuse; - } iso; - } u; -}; - -#define OHCI_INTR_ENDPT 1 - -static struct usbd_bus_methods ohci_bus_methods = { - ohci_open, - ohci_softintr, - ohci_poll, - ohci_allocm, - ohci_freem, - ohci_allocx, - ohci_freex, -}; - -static struct usbd_pipe_methods ohci_root_ctrl_methods = { - ohci_root_ctrl_transfer, - ohci_root_ctrl_start, - ohci_root_ctrl_abort, - ohci_root_ctrl_close, - ohci_noop, - ohci_root_ctrl_done, -}; - -static struct usbd_pipe_methods ohci_root_intr_methods = { - ohci_root_intr_transfer, - ohci_root_intr_start, - ohci_root_intr_abort, - ohci_root_intr_close, - ohci_noop, - ohci_root_intr_done, -}; - -static struct usbd_pipe_methods ohci_device_ctrl_methods = { - ohci_device_ctrl_transfer, - ohci_device_ctrl_start, - ohci_device_ctrl_abort, - ohci_device_ctrl_close, - ohci_noop, - ohci_device_ctrl_done, -}; - -static struct usbd_pipe_methods ohci_device_intr_methods = { - ohci_device_intr_transfer, - ohci_device_intr_start, - ohci_device_intr_abort, - ohci_device_intr_close, - ohci_device_clear_toggle, - ohci_device_intr_done, -}; - -static struct usbd_pipe_methods ohci_device_bulk_methods = { - ohci_device_bulk_transfer, - ohci_device_bulk_start, - ohci_device_bulk_abort, - ohci_device_bulk_close, - ohci_device_clear_toggle, - ohci_device_bulk_done, -}; - -static struct usbd_pipe_methods ohci_device_isoc_methods = { - ohci_device_isoc_transfer, - ohci_device_isoc_start, - ohci_device_isoc_abort, - ohci_device_isoc_close, - ohci_noop, - ohci_device_isoc_done, -}; - -int -ohci_detach(struct ohci_softc *sc, int flags) -{ - int i, rv = 0; - - sc->sc_dying = 1; - callout_stop(&sc->sc_tmo_rhsc); - -#if defined(__NetBSD__) || defined(__OpenBSD__) - powerhook_disestablish(sc->sc_powerhook); - shutdownhook_disestablish(sc->sc_shutdownhook); -#endif - - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - - for (i = 0; i < OHCI_NO_EDS; i++) - ohci_free_sed(sc, sc->sc_eds[i]); - ohci_free_sed(sc, sc->sc_isoc_head); - ohci_free_sed(sc, sc->sc_bulk_head); - ohci_free_sed(sc, sc->sc_ctrl_head); - usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - - return (rv); -} - -ohci_soft_ed_t * -ohci_alloc_sed(ohci_softc_t *sc) -{ - ohci_soft_ed_t *sed; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeeds == NULL) { - DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK, - OHCI_ED_ALIGN, &dma); - if (err) - return (NULL); - for(i = 0; i < OHCI_SED_CHUNK; i++) { - offs = i * OHCI_SED_SIZE; - sed = KERNADDR(&dma, offs); - sed->physaddr = DMAADDR(&dma, offs); - sed->next = sc->sc_freeeds; - sc->sc_freeeds = sed; - } - } - sed = sc->sc_freeeds; - sc->sc_freeeds = sed->next; - memset(&sed->ed, 0, sizeof(ohci_ed_t)); - sed->next = 0; - return (sed); -} - -void -ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed) -{ - sed->next = sc->sc_freeeds; - sc->sc_freeeds = sed; -} - -ohci_soft_td_t * -ohci_alloc_std(ohci_softc_t *sc) -{ - ohci_soft_td_t *std; - usbd_status err; - int i, offs; - usb_dma_t dma; - int s; - - if (sc->sc_freetds == NULL) { - DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, - OHCI_TD_ALIGN, &dma); - if (err) - return (NULL); - s = splusb(); - for(i = 0; i < OHCI_STD_CHUNK; i++) { - offs = i * OHCI_STD_SIZE; - std = KERNADDR(&dma, offs); - std->physaddr = DMAADDR(&dma, offs); - std->nexttd = sc->sc_freetds; - sc->sc_freetds = std; - } - splx(s); - } - - s = splusb(); - std = sc->sc_freetds; - sc->sc_freetds = std->nexttd; - memset(&std->td, 0, sizeof(ohci_td_t)); - std->nexttd = NULL; - std->xfer = NULL; - ohci_hash_add_td(sc, std); - splx(s); - - return (std); -} - -void -ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - int s; - - s = splusb(); - ohci_hash_rem_td(sc, std); - std->nexttd = sc->sc_freetds; - sc->sc_freetds = std; - splx(s); -} - -usbd_status -ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, - int alen, int rd, usbd_xfer_handle xfer, - ohci_soft_td_t *sp, ohci_soft_td_t **ep) -{ - ohci_soft_td_t *next, *cur, *end; - ohci_physaddr_t dataphys, physend; - u_int32_t tdflags; - int offset = 0; - int len, maxp, curlen, curlen2, seg, segoff; - struct usb_dma_mapping *dma = &xfer->dmamap; - u_int16_t flags = xfer->flags; - - DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen)); - - len = alen; - cur = sp; - end = NULL; - - maxp = UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize); - tdflags = htole32( - (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_SET_DI(6)); - - seg = 0; - segoff = 0; - while (len > 0) { - next = ohci_alloc_std(sc); - if (next == NULL) - goto nomem; - - /* - * The OHCI hardware can handle at most one 4k crossing. - * The OHCI spec says: If during the data transfer the buffer - * address contained in the HC's working copy of - * CurrentBufferPointer crosses a 4K boundary, the upper 20 - * bits of Buffer End are copied to the working value of - * CurrentBufferPointer causing the next buffer address to - * be the 0th byte in the same 4K page that contains the - * last byte of the buffer (the 4K boundary crossing may - * occur within a data packet transfer.) - */ - KASSERT(seg < dma->nsegs, ("ohci_alloc_std_chain: overrun")); - dataphys = dma->segs[seg].ds_addr + segoff; - curlen = dma->segs[seg].ds_len - segoff; - if (curlen > len) - curlen = len; - physend = dataphys + curlen - 1; - if (OHCI_PAGE(dataphys) != OHCI_PAGE(physend)) { - /* Truncate to two OHCI pages if there are more. */ - if (curlen > 2 * OHCI_PAGE_SIZE - - OHCI_PAGE_OFFSET(dataphys)) - curlen = 2 * OHCI_PAGE_SIZE - - OHCI_PAGE_OFFSET(dataphys); - if (curlen < len) - curlen -= curlen % maxp; - physend = dataphys + curlen - 1; - } else if (OHCI_PAGE_OFFSET(physend + 1) == 0 && curlen < len && - curlen + segoff == dma->segs[seg].ds_len) { - /* We can possibly include another segment. */ - KASSERT(seg + 1 < dma->nsegs, - ("ohci_alloc_std_chain: overrun2")); - seg++; - - /* Determine how much of the second segment to use. */ - curlen2 = dma->segs[seg].ds_len; - if (curlen + curlen2 > len) - curlen2 = len - curlen; - if (OHCI_PAGE(dma->segs[seg].ds_addr) != - OHCI_PAGE(dma->segs[seg].ds_addr + curlen2 - 1)) - curlen2 = OHCI_PAGE_SIZE - - OHCI_PAGE_OFFSET(dma->segs[seg].ds_addr); - if (curlen + curlen2 < len) - curlen2 -= (curlen + curlen2) % maxp; - - if (curlen2 > 0) { - /* We can include a second segment */ - segoff = curlen2; - physend = dma->segs[seg].ds_addr + curlen2 - 1; - curlen += curlen2; - } else { - /* Second segment not usable now. */ - seg--; - segoff += curlen; - } - } else { - /* Simple case where there is just one OHCI page. */ - segoff += curlen; - } - if (curlen == 0 && len != 0) { - /* - * A maxp length packet would need to be split. - * This shouldn't be possible if PAGE_SIZE >= 4k - * and the buffer is contiguous in virtual memory. - */ - panic("ohci_alloc_std_chain: XXX need to copy"); - } - if (segoff >= dma->segs[seg].ds_len) { - KASSERT(segoff == dma->segs[seg].ds_len, - ("ohci_alloc_std_chain: overlap")); - seg++; - segoff = 0; - } - DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x " - "len=%d curlen=%d\n", - dataphys, len, curlen)); - len -= curlen; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = htole32(dataphys); - cur->nexttd = next; - cur->td.td_nexttd = htole32(next->physaddr); - cur->td.td_be = htole32(physend); - cur->len = curlen; - cur->flags = OHCI_ADD_LEN; - cur->xfer = xfer; - DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n", - dataphys, dataphys + curlen - 1)); - if (len < 0) - panic("Length went negative: %d curlen %d dma %p offset %08x", len, curlen, dma, (int)0); - - DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n")); - offset += curlen; - end = cur; - cur = next; - } - if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) && - alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) { - /* Force a 0 length transfer at the end. */ - next = ohci_alloc_std(sc); - if (next == NULL) - goto nomem; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = 0; /* indicate 0 length packet */ - cur->nexttd = next; - cur->td.td_nexttd = htole32(next->physaddr); - cur->td.td_be = ~0; - cur->len = 0; - cur->flags = 0; - cur->xfer = xfer; - DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n")); - end = cur; - } - *ep = end; - - return (USBD_NORMAL_COMPLETION); - - nomem: - /* XXX free chain */ - return (USBD_NOMEM); -} - -#if 0 -static void -ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std, - ohci_soft_td_t *stdend) -{ - ohci_soft_td_t *p; - - for (; std != stdend; std = p) { - p = std->nexttd; - ohci_free_std(sc, std); - } -} -#endif - -ohci_soft_itd_t * -ohci_alloc_sitd(ohci_softc_t *sc) -{ - ohci_soft_itd_t *sitd; - usbd_status err; - int i, s, offs; - usb_dma_t dma; - - if (sc->sc_freeitds == NULL) { - DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE * OHCI_SITD_CHUNK, - OHCI_ITD_ALIGN, &dma); - if (err) - return (NULL); - s = splusb(); - for(i = 0; i < OHCI_SITD_CHUNK; i++) { - offs = i * OHCI_SITD_SIZE; - sitd = KERNADDR(&dma, offs); - sitd->physaddr = DMAADDR(&dma, offs); - sitd->nextitd = sc->sc_freeitds; - sc->sc_freeitds = sitd; - } - splx(s); - } - - s = splusb(); - sitd = sc->sc_freeitds; - sc->sc_freeitds = sitd->nextitd; - memset(&sitd->itd, 0, sizeof(ohci_itd_t)); - sitd->nextitd = NULL; - sitd->xfer = NULL; - ohci_hash_add_itd(sc, sitd); - splx(s); - -#ifdef DIAGNOSTIC - sitd->isdone = 0; -#endif - - return (sitd); -} - -void -ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) -{ - int s; - - DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd)); - -#ifdef DIAGNOSTIC - if (!sitd->isdone) { - panic("ohci_free_sitd: sitd=%p not done", sitd); - return; - } - /* Warn double free */ - sitd->isdone = 0; -#endif - - s = splusb(); - ohci_hash_rem_itd(sc, sitd); - sitd->nextitd = sc->sc_freeitds; - sc->sc_freeitds = sitd; - splx(s); -} - -usbd_status -ohci_init(ohci_softc_t *sc) -{ - ohci_soft_ed_t *sed, *psed; - usbd_status err; - int i; - u_int32_t rev; - - DPRINTF(("ohci_init: start\n")); - printf("%s:", device_get_nameunit(sc->sc_bus.bdev)); - rev = OREAD4(sc, OHCI_REVISION); - printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), - OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); - - if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { - printf("%s: unsupported OHCI revision\n", - device_get_nameunit(sc->sc_bus.bdev)); - sc->sc_bus.usbrev = USBREV_UNKNOWN; - return (USBD_INVAL); - } - sc->sc_bus.usbrev = USBREV_1_0; - - for (i = 0; i < OHCI_HASH_SIZE; i++) - LIST_INIT(&sc->sc_hash_tds[i]); - for (i = 0; i < OHCI_HASH_SIZE; i++) - LIST_INIT(&sc->sc_hash_itds[i]); - - STAILQ_INIT(&sc->sc_free_xfers); - - /* XXX determine alignment by R/W */ - /* Allocate the HCCA area. */ - err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, - OHCI_HCCA_ALIGN, &sc->sc_hccadma); - if (err) - return (err); - sc->sc_hcca = KERNADDR(&sc->sc_hccadma, 0); - memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE); - - sc->sc_eintrs = OHCI_NORMAL_INTRS; - - /* Allocate dummy ED that starts the control list. */ - sc->sc_ctrl_head = ohci_alloc_sed(sc); - if (sc->sc_ctrl_head == NULL) { - err = USBD_NOMEM; - goto bad1; - } - sc->sc_ctrl_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate dummy ED that starts the bulk list. */ - sc->sc_bulk_head = ohci_alloc_sed(sc); - if (sc->sc_bulk_head == NULL) { - err = USBD_NOMEM; - goto bad2; - } - sc->sc_bulk_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate dummy ED that starts the isochronous list. */ - sc->sc_isoc_head = ohci_alloc_sed(sc); - if (sc->sc_isoc_head == NULL) { - err = USBD_NOMEM; - goto bad3; - } - sc->sc_isoc_head->ed.ed_flags |= htole32(OHCI_ED_SKIP); - - /* Allocate all the dummy EDs that make up the interrupt tree. */ - for (i = 0; i < OHCI_NO_EDS; i++) { - sed = ohci_alloc_sed(sc); - if (sed == NULL) { - while (--i >= 0) - ohci_free_sed(sc, sc->sc_eds[i]); - err = USBD_NOMEM; - goto bad4; - } - /* All ED fields are set to 0. */ - sc->sc_eds[i] = sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if (i != 0) - psed = sc->sc_eds[(i-1) / 2]; - else - psed= sc->sc_isoc_head; - 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]] = - htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr); - -#ifdef USB_DEBUG - if (ohcidebug > 15) { - for (i = 0; i < OHCI_NO_EDS; i++) { - printf("ed#%d ", i); - ohci_dump_ed(sc->sc_eds[i]); - } - printf("iso "); - ohci_dump_ed(sc->sc_isoc_head); - } -#endif - - err = ohci_controller_init(sc); - if (err != USBD_NORMAL_COMPLETION) - goto bad5; - - /* Set up the bus struct. */ - sc->sc_bus.methods = &ohci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct ohci_pipe); - -#if defined(__NetBSD__) || defined(__OpenBSD__) - sc->sc_powerhook = powerhook_establish(ohci_power, sc); - sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc); -#endif - - callout_init(&sc->sc_tmo_rhsc, 0); - - return (USBD_NORMAL_COMPLETION); - - bad5: - for (i = 0; i < OHCI_NO_EDS; i++) - ohci_free_sed(sc, sc->sc_eds[i]); - bad4: - ohci_free_sed(sc, sc->sc_isoc_head); - bad3: - ohci_free_sed(sc, sc->sc_bulk_head); - bad2: - ohci_free_sed(sc, sc->sc_ctrl_head); - bad1: - usb_freemem(&sc->sc_bus, &sc->sc_hccadma); - return (err); -} - -static usbd_status -ohci_controller_init(ohci_softc_t *sc) -{ - int i; - u_int32_t ctl, ival, hcr, fm, per, desca; - - /* Determine in what context we are running. */ - ctl = OREAD4(sc, OHCI_CONTROL); - if (ctl & OHCI_IR) { - /* SMM active, request change */ - DPRINTF(("ohci_init: SMM active, request owner change\n")); - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_OCR); - for (i = 0; i < 100 && (ctl & OHCI_IR); i++) { - usb_delay_ms(&sc->sc_bus, 1); - ctl = OREAD4(sc, OHCI_CONTROL); - } - if (ctl & OHCI_IR) { - printf("%s: SMM does not respond, resetting\n", - device_get_nameunit(sc->sc_bus.bdev)); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - goto reset; - } -#if 0 -/* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */ - } else if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_RESET) { - /* BIOS started controller. */ - DPRINTF(("ohci_init: BIOS active\n")); - if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) { - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - } -#endif - } else { - DPRINTF(("ohci_init: cold started\n")); - reset: - /* Controller was cold started. */ - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); - } - - /* - * This reset should not be necessary according to the OHCI spec, but - * without it some controllers do not start. - */ - DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev))); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); - - /* We now own the host controller and the bus has been reset. */ - ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL)); - - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */ - /* Nominal time for a reset is 10 us. */ - for (i = 0; i < 10; i++) { - delay(10); - hcr = OREAD4(sc, OHCI_COMMAND_STATUS) & OHCI_HCR; - if (!hcr) - break; - } - if (hcr) { - printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev)); - return (USBD_IOERROR); - } -#ifdef USB_DEBUG - if (ohcidebug > 15) - ohci_dumpregs(sc); -#endif - - /* The controller is now in SUSPEND state, we have 2ms to finish. */ - - /* Set up HC registers. */ - OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); - OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); - OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); - /* disable all interrupts and then switch on all desired interrupts */ - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE); - /* switch on desired functional features */ - ctl = OREAD4(sc, OHCI_CONTROL); - ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR); - ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE | - OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL; - /* And finally start it! */ - OWRITE4(sc, OHCI_CONTROL, ctl); - - /* - * The controller is now OPERATIONAL. Set a some final - * registers that should be set earlier, but that the - * controller ignores when in the SUSPEND state. - */ - fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT; - fm |= OHCI_FSMPS(ival) | ival; - OWRITE4(sc, OHCI_FM_INTERVAL, fm); - per = OHCI_PERIODIC(ival); /* 90% periodic */ - OWRITE4(sc, OHCI_PERIODIC_START, per); - - /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */ - desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); - OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP); - OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */ - usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY); - OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca); - - /* - * The AMD756 requires a delay before re-reading the register, - * otherwise it will occasionally report 0 ports. - */ - sc->sc_noport = 0; - for (i = 0; i < 10 && sc->sc_noport == 0; i++) { - usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY); - sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A)); - } - -#ifdef USB_DEBUG - if (ohcidebug > 5) - ohci_dumpregs(sc); -#endif - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -ohci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - return (usb_allocmem(bus, size, 0, dma)); -} - -void -ohci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -ohci_allocx(struct usbd_bus *bus) -{ - struct ohci_softc *sc = (struct ohci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, 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)); - usb_init_task(&OXFER(xfer)->abort_task, ohci_timeout_task, - xfer); - OXFER(xfer)->ohci_xfer_flags = 0; -#ifdef DIAGNOSTIC - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -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 - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -/* - * Shut down the controller when the system is going down. - */ -void -ohci_shutdown(void *v) -{ - ohci_softc_t *sc = v; - - DPRINTF(("ohci_shutdown: stopping the HC\n")); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an intterupt context. This is all right since we - * are almost suspended anyway. - */ -void -ohci_power(int why, void *v) -{ - ohci_softc_t *sc = v; - u_int32_t ctl; - int s; - -#ifdef USB_DEBUG - DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why)); - ohci_dumpregs(sc); -#endif - - s = splhardusb(); - if (why != PWR_RESUME) { - sc->sc_bus.use_polling++; - ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_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, OHCI_INTERRUPT_ENABLE); - } - ctl |= OHCI_HCFS_SUSPEND; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_bus.use_polling--; - } else { - sc->sc_bus.use_polling++; - - /* Some broken BIOSes never initialize Controller chip */ - ohci_controller_init(sc); - - if (sc->sc_intre) - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, - sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); - if (sc->sc_control) - ctl = sc->sc_control; - else - ctl = OREAD4(sc, OHCI_CONTROL); - ctl |= OHCI_HCFS_RESUME; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; - OWRITE4(sc, OHCI_CONTROL, ctl); - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_control = sc->sc_intre = 0; - sc->sc_bus.use_polling--; - } - splx(s); -} - -#ifdef USB_DEBUG -void -ohci_dumpregs(ohci_softc_t *sc) -{ - DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n", - OREAD4(sc, OHCI_REVISION), - OREAD4(sc, OHCI_CONTROL), - OREAD4(sc, OHCI_COMMAND_STATUS))); - DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n", - OREAD4(sc, OHCI_INTERRUPT_STATUS), - OREAD4(sc, OHCI_INTERRUPT_ENABLE), - OREAD4(sc, OHCI_INTERRUPT_DISABLE))); - DPRINTF((" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n", - OREAD4(sc, OHCI_HCCA), - OREAD4(sc, OHCI_PERIOD_CURRENT_ED), - OREAD4(sc, OHCI_CONTROL_HEAD_ED))); - DPRINTF((" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n", - OREAD4(sc, OHCI_CONTROL_CURRENT_ED), - OREAD4(sc, OHCI_BULK_HEAD_ED), - OREAD4(sc, OHCI_BULK_CURRENT_ED))); - DPRINTF((" done=0x%08x fmival=0x%08x fmrem=0x%08x\n", - OREAD4(sc, OHCI_DONE_HEAD), - OREAD4(sc, OHCI_FM_INTERVAL), - OREAD4(sc, OHCI_FM_REMAINING))); - DPRINTF((" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n", - OREAD4(sc, OHCI_FM_NUMBER), - OREAD4(sc, OHCI_PERIODIC_START), - OREAD4(sc, OHCI_LS_THRESHOLD))); - DPRINTF((" desca=0x%08x descb=0x%08x stat=0x%08x\n", - OREAD4(sc, OHCI_RH_DESCRIPTOR_A), - OREAD4(sc, OHCI_RH_DESCRIPTOR_B), - OREAD4(sc, OHCI_RH_STATUS))); - DPRINTF((" port1=0x%08x port2=0x%08x\n", - OREAD4(sc, OHCI_RH_PORT_STATUS(1)), - OREAD4(sc, OHCI_RH_PORT_STATUS(2)))); - DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n", - le32toh(sc->sc_hcca->hcca_frame_number), - le32toh(sc->sc_hcca->hcca_done_head))); -} -#endif - -static int ohci_intr1(ohci_softc_t *); - -void -ohci_intr(void *p) -{ - ohci_softc_t *sc = p; - - if (sc == NULL || sc->sc_dying) - return; - - /* If we get an interrupt while polling, then just ignore it. */ - if (sc->sc_bus.use_polling) { -#ifdef DIAGNOSTIC - printf("ohci_intr: ignored interrupt while polling\n"); -#endif - return; - } - - ohci_intr1(sc); -} - -static int -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 - printf("ohci_intr: sc->sc_hcca == NULL\n"); -#endif - return (0); - } - - intrs = 0; - done = le32toh(sc->sc_hcca->hcca_done_head); - - /* The LSb of done is used to inform the HC Driver that an interrupt - * condition exists for both the Done list and for another event - * recorded in HcInterruptStatus. On an interrupt from the HC, the HC - * Driver checks the HccaDoneHead Value. If this value is 0, then the - * interrupt was caused by other than the HccaDoneHead update and the - * HcInterruptStatus register needs to be accessed to determine that - * exact interrupt cause. If HccaDoneHead is nonzero, then a Done list - * update interrupt is indicated and if the LSb of done is nonzero, - * then an additional interrupt event is indicated and - * HcInterruptStatus should be checked to determine its cause. - */ - if (done != 0) { - if (done & ~OHCI_DONE_INTRS) - intrs = OHCI_WDH; - if (done & OHCI_DONE_INTRS) { - intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS); - done &= ~OHCI_DONE_INTRS; - } - sc->sc_hcca->hcca_done_head = 0; - } else - intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & ~OHCI_WDH; - - if (intrs == 0) /* nothing to be done (PCI shared interrupt) */ - return (0); - - intrs &= ~OHCI_MIE; - OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */ - eintrs = intrs & sc->sc_eintrs; - if (!eintrs) - return (0); - - 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", - sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), - (u_int)eintrs)); - - if (eintrs & OHCI_SO) { - sc->sc_overrun_cnt++; - if (usbd_ratecheck(&sc->sc_overrun_ntc)) { - printf("%s: %u scheduling overruns\n", - device_get_nameunit(sc->sc_bus.bdev), sc->sc_overrun_cnt); - sc->sc_overrun_cnt = 0; - } - /* XXX do what */ - eintrs &= ~OHCI_SO; - } - if (eintrs & OHCI_WDH) { - ohci_add_done(sc, done &~ OHCI_DONE_INTRS); - usb_schedsoftintr(&sc->sc_bus); - eintrs &= ~OHCI_WDH; - } - if (eintrs & OHCI_RD) { - printf("%s: resume detect\n", device_get_nameunit(sc->sc_bus.bdev)); - /* XXX process resume detect */ - } - if (eintrs & OHCI_UE) { - printf("%s: unrecoverable error, controller halted\n", - device_get_nameunit(sc->sc_bus.bdev)); - OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); - /* XXX what else */ - } - if (eintrs & OHCI_RHSC) { - ohci_rhsc(sc, sc->sc_intrxfer); - /* - * Disable RHSC interrupt for now, because it will be - * on until the port has been reset. - */ - ohci_rhsc_able(sc, 0); - /* Do not allow RHSC interrupts > 1 per second */ - callout_reset(&sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc); - eintrs &= ~OHCI_RHSC; - } - - 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", - device_get_nameunit(sc->sc_bus.bdev), eintrs); - } - - return (1); -} - -void -ohci_rhsc_able(ohci_softc_t *sc, int on) -{ - DPRINTFN(4, ("ohci_rhsc_able: on=%d\n", on)); - if (on) { - sc->sc_eintrs |= OHCI_RHSC; - OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC); - } else { - sc->sc_eintrs &= ~OHCI_RHSC; - OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC); - } -} - -void -ohci_rhsc_enable(void *v_sc) -{ - ohci_softc_t *sc = v_sc; - int s; - - s = splhardusb(); - ohci_rhsc_able(sc, 1); - splx(s); -} - -#ifdef USB_DEBUG -char *ohci_cc_strs[] = { - "NO_ERROR", - "CRC", - "BIT_STUFFING", - "DATA_TOGGLE_MISMATCH", - "STALL", - "DEVICE_NOT_RESPONDING", - "PID_CHECK_FAILURE", - "UNEXPECTED_PID", - "DATA_OVERRUN", - "DATA_UNDERRUN", - "BUFFER_OVERRUN", - "BUFFER_UNDERRUN", - "reserved", - "reserved", - "NOT_ACCESSED", - "NOT_ACCESSED" -}; -#endif - -void -ohci_add_done(ohci_softc_t *sc, ohci_physaddr_t done) -{ - ohci_soft_itd_t *sitd, *sidone, **ip; - ohci_soft_td_t *std, *sdone, **p; - - /* Reverse the done list. */ - for (sdone = NULL, sidone = NULL; done != 0; ) { - std = ohci_hash_find_td(sc, done); - if (std != NULL) { - std->dnext = sdone; - done = le32toh(std->td.td_nexttd); - sdone = std; - DPRINTFN(10,("add TD %p\n", std)); - continue; - } - sitd = ohci_hash_find_itd(sc, done); - if (sitd != NULL) { - sitd->dnext = sidone; - done = le32toh(sitd->itd.itd_nextitd); - sidone = sitd; - DPRINTFN(5,("add ITD %p\n", sitd)); - continue; - } - panic("ohci_add_done: addr 0x%08lx not found", (u_long)done); - } - - /* sdone & sidone now hold the done lists. */ - /* Put them on the already processed lists. */ - for (p = &sc->sc_sdone; *p != NULL; p = &(*p)->dnext) - ; - *p = sdone; - for (ip = &sc->sc_sidone; *ip != NULL; ip = &(*ip)->dnext) - ; - *ip = sidone; -} - -void -ohci_softintr(void *v) -{ - ohci_softc_t *sc = v; - ohci_soft_itd_t *sitd, *sidone, *sitdnext; - ohci_soft_td_t *std, *sdone, *stdnext, *p, *n; - usbd_xfer_handle xfer; - struct ohci_pipe *opipe; - int len, cc, s; - int i, j, iframes; - - DPRINTFN(10,("ohci_softintr: enter\n")); - - sc->sc_bus.intr_context++; - - s = splhardusb(); - sdone = sc->sc_sdone; - sc->sc_sdone = NULL; - sidone = sc->sc_sidone; - sc->sc_sidone = NULL; - splx(s); - - DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone)); - -#ifdef USB_DEBUG - if (ohcidebug > 10) { - DPRINTF(("ohci_process_done: TD done:\n")); - ohci_dump_tds(sdone); - } -#endif - - for (std = sdone; std; std = stdnext) { - xfer = std->xfer; - stdnext = std->dnext; - DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n", - std, xfer, (xfer ? xfer->hcpriv : NULL))); - if (xfer == NULL) { - /* - * xfer == NULL: There seems to be no xfer associated - * with this TD. It is tailp that happened to end up on - * the done queue. - */ - continue; - } - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ohci_process_done: cancel/timeout %p\n", - xfer)); - /* Handled by abort routine. */ - continue; - } - - len = std->len; - if (std->td.td_cbp != 0) - len -= le32toh(std->td.td_be) - - le32toh(std->td.td_cbp) + 1; - DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len, - std->flags)); - if (std->flags & OHCI_ADD_LEN) - xfer->actlen += len; - - cc = OHCI_TD_GET_CC(le32toh(std->td.td_flags)); - if (cc != OHCI_CC_NO_ERROR) { - /* - * Endpoint is halted. First unlink all the TDs - * belonging to the failed transfer, and then restart - * the endpoint. - */ - opipe = (struct ohci_pipe *)xfer->pipe; - - DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n", - OHCI_TD_GET_CC(le32toh(std->td.td_flags)), - ohci_cc_strs[OHCI_TD_GET_CC(le32toh(std->td.td_flags))])); - callout_stop(&xfer->timeout_handle); - usb_rem_task(OXFER(xfer)->xfer.pipe->device, - &OXFER(xfer)->abort_task); - - /* Remove all this xfer's TDs from the done queue. */ - for (p = std; p->dnext != NULL; p = p->dnext) { - if (p->dnext->xfer != xfer) - continue; - p->dnext = p->dnext->dnext; - } - /* The next TD may have been removed. */ - stdnext = std->dnext; - - /* Remove all TDs belonging to this xfer. */ - for (p = xfer->hcpriv; p->xfer == xfer; p = n) { - n = p->nexttd; - ohci_free_std(sc, p); - } - - /* clear halt */ - opipe->sed->ed.ed_headp = htole32(p->physaddr); - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - - if (cc == OHCI_CC_STALL) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - continue; - } - /* - * Skip intermediate TDs. They remain linked from - * xfer->hcpriv and we free them when the transfer completes. - */ - if ((std->flags & OHCI_CALL_DONE) == 0) - continue; - - /* Normal transfer completion */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(OXFER(xfer)->xfer.pipe->device, - &OXFER(xfer)->abort_task); - for (p = xfer->hcpriv; p->xfer == xfer; p = n) { - n = p->nexttd; - ohci_free_std(sc, p); - } - xfer->status = USBD_NORMAL_COMPLETION; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - } - -#ifdef USB_DEBUG - if (ohcidebug > 10) { - DPRINTF(("ohci_softintr: ITD done:\n")); - ohci_dump_itds(sidone); - } -#endif - - for (sitd = sidone; sitd != NULL; sitd = sitdnext) { - xfer = sitd->xfer; - sitdnext = sitd->dnext; - sitd->flags |= OHCI_ITD_INTFIN; - DPRINTFN(1, ("ohci_process_done: sitd=%p xfer=%p hcpriv=%p\n", - sitd, xfer, xfer ? xfer->hcpriv : 0)); - if (xfer == NULL) - continue; - if (xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT) { - DPRINTF(("ohci_process_done: cancel/timeout %p\n", - xfer)); - /* Handled by abort routine. */ - continue; - } - if (xfer->pipe) - if (xfer->pipe->aborting) - continue; /*Ignore.*/ -#ifdef DIAGNOSTIC - if (sitd->isdone) - printf("ohci_softintr: sitd=%p is done\n", sitd); - sitd->isdone = 1; -#endif - opipe = (struct ohci_pipe *)xfer->pipe; - if (opipe->aborting) - continue; - - if (sitd->flags & OHCI_CALL_DONE) { - ohci_soft_itd_t *next; - - opipe->u.iso.inuse -= xfer->nframes; - xfer->status = USBD_NORMAL_COMPLETION; - for (i = 0, sitd = xfer->hcpriv;;sitd = next) { - next = sitd->nextitd; - if (OHCI_ITD_GET_CC(sitd->itd.itd_flags) != OHCI_CC_NO_ERROR) - xfer->status = USBD_IOERROR; - - if (xfer->status == USBD_NORMAL_COMPLETION) { - iframes = OHCI_ITD_GET_FC(sitd->itd.itd_flags); - for (j = 0; j < iframes; i++, j++) { - len = le16toh(sitd->itd.itd_offset[j]); - len = - (OHCI_ITD_PSW_GET_CC(len) == - OHCI_CC_NOT_ACCESSED) ? 0 : - OHCI_ITD_PSW_LENGTH(len); - xfer->frlengths[i] = len; - } - } - if (sitd->flags & OHCI_CALL_DONE) - break; - } - for (sitd = xfer->hcpriv; sitd->xfer == xfer; - sitd = next) { - next = sitd->nextitd; - ohci_free_sitd(sc, sitd); - } - - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - } - } - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; - DPRINTFN(10,("ohci_softintr: done:\n")); -} - -void -ohci_device_ctrl_done(usbd_xfer_handle xfer) -{ - DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) { - panic("ohci_device_ctrl_done: not a request"); - } -#endif - xfer->hcpriv = NULL; -} - -void -ohci_device_intr_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; - usbd_status err; - - DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - xfer->hcpriv = NULL; - if (xfer->pipe->repeat) { - err = ohci_device_intr_insert(sc, xfer); - if (err) { - xfer->status = err; - return; - } - } -} - -void -ohci_device_bulk_done(usbd_xfer_handle xfer) -{ - DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", - xfer, xfer->actlen)); - - xfer->hcpriv = NULL; -} - -/* - * XXX write back xfer data for architectures with a write-back - * data cache; this is a hack because usb is mis-architected - * in blindly mixing bus_dma w/ PIO. - */ -static __inline void -hacksync(usbd_xfer_handle xfer) -{ - bus_dma_tag_t tag; - struct usb_dma_mapping *dmap; - - if (xfer->length == 0) - return; - tag = xfer->pipe->device->bus->buffer_dmatag; - dmap = &xfer->dmamap; - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); -} - -void -ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe; - u_char *p; - int i, m; - int hstatus; - - hstatus = OREAD4(sc, OHCI_RH_STATUS); - DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", - sc, xfer, hstatus)); - - if (xfer == NULL) { - /* Just ignore the change. */ - return; - } - - pipe = xfer->pipe; - - p = xfer->buffer; - 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 (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16) - p[i/8] |= 1 << (i%8); - } - DPRINTF(("ohci_rhsc: change=0x%02x\n", *p)); - xfer->actlen = xfer->length; - xfer->status = USBD_NORMAL_COMPLETION; - - hacksync(xfer); /* XXX to compensate for usb_transfer_complete */ - usb_transfer_complete(xfer); -} - -void -ohci_root_intr_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -void -ohci_root_ctrl_done(usbd_xfer_handle xfer) -{ - xfer->hcpriv = NULL; -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call ohci_intr and return. Use timeout to avoid waiting - * too long. - */ -void -ohci_waitintr(ohci_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 = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; - DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs)); -#ifdef USB_DEBUG - if (ohcidebug > 15) - ohci_dumpregs(sc); -#endif - if (intrs) { - ohci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - } - - /* Timeout */ - DPRINTF(("ohci_waitintr: timeout\n")); - xfer->status = USBD_TIMEOUT; - usb_transfer_complete(xfer); - /* XXX should free TD */ -} - -void -ohci_poll(struct usbd_bus *bus) -{ - ohci_softc_t *sc = (ohci_softc_t *)bus; -#ifdef USB_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); -} - -usbd_status -ohci_device_request(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - ohci_soft_td_t *setup, *stat, *next, *tail; - ohci_soft_ed_t *sed; - int isread; - int len; - usbd_status err; - int s; - - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - 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, dev->address, - opipe->pipe.endpoint->edesc->bEndpointAddress)); - - setup = opipe->tail.td; - stat = ohci_alloc_std(sc); - if (stat == NULL) { - err = USBD_NOMEM; - goto bad1; - } - tail = ohci_alloc_std(sc); - if (tail == NULL) { - err = USBD_NOMEM; - goto bad2; - } - tail->xfer = NULL; - - sed = opipe->sed; - opipe->u.ctl.length = len; - next = stat; - - /* Set up data transaction */ - if (len != 0) { - ohci_soft_td_t *std = stat; - - err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, - std, &stat); - stat = stat->nexttd; /* point at free TD */ - if (err) - goto bad3; - /* Start toggle at 1 and then use the carried toggle. */ - std->td.td_flags &= htole32(~OHCI_TD_TOGGLE_MASK); - std->td.td_flags |= htole32(OHCI_TD_TOGGLE_1); - } - - memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req); - - setup->td.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC | - OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DI(6)); - setup->td.td_cbp = htole32(DMAADDR(&opipe->u.ctl.reqdma, 0)); - setup->nexttd = next; - setup->td.td_nexttd = htole32(next->physaddr); - setup->td.td_be = htole32(le32toh(setup->td.td_cbp) + sizeof *req - 1); - setup->len = 0; - setup->xfer = xfer; - setup->flags = 0; - xfer->hcpriv = setup; - - stat->td.td_flags = htole32( - (isread ? OHCI_TD_OUT : OHCI_TD_IN) | - OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1)); - stat->td.td_cbp = 0; - stat->nexttd = tail; - stat->td.td_nexttd = htole32(tail->physaddr); - stat->td.td_be = 0; - stat->flags = OHCI_CALL_DONE; - stat->len = 0; - stat->xfer = xfer; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_request:\n")); - ohci_dump_ed(sed); - ohci_dump_tds(setup); - } -#endif - - /* Insert ED in schedule */ - s = splusb(); - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ohci_timeout, xfer); - } - splx(s); - -#ifdef USB_DEBUG - if (ohcidebug > 20) { - 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); - } -#endif - - return (USBD_NORMAL_COMPLETION); - - bad3: - ohci_free_std(sc, tail); - bad2: - ohci_free_std(sc, stat); - bad1: - return (err); -} - -/* - * Add an ED to the schedule. Called at splusb(). - */ -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; - head->next = sed; - head->ed.ed_nexted = htole32(sed->physaddr); -} - -/* - * Remove an ED from the schedule. Called at splusb(). - */ -void -ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) -{ - ohci_soft_ed_t *p; - - SPLUSBCHECK; - - /* XXX */ - for (p = head; p != NULL && p->next != sed; p = p->next) - ; - if (p == NULL) - panic("ohci_rem_ed: ED not found"); - p->next = sed->next; - p->ed.ed_nexted = sed->ed.ed_nexted; -} - -/* - * When a transfer is completed the TD is added to the done queue by - * the host controller. This queue is the processed by software. - * Unfortunately the queue contains the physical address of the TD - * and we have no simple way to translate this back to a kernel address. - * To make the translation possible (and fast) we use a hash table of - * TDs currently in the schedule. The physical address is used as the - * hash value. - */ - -#define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) -/* Called at splusb() */ -void -ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - int h = HASH(std->physaddr); - - SPLUSBCHECK; - - LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); -} - -/* Called at splusb() */ -void -ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) -{ - SPLUSBCHECK; - - LIST_REMOVE(std, hnext); -} - -ohci_soft_td_t * -ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) -{ - int h = HASH(a); - ohci_soft_td_t *std; - - /* if these are present they should be masked out at an earlier - * stage. - */ - KASSERT((a&~OHCI_HEADMASK) == 0, ("%s: 0x%b has lower bits set\n", - device_get_nameunit(sc->sc_bus.bdev), - (int) a, "\20\1HALT\2TOGGLE")); - - for (std = LIST_FIRST(&sc->sc_hash_tds[h]); - std != NULL; - std = LIST_NEXT(std, hnext)) - if (std->physaddr == a) - return (std); - - DPRINTF(("%s: ohci_hash_find_td: addr 0x%08lx not found\n", - device_get_nameunit(sc->sc_bus.bdev), (u_long) a)); - return (NULL); -} - -/* Called at splusb() */ -void -ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) -{ - int h = HASH(sitd->physaddr); - - SPLUSBCHECK; - - 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); -} - -/* Called at splusb() */ -void -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", - sitd, (u_long)sitd->physaddr)); - - LIST_REMOVE(sitd, hnext); -} - -ohci_soft_itd_t * -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]); - sitd != NULL; - sitd = LIST_NEXT(sitd, hnext)) - if (sitd->physaddr == a) - return (sitd); - return (NULL); -} - -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_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task, - USB_TASKQ_HC); -} - -void -ohci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - int s; - - DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer)); - - s = splusb(); - ohci_abort_xfer(xfer, USBD_TIMEOUT); - splx(s); -} - -#ifdef USB_DEBUG -void -ohci_dump_tds(ohci_soft_td_t *std) -{ - for (; std; std = std->nexttd) - ohci_dump_td(std); -} - -void -ohci_dump_td(ohci_soft_td_t *std) -{ - char sbuf[128]; - - bitmask_snprintf((u_int32_t)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)); -} - -void -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)); - for (i = 0; i < OHCI_ITD_NOFFSET; i++) - printf("offs[%d]=0x%04x ", i, - (u_int)le16toh(sitd->itd.itd_offset[i])); - printf("\n"); -} - -void -ohci_dump_itds(ohci_soft_itd_t *sitd) -{ - for (; sitd; sitd = sitd->nextitd) - ohci_dump_itd(sitd); -} - -void -ohci_dump_ed(ohci_soft_ed_t *sed) -{ - char sbuf[128], sbuf2[128]; - - bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_flags), - "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO", - sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)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\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 - -usbd_status -ohci_open(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - u_int8_t addr = dev->address; - u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; - ohci_soft_ed_t *sed; - ohci_soft_td_t *std; - ohci_soft_itd_t *sitd; - ohci_physaddr_t tdphys; - u_int32_t fmt; - usbd_status err; - int s; - int ival; - - DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, addr, ed->bEndpointAddress, sc->sc_addr)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - std = NULL; - sed = NULL; - - if (addr == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &ohci_root_ctrl_methods; - break; - case UE_DIR_IN | OHCI_INTR_ENDPT: - pipe->methods = &ohci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - } else { - sed = ohci_alloc_sed(sc); - if (sed == NULL) - goto bad0; - opipe->sed = sed; - if (xfertype == UE_ISOCHRONOUS) { - sitd = ohci_alloc_sitd(sc); - if (sitd == NULL) - goto bad1; - opipe->tail.itd = sitd; - opipe->aborting = 0; - tdphys = sitd->physaddr; - fmt = OHCI_ED_FORMAT_ISO; - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - fmt |= OHCI_ED_DIR_IN; - else - fmt |= OHCI_ED_DIR_OUT; - } else { - std = ohci_alloc_std(sc); - if (std == NULL) - goto bad1; - opipe->tail.td = std; - tdphys = std->physaddr; - fmt = OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD; - } - sed->ed.ed_flags = htole32( - OHCI_ED_SET_FA(addr) | - OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) | - (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) | - fmt | - OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); - sed->ed.ed_headp = htole32(tdphys | - (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0)); - 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), - 0, &opipe->u.ctl.reqdma); - if (err) - goto bad; - s = splusb(); - ohci_add_ed(sed, sc->sc_ctrl_head); - splx(s); - break; - case UE_INTERRUPT: - pipe->methods = &ohci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (ohci_device_setintr(sc, opipe, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &ohci_device_isoc_methods; - return (ohci_setup_isoc(pipe)); - case UE_BULK: - pipe->methods = &ohci_device_bulk_methods; - s = splusb(); - ohci_add_ed(sed, sc->sc_bulk_head); - splx(s); - break; - } - } - return (USBD_NORMAL_COMPLETION); - - bad: - if (std != NULL) - ohci_free_std(sc, std); - bad1: - if (sed != NULL) - ohci_free_sed(sc, sed); - bad0: - return (USBD_NOMEM); - -} - -/* - * Close a reqular pipe. - * Assumes that there are no pending transactions. - */ -void -ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - ohci_soft_ed_t *sed = opipe->sed; - int s; - - s = splusb(); -#ifdef DIAGNOSTIC - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) { - ohci_soft_td_t *std; - std = ohci_hash_find_td(sc, le32toh(sed->ed.ed_headp)); - 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 USB_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) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - printf("ohci_close_pipe: pipe still not empty\n"); - } -#endif - ohci_rem_ed(sed, head); - /* Make sure the host controller is not touching this ED */ - usb_delay_ms(&sc->sc_bus, 1); - splx(s); - pipe->endpoint->savedtoggle = - (le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; - 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 - * 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. - */ -void -ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - struct ohci_xfer *oxfer = OXFER(xfer); - 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; - - DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed)); - - if (sc->sc_dying) { - /* If we're dying, just do the software part. */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task); - usb_transfer_complete(xfer); - splx(s); - return; - } - - if (xfer->device->bus->intr_context || !curproc) - panic("ohci_abort_xfer: not in process context"); - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - if (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING) { - DPRINTFN(2, ("ohci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n")); - oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTWAIT; - while (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING) - tsleep(&oxfer->ohci_xfer_flags, PZERO, "ohciaw", 0); - return; - } - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - s = splusb(); - oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task); - splx(s); - 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 */ - s = splusb(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - tsleep(&sc->sc_softwake, PZERO, "ohciab", 0); -#endif /* USB_USE_SOFTINTR */ - 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) { - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; /* XXX */ - splx(s); - printf("ohci_abort_xfer: hcpriv is NULL\n"); - return; - } -#endif -#ifdef USB_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->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */ - - /* - * Step 5: Execute callback. - */ - /* Do the wakeup first to avoid touching the xfer after the callback. */ - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; - if (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTWAIT) { - oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTWAIT; - wakeup(&oxfer->ohci_xfer_flags); - } - usb_transfer_complete(xfer); - - splx(s); -} - -/* - * Data structures and routines to emulate the root hub. - */ -static usb_device_descriptor_t ohci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x01}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -static usb_config_descriptor_t ohci_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 ohci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_FSHUB, - 0 -}; - -static usb_endpoint_descriptor_t ohci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | OHCI_INTR_ENDPT, - UE_INTERRUPT, - {8, 0}, /* max packet */ - 255 -}; - -static usb_hub_descriptor_t ohci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 0, - {0,0}, - 0, - 0, - {0}, -}; - -static int -ohci_str(usb_string_descriptor_t *p, int l, const 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 -ohci_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 (ohci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_root_ctrl_start(usbd_xfer_handle xfer) -{ - ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, i; - int s, len, value, index, l, totlen = 0; - usb_port_status_t ps; - usb_hub_descriptor_t hubd; - usbd_status 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,("ohci_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 = xfer->buffer; - -#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,("ohci_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(ohci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &ohci_devd, l); - break; - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &ohci_confd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ohci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &ohci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 1: /* Vendor */ - totlen = ohci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = ohci_str(buf, len, "OHCI 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, ("ohci_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 = OHCI_RH_PORT_STATUS(index); - switch(value) { - case UHF_PORT_ENABLE: - OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS); - break; - case UHF_PORT_SUSPEND: - OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR); - break; - case UHF_PORT_POWER: - /* Yes, writing to the LOW_SPEED bit clears power. */ - OWRITE4(sc, port, UPS_LOW_SPEED); - break; - case UHF_C_PORT_CONNECTION: - OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16); - break; - case UHF_C_PORT_ENABLE: - OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16); - break; - case UHF_C_PORT_SUSPEND: - OWRITE4(sc, port, UPS_C_SUSPEND << 16); - break; - case UHF_C_PORT_OVER_CURRENT: - OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16); - break; - case UHF_C_PORT_RESET: - OWRITE4(sc, port, UPS_C_PORT_RESET << 16); - break; - default: - err = USBD_IOERROR; - goto ret; - } - 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) - ohci_rhsc_able(sc, 1); - break; - default: - break; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A); - hubd = ohci_hubd; - hubd.bNbrPorts = sc->sc_noport; - USETW(hubd.wHubCharacteristics, - (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) - hubd.DeviceRemovable[i++] = (u_int8_t)v; - 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,("ohci_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 = OREAD4(sc, OHCI_RH_PORT_STATUS(index)); - DPRINTFN(8,("ohci_root_ctrl_transfer: port status=0x%04x\n", - v)); - USETW(ps.wPortStatus, v); - USETW(ps.wPortChange, v >> 16); - 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 = OHCI_RH_PORT_STATUS(index); - switch(value) { - case UHF_PORT_ENABLE: - OWRITE4(sc, port, UPS_PORT_ENABLED); - break; - case UHF_PORT_SUSPEND: - OWRITE4(sc, port, UPS_SUSPEND); - break; - case UHF_PORT_RESET: - 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; - } - if ((OREAD4(sc, port) & UPS_RESET) == 0) - break; - } - DPRINTFN(8,("ohci port %d reset, status = 0x%04x\n", - index, OREAD4(sc, port))); - break; - case UHF_PORT_POWER: - DPRINTFN(2,("ohci_root_ctrl_transfer: set port power " - "%d\n", index)); - OWRITE4(sc, port, UPS_PORT_POWER); - break; - default: - err = USBD_IOERROR; - goto ret; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - s = splusb(); - hacksync(xfer); /* XXX to compensate for usb_transfer_complete */ - usb_transfer_complete(xfer); - splx(s); - return (USBD_IN_PROGRESS); -} - -/* Abort a root control request. */ -static void -ohci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -static void -ohci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("ohci_root_ctrl_close\n")); - /* Nothing to do. */ -} - -static usbd_status -ohci_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 (ohci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - ohci_softc_t *sc = (ohci_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 -ohci_root_intr_abort(usbd_xfer_handle xfer) -{ - int s; - - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ohci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - xfer->status = USBD_CANCELLED; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); -} - -/* Close the root pipe. */ -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; -} - -/************************/ - -static usbd_status -ohci_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 (ohci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_ctrl_start(usbd_xfer_handle xfer) -{ - ohci_softc_t *sc = (ohci_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("ohci_device_ctrl_transfer: not a request\n"); - return (USBD_INVAL); - } -#endif - - err = ohci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - ohci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -/* Abort a device control request. */ -static void -ohci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -static void -ohci_device_ctrl_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); - ohci_close_pipe(pipe, sc->sc_ctrl_head); - ohci_free_std(sc, opipe->tail.td); -} - -/************************/ - -static void -ohci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - - opipe->sed->ed.ed_headp &= htole32(~OHCI_TOGGLECARRY); -} - -static void -ohci_noop(usbd_pipe_handle pipe) -{ -} - -static usbd_status -ohci_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 (ohci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_bulk_start(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - int addr = dev->address; - ohci_soft_td_t *data, *tail, *tdp; - ohci_soft_ed_t *sed; - int s, len, isread, endpt; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) { - /* XXX panic */ - printf("ohci_device_bulk_start: a request\n"); - return (USBD_INVAL); - } -#endif - - len = xfer->length; - endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sed = opipe->sed; - - DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " - "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, - endpt)); - - opipe->u.bulk.isread = isread; - opipe->u.bulk.length = len; - - /* Update device address */ - sed->ed.ed_flags = htole32( - (le32toh(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) | - OHCI_ED_SET_FA(addr)); - - /* Allocate a chain of new TDs (including a new tail). */ - data = opipe->tail.td; - err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, - data, &tail); - /* We want interrupt at the end of the transfer. */ - tail->td.td_flags &= htole32(~OHCI_TD_INTR_MASK); - tail->td.td_flags |= htole32(OHCI_TD_SET_DI(1)); - tail->flags |= OHCI_CALL_DONE; - tail = tail->nexttd; /* point at sentinel */ - if (err) - return (err); - - tail->xfer = NULL; - xfer->hcpriv = data; - - DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " - "td_cbp=0x%08x td_be=0x%08x\n", - (int)le32toh(sed->ed.ed_flags), - (int)le32toh(data->td.td_flags), - (int)le32toh(data->td.td_cbp), - (int)le32toh(data->td.td_be))); - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - /* Insert ED in schedule */ - s = splusb(); - for (tdp = data; tdp != tail; tdp = tdp->nexttd) { - tdp->xfer = xfer; - } - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - ohci_timeout, xfer); - } - -#if 0 -/* This goes wrong if we are too slow. */ - if (ohcidebug > 10) { - delay(10000); - DPRINTF(("ohci_device_intr_transfer: status=%x\n", - OREAD4(sc, OHCI_COMMAND_STATUS))); - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - splx(s); - - if (sc->sc_bus.use_polling) - ohci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -} - -static void -ohci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * Close a device bulk pipe. - */ -static void -ohci_device_bulk_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - - DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); - ohci_close_pipe(pipe, sc->sc_bulk_head); - ohci_free_std(sc, opipe->tail.td); -} - -/************************/ - -static usbd_status -ohci_device_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 (ohci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -static usbd_status -ohci_device_intr_start(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_ed_t *sed = opipe->sed; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - - DPRINTFN(3, ("ohci_device_intr_start: xfer=%p len=%d " - "flags=%d priv=%p\n", - xfer, xfer->length, xfer->flags, xfer->priv)); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("ohci_device_intr_start: a request"); -#endif - - err = ohci_device_intr_insert(sc, xfer); - if (err) - return (err); - - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - - return (USBD_IN_PROGRESS); -} - -/* - * Insert an interrupt transfer into an endpoint descriptor list - */ -static usbd_status -ohci_device_intr_insert(ohci_softc_t *sc, usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - ohci_soft_ed_t *sed = opipe->sed; - ohci_soft_td_t *data, *tail; - ohci_physaddr_t dataphys, physend; - int s; - - DPRINTFN(4, ("ohci_device_intr_insert: xfer=%p", xfer)); - - data = opipe->tail.td; - tail = ohci_alloc_std(sc); - if (tail == NULL) - return (USBD_NOMEM); - tail->xfer = NULL; - - data->td.td_flags = htole32( - 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); - /* - * Assume a short mapping with no complications, which - * should always be true for <= 4k buffers in contiguous - * virtual memory. The data can take the following forms: - * 1 segment in 1 OHCI page - * 1 segment in 2 OHCI pages - * 2 segments in 2 OHCI pages - * (see comment in ohci_alloc_std_chain() for details) - */ - KASSERT(xfer->length > 0 && xfer->length <= OHCI_PAGE_SIZE, - ("ohci_device_intr_insert: bad length %d", xfer->length)); - dataphys = xfer->dmamap.segs[0].ds_addr; - physend = dataphys + xfer->length - 1; - if (xfer->dmamap.nsegs == 2) { - KASSERT(OHCI_PAGE_OFFSET(dataphys + - xfer->dmamap.segs[0].ds_len) == 0, - ("ohci_device_intr_insert: bad seg 0 termination")); - physend = xfer->dmamap.segs[1].ds_addr + xfer->length - - xfer->dmamap.segs[0].ds_len - 1; - } else { - KASSERT(xfer->dmamap.nsegs == 1, - ("ohci_device_intr_insert: bad seg count %d", - (u_int)xfer->dmamap.nsegs)); - } - data->td.td_cbp = htole32(dataphys); - data->nexttd = tail; - data->td.td_nexttd = htole32(tail->physaddr); - data->td.td_be = htole32(physend); - data->len = xfer->length; - data->xfer = xfer; - data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN; - xfer->hcpriv = data; - xfer->actlen = 0; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_intr_insert:\n")); - ohci_dump_ed(sed); - ohci_dump_tds(data); - } -#endif - - /* Insert ED in schedule */ - s = splusb(); - sed->ed.ed_tailp = htole32(tail->physaddr); - opipe->tail.td = tail; - splx(s); - - return (USBD_NORMAL_COMPLETION); -} - -/* Abort a device control request. */ -static void -ohci_device_intr_abort(usbd_xfer_handle xfer) -{ - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("ohci_device_intr_abort: remove\n")); - xfer->pipe->intrxfer = NULL; - } - ohci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device interrupt pipe. */ -static void -ohci_device_intr_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - int nslots = opipe->u.intr.nslots; - int pos = opipe->u.intr.pos; - int j; - ohci_soft_ed_t *p, *sed = opipe->sed; - int s; - - DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", - pipe, nslots, pos)); - s = splusb(); - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - usb_delay_ms(&sc->sc_bus, 2); -#ifdef DIAGNOSTIC - if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) != - (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) - panic("%s: Intr pipe %p still has TDs queued", - device_get_nameunit(sc->sc_bus.bdev), pipe); -#endif - - for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) - ; -#ifdef DIAGNOSTIC - if (p == NULL) - panic("ohci_device_intr_close: ED not found"); -#endif - p->next = sed->next; - p->ed.ed_nexted = sed->ed.ed_nexted; - splx(s); - - for (j = 0; j < nslots; j++) - --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; - - ohci_free_std(sc, opipe->tail.td); - ohci_free_sed(sc, opipe->sed); -} - -static usbd_status -ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival) -{ - int i, j, s, best; - u_int npoll, slow, shigh, nslots; - u_int bestbw, bw; - ohci_soft_ed_t *hsed, *sed = opipe->sed; - - DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe)); - if (ival == 0) { - printf("ohci_setintr: 0 interval\n"); - return (USBD_INVAL); - } - - npoll = OHCI_NO_INTRS; - while (npoll > ival) - npoll /= 2; - DPRINTFN(2, ("ohci_setintr: ival=%d npoll=%d\n", ival, npoll)); - - /* - * We now know which level in the tree the ED must go into. - * Figure out which slot has most bandwidth left over. - * Slots to examine: - * npoll - * 1 0 - * 2 1 2 - * 4 3 4 5 6 - * 8 7 8 9 10 11 12 13 14 - * N (N-1) .. (N-1+N-1) - */ - slow = npoll-1; - shigh = slow + npoll; - nslots = OHCI_NO_INTRS / npoll; - for (best = i = slow, bestbw = ~0; i < shigh; i++) { - bw = 0; - for (j = 0; j < nslots; j++) - bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS]; - if (bw < bestbw) { - best = i; - bestbw = bw; - } - } - DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", - best, slow, shigh, bestbw)); - - s = splusb(); - hsed = sc->sc_eds[best]; - sed->next = hsed->next; - sed->ed.ed_nexted = hsed->ed.ed_nexted; - hsed->next = sed; - hsed->ed.ed_nexted = htole32(sed->physaddr); - splx(s); - - for (j = 0; j < nslots; j++) - ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; - opipe->u.intr.nslots = nslots; - opipe->u.intr.pos = best; - - DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); - return (USBD_NORMAL_COMPLETION); -} - -/***********************/ - -usbd_status -ohci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); - - /* Put it on our queue, */ - err = usb_insert_transfer(xfer); - - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return (err); - - /* XXX should check inuse here */ - - /* insert into schedule, */ - ohci_device_isoc_enter(xfer); - - /* and start if the pipe wasn't running */ - if (!err) - ohci_device_isoc_start(STAILQ_FIRST(&xfer->pipe->queue)); - - return (err); -} - -void -ohci_device_isoc_enter(usbd_xfer_handle xfer) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; - usbd_device_handle dev = opipe->pipe.device; - ohci_softc_t *sc = (ohci_softc_t *)dev->bus; - ohci_soft_ed_t *sed = opipe->sed; - struct iso *iso = &opipe->u.iso; - struct usb_dma_mapping *dma = &xfer->dmamap; - ohci_soft_itd_t *sitd, *nsitd; - ohci_physaddr_t dataphys, bp0, physend, prevpage; - int curlen, i, len, ncur, nframes, npages, seg, segoff; - int s; - - DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p " - "nframes=%d\n", - iso->inuse, iso->next, xfer, xfer->nframes)); - - if (sc->sc_dying) - return; - - 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", - iso->next)); - } - - sitd = opipe->tail.itd; - nframes = xfer->nframes; - xfer->hcpriv = sitd; - seg = 0; - segoff = 0; - i = 0; - while (i < nframes) { - /* - * Fill in as many ITD frames as possible. - */ - KASSERT(seg < dma->nsegs, ("ohci_device_isoc_enter: overrun")); - bp0 = dma->segs[seg].ds_addr + segoff; - sitd->itd.itd_bp0 = htole32(bp0); - prevpage = OHCI_PAGE(bp0); - npages = 1; - - ncur = 0; - while (ncur < OHCI_ITD_NOFFSET && i < nframes) { - /* Find the frame start and end physical addresses. */ - len = xfer->frlengths[i]; - dataphys = dma->segs[seg].ds_addr + segoff; - curlen = dma->segs[seg].ds_len - segoff; - if (len > curlen) { - KASSERT(seg + 1 < dma->nsegs, - ("ohci_device_isoc_enter: overrun2")); - seg++; - segoff = len - curlen; - } else { - segoff += len; - } - KASSERT(segoff <= dma->segs[seg].ds_len, - ("ohci_device_isoc_enter: overrun3")); - physend = dma->segs[seg].ds_addr + segoff - 1; - - /* Check if there would be more than 2 pages . */ - if (OHCI_PAGE(dataphys) != prevpage) { - prevpage = OHCI_PAGE(dataphys); - npages++; - } - if (OHCI_PAGE(physend) != prevpage) { - prevpage = OHCI_PAGE(physend); - npages++; - } - if (npages > 2) { - /* We cannot fit this frame now. */ - segoff -= len; - if (segoff < 0) { - seg--; - segoff += dma->segs[seg].ds_len; - } - break; - } - - sitd->itd.itd_be = htole32(physend); - sitd->itd.itd_offset[ncur] = - htole16(OHCI_ITD_MK_OFFS(OHCI_PAGE(dataphys) == - OHCI_PAGE(bp0) ? 0 : 1, dataphys)); - i++; - ncur++; - } - if (segoff >= dma->segs[seg].ds_len) { - KASSERT(segoff == dma->segs[seg].ds_len, - ("ohci_device_isoc_enter: overlap")); - seg++; - segoff = 0; - } - - /* Allocate next ITD */ - nsitd = ohci_alloc_sitd(sc); - if (nsitd == NULL) { - /* XXX what now? */ - printf("%s: isoc TD alloc failed\n", - device_get_nameunit(sc->sc_bus.bdev)); - return; - } - - /* Fill out remaining fields of current ITD */ - sitd->nextitd = nsitd; - sitd->itd.itd_nextitd = htole32(nsitd->physaddr); - sitd->xfer = xfer; - if (i < nframes) { - sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | - OHCI_ITD_SET_SF(iso->next) | - OHCI_ITD_SET_DI(6) | /* delay intr a little */ - OHCI_ITD_SET_FC(ncur)); - sitd->flags = OHCI_ITD_ACTIVE; - } else { - sitd->itd.itd_flags = htole32( - OHCI_ITD_NOCC | - OHCI_ITD_SET_SF(iso->next) | - OHCI_ITD_SET_DI(0) | - OHCI_ITD_SET_FC(ncur)); - sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE; - } - iso->next += ncur; - - sitd = nsitd; - } - - iso->inuse += nframes; - - /* XXX pretend we did it all */ - xfer->actlen = 0; - for (i = 0; i < nframes; i++) - xfer->actlen += xfer->frlengths[i]; - - xfer->status = USBD_IN_PROGRESS; - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - DPRINTF(("ohci_device_isoc_enter: frame=%d\n", - le32toh(sc->sc_hcca->hcca_frame_number))); - ohci_dump_itds(xfer->hcpriv); - ohci_dump_ed(sed); - } -#endif - - s = splusb(); - opipe->tail.itd = sitd; - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); - sed->ed.ed_tailp = htole32(sitd->physaddr); - splx(s); - -#ifdef USB_DEBUG - if (ohcidebug > 5) { - delay(150000); - DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", - le32toh(sc->sc_hcca->hcca_frame_number))); - ohci_dump_itds(xfer->hcpriv); - ohci_dump_ed(sed); - } -#endif -} - -usbd_status -ohci_device_isoc_start(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_ed_t *sed; - int s; - - DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->status != USBD_IN_PROGRESS) - printf("ohci_device_isoc_start: not in progress %p\n", xfer); -#endif - - /* XXX anything to do? */ - - s = splusb(); - sed = opipe->sed; /* Turn off ED skip-bit to start processing */ - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* ED's ITD list.*/ - splx(s); - - return (USBD_IN_PROGRESS); -} - -void -ohci_device_isoc_abort(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_ed_t *sed; - ohci_soft_itd_t *sitd, *sitdnext, *tmp_sitd; - int s,undone,num_sitds; - - s = splusb(); - opipe->aborting = 1; - - DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); - - /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && - xfer->status != USBD_IN_PROGRESS) { - splx(s); - printf("ohci_device_isoc_abort: early return\n"); - return; - } - - /* Give xfer the requested abort code. */ - xfer->status = USBD_CANCELLED; - - sed = opipe->sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */ - - num_sitds = 0; - sitd = xfer->hcpriv; -#ifdef DIAGNOSTIC - if (sitd == NULL) { - splx(s); - printf("ohci_device_isoc_abort: hcpriv==0\n"); - return; - } -#endif - for (; sitd != NULL && sitd->xfer == xfer; sitd = sitd->nextitd) { - num_sitds++; -#ifdef DIAGNOSTIC - DPRINTFN(1,("abort sets done sitd=%p\n", sitd)); - sitd->isdone = 1; -#endif - } - - splx(s); - - /* - * Each sitd has up to OHCI_ITD_NOFFSET transfers, each can - * take a usb 1ms cycle. Conservatively wait for it to drain. - * Even with DMA done, it can take awhile for the "batch" - * delivery of completion interrupts to occur thru the controller. - */ - - do { - usb_delay_ms(&sc->sc_bus, 2*(num_sitds*OHCI_ITD_NOFFSET)); - - undone = 0; - tmp_sitd = xfer->hcpriv; - for (; tmp_sitd != NULL && tmp_sitd->xfer == xfer; - tmp_sitd = tmp_sitd->nextitd) { - if (OHCI_CC_NO_ERROR == - OHCI_ITD_GET_CC(le32toh(tmp_sitd->itd.itd_flags)) && - tmp_sitd->flags & OHCI_ITD_ACTIVE && - (tmp_sitd->flags & OHCI_ITD_INTFIN) == 0) - undone++; - } - } while( undone != 0 ); - - /* Free the sitds */ - for (sitd = xfer->hcpriv; sitd->xfer == xfer; - sitd = sitdnext) { - sitdnext = sitd->nextitd; - ohci_free_sitd(sc, sitd); - } - - s = splusb(); - - /* Run callback. */ - usb_transfer_complete(xfer); - - /* There is always a `next' sitd so link it up. */ - sed->ed.ed_headp = htole32(sitd->physaddr); - - sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */ - - splx(s); -} - -void -ohci_device_isoc_done(usbd_xfer_handle xfer) -{ - /* This null routine corresponds to non-isoc "done()" routines - * that free the stds associated with an xfer after a completed - * xfer interrupt. However, in the case of isoc transfers, the - * sitds associated with the transfer have already been processed - * and reallocated for the next iteration by - * "ohci_device_isoc_transfer()". - * - * Routine "usb_transfer_complete()" is called at the end of every - * relevant usb interrupt. "usb_transfer_complete()" indirectly - * calls 1) "ohci_device_isoc_transfer()" (which keeps pumping the - * pipeline by setting up the next transfer iteration) and 2) then - * calls "ohci_device_isoc_done()". Isoc transfers have not been - * working for the ohci usb because this routine was trashing the - * xfer set up for the next iteration (thus, only the first - * UGEN_NISOREQS xfers outstanding on an open would work). Perhaps - * this could all be re-factored, but that's another pass... - */ -} - -usbd_status -ohci_setup_isoc(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - struct iso *iso = &opipe->u.iso; - int s; - - iso->next = -1; - iso->inuse = 0; - - s = splusb(); - ohci_add_ed(opipe->sed, sc->sc_isoc_head); - splx(s); - - return (USBD_NORMAL_COMPLETION); -} - -void -ohci_device_isoc_close(usbd_pipe_handle pipe) -{ - struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; - ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus; - ohci_soft_ed_t *sed; - - DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); - - sed = opipe->sed; - sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* Stop device. */ - - ohci_close_pipe(pipe, sc->sc_isoc_head); /* Stop isoc list, free ED.*/ - - /* up to NISOREQs xfers still outstanding. */ - -#ifdef DIAGNOSTIC - opipe->tail.itd->isdone = 1; -#endif - ohci_free_sitd(sc, opipe->tail.itd); /* Next `avail free' sitd.*/ -} diff --git a/sys/dev/usb/ohci_pci.c b/sys/dev/usb/ohci_pci.c deleted file mode 100644 index fadffb6..0000000 --- a/sys/dev/usb/ohci_pci.c +++ /dev/null @@ -1,411 +0,0 @@ -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) 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> -__FBSDID("$FreeBSD$"); - -/* - * USB Open Host Controller driver. - * - * OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf - */ - -/* The low level controller code for OHCI has been split into - * PCI probes and OHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/queue.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <machine/resource.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.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/ohcireg.h> -#include <dev/usb/ohcivar.h> - -#define PCI_OHCI_VENDORID_ACERLABS 0x10b9 -#define PCI_OHCI_VENDORID_AMD 0x1022 -#define PCI_OHCI_VENDORID_APPLE 0x106b -#define PCI_OHCI_VENDORID_ATI 0x1002 -#define PCI_OHCI_VENDORID_CMDTECH 0x1095 -#define PCI_OHCI_VENDORID_NEC 0x1033 -#define PCI_OHCI_VENDORID_NVIDIA 0x12D2 -#define PCI_OHCI_VENDORID_NVIDIA2 0x10DE -#define PCI_OHCI_VENDORID_OPTI 0x1045 -#define PCI_OHCI_VENDORID_SIS 0x1039 -#define PCI_OHCI_VENDORID_SUN 0x108e - -#define PCI_OHCI_DEVICEID_ALADDIN_V 0x523710b9 -static const char *ohci_device_aladdin_v = "AcerLabs M5237 (Aladdin-V) USB controller"; - -#define PCI_OHCI_DEVICEID_AMD756 0x740c1022 -static const char *ohci_device_amd756 = "AMD-756 USB Controller"; - -#define PCI_OHCI_DEVICEID_AMD766 0x74141022 -static const char *ohci_device_amd766 = "AMD-766 USB Controller"; - -#define PCI_OHCI_DEVICEID_SB400_1 0x43741002 -#define PCI_OHCI_DEVICEID_SB400_2 0x43751002 -static const char *ohci_device_sb400 = "ATI SB400 USB Controller"; - -#define PCI_OHCI_DEVICEID_FIRELINK 0xc8611045 -static const char *ohci_device_firelink = "OPTi 82C861 (FireLink) USB controller"; - -#define PCI_OHCI_DEVICEID_NEC 0x00351033 -static const char *ohci_device_nec = "NEC uPD 9210 USB controller"; - -#define PCI_OHCI_DEVICEID_NFORCE3 0x00d710de -static const char *ohci_device_nforce3 = "nVidia nForce3 USB Controller"; - -#define PCI_OHCI_DEVICEID_USB0670 0x06701095 -static const char *ohci_device_usb0670 = "CMD Tech 670 (USB0670) USB controller"; - -#define PCI_OHCI_DEVICEID_USB0673 0x06731095 -static const char *ohci_device_usb0673 = "CMD Tech 673 (USB0673) USB controller"; - -#define PCI_OHCI_DEVICEID_SIS5571 0x70011039 -static const char *ohci_device_sis5571 = "SiS 5571 USB controller"; - -#define PCI_OHCI_DEVICEID_KEYLARGO 0x0019106b -static const char *ohci_device_keylargo = "Apple KeyLargo USB controller"; - -#define PCI_OHCI_DEVICEID_PCIO2USB 0x1103108e -static const char *ohci_device_pcio2usb = "Sun PCIO-2 USB controller"; - -static const char *ohci_device_generic = "OHCI (generic) USB controller"; - -#define PCI_OHCI_BASE_REG 0x10 - - -static device_attach_t ohci_pci_attach; -static device_detach_t ohci_pci_detach; -static device_suspend_t ohci_pci_suspend; -static device_resume_t ohci_pci_resume; - -static int -ohci_pci_suspend(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return err; - ohci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -ohci_pci_resume(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - - ohci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static const char * -ohci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - switch (device_id) { - case PCI_OHCI_DEVICEID_ALADDIN_V: - return (ohci_device_aladdin_v); - case PCI_OHCI_DEVICEID_AMD756: - return (ohci_device_amd756); - case PCI_OHCI_DEVICEID_AMD766: - return (ohci_device_amd766); - case PCI_OHCI_DEVICEID_SB400_1: - case PCI_OHCI_DEVICEID_SB400_2: - return (ohci_device_sb400); - case PCI_OHCI_DEVICEID_USB0670: - return (ohci_device_usb0670); - case PCI_OHCI_DEVICEID_USB0673: - return (ohci_device_usb0673); - case PCI_OHCI_DEVICEID_FIRELINK: - return (ohci_device_firelink); - case PCI_OHCI_DEVICEID_NEC: - return (ohci_device_nec); - case PCI_OHCI_DEVICEID_NFORCE3: - return (ohci_device_nforce3); - case PCI_OHCI_DEVICEID_SIS5571: - return (ohci_device_sis5571); - case PCI_OHCI_DEVICEID_KEYLARGO: - return (ohci_device_keylargo); - case PCI_OHCI_DEVICEID_PCIO2USB: - return (ohci_device_pcio2usb); - default: - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_OHCI) { - return (ohci_device_generic); - } - } - - return NULL; /* dunno */ -} - -static int -ohci_pci_probe(device_t self) -{ - const char *desc = ohci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - return BUS_PROBE_DEFAULT; - } else { - return ENXIO; - } -} - -static int -ohci_pci_attach(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - int err; - int rid; - - /* XXX where does it say so in the spec? */ - sc->sc_bus.usbrev = USBREV_1_0; - - pci_enable_busmaster(self); - - /* - * Some Sun PCIO-2 USB controllers have their intpin register - * bogusly set to 0, although it should be 4. Correct that. - */ - if (pci_get_devid(self) == PCI_OHCI_DEVICEID_PCIO2USB && - pci_get_intpin(self) == 0) - pci_set_intpin(self, 4); - - rid = PCI_CBMEM; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map memory\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - ohci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - ohci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* ohci_pci_match will never return NULL if ohci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, ohci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_OHCI_VENDORID_ACERLABS: - sprintf(sc->sc_vendor, "AcerLabs"); - break; - case PCI_OHCI_VENDORID_AMD: - sprintf(sc->sc_vendor, "AMD"); - break; - case PCI_OHCI_VENDORID_APPLE: - sprintf(sc->sc_vendor, "Apple"); - break; - case PCI_OHCI_VENDORID_ATI: - sprintf(sc->sc_vendor, "ATI"); - break; - case PCI_OHCI_VENDORID_CMDTECH: - sprintf(sc->sc_vendor, "CMDTECH"); - break; - case PCI_OHCI_VENDORID_NEC: - sprintf(sc->sc_vendor, "NEC"); - break; - case PCI_OHCI_VENDORID_NVIDIA: - case PCI_OHCI_VENDORID_NVIDIA2: - sprintf(sc->sc_vendor, "nVidia"); - break; - case PCI_OHCI_VENDORID_OPTI: - sprintf(sc->sc_vendor, "OPTi"); - break; - case PCI_OHCI_VENDORID_SIS: - sprintf(sc->sc_vendor, "SiS"); - break; - default: - if (bootverbose) - device_printf(self, "(New OHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, NULL, ohci_intr, - sc, &sc->ih); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - ohci_pci_detach(self); - return ENXIO; - } - - /* Allocate a parent dma tag for DMA maps */ - err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - NULL, NULL, &sc->sc_bus.parent_dmatag); - if (err) { - device_printf(self, "Could not allocate parent DMA tag (%d)\n", - err); - ohci_pci_detach(self); - return ENXIO; - } - /* Allocate a dma tag for transfer buffers */ - err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); - if (err) { - device_printf(self, "Could not allocate transfer tag (%d)\n", - err); - ohci_pci_detach(self); - return ENXIO; - } - - err = ohci_init(sc); - if (!err) { - sc->sc_flags |= OHCI_SCFLG_DONEINIT; - err = device_probe_and_attach(sc->sc_bus.bdev); - } - - if (err) { - device_printf(self, "USB init failed\n"); - ohci_pci_detach(self); - return EIO; - } - return 0; -} - -static int -ohci_pci_detach(device_t self) -{ - ohci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & OHCI_SCFLG_DONEINIT) { - ohci_detach(sc, 0); - sc->sc_flags &= ~OHCI_SCFLG_DONEINIT; - } - - if (sc->sc_bus.parent_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.parent_dmatag); - if (sc->sc_bus.buffer_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag); - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, - sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - -static device_method_t ohci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ohci_pci_probe), - DEVMETHOD(device_attach, ohci_pci_attach), - DEVMETHOD(device_detach, ohci_pci_detach), - DEVMETHOD(device_suspend, ohci_pci_suspend), - DEVMETHOD(device_resume, ohci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - {0, 0} -}; - -static driver_t ohci_driver = { - "ohci", - ohci_methods, - sizeof(ohci_softc_t), -}; - -static devclass_t ohci_devclass; - -DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0); -DRIVER_MODULE(ohci, cardbus, ohci_driver, ohci_devclass, 0, 0); -MODULE_DEPEND(ohci, usb, 1, 1, 1); diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h deleted file mode 100644 index 429beb8..0000000 --- a/sys/dev/usb/ohcireg.h +++ /dev/null @@ -1,250 +0,0 @@ -/* $NetBSD: ohcireg.h,v 1.17 2000/04/01 09:27:35 augustss Exp $ */ -/* $FreeBSD$ */ - - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _DEV_PCI_OHCIREG_H_ -#define _DEV_PCI_OHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_CBMEM 0x10 /* configuration base memory */ - -#define PCI_INTERFACE_OHCI 0x10 - -/*** OHCI registers */ - -#define OHCI_REVISION 0x00 /* OHCI revision # */ -#define OHCI_REV_LO(rev) ((rev)&0xf) -#define OHCI_REV_HI(rev) (((rev)>>4)&0xf) -#define OHCI_REV_LEGACY(rev) ((rev) & 0x100) - -#define OHCI_CONTROL 0x04 -#define OHCI_CBSR_MASK 0x00000003 /* Control/Bulk Service Ratio */ -#define OHCI_RATIO_1_1 0x00000000 -#define OHCI_RATIO_1_2 0x00000001 -#define OHCI_RATIO_1_3 0x00000002 -#define OHCI_RATIO_1_4 0x00000003 -#define OHCI_PLE 0x00000004 /* Periodic List Enable */ -#define OHCI_IE 0x00000008 /* Isochronous Enable */ -#define OHCI_CLE 0x00000010 /* Control List Enable */ -#define OHCI_BLE 0x00000020 /* Bulk List Enable */ -#define OHCI_HCFS_MASK 0x000000c0 /* HostControllerFunctionalState */ -#define OHCI_HCFS_RESET 0x00000000 -#define OHCI_HCFS_RESUME 0x00000040 -#define OHCI_HCFS_OPERATIONAL 0x00000080 -#define OHCI_HCFS_SUSPEND 0x000000c0 -#define OHCI_IR 0x00000100 /* Interrupt Routing */ -#define OHCI_RWC 0x00000200 /* Remote Wakeup Connected */ -#define OHCI_RWE 0x00000400 /* Remote Wakeup Enabled */ -#define OHCI_COMMAND_STATUS 0x08 -#define OHCI_HCR 0x00000001 /* Host Controller Reset */ -#define OHCI_CLF 0x00000002 /* Control List Filled */ -#define OHCI_BLF 0x00000004 /* Bulk List Filled */ -#define OHCI_OCR 0x00000008 /* Ownership Change Request */ -#define OHCI_SOC_MASK 0x00030000 /* Scheduling Overrun Count */ -#define OHCI_INTERRUPT_STATUS 0x0c -#define OHCI_SO 0x00000001 /* Scheduling Overrun */ -#define OHCI_WDH 0x00000002 /* Writeback Done Head */ -#define OHCI_SF 0x00000004 /* Start of Frame */ -#define OHCI_RD 0x00000008 /* Resume Detected */ -#define OHCI_UE 0x00000010 /* Unrecoverable Error */ -#define OHCI_FNO 0x00000020 /* Frame Number Overflow */ -#define OHCI_RHSC 0x00000040 /* Root Hub Status Change */ -#define OHCI_OC 0x40000000 /* Ownership Change */ -#define OHCI_MIE 0x80000000 /* Master Interrupt Enable */ -#define OHCI_INTERRUPT_ENABLE 0x10 -#define OHCI_INTERRUPT_DISABLE 0x14 -#define OHCI_HCCA 0x18 -#define OHCI_PERIOD_CURRENT_ED 0x1c -#define OHCI_CONTROL_HEAD_ED 0x20 -#define OHCI_CONTROL_CURRENT_ED 0x24 -#define OHCI_BULK_HEAD_ED 0x28 -#define OHCI_BULK_CURRENT_ED 0x2c -#define OHCI_DONE_HEAD 0x30 -#define OHCI_FM_INTERVAL 0x34 -#define OHCI_GET_IVAL(s) ((s) & 0x3fff) -#define OHCI_GET_FSMPS(s) (((s) >> 16) & 0x7fff) -#define OHCI_FIT 0x80000000 -#define OHCI_FM_REMAINING 0x38 -#define OHCI_FM_NUMBER 0x3c -#define OHCI_PERIODIC_START 0x40 -#define OHCI_LS_THRESHOLD 0x44 -#define OHCI_RH_DESCRIPTOR_A 0x48 -#define OHCI_GET_NDP(s) ((s) & 0xff) -#define OHCI_PSM 0x0100 /* Power Switching Mode */ -#define OHCI_NPS 0x0200 /* No Power Switching */ -#define OHCI_DT 0x0400 /* Device Type */ -#define OHCI_OCPM 0x0800 /* Overcurrent Protection Mode */ -#define OHCI_NOCP 0x1000 /* No Overcurrent Protection */ -#define OHCI_GET_POTPGT(s) ((s) >> 24) -#define OHCI_RH_DESCRIPTOR_B 0x4c -#define OHCI_RH_STATUS 0x50 -#define OHCI_LPS 0x00000001 /* Local Power Status */ -#define OHCI_OCI 0x00000002 /* OverCurrent Indicator */ -#define OHCI_DRWE 0x00008000 /* Device Remote Wakeup Enable */ -#define OHCI_LPSC 0x00010000 /* Local Power Status Change */ -#define OHCI_CCIC 0x00020000 /* OverCurrent Indicator Change */ -#define OHCI_CRWE 0x80000000 /* Clear Remote Wakeup Enable */ -#define OHCI_RH_PORT_STATUS(n) (0x50 + (n)*4) /* 1 based indexing */ - -#define OHCI_LES (OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE) -#define OHCI_ALL_INTRS (OHCI_SO | OHCI_WDH | OHCI_SF | OHCI_RD | OHCI_UE | \ - OHCI_FNO | OHCI_RHSC | OHCI_OC) -#define OHCI_NORMAL_INTRS (OHCI_WDH | OHCI_RD | OHCI_UE | OHCI_RHSC) - -#define OHCI_FSMPS(i) (((i-210)*6/7) << 16) -#define OHCI_PERIODIC(i) ((i)*9/10) - -typedef u_int32_t ohci_physaddr_t; - -#define OHCI_NO_INTRS 32 -struct ohci_hcca { - ohci_physaddr_t hcca_interrupt_table[OHCI_NO_INTRS]; - u_int32_t hcca_frame_number; - ohci_physaddr_t hcca_done_head; -#define OHCI_DONE_INTRS 1 -}; -#define OHCI_HCCA_SIZE 256 -#define OHCI_HCCA_ALIGN 256 - -#define OHCI_PAGE_SIZE 0x1000 -#define OHCI_PAGE(x) ((x) &~ 0xfff) -#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff) -#define OHCI_PAGE_MASK(x) ((x) & 0xfff) - -typedef struct { - u_int32_t ed_flags; -#define OHCI_ED_GET_FA(s) ((s) & 0x7f) -#define OHCI_ED_ADDRMASK 0x0000007f -#define OHCI_ED_SET_FA(s) (s) -#define OHCI_ED_GET_EN(s) (((s) >> 7) & 0xf) -#define OHCI_ED_SET_EN(s) ((s) << 7) -#define OHCI_ED_DIR_MASK 0x00001800 -#define OHCI_ED_DIR_TD 0x00000000 -#define OHCI_ED_DIR_OUT 0x00000800 -#define OHCI_ED_DIR_IN 0x00001000 -#define OHCI_ED_SPEED 0x00002000 -#define OHCI_ED_SKIP 0x00004000 -#define OHCI_ED_FORMAT_GEN 0x00000000 -#define OHCI_ED_FORMAT_ISO 0x00008000 -#define OHCI_ED_GET_MAXP(s) (((s) >> 16) & 0x07ff) -#define OHCI_ED_SET_MAXP(s) ((s) << 16) -#define OHCI_ED_MAXPMASK (0x7ff << 16) - ohci_physaddr_t ed_tailp; - ohci_physaddr_t ed_headp; -#define OHCI_HALTED 0x00000001 -#define OHCI_TOGGLECARRY 0x00000002 -#define OHCI_HEADMASK 0xfffffffc - ohci_physaddr_t ed_nexted; -} ohci_ed_t; -/* #define OHCI_ED_SIZE 16 */ -#define OHCI_ED_ALIGN 16 - -typedef struct { - u_int32_t td_flags; -#define OHCI_TD_R 0x00040000 /* Buffer Rounding */ -#define OHCI_TD_DP_MASK 0x00180000 /* Direction / PID */ -#define OHCI_TD_SETUP 0x00000000 -#define OHCI_TD_OUT 0x00080000 -#define OHCI_TD_IN 0x00100000 -#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */ -#define OHCI_TD_SET_DI(x) ((x) << 21) -#define OHCI_TD_NOINTR 0x00e00000 -#define OHCI_TD_INTR_MASK 0x00e00000 -#define OHCI_TD_TOGGLE_CARRY 0x00000000 -#define OHCI_TD_TOGGLE_0 0x02000000 -#define OHCI_TD_TOGGLE_1 0x03000000 -#define OHCI_TD_TOGGLE_MASK 0x03000000 -#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */ -#define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */ -#define OHCI_TD_NOCC 0xf0000000 - ohci_physaddr_t td_cbp; /* Current Buffer Pointer */ - ohci_physaddr_t td_nexttd; /* Next TD */ - ohci_physaddr_t td_be; /* Buffer End */ -} ohci_td_t; -/* #define OHCI_TD_SIZE 16 */ -#define OHCI_TD_ALIGN 16 - -#define OHCI_ITD_NOFFSET 8 -typedef struct { - u_int32_t itd_flags; -#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff) -#define OHCI_ITD_SET_SF(x) ((x) & 0xffff) -#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */ -#define OHCI_ITD_SET_DI(x) ((x) << 21) -#define OHCI_ITD_NOINTR 0x00e00000 -#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */ -#define OHCI_ITD_SET_FC(x) (((x)-1) << 24) -#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */ -#define OHCI_ITD_NOCC 0xf0000000 - ohci_physaddr_t itd_bp0; /* Buffer Page 0 */ - ohci_physaddr_t itd_nextitd; /* Next ITD */ - ohci_physaddr_t itd_be; /* Buffer End */ - u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */ -#define itd_pswn itd_offset /* Packet Status Word*/ -#define OHCI_ITD_PAGE_SELECT 0x00001000 -#define OHCI_ITD_MK_OFFS(page, off) \ - (0xe000 | ((page) ? OHCI_ITD_PAGE_SELECT : 0) | ((off) & 0xfff)) -#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */ -#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */ -} ohci_itd_t; -/* #define OHCI_ITD_SIZE 32 */ -#define OHCI_ITD_ALIGN 32 - - -#define OHCI_CC_NO_ERROR 0 -#define OHCI_CC_CRC 1 -#define OHCI_CC_BIT_STUFFING 2 -#define OHCI_CC_DATA_TOGGLE_MISMATCH 3 -#define OHCI_CC_STALL 4 -#define OHCI_CC_DEVICE_NOT_RESPONDING 5 -#define OHCI_CC_PID_CHECK_FAILURE 6 -#define OHCI_CC_UNEXPECTED_PID 7 -#define OHCI_CC_DATA_OVERRUN 8 -#define OHCI_CC_DATA_UNDERRUN 9 -#define OHCI_CC_BUFFER_OVERRUN 12 -#define OHCI_CC_BUFFER_UNDERRUN 13 -#define OHCI_CC_NOT_ACCESSED 15 - -/* Some delay needed when changing certain registers. */ -#define OHCI_ENABLE_POWER_DELAY 5 -#define OHCI_READ_DESC_DELAY 5 - -#endif /* _DEV_PCI_OHCIREG_H_ */ diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h deleted file mode 100644 index 48f99e7..0000000 --- a/sys/dev/usb/ohcivar.h +++ /dev/null @@ -1,164 +0,0 @@ -/* $NetBSD: ohcivar.h,v 1.30 2001/12/31 12:20:35 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -typedef struct ohci_soft_ed { - ohci_ed_t ed; - struct ohci_soft_ed *next; - ohci_physaddr_t physaddr; -} ohci_soft_ed_t; -#define OHCI_SED_SIZE ((sizeof (struct ohci_soft_ed) + OHCI_ED_ALIGN - 1) / OHCI_ED_ALIGN * OHCI_ED_ALIGN) -#define OHCI_SED_CHUNK (PAGE_SIZE / OHCI_SED_SIZE) - -typedef struct ohci_soft_td { - ohci_td_t td; - struct ohci_soft_td *nexttd; /* mirrors nexttd in TD */ - struct ohci_soft_td *dnext; /* next in done list */ - ohci_physaddr_t physaddr; - LIST_ENTRY(ohci_soft_td) hnext; - usbd_xfer_handle xfer; - u_int16_t len; - u_int16_t flags; -#define OHCI_CALL_DONE 0x0001 -#define OHCI_ADD_LEN 0x0002 -} ohci_soft_td_t; -#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN) -#define OHCI_STD_CHUNK (PAGE_SIZE / OHCI_STD_SIZE) - -typedef struct ohci_soft_itd { - ohci_itd_t itd; - struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */ - struct ohci_soft_itd *dnext; /* next in done list */ - ohci_physaddr_t physaddr; - LIST_ENTRY(ohci_soft_itd) hnext; - usbd_xfer_handle xfer; - u_int16_t flags; -#define OHCI_ITD_ACTIVE 0x0010 /* Hardware op in progress */ -#define OHCI_ITD_INTFIN 0x0020 /* Hw completion interrupt seen.*/ -#ifdef DIAGNOSTIC - char isdone; -#endif -} ohci_soft_itd_t; -#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN) -#define OHCI_SITD_CHUNK (PAGE_SIZE / OHCI_SITD_SIZE) - -#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1) - -#define OHCI_HASH_SIZE 128 - -#define OHCI_SCFLG_DONEINIT 0x0001 /* ohci_init() done. */ - -typedef struct ohci_softc { - struct usbd_bus sc_bus; /* base device */ - int sc_flags; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - - void *ih; - - struct resource *io_res; - struct resource *irq_res; - - usb_dma_t sc_hccadma; - struct ohci_hcca *sc_hcca; - ohci_soft_ed_t *sc_eds[OHCI_NO_EDS]; - u_int sc_bws[OHCI_NO_INTRS]; - - u_int32_t sc_eintrs; /* enabled interrupts */ - - ohci_soft_ed_t *sc_isoc_head; - ohci_soft_ed_t *sc_ctrl_head; - ohci_soft_ed_t *sc_bulk_head; - - LIST_HEAD(, ohci_soft_td) sc_hash_tds[OHCI_HASH_SIZE]; - LIST_HEAD(, ohci_soft_itd) sc_hash_itds[OHCI_HASH_SIZE]; - - int sc_noport; - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - ohci_soft_ed_t *sc_freeeds; - ohci_soft_td_t *sc_freetds; - ohci_soft_itd_t *sc_freeitds; - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - usbd_xfer_handle sc_intrxfer; - - ohci_soft_itd_t *sc_sidone; - ohci_soft_td_t *sc_sdone; - - char sc_vendor[16]; - int sc_id_vendor; - -#if defined(__NetBSD__) || defined(__OpenBSD__) - void *sc_powerhook; /* cookie from power hook */ - void *sc_shutdownhook; /* cookie from shutdown hook */ -#endif - u_int32_t sc_control; /* Preserved during suspend/standby */ - u_int32_t sc_intre; - - u_int sc_overrun_cnt; - struct timeval sc_overrun_ntc; - - struct callout sc_tmo_rhsc; - char sc_dying; -} ohci_softc_t; - -struct ohci_xfer { - struct usbd_xfer xfer; - struct usb_task abort_task; - u_int32_t ohci_xfer_flags; -}; -#define OHCI_XFER_ABORTING 0x01 /* xfer is aborting. */ -#define OHCI_XFER_ABORTWAIT 0x02 /* abort completion is being awaited. */ - -#define OXFER(xfer) ((struct ohci_xfer *)(xfer)) -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -usbd_status ohci_init(ohci_softc_t *); -void ohci_intr(void *); -int ohci_detach(ohci_softc_t *, int); -void ohci_shutdown(void *v); -void ohci_power(int state, void *priv); diff --git a/sys/dev/usb/rio500_usb.h b/sys/dev/usb/rio500_usb.h deleted file mode 100644 index 5b53e2c..0000000 --- a/sys/dev/usb/rio500_usb.h +++ /dev/null @@ -1,48 +0,0 @@ -/*- - ---------------------------------------------------------------------- - - Copyright (C) 2000 Cesar Miquel (miquel@df.uba.ar) - - Redistribution and use in source and binary forms, with or without - modification, are permitted under any licence of your choise which - meets the open source licence definiton - http://www.opensource.org/opd.html such as the GNU licence or the - BSD licence. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License or the BSD license for more details. - - ---------------------------------------------------------------------- - - Modified for FreeBSD by Iwasa Kazmi <kzmi@ca2.so-net.ne.jp> - - ---------------------------------------------------------------------- */ - -/* $FreeBSD$ */ - -#include <sys/ioccom.h> -#ifndef USB_VENDOR_DIAMOND -#define USB_VENDOR_DIAMOND 0x841 -#endif -#ifndef USB_PRODUCT_DIAMOND_RIO500USB -#define USB_PRODUCT_DIAMOND_RIO500USB 0x1 -#endif - -struct RioCommand -{ - uint16_t length; - int request; - int requesttype; - int value; - int index; - void *buffer; - int timeout; -}; - -#define RIO_SEND_COMMAND _IOWR('U', 200, struct RioCommand) -#define RIO_RECV_COMMAND _IOWR('U', 201, struct RioCommand) - -#define RIO_DIR_OUT 0x0 -#define RIO_DIR_IN 0x1 diff --git a/sys/dev/usb/rt2573_ucode.h b/sys/dev/usb/rt2573_ucode.h deleted file mode 100644 index f2040f3..0000000 --- a/sys/dev/usb/rt2573_ucode.h +++ /dev/null @@ -1,213 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005-2006, Ralink Technology, Corp. - * Paul Lin <paul_lin@ralinktech.com.tw> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file contains the loadable 8051 microcode for the Ralink RT2573 - * chipset. - */ - -static const uint8_t rt2573_ucode[] = { - 0x02, 0x13, 0x25, 0x12, 0x10, 0xd9, 0x02, 0x12, 0x58, 0x02, 0x13, - 0x58, 0x02, 0x13, 0x5a, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0x12, 0x13, - 0x5c, 0xd0, 0xd0, 0x22, 0x02, 0x14, 0x5c, 0x02, 0x14, 0xe7, 0xed, - 0x4c, 0x70, 0x44, 0x90, 0x01, 0xa8, 0x74, 0x80, 0xf0, 0xef, 0x30, - 0xe5, 0x07, 0xe4, 0x90, 0x00, 0x0f, 0xf0, 0x80, 0x2c, 0xe5, 0x40, - 0x24, 0xc0, 0x60, 0x13, 0x24, 0xc0, 0x60, 0x16, 0x24, 0xc0, 0x60, - 0x19, 0x24, 0xc0, 0x70, 0x1a, 0xe4, 0x90, 0x00, 0x0b, 0xf0, 0x80, - 0x13, 0xe4, 0x90, 0x00, 0x13, 0xf0, 0x80, 0x0c, 0xe4, 0x90, 0x00, - 0x1b, 0xf0, 0x80, 0x05, 0xe4, 0x90, 0x00, 0x23, 0xf0, 0xe4, 0x90, - 0x01, 0xa8, 0xf0, 0xd3, 0x22, 0x90, 0x02, 0x02, 0xed, 0xf0, 0x90, - 0x02, 0x01, 0xef, 0xf0, 0xd3, 0x22, 0xef, 0x24, 0xc0, 0x60, 0x1f, - 0x24, 0xc0, 0x60, 0x2e, 0x24, 0xc0, 0x60, 0x3d, 0x24, 0xc0, 0x70, - 0x53, 0x90, 0x00, 0x0b, 0xe0, 0x30, 0xe1, 0x02, 0xc3, 0x22, 0x90, - 0x00, 0x09, 0xe0, 0xfe, 0x90, 0x00, 0x08, 0x80, 0x37, 0x90, 0x00, - 0x13, 0xe0, 0x30, 0xe1, 0x02, 0xc3, 0x22, 0x90, 0x00, 0x11, 0xe0, - 0xfe, 0x90, 0x00, 0x10, 0x80, 0x24, 0x90, 0x00, 0x1b, 0xe0, 0x30, - 0xe1, 0x02, 0xc3, 0x22, 0x90, 0x00, 0x19, 0xe0, 0xfe, 0x90, 0x00, - 0x18, 0x80, 0x11, 0x90, 0x00, 0x23, 0xe0, 0x30, 0xe1, 0x02, 0xc3, - 0x22, 0x90, 0x00, 0x21, 0xe0, 0xfe, 0x90, 0x00, 0x20, 0xe0, 0xfd, - 0xee, 0xf5, 0x37, 0xed, 0xf5, 0x38, 0xd3, 0x22, 0x30, 0x09, 0x20, - 0x20, 0x04, 0x0b, 0x90, 0x02, 0x08, 0xe0, 0x54, 0x0f, 0x70, 0x03, - 0x02, 0x12, 0x57, 0xc2, 0x09, 0x90, 0x02, 0x00, 0xe0, 0x44, 0x04, - 0xf0, 0x74, 0x04, 0x12, 0x0c, 0x3a, 0xc2, 0x04, 0xc2, 0x07, 0x90, - 0x02, 0x01, 0xe0, 0x30, 0xe0, 0x03, 0x00, 0x80, 0xf6, 0x90, 0x03, - 0x26, 0xe0, 0x20, 0xe2, 0x03, 0x02, 0x12, 0x57, 0x90, 0x02, 0x08, - 0xe0, 0x70, 0x1b, 0x20, 0x07, 0x03, 0x02, 0x12, 0x57, 0x90, 0x03, - 0x12, 0xe0, 0x64, 0x22, 0x60, 0x03, 0x02, 0x12, 0x57, 0xd2, 0x09, - 0xc2, 0x07, 0x74, 0x02, 0x12, 0x0c, 0x3a, 0x22, 0x90, 0x02, 0x03, - 0xe0, 0x30, 0xe4, 0x47, 0x20, 0x06, 0x44, 0xe5, 0x3c, 0x60, 0x34, - 0xe5, 0x40, 0x24, 0xc0, 0x60, 0x14, 0x24, 0xc0, 0x60, 0x18, 0x24, - 0xc0, 0x60, 0x1c, 0x24, 0xc0, 0x70, 0x22, 0x90, 0x00, 0x0b, 0xe0, - 0x30, 0xe1, 0x1b, 0x22, 0x90, 0x00, 0x13, 0xe0, 0x30, 0xe1, 0x13, - 0x22, 0x90, 0x00, 0x1b, 0xe0, 0x30, 0xe1, 0x0b, 0x22, 0x90, 0x00, - 0x23, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x12, 0x57, 0x90, 0x02, 0x03, - 0x74, 0x01, 0xf0, 0x00, 0xe0, 0x54, 0xc0, 0xf5, 0x40, 0xe5, 0x40, - 0x24, 0xc0, 0x60, 0x20, 0x24, 0xc0, 0x60, 0x30, 0x24, 0xc0, 0x60, - 0x40, 0x24, 0xc0, 0x70, 0x56, 0x90, 0x00, 0x0b, 0xe0, 0x30, 0xe1, - 0x03, 0x02, 0x12, 0x57, 0x90, 0x00, 0x09, 0xe0, 0xfe, 0x90, 0x00, - 0x08, 0x80, 0x3a, 0x90, 0x00, 0x13, 0xe0, 0x30, 0xe1, 0x03, 0x02, - 0x12, 0x57, 0x90, 0x00, 0x11, 0xe0, 0xfe, 0x90, 0x00, 0x10, 0x80, - 0x26, 0x90, 0x00, 0x1b, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x12, 0x57, - 0x90, 0x00, 0x19, 0xe0, 0xfe, 0x90, 0x00, 0x18, 0x80, 0x12, 0x90, - 0x00, 0x23, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x12, 0x57, 0x90, 0x00, - 0x21, 0xe0, 0xfe, 0x90, 0x00, 0x20, 0xe0, 0xfd, 0xee, 0xf5, 0x37, - 0xed, 0xf5, 0x38, 0x90, 0x03, 0x27, 0x74, 0x82, 0xf0, 0x90, 0x02, - 0x01, 0xe5, 0x40, 0xf0, 0x90, 0x02, 0x06, 0xe0, 0xf5, 0x3c, 0xc3, - 0xe5, 0x38, 0x95, 0x3a, 0xe5, 0x37, 0x95, 0x39, 0x50, 0x21, 0xe5, - 0x40, 0x44, 0x05, 0xff, 0xe5, 0x37, 0xa2, 0xe7, 0x13, 0xfc, 0xe5, - 0x38, 0x13, 0xfd, 0x12, 0x10, 0x20, 0xe5, 0x3c, 0x30, 0xe2, 0x04, - 0xd2, 0x06, 0x80, 0x02, 0xc2, 0x06, 0x53, 0x3c, 0x01, 0x22, 0x30, - 0x0b, 0x07, 0xe4, 0x90, 0x02, 0x02, 0xf0, 0x80, 0x06, 0x90, 0x02, - 0x02, 0x74, 0x20, 0xf0, 0xe5, 0x40, 0x44, 0x01, 0x90, 0x02, 0x01, - 0xf0, 0x90, 0x02, 0x01, 0xe0, 0x30, 0xe0, 0x03, 0x00, 0x80, 0xf6, - 0x90, 0x03, 0x27, 0x74, 0x02, 0xf0, 0xaf, 0x40, 0x12, 0x10, 0x74, - 0x40, 0xa5, 0x00, 0x80, 0xf6, 0x22, 0x90, 0x7f, 0xf8, 0xe0, 0xb4, - 0x02, 0x03, 0x12, 0x16, 0x38, 0x90, 0x02, 0x01, 0xe0, 0x30, 0xe0, - 0x03, 0x00, 0x80, 0xf6, 0x90, 0x03, 0x26, 0xe0, 0x20, 0xe1, 0x07, - 0xe5, 0x3b, 0x70, 0x03, 0x02, 0x13, 0x24, 0xe5, 0x3b, 0x70, 0x15, - 0x90, 0x03, 0x24, 0xe0, 0x75, 0xf0, 0x40, 0xa4, 0xf5, 0x36, 0x85, - 0xf0, 0x35, 0x75, 0x24, 0x83, 0x75, 0x3b, 0x01, 0x80, 0x03, 0x75, - 0x24, 0x03, 0xd3, 0xe5, 0x36, 0x95, 0x3a, 0xe5, 0x35, 0x95, 0x39, - 0x40, 0x36, 0x90, 0x02, 0x01, 0xe0, 0x30, 0xe0, 0x03, 0x00, 0x80, - 0xf6, 0x90, 0x03, 0x27, 0xe5, 0x24, 0xf0, 0x90, 0x00, 0x0f, 0xe0, - 0x30, 0xe1, 0x04, 0x30, 0x0e, 0xf6, 0x22, 0x30, 0x0b, 0x07, 0xe4, - 0x90, 0x02, 0x02, 0xf0, 0x80, 0x06, 0x90, 0x02, 0x02, 0x74, 0x20, - 0xf0, 0x90, 0x02, 0x01, 0x74, 0x21, 0xf0, 0x75, 0x24, 0x03, 0x80, - 0x3d, 0xe5, 0x35, 0xa2, 0xe7, 0x13, 0xfe, 0xe5, 0x36, 0x13, 0xfd, - 0xac, 0x06, 0x90, 0x02, 0x01, 0xe0, 0x30, 0xe0, 0x03, 0x00, 0x80, - 0xf6, 0x90, 0x03, 0x27, 0xe5, 0x24, 0xf0, 0x90, 0x00, 0x0f, 0xe0, - 0x30, 0xe1, 0x04, 0x30, 0x0e, 0xf6, 0x22, 0x7f, 0x25, 0x12, 0x10, - 0x20, 0xe5, 0x36, 0xb5, 0x3a, 0x08, 0xe5, 0x35, 0xb5, 0x39, 0x03, - 0x00, 0x80, 0x04, 0xe4, 0xf5, 0x3b, 0x22, 0xc3, 0xe5, 0x36, 0x95, - 0x3a, 0xf5, 0x36, 0xe5, 0x35, 0x95, 0x39, 0xf5, 0x35, 0x02, 0x12, - 0x96, 0x22, 0x75, 0xa8, 0x0f, 0x90, 0x03, 0x06, 0x74, 0x01, 0xf0, - 0x90, 0x03, 0x07, 0xf0, 0x90, 0x03, 0x08, 0x04, 0xf0, 0x90, 0x03, - 0x09, 0x74, 0x6c, 0xf0, 0x90, 0x03, 0x0a, 0x74, 0xff, 0xf0, 0x90, - 0x03, 0x02, 0x74, 0x1f, 0xf0, 0x90, 0x03, 0x00, 0x74, 0x04, 0xf0, - 0x90, 0x03, 0x25, 0x74, 0x31, 0xf0, 0xd2, 0xaf, 0x22, 0x00, 0x22, - 0x00, 0x22, 0x90, 0x03, 0x05, 0xe0, 0x30, 0xe0, 0x0b, 0xe0, 0x44, - 0x01, 0xf0, 0x30, 0x09, 0x02, 0xd2, 0x04, 0xc2, 0x07, 0x22, 0x8d, - 0x24, 0xa9, 0x07, 0x90, 0x7f, 0xfc, 0xe0, 0x75, 0x25, 0x00, 0xf5, - 0x26, 0xa3, 0xe0, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xa3, 0xe0, 0xff, - 0xa3, 0xe0, 0xfd, 0xe9, 0x30, 0xe5, 0x14, 0x54, 0xc0, 0x60, 0x05, - 0x43, 0x05, 0x03, 0x80, 0x03, 0x53, 0x05, 0xfc, 0xef, 0x54, 0x3f, - 0x44, 0x40, 0xff, 0x80, 0x06, 0x53, 0x07, 0x3f, 0x53, 0x05, 0xf0, - 0xe5, 0x24, 0x30, 0xe0, 0x05, 0x43, 0x05, 0x10, 0x80, 0x03, 0x53, - 0x05, 0xef, 0x90, 0x7f, 0xfc, 0xe5, 0x26, 0xf0, 0xa3, 0xe5, 0x28, - 0xf0, 0xa3, 0xef, 0xf0, 0xa3, 0xed, 0xf0, 0x22, 0x8f, 0x24, 0xa9, - 0x05, 0x90, 0x7f, 0xfc, 0xe0, 0x75, 0x25, 0x00, 0xf5, 0x26, 0xa3, - 0xe0, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, - 0xfd, 0xe5, 0x24, 0x30, 0xe5, 0x0b, 0x43, 0x05, 0x0f, 0xef, 0x54, - 0x3f, 0x44, 0x40, 0xff, 0x80, 0x06, 0x53, 0x05, 0xf0, 0x53, 0x07, - 0x3f, 0xe9, 0x30, 0xe0, 0x05, 0x43, 0x05, 0x10, 0x80, 0x03, 0x53, - 0x05, 0xef, 0x90, 0x7f, 0xfc, 0xe5, 0x26, 0xf0, 0xa3, 0xe5, 0x28, - 0xf0, 0xa3, 0xef, 0xf0, 0xa3, 0xed, 0xf0, 0x22, 0x90, 0x7f, 0xfc, - 0xe0, 0xf9, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfb, - 0xef, 0x30, 0xe5, 0x0b, 0x43, 0x03, 0x0f, 0xec, 0x54, 0x3f, 0x44, - 0x40, 0xfc, 0x80, 0x06, 0x53, 0x03, 0xf0, 0x53, 0x04, 0x3f, 0xed, - 0x30, 0xe0, 0x07, 0xef, 0x54, 0xc0, 0x60, 0x07, 0x80, 0x0a, 0xef, - 0x54, 0xc0, 0x60, 0x05, 0x43, 0x03, 0x10, 0x80, 0x03, 0x53, 0x03, - 0xef, 0x90, 0x7f, 0xfc, 0xe9, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xec, - 0xf0, 0xa3, 0xeb, 0xf0, 0x22, 0xe5, 0x4b, 0xfd, 0x54, 0x1f, 0x90, - 0x7f, 0xf8, 0xf0, 0xe5, 0x4a, 0xf5, 0x09, 0x90, 0x30, 0x38, 0xe0, - 0x90, 0x7f, 0xfc, 0xf0, 0x90, 0x30, 0x39, 0xe0, 0x90, 0x7f, 0xfd, - 0xf0, 0x90, 0x30, 0x3a, 0xe0, 0x90, 0x7f, 0xfe, 0xf0, 0x90, 0x30, - 0x3b, 0xe0, 0x90, 0x7f, 0xff, 0xf0, 0xed, 0x30, 0xe5, 0x0c, 0x54, - 0xc0, 0x60, 0x0d, 0x90, 0x7f, 0xf0, 0xe5, 0x47, 0xf0, 0x80, 0x05, - 0xe4, 0x90, 0x7f, 0xf0, 0xf0, 0x90, 0x7f, 0xf8, 0xe0, 0x14, 0x60, - 0x08, 0x24, 0xfe, 0x60, 0x0d, 0x24, 0x03, 0x80, 0x12, 0xaf, 0x05, - 0xad, 0x09, 0x12, 0x13, 0xc5, 0x80, 0x10, 0xaf, 0x05, 0xad, 0x09, - 0x12, 0x14, 0x12, 0x80, 0x07, 0xaf, 0x05, 0xad, 0x09, 0x12, 0x13, - 0x6f, 0x90, 0x7f, 0xfc, 0xe0, 0x90, 0x30, 0x38, 0xf0, 0x90, 0x7f, - 0xfd, 0xe0, 0x90, 0x30, 0x39, 0xf0, 0x90, 0x7f, 0xfe, 0xe0, 0x90, - 0x30, 0x3a, 0xf0, 0x90, 0x7f, 0xff, 0xe0, 0x90, 0x30, 0x3b, 0xf0, - 0x22, 0xe5, 0x4b, 0x64, 0x01, 0x60, 0x03, 0x02, 0x15, 0x71, 0xf5, - 0x4b, 0xe5, 0x44, 0x45, 0x43, 0x70, 0x03, 0x02, 0x15, 0xa0, 0x12, - 0x0c, 0x14, 0x12, 0x0b, 0x86, 0x50, 0xfb, 0x90, 0x00, 0x00, 0xe0, - 0xf5, 0x25, 0x12, 0x15, 0xb4, 0xc2, 0x92, 0xe4, 0xf5, 0x24, 0xe5, - 0x24, 0xc3, 0x95, 0x25, 0x50, 0x49, 0x7e, 0x00, 0x7f, 0x4c, 0x74, - 0x40, 0x25, 0x24, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xad, 0x82, 0xfc, - 0x75, 0x2b, 0x02, 0x7b, 0x10, 0x12, 0x07, 0x1e, 0xc2, 0x93, 0x12, - 0x15, 0xa1, 0x7d, 0xa0, 0x12, 0x15, 0xd0, 0xe5, 0x24, 0x54, 0x0f, - 0x24, 0x4c, 0xf8, 0xe6, 0xfd, 0xaf, 0x4b, 0xae, 0x4a, 0x12, 0x15, - 0xd8, 0x05, 0x4b, 0xe5, 0x4b, 0x70, 0x02, 0x05, 0x4a, 0x12, 0x0a, - 0x5f, 0x05, 0x24, 0xe5, 0x24, 0x54, 0x0f, 0x70, 0xd5, 0xd2, 0x93, - 0x80, 0xb0, 0xc3, 0xe5, 0x44, 0x95, 0x25, 0xf5, 0x44, 0xe5, 0x43, - 0x94, 0x00, 0xf5, 0x43, 0x02, 0x14, 0xf2, 0x12, 0x15, 0xb4, 0xc2, - 0x93, 0xc2, 0x92, 0x12, 0x15, 0xa1, 0x7d, 0x80, 0x12, 0x15, 0xd0, - 0x7d, 0xaa, 0x74, 0x55, 0xff, 0xfe, 0x12, 0x15, 0xd8, 0x7d, 0x55, - 0x7f, 0xaa, 0x7e, 0x2a, 0x12, 0x15, 0xd8, 0x7d, 0x30, 0xaf, 0x4b, - 0xae, 0x4a, 0x12, 0x15, 0xd8, 0x12, 0x0a, 0x5f, 0xd2, 0x93, 0x22, - 0x7d, 0xaa, 0x74, 0x55, 0xff, 0xfe, 0x12, 0x15, 0xd8, 0x7d, 0x55, - 0x7f, 0xaa, 0x7e, 0x2a, 0x12, 0x15, 0xd8, 0x22, 0xad, 0x47, 0x7f, - 0x34, 0x7e, 0x30, 0x12, 0x15, 0xd8, 0x7d, 0xff, 0x7f, 0x35, 0x7e, - 0x30, 0x12, 0x15, 0xd8, 0xe4, 0xfd, 0x7f, 0x37, 0x7e, 0x30, 0x12, - 0x15, 0xd8, 0x22, 0x74, 0x55, 0xff, 0xfe, 0x12, 0x15, 0xd8, 0x22, - 0x8f, 0x82, 0x8e, 0x83, 0xed, 0xf0, 0x22, 0xe4, 0xfc, 0x90, 0x7f, - 0xf0, 0xe0, 0xaf, 0x09, 0x14, 0x60, 0x14, 0x14, 0x60, 0x15, 0x14, - 0x60, 0x16, 0x14, 0x60, 0x17, 0x14, 0x60, 0x18, 0x24, 0x05, 0x70, - 0x16, 0xe4, 0xfc, 0x80, 0x12, 0x7c, 0x01, 0x80, 0x0e, 0x7c, 0x03, - 0x80, 0x0a, 0x7c, 0x07, 0x80, 0x06, 0x7c, 0x0f, 0x80, 0x02, 0x7c, - 0x1f, 0xec, 0x6f, 0xf4, 0x54, 0x1f, 0xfc, 0x90, 0x30, 0x34, 0xe0, - 0x54, 0xe0, 0x4c, 0xfd, 0xa3, 0xe0, 0xfc, 0x43, 0x04, 0x1f, 0x7f, - 0x34, 0x7e, 0x30, 0x12, 0x15, 0xd8, 0xad, 0x04, 0x0f, 0x12, 0x15, - 0xd8, 0xe4, 0xfd, 0x7f, 0x37, 0x02, 0x15, 0xd8, 0x02, 0x15, 0xdf, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, - 0x29, 0xe9 -}; diff --git a/sys/dev/usb/sl811hs.c b/sys/dev/usb/sl811hs.c deleted file mode 100644 index 3620d5f..0000000 --- a/sys/dev/usb/sl811hs.c +++ /dev/null @@ -1,1654 +0,0 @@ -/* $NetBSD: sl811hs.c,v 1.5 2005/02/27 00:27:02 perry Exp $ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Tetsuya Isaki. - * - * 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. - */ - - -/* - * ScanLogic SL811HS/T USB Host Controller - */ -/* - * !! HIGHLY EXPERIMENTAL CODE !! - */ - -#include <sys/cdefs.h> -//_RCSID(0, "$NetBSD: sl811hs.c,v 1.5 2005/02/27 00:27:02 perry Exp $"); - -#include "opt_slhci.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/bus.h> -#include <sys/malloc.h> - -#include <machine/bus.h> -#include <machine/cpu.h> -#include <sys/module.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_port.h> -#include "usbdevs.h" - -#include <dev/usb/sl811hsreg.h> -#include <dev/usb/sl811hsvar.h> - -__FBSDID("$FreeBSD$"); - -static inline u_int8_t sl11read(struct slhci_softc *, int); -static inline void sl11write(struct slhci_softc *, int, u_int8_t); -static inline void sl11read_region(struct slhci_softc *, u_char *, int, int); -static inline void sl11write_region(struct slhci_softc *, int, u_char *, int); - -static void sl11_reset(struct slhci_softc *); -static void sl11_speed(struct slhci_softc *); - -static usbd_status slhci_open(usbd_pipe_handle); -static void slhci_softintr(void *); -static void slhci_poll(struct usbd_bus *); -static void slhci_poll_hub(void *); -static void slhci_poll_device(void *arg); -static usbd_status slhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void slhci_freem(struct usbd_bus *, usb_dma_t *); -static usbd_xfer_handle slhci_allocx(struct usbd_bus *); -static void slhci_freex(struct usbd_bus *, usbd_xfer_handle); - -static int slhci_str(usb_string_descriptor_t *, int, const char *); - -static usbd_status slhci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status slhci_root_ctrl_start(usbd_xfer_handle); -static void slhci_root_ctrl_abort(usbd_xfer_handle); -static void slhci_root_ctrl_close(usbd_pipe_handle); -static void slhci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status slhci_root_intr_transfer(usbd_xfer_handle); -static usbd_status slhci_root_intr_start(usbd_xfer_handle); -static void slhci_root_intr_abort(usbd_xfer_handle); -static void slhci_root_intr_close(usbd_pipe_handle); -static void slhci_root_intr_done(usbd_xfer_handle); - -static usbd_status slhci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status slhci_device_ctrl_start(usbd_xfer_handle); -static void slhci_device_ctrl_abort(usbd_xfer_handle); -static void slhci_device_ctrl_close(usbd_pipe_handle); -static void slhci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status slhci_device_intr_transfer(usbd_xfer_handle); -static usbd_status slhci_device_intr_start(usbd_xfer_handle); -static void slhci_device_intr_abort(usbd_xfer_handle); -static void slhci_device_intr_close(usbd_pipe_handle); -static void slhci_device_intr_done(usbd_xfer_handle); - -static usbd_status slhci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status slhci_device_isoc_start(usbd_xfer_handle); -static void slhci_device_isoc_abort(usbd_xfer_handle); -static void slhci_device_isoc_close(usbd_pipe_handle); -static void slhci_device_isoc_done(usbd_xfer_handle); - -static usbd_status slhci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status slhci_device_bulk_start(usbd_xfer_handle); -static void slhci_device_bulk_abort(usbd_xfer_handle); -static void slhci_device_bulk_close(usbd_pipe_handle); -static void slhci_device_bulk_done(usbd_xfer_handle); - -static int slhci_transaction(struct slhci_softc *, - usbd_pipe_handle, u_int8_t, int, u_char *, u_int8_t); -static void slhci_noop(usbd_pipe_handle); -static void slhci_abort_xfer(usbd_xfer_handle, usbd_status); -static void slhci_device_clear_toggle(usbd_pipe_handle); - -extern int usbdebug; - -/* For root hub */ -#define SLHCI_INTR_ENDPT (1) - -#ifdef SLHCI_DEBUG -#define D_TRACE (0x0001) /* function trace */ -#define D_MSG (0x0002) /* debug messages */ -#define D_XFER (0x0004) /* transfer messages (noisy!) */ -#define D_MEM (0x0008) /* memory allocation */ - -int slhci_debug = D_MSG | D_XFER; -#define DPRINTF(z,x) if((slhci_debug&(z))!=0)printf x -void print_req(usb_device_request_t *); -void print_req_hub(usb_device_request_t *); -void print_dumpreg(struct slhci_softc *); -void print_xfer(usbd_xfer_handle); -#else -#define DPRINTF(z,x) -#endif - - -/* XXX: sync with argument */ -static const char *sltypestr [] = { - "SL11H/T", - "SL811HS/T", -}; - - -struct usbd_bus_methods slhci_bus_methods = { - slhci_open, - slhci_softintr, - slhci_poll, - slhci_allocm, - slhci_freem, - slhci_allocx, - slhci_freex, -}; - -struct usbd_pipe_methods slhci_root_ctrl_methods = { - slhci_root_ctrl_transfer, - slhci_root_ctrl_start, - slhci_root_ctrl_abort, - slhci_root_ctrl_close, - slhci_noop, - slhci_root_ctrl_done, -}; - -struct usbd_pipe_methods slhci_root_intr_methods = { - slhci_root_intr_transfer, - slhci_root_intr_start, - slhci_root_intr_abort, - slhci_root_intr_close, - slhci_noop, - slhci_root_intr_done, -}; - -struct usbd_pipe_methods slhci_device_ctrl_methods = { - slhci_device_ctrl_transfer, - slhci_device_ctrl_start, - slhci_device_ctrl_abort, - slhci_device_ctrl_close, - slhci_noop, - slhci_device_ctrl_done, -}; - -struct usbd_pipe_methods slhci_device_intr_methods = { - slhci_device_intr_transfer, - slhci_device_intr_start, - slhci_device_intr_abort, - slhci_device_intr_close, - slhci_device_clear_toggle, - slhci_device_intr_done, -}; - -struct usbd_pipe_methods slhci_device_isoc_methods = { - slhci_device_isoc_transfer, - slhci_device_isoc_start, - slhci_device_isoc_abort, - slhci_device_isoc_close, - slhci_noop, - slhci_device_isoc_done, -}; - -struct usbd_pipe_methods slhci_device_bulk_methods = { - slhci_device_bulk_transfer, - slhci_device_bulk_start, - slhci_device_bulk_abort, - slhci_device_bulk_close, - slhci_noop, - slhci_device_bulk_done, -}; - -struct slhci_pipe { - struct usbd_pipe pipe; -}; - - -/* - * SL811HS Register read/write routine - */ -static inline u_int8_t -sl11read(struct slhci_softc *sc, int reg) -{ -#if 1 - int b; - DELAY(80); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg); - b = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA); - return b; -#else - outb(0x4000, reg&0xff); - return (inb(0x4001)&0xff); -#endif -} - -static inline void -sl11write(struct slhci_softc *sc, int reg, u_int8_t data) -{ -#if 1 - DELAY(80); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg); - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, data); -#else - outb(0x4000, reg&0xff); - outb(0x4000, data&0xff); -#endif -} - -static inline void -sl11read_region(struct slhci_softc *sc, u_char *buf, int reg, int len) -{ - int i; - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg); - for (i = 0; i < len; i++) - buf[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA); -} - -static inline void -sl11write_region(struct slhci_softc *sc, int reg, u_char *buf, int len) -{ - int i; - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_ADDR, reg); - for (i = 0; i < len; i++) - bus_space_write_1(sc->sc_iot, sc->sc_ioh, SL11_IDX_DATA, buf[i]); -} - -/* - * USB bus reset. From sl811hs_appnote.pdf, p22 - */ -static void -sl11_reset(struct slhci_softc *sc) -{ - u_int8_t r; - - DPRINTF(D_TRACE, ("%s() ", __FUNCTION__)); - // r = sl11read(sc, SL11_CTRL); - r = 0; - sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE); - delay_ms(250); - sl11write(sc, SL11_CTRL, r | SL11_CTRL_JKSTATE | SL11_CTRL_RESETENGINE); delay_ms(150); - sl11write(sc, SL11_CTRL, r | SL11_CTRL_RESETENGINE); - delay_ms(10); - sl11write(sc, SL11_CTRL, r); -} - -/* - * Detect the speed of attached device. - */ -static void -sl11_speed(struct slhci_softc *sc) -{ - u_int8_t r; - - sl11write(sc, SL11_ISR, 0xff); - r = sl11read(sc, SL11_ISR); - if ((r & SL11_ISR_RESET)) { - DPRINTF(D_MSG, ("NC ")); - sl11write(sc, SL11_ISR, SL11_ISR_RESET); - sc->sc_connect = 0; - } - - if ((sl11read(sc, SL11_ISR) & SL11_ISR_RESET)) { - sl11write(sc, SL11_ISR, 0xff); - } else { - u_int8_t pol = 0, ctrl = 0; - - sc->sc_connect = 1; - if (r & SL11_ISR_DATA) { - DPRINTF(D_MSG, ("FS ")); - pol = 0; - ctrl = SL11_CTRL_EOF2; - sc->sc_fullspeed = 1; - } else { - DPRINTF(D_MSG, ("LS ")); - pol = SL811_CSOF_POLARITY; - ctrl = SL11_CTRL_LOWSPEED; - sc->sc_fullspeed = 0; - } - sl11write(sc, SL811_CSOF, pol | SL811_CSOF_MASTER | 0x2e); - sl11write(sc, SL11_DATA, 0xe0); - sl11write(sc, SL11_CTRL, ctrl | SL11_CTRL_ENABLESOF); - } - - sl11write(sc, SL11_E0PID, (SL11_PID_SOF << 4) + 0); - sl11write(sc, SL11_E0DEV, 0); - sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM); - delay_ms(30); -} - -/* - * If detect some known controller, return the type. - * If does not, return -1. - */ -int -sl811hs_find(struct slhci_softc *sc) -{ - int rev; - sc->sc_sltype = -1; - - rev = sl11read(sc, SL11_REV) >> 4; - if (rev >= SLTYPE_SL11H && rev <= SLTYPE_SL811HS_R14) - sc->sc_sltype = rev; - return sc->sc_sltype; -} - -/* - * Attach SL11H/SL811HS. Return 0 if success. - */ -int -slhci_attach(struct slhci_softc *sc) -{ - int rev; - /* Detect and check the controller type */ - - rev = sl811hs_find(sc); - if (rev == -1) - return -1; - - printf("%s: ScanLogic %s USB Host Controller", - device_get_nameunit(sc->sc_bus.bdev), sltypestr[(rev > 0)]); - switch (rev) { - case SLTYPE_SL11H: - break; - case SLTYPE_SL811HS_R12: - printf(" (rev 1.2)"); - break; - case SLTYPE_SL811HS_R14: - printf(" (rev 1.4)"); - break; - default: - printf(" (unknown revision)"); - break; - } - printf("\n"); - - - /* Initialize sc */ - sc->sc_bus.usbrev = USBREV_1_1; - sc->sc_bus.methods = &slhci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct slhci_pipe); - sc->sc_bus.parent_dmatag = NULL; /* XXX */ - sc->sc_bus.buffer_dmatag = NULL; /* XXX */ - STAILQ_INIT(&sc->sc_free_xfers); - - usb_callout_init(sc->sc_poll_handle); - - /* Disable interrupt, then wait 40msec */ - sl11write(sc, SL11_IER, 0x00); - delay_ms(40); - - /* Initialize controller */ - sl11write(sc, SL811_CSOF, SL811_CSOF_MASTER | 0x2e); - delay_ms(40); - - sl11write(sc, SL11_ISR, 0xff); - - /* Disable interrupt, then wait 40msec */ - sl11write(sc, SL11_IER, 0x00); - - /* Reset USB engine */ - sl11write(sc, SL11_CTRL, SL11_CTRL_JKSTATE| SL11_CTRL_RESETENGINE); - delay_ms(40); - sl11write(sc, SL11_CTRL, 0x00); - delay_ms(10); - - /* USB Bus reset for GET_PORT_STATUS */ - sl11_reset(sc); - sc->sc_flags = SLF_ATTACHED; - - /* Enable interrupt */ - sl11write(sc, SL11_IER, SL11_IER_INSERT); - /* x68k Nereid USB controller needs it */ - if (sc->sc_enable_intr) - sc->sc_enable_intr(sc->sc_arg, INTR_ON); -#ifdef USB_DEBUG - usbdebug = 0; -#endif - - return 0; -} - -int -slhci_intr(void *arg) -{ - struct slhci_softc *sc = arg; - u_int8_t r; -#ifdef SLHCI_DEBUG - char bitbuf[256]; -#endif - - - if((sc->sc_flags & SLF_ATTACHED) == 0) - return 0; - - r = sl11read(sc, SL11_ISR); - - - - sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER); - - if ((r & SL11_ISR_RESET)) { - sc->sc_flags |= SLF_RESET; - sl11write(sc, SL11_ISR, SL11_ISR_RESET); - } - if ((r & SL11_ISR_INSERT)) { - sc->sc_flags |= SLF_INSERT; - sl11write(sc, SL11_ISR, SL11_ISR_INSERT); - } - -#ifdef SLHCI_DEBUG - bitmask_snprintf(r, - (sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND) - ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA" - : "\20\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA", - bitbuf, sizeof(bitbuf)); - DPRINTF(D_XFER, ("I=%s ", bitbuf)); -#endif /* SLHCI_DEBUG */ - - return 0; -} - -usbd_status -slhci_open(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - struct slhci_softc *sc = (struct slhci_softc *)dev->bus; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - - DPRINTF(D_TRACE, ("slhci_open(addr=%d,ep=%d,scaddr=%d)", - dev->address, ed->bEndpointAddress, sc->sc_addr)); - - if (dev->address == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &slhci_root_ctrl_methods; - break; - case UE_DIR_IN | SLHCI_INTR_ENDPT: - pipe->methods = &slhci_root_intr_methods; - break; - default: - printf("open:endpointErr!\n"); - return USBD_INVAL; - } - } else { - switch (ed->bmAttributes & UE_XFERTYPE) { - case UE_CONTROL: - DPRINTF(D_MSG, ("control ")); - pipe->methods = &slhci_device_ctrl_methods; - break; - case UE_INTERRUPT: - DPRINTF(D_MSG, ("interrupt ")); - pipe->methods = &slhci_device_intr_methods; - break; - case UE_ISOCHRONOUS: - DPRINTF(D_MSG, ("isochronous ")); - pipe->methods = &slhci_device_isoc_methods; - break; - case UE_BULK: - DPRINTF(D_MSG, ("bluk ")); - pipe->methods = &slhci_device_bulk_methods; - break; - } - } - return USBD_NORMAL_COMPLETION; -} - -void -slhci_softintr(void *arg) -{ - DPRINTF(D_TRACE, ("%s()", __FUNCTION__)); -} - -void -slhci_poll(struct usbd_bus *bus) -{ - DPRINTF(D_TRACE, ("%s()", __FUNCTION__)); -} - -/* - * Emulation of interrupt transfer for status change endpoint - * of root hub. - */ -void -slhci_poll_hub(void *arg) -{ - usbd_xfer_handle xfer = arg; - usbd_pipe_handle pipe = xfer->pipe; - struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; - int s; - u_char *p; - - usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer); - - /* USB spec 11.13.3 (p.260) */ - p = xfer->buffer; - p[0] = 0; - if ((sc->sc_flags & (SLF_INSERT | SLF_RESET))) { - p[0] = 2; - DPRINTF(D_TRACE, ("!")); - } - - /* no change, return NAK */ - if (p[0] == 0) - return; - - xfer->actlen = 1; - xfer->status = USBD_NORMAL_COMPLETION; - s = splusb(); - xfer->device->bus->intr_context++; - usb_transfer_complete(xfer); - xfer->device->bus->intr_context--; - splx(s); -} - -usbd_status -slhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - struct slhci_softc *sc = (struct slhci_softc *)bus; - - DPRINTF(D_MEM, ("SLallocm")); - return usb_allocmem(&sc->sc_bus, size, 0, dma); -} - -void -slhci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - struct slhci_softc *sc = (struct slhci_softc *)bus; - - DPRINTF(D_MEM, ("SLfreem")); - usb_freemem(&sc->sc_bus, dma); -} - -usbd_xfer_handle -slhci_allocx(struct usbd_bus *bus) -{ - struct slhci_softc *sc = (struct slhci_softc *)bus; - usbd_xfer_handle xfer; - - DPRINTF(D_MEM, ("SLallocx")); - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_FREE) { - printf("slhci_allocx: xfer=%p not free, 0x%08x\n", - xfer, xfer->busy_free); - } -#endif - } else { - xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT); - } - - if (xfer) { - memset(xfer, 0, sizeof(*xfer)); -#ifdef DIAGNOSTIC - xfer->busy_free = XFER_BUSY; -#endif - } - - return xfer; -} - -void -slhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct slhci_softc *sc = (struct slhci_softc *)bus; - - DPRINTF(D_MEM, ("SLfreex")); - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("slhci_freex: xfer=%p not busy, 0x%08x\n", - xfer, xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; -#endif - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -void -slhci_noop(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("%s()", __FUNCTION__)); -} - -/* - * Data structures and routines to emulate the root hub. - */ -usb_device_descriptor_t slhci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x01, 0x01}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - 0, /* protocol */ - 64, /* max packet */ - {USB_VENDOR_SCANLOGIC & 0xff, /* vendor ID (low) */ - USB_VENDOR_SCANLOGIC >> 8 }, /* vendor ID (high) */ - {0} /* ? */, /* product ID */ - {0}, /* device */ - 1, /* index to manufacturer */ - 2, /* index to product */ - 0, /* index to serial number */ - 1 /* number of configurations */ -}; - -usb_config_descriptor_t slhci_confd = { - USB_CONFIG_DESCRIPTOR_SIZE, - UDESC_CONFIG, - {USB_CONFIG_DESCRIPTOR_SIZE + - USB_INTERFACE_DESCRIPTOR_SIZE + - USB_ENDPOINT_DESCRIPTOR_SIZE}, - 1, /* number of interfaces */ - 1, /* configuration value */ - 0, /* index to configuration */ - UC_SELF_POWERED, /* attributes */ - 15 /* max current is 30mA... */ -}; - -usb_interface_descriptor_t slhci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, /* interface number */ - 0, /* alternate setting */ - 1, /* number of endpoint */ - UICLASS_HUB, /* class */ - UISUBCLASS_HUB, /* subclass */ - 0, /* protocol */ - 0 /* index to interface */ -}; - -usb_endpoint_descriptor_t slhci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | SLHCI_INTR_ENDPT, /* endpoint address */ - UE_INTERRUPT, /* attributes */ - {8}, /* max packet size */ - 255 /* interval */ -}; - -usb_hub_descriptor_t slhci_hubd = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 1, /* number of ports */ - {UHD_PWR_INDIVIDUAL | UHD_OC_NONE, 0}, /* hub characteristics */ - 20 /* ? */, /* 5:power on to power good */ - 50, /* 6:maximum current */ - { 0x00 }, /* both ports are removable */ - { 0x00 } /* port power control mask */ -}; - -static int -slhci_str(usb_string_descriptor_t *p, int l, const 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; -} - -usbd_status -slhci_root_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status error; - - DPRINTF(D_TRACE, ("SLRCtrans ")); - - /* Insert last in queue */ - error = usb_insert_transfer(xfer); - if (error) { - DPRINTF(D_MSG, ("usb_insert_transfer returns err! ")); - return error; - } - - /* - * Pipe isn't running (otherwise error would be USBD_INPROG), - * so start it first. - */ - return slhci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue)); -} - -usbd_status -slhci_root_ctrl_start(usbd_xfer_handle xfer) -{ - struct slhci_softc *sc = (struct slhci_softc *)xfer->pipe->device->bus; - usb_device_request_t *req; - int len, value, index, l, s, status; - int totlen = 0; - void *buf = NULL; - usb_port_status_t ps; - usbd_status error; - char slbuf[50]; - u_int8_t r; - - DPRINTF(D_TRACE, ("SLRCstart ")); - - req = &xfer->request; - - len = UGETW(req->wLength); - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - if (len) - buf = xfer->buffer; - -#ifdef SLHCI_DEBUG - if ((slhci_debug & D_TRACE)) - print_req_hub(req); -#endif - -#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): - DPRINTF(D_MSG, ("UR_CLEAR_FEATURE ")); - break; - case C(UR_GET_CONFIG, UT_READ_DEVICE): - DPRINTF(D_MSG, ("UR_GET_CONFIG ")); - if (len > 0) { - *(u_int8_t *)buf = sc->sc_conf; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): - switch (value >> 8) { - case UDESC_DEVICE: - DPRINTF(D_MSG, ("UDESC_DEVICE ")); - if ((value & 0xff) != 0) { - error = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE); - memcpy(buf, &slhci_devd, l); - break; - case UDESC_CONFIG: - DPRINTF(D_MSG, ("UDESC_CONFIG ")); - if ((value & 0xff) != 0) { - error = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &slhci_confd, l); - buf = (char *)buf + l; - len -= l; - - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &slhci_ifcd, l); - buf = (char *)buf + l; - len -= l; - - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &slhci_endpd, l); - break; - case UDESC_STRING: - DPRINTF(D_MSG, ("UDESC_STR ")); - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 0: - break; - case 1: /* Vendor */ - totlen = slhci_str(buf, len, "ScanLogic"); - break; - case 2: /* Product */ - snprintf(slbuf, sizeof(slbuf), "%s root hub", - sltypestr[sc->sc_sltype>0]); - totlen = slhci_str(buf, len, slbuf); - break; - default: - printf("strerr%d ", value & 0xff); - break; - } - break; - default: - printf("unknownGetDescriptor=%x", value); - error = USBD_IOERROR; - break; - } - break; - case C(UR_GET_INTERFACE, UT_READ_INTERFACE): - /* Get Interface, 9.4.4 */ - if (len > 0) { - *(u_int8_t *)buf = 0; - totlen = 1; - } - break; - case C(UR_GET_STATUS, UT_READ_DEVICE): - /* Get Status from device, 9.4.5 */ - 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): - /* Get Status from interface, endpoint, 9.4.5 */ - if (len > 1) { - USETW(((usb_status_t *)buf)->wStatus, 0); - totlen = 2; - } - break; - case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): - /* Set Address, 9.4.6 */ - DPRINTF(D_MSG, ("UR_SET_ADDRESS ")); - if (value >= USB_MAX_DEVICES) { - error = USBD_IOERROR; - goto ret; - } - sc->sc_addr = value; - break; - case C(UR_SET_CONFIG, UT_WRITE_DEVICE): - /* Set Configuration, 9.4.7 */ - DPRINTF(D_MSG, ("UR_SET_CONFIG ")); - if (value != 0 && value != 1) { - error = USBD_IOERROR; - goto ret; - } - sc->sc_conf = value; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): - /* Set Descriptor, 9.4.8, not supported */ - DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n")); - 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): - /* Set Feature, 9.4.9, not supported */ - DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n")); - error = USBD_IOERROR; - break; - case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): - /* Set Interface, 9.4.10, not supported */ - break; - case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): - /* Synch Frame, 9.4.11, not supported */ - break; - - /* - * Hub specific requests - */ - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE): - /* Clear Hub Feature, 11.16.2.1, not supported */ - DPRINTF(D_MSG, ("ClearHubFeature not supported\n")); - break; - case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): - /* Clear Port Feature, 11.16.2.2 */ - if (index != 1) { - error = USBD_IOERROR; - goto ret; - } - switch (value) { - case UHF_PORT_POWER: - DPRINTF(D_MSG, ("POWER_OFF ")); - sc->sc_powerstat = POWER_OFF; - /* x68k Nereid USB controller needs it */ - if (sc->sc_enable_power) - sc->sc_enable_power(sc, sc->sc_powerstat); - break; - case UHF_PORT_SUSPEND: - DPRINTF(D_MSG, ("SUSPEND ")); - sl11write(sc, SL11_CTRL, - sl11read(sc, SL11_CTRL) & ~SL11_CTRL_SUSPEND); - break; - case UHF_C_PORT_CONNECTION: - sc->sc_change &= ~UPS_C_CONNECT_STATUS; - break; - case UHF_C_PORT_RESET: - sc->sc_change &= ~UPS_C_PORT_RESET; - break; - case UHF_PORT_ENABLE: - break; - case UHF_C_PORT_SUSPEND: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_OVER_CURRENT: - default: - printf("ClrPortFeatERR:value=0x%x ", value); - error = USBD_IOERROR; - break; - } - //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change)); - break; - case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER): - /* Get Bus State, 11.16.2.3, not supported */ - /* shall return a STALL... */ - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - /* Get Hub Descriptor, 11.16.2.4 */ - if (value != 0) { - error = USBD_IOERROR; - goto ret; - } - l = min(len, USB_HUB_DESCRIPTOR_SIZE); - totlen = l; - memcpy(buf, &slhci_hubd, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - /* Get Hub Status, 11.16.2.5 */ - DPRINTF(D_MSG, ("UR_GET_STATUS RCD")); - if (len != 4) { - error = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - /* Get Port Status, 11.16.2.6 */ - if (index != 1 || len != 4) { - printf("index=%d,len=%d ", index, len); - error = USBD_IOERROR; - goto ret; - } - /* - * change - * o port is always enabled. - * o cannot detect over current. - */ - s = splusb(); - sc->sc_change &= ~(UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET); - if ((sc->sc_flags & SLF_INSERT)) { - sc->sc_flags &= ~SLF_INSERT; - sc->sc_change |= UPS_C_CONNECT_STATUS; - } - if ((sc->sc_flags & SLF_RESET)) { - sc->sc_flags &= ~SLF_RESET; - sc->sc_change |= UPS_C_PORT_RESET; - } - splx(s); - /* - * XXX It can recognize that device is detached, - * while there is sl11_speed() here. - */ - if (sc->sc_change) - sl11_speed(sc); - /* - * status - * o port is always enabled. - * o cannot detect over current. - */ - status = 0; - if (sc->sc_connect) - status |= UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED; - r = sl11read(sc, SL11_CTRL); - if (r & SL11_CTRL_SUSPEND) - status |= UPS_SUSPEND; - if (sc->sc_powerstat) - status |= UPS_PORT_POWER; - if (!sc->sc_fullspeed) - status |= UPS_LOW_SPEED; - - //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change)); - USETW(ps.wPortStatus, status); - USETW(ps.wPortChange, sc->sc_change); - l = min(len, sizeof(ps)); - memcpy(buf, &ps, l); - totlen = l; - break; - case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): - /* Set Hub Descriptor, 11.16.2.7, not supported */ - /* STALL ? */ - error = USBD_IOERROR; - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE): - /* Set Hub Feature, 11.16.2.8, not supported */ - break; - case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): - /* Set Port Feature, 11.16.2.9 */ - if (index != 1) { - printf("index=%d ", index); - error = USBD_IOERROR; - goto ret; - } - switch (value) { - case UHF_PORT_RESET: - DPRINTF(D_MSG, ("PORT_RESET ")); - sl11_reset(sc); - sl11_speed(sc); - sc->sc_change = 0; - break; - case UHF_PORT_POWER: - DPRINTF(D_MSG, ("PORT_POWER ")); - sc->sc_powerstat = POWER_ON; - /* x68k Nereid USB controller needs it */ - if (sc->sc_enable_power) - sc->sc_enable_power(sc, sc->sc_powerstat); - delay_ms(25); - break; - default: - printf("SetPortFeatERR=0x%x ", value); - error = USBD_IOERROR; - break; - } - break; - default: - DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ", - req->bRequest, req->bmRequestType)); - error = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - error = USBD_NORMAL_COMPLETION; - ret: - xfer->status = error; - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - return USBD_IN_PROGRESS; -} - -void -slhci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("SLRCabort ")); -} - -void -slhci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("SLRCclose ")); -} - -void -slhci_root_ctrl_done(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("SLRCdone\n")); -} - -static usbd_status -slhci_root_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status error; - - DPRINTF(D_TRACE, ("SLRItransfer ")); - - /* Insert last in queue */ - error = usb_insert_transfer(xfer); - if (error) - return error; - - /* - * Pipe isn't running (otherwise error would be USBD_INPROG), - * start first. - */ - return slhci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue)); -} - -static usbd_status -slhci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; - - DPRINTF(D_TRACE, ("SLRIstart ")); - - sc->sc_interval = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); - usb_callout(sc->sc_poll_handle, sc->sc_interval, slhci_poll_hub, xfer); - sc->sc_intr_xfer = xfer; - return USBD_IN_PROGRESS; -} - -static void -slhci_root_intr_abort(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("SLRIabort ")); -} - -static void -slhci_root_intr_close(usbd_pipe_handle pipe) -{ - struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; - - DPRINTF(D_TRACE, ("SLRIclose ")); - - usb_uncallout(sc->sc_poll_handle, slhci_poll_hub, sc->sc_intr_xfer); - sc->sc_intr_xfer = NULL; -} - -static void -slhci_root_intr_done(usbd_xfer_handle xfer) -{ - //DPRINTF(D_XFER, ("RIdn ")); -} - -static usbd_status -slhci_device_ctrl_transfer(usbd_xfer_handle xfer) -{ - usbd_status error; - - DPRINTF(D_TRACE, ("C")); - - error = usb_insert_transfer(xfer); - if (error) - return error; - - return slhci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue)); -} - -static usbd_status -slhci_device_ctrl_start(usbd_xfer_handle xfer) -{ - usb_device_request_t *req = &xfer->request; - usbd_pipe_handle pipe = xfer->pipe; - struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; - usbd_status status = USBD_NORMAL_COMPLETION; - u_char *buf; - int pid = SL11_PID_OUT; - int len, actlen, size; - int s; - u_int8_t toggle = 0; - - DPRINTF(D_TRACE, ("st ")); -#ifdef SLHCI_DEBUG - if ((slhci_debug & D_TRACE)) - print_req_hub(req); -#endif - - /* SETUP transaction */ - if (slhci_transaction(sc, pipe, SL11_PID_SETUP, - sizeof(*req), (u_char*)req, toggle) == -1) { - status = USBD_IOERROR; - goto ret; - } - toggle ^= SL11_EPCTRL_DATATOGGLE; - - /* DATA transaction */ - actlen = 0; - len = UGETW(req->wLength); - if (len) { - buf = xfer->buffer; - if (req->bmRequestType & UT_READ) - pid = SL11_PID_IN; - for (; actlen < len; ) { - size = min(len - actlen, 8/* Minimum size */); - if (slhci_transaction(sc, pipe, pid, size, buf, toggle) == -1) - break; - toggle ^= SL11_EPCTRL_DATATOGGLE; - buf += size; - actlen += size; - } - } - xfer->actlen = actlen; - - /* ACK (status) */ - if (pid == SL11_PID_IN) - pid = SL11_PID_OUT; - else - pid = SL11_PID_IN; - if (slhci_transaction(sc, pipe, pid, 0, NULL, toggle) == -1) - status = USBD_IOERROR; - - ret: - xfer->status = status; - -#ifdef SLHCI_DEBUG - if((slhci_debug & D_TRACE) && UGETW(req->wLength) > 0){ - int i; - for(i=0; i < UGETW(req->wLength); i++) - printf("%02x", ((unsigned char *)xfer->buffer)[i]); - printf(" "); - } -#endif - s = splusb(); - usb_transfer_complete(xfer); - splx(s); - return USBD_IN_PROGRESS; -} - -static void -slhci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Cab ")); - slhci_abort_xfer(xfer, USBD_CANCELLED); -} - -static void -slhci_device_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("Ccl ")); -} - -static void -slhci_device_ctrl_done(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Cdn ")); -} - -static usbd_status -slhci_device_intr_transfer(usbd_xfer_handle xfer) -{ - usbd_status error; - - DPRINTF(D_TRACE, ("INTRtrans ")); - - error = usb_insert_transfer(xfer); - if (error) - return error; - - return slhci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue)); -} - -static usbd_status -slhci_device_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - struct slhci_xfer *sx; - - DPRINTF(D_TRACE, ("INTRstart ")); - - sx = malloc(sizeof(*sx), M_USB, M_NOWAIT); - if (sx == NULL) - goto reterr; - memset(sx, 0, sizeof(*sx)); - sx->sx_xfer = xfer; - xfer->hcpriv = sx; - - /* initialize callout */ - usb_callout_init(sx->sx_callout_t); - usb_callout(sx->sx_callout_t, - MS_TO_TICKS(pipe->endpoint->edesc->bInterval), - slhci_poll_device, sx); - - /* ACK */ - return USBD_IN_PROGRESS; - - reterr: - return USBD_IOERROR; -} - -static void -slhci_poll_device(void *arg) -{ - struct slhci_xfer *sx = (struct slhci_xfer *)arg; - usbd_xfer_handle xfer = sx->sx_xfer; - usbd_pipe_handle pipe = xfer->pipe; - struct slhci_softc *sc = (struct slhci_softc *)pipe->device->bus; - void *buf; - int pid; - int r; - int s; - - DPRINTF(D_TRACE, ("pldev")); - - usb_callout(sx->sx_callout_t, - MS_TO_TICKS(pipe->endpoint->edesc->bInterval), - slhci_poll_device, sx); - - /* interrupt transfer */ - pid = (UE_GET_DIR(pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN) - ? SL11_PID_IN : SL11_PID_OUT; - buf = xfer->buffer; - - r = slhci_transaction(sc, pipe, pid, xfer->length, buf, 0/*toggle*/); - if (r < 0) { - DPRINTF(D_MSG, ("%s error", __FUNCTION__)); - return; - } - /* no change, return NAK */ - if (r == 0) - return; - - xfer->status = USBD_NORMAL_COMPLETION; - s = splusb(); - xfer->device->bus->intr_context++; - usb_transfer_complete(xfer); - xfer->device->bus->intr_context--; - splx(s); -} - -static void -slhci_device_intr_abort(usbd_xfer_handle xfer) -{ - struct slhci_xfer *sx; - - DPRINTF(D_TRACE, ("INTRabort ")); - - sx = xfer->hcpriv; - if (sx) { - usb_uncallout(sx->sx_callout_t, slhci_poll_device, sx); - free(sx, M_USB); - xfer->hcpriv = NULL; - } else { - printf("%s: sx == NULL!\n", __FUNCTION__); - } - slhci_abort_xfer(xfer, USBD_CANCELLED); -} - -static void -slhci_device_intr_close(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("INTRclose ")); -} - -static void -slhci_device_intr_done(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("INTRdone ")); -} - -static usbd_status -slhci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("S")); - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -slhci_device_isoc_start(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("st ")); - return USBD_NORMAL_COMPLETION; -} - -static void -slhci_device_isoc_abort(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Sab ")); -} - -static void -slhci_device_isoc_close(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("Scl ")); -} - -static void -slhci_device_isoc_done(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Sdn ")); -} - -static usbd_status -slhci_device_bulk_transfer(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("B")); - return USBD_NORMAL_COMPLETION; -} - -static usbd_status -slhci_device_bulk_start(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("st ")); - return USBD_NORMAL_COMPLETION; -} - -static void -slhci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Bab ")); -} - -static void -slhci_device_bulk_close(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("Bcl ")); -} - -static void -slhci_device_bulk_done(usbd_xfer_handle xfer) -{ - DPRINTF(D_TRACE, ("Bdn ")); -} - -#define DATA0_RD (0x03) -#define DATA0_WR (0x07) -#define SLHCI_TIMEOUT (5000) - -/* - * Do a transaction. - * return 1 if ACK, 0 if NAK, -1 if error. - */ -static int -slhci_transaction(struct slhci_softc *sc, usbd_pipe_handle pipe, - u_int8_t pid, int len, u_char *buf, u_int8_t toggle) -{ -#ifdef SLHCI_DEBUG - char str[64]; - int i; -#endif - int timeout; - int ls_via_hub = 0; - int pl; - u_int8_t isr; - u_int8_t result = 0; - u_int8_t devaddr = pipe->device->address; - u_int8_t endpointaddr = pipe->endpoint->edesc->bEndpointAddress; - u_int8_t endpoint; - u_int8_t cmd = DATA0_RD; - - endpoint = UE_GET_ADDR(endpointaddr); - DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ", - pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint)); - - /* Set registers */ - sl11write(sc, SL11_E0ADDR, 0x40); - sl11write(sc, SL11_E0LEN, len); - sl11write(sc, SL11_E0PID, (pid << 4) + endpoint); - sl11write(sc, SL11_E0DEV, devaddr); - - /* Set buffer unless PID_IN */ - if (pid != SL11_PID_IN) { - if (len > 0) - sl11write_region(sc, 0x40, buf, len); - cmd = DATA0_WR; - } - - /* timing ? */ - pl = (len >> 3) + 3; - - /* Low speed device via HUB */ - /* XXX does not work... */ - if ((sc->sc_fullspeed) && pipe->device->speed == USB_SPEED_LOW) { - pl = len + 16; - cmd |= SL11_EPCTRL_PREAMBLE; - - /* - * SL811HS/T rev 1.2 has a bug, when it got PID_IN - * from LowSpeed device via HUB. - */ - if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) { - ls_via_hub = 1; - DPRINTF(D_MSG, ("LSvH ")); - } - } - - /* timing ? */ - if (sl11read(sc, SL811_CSOF) <= (u_int8_t)pl) - cmd |= SL11_EPCTRL_SOF; - - /* Transfer */ - sl11write(sc, SL11_ISR, 0xff); - sl11write(sc, SL11_E0CTRL, cmd | toggle); - - /* Polling */ - for (timeout = SLHCI_TIMEOUT; timeout; timeout--) { - isr = sl11read(sc, SL11_ISR); - if ((isr & SL11_ISR_USBA)) - break; - } - - /* Check result status */ - result = sl11read(sc, SL11_E0STAT); - if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) { - /* Resend PID_IN within 20usec */ - sl11write(sc, SL11_ISR, 0xff); - sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM); - } - - sl11write(sc, SL11_ISR, 0xff); - - DPRINTF(D_XFER, ("t=%d i=%x ", SLHCI_TIMEOUT - timeout, isr)); -#ifdef SLHCI_DEBUG - bitmask_snprintf(result, - "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", - str, sizeof(str)); - DPRINTF(D_XFER, ("STAT=%s ", str)); -#endif - - if ((result & SL11_EPSTAT_ERROR)) - return -1; - - if ((result & SL11_EPSTAT_NAK)) - return 0; - - /* Read buffer if PID_IN */ - if (pid == SL11_PID_IN && len > 0) { - sl11read_region(sc, buf, 0x40, len); -#ifdef SLHCI_DEBUG - for (i = 0; i < len; i++) - DPRINTF(D_XFER, ("%02X ", buf[i])); -#endif - } - - return 1; -} - -void -slhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - xfer->status = status; - usb_transfer_complete(xfer); -} - -void -slhci_device_clear_toggle(usbd_pipe_handle pipe) -{ - DPRINTF(D_TRACE, ("SLdevice_clear_toggle ")); -} - -#ifdef SLHCI_DEBUG -void -print_req(usb_device_request_t *r) -{ - char *xmes[]={ - "GETSTAT", - "CLRFEAT", - "res", - "SETFEAT", - "res", - "SETADDR", - "GETDESC", - "SETDESC", - "GETCONF", - "SETCONF", - "GETIN/F", - "SETIN/F", - "SYNC_FR" - }; - int req, type, value, index, len; - - req = r->bRequest; - type = r->bmRequestType; - value = UGETW(r->wValue); - index = UGETW(r->wIndex); - len = UGETW(r->wLength); - - printf("%x,%s,v=%d,i=%d,l=%d ", - type, xmes[req], value, index, len); -} - -void -print_req_hub(usb_device_request_t *r) -{ - struct { - int req; - int type; - char *str; - } conf[] = { - { 1, 0x20, "ClrHubFeat" }, - { 1, 0x23, "ClrPortFeat" }, - { 2, 0xa3, "GetBusState" }, - { 6, 0xa0, "GetHubDesc" }, - { 0, 0xa0, "GetHubStat" }, - { 0, 0xa3, "GetPortStat" }, - { 7, 0x20, "SetHubDesc" }, - { 3, 0x20, "SetHubFeat" }, - { 3, 0x23, "SetPortFeat" }, - {-1, 0, NULL}, - }; - int i; - int value, index, len; - - value = UGETW(r->wValue); - index = UGETW(r->wIndex); - len = UGETW(r->wLength); - for (i = 0; ; i++) { - if (conf[i].req == -1 ) - return print_req(r); - if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) { - printf("%s", conf[i].str); - break; - } - } - printf(",v=%d,i=%d,l=%d ", value, index, len); -} - -void -print_dumpreg(struct slhci_softc *sc) -{ - printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x," - "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,", - sl11read(sc, 0), sl11read(sc, 1), - sl11read(sc, 2), sl11read(sc, 3), - sl11read(sc, 4), sl11read(sc, 8), - sl11read(sc, 9), sl11read(sc, 10), - sl11read(sc, 11), sl11read(sc, 12) - ); - printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ", - sl11read(sc, 5), sl11read(sc, 6), - sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15) - ); -} - -void -print_xfer(usbd_xfer_handle xfer) -{ - printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,", - xfer->length, xfer->actlen, xfer->flags, xfer->timeout); - printf("request{ "); - print_req_hub(&xfer->request); - printf("} "); -} -#endif /* SLHCI_DEBUG */ diff --git a/sys/dev/usb/sl811hsreg.h b/sys/dev/usb/sl811hsreg.h deleted file mode 100644 index f9c0328..0000000 --- a/sys/dev/usb/sl811hsreg.h +++ /dev/null @@ -1,126 +0,0 @@ -/* $NetBSD$ */ -/* $FreeBSD$ */ - - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Tetsuya Isaki. - * - * 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. - */ - -/* - * ScanLogic SL811HS/T USB Host Controller - */ - -#define SL11_IDX_ADDR (0x00) -#define SL11_IDX_DATA (0x01) -#define SL11_PORTSIZE (0x02) - -#define SL11_E0BASE (0x00) /* Base of Control0 */ -#define SL11_E0CTRL (0x00) /* Host Control Register */ -#define SL11_E0ADDR (0x01) /* Host Base Address */ -#define SL11_E0LEN (0x02) /* Host Base Length */ -#define SL11_E0STAT (0x03) /* USB Status (Read) */ -#define SL11_E0PID SL11_E0STAT /* Host PID, Device Endpoint (Write) */ -#define SL11_E0CONT (0x04) /* Transfer Count (Read) */ -#define SL11_E0DEV SL11_E0CONT /* Host Device Address (Write) */ - -#define SL11_E1BASE (0x08) /* Base of Control1 */ -#define SL11_E1CTRL (SL11_E1BASE + SL11_E0CTRL) -#define SL11_E1ADDR (SL11_E1BASE + SL11_E0ADDR) -#define SL11_E1LEN (SL11_E1BASE + SL11_E0LEN) -#define SL11_E1STAT (SL11_E1BASE + SL11_E0STAT) -#define SL11_E1PID (SL11_E1BASE + SL11_E0PID) -#define SL11_E1CONT (SL11_E1BASE + SL11_E0CONT) -#define SL11_E1DEV (SL11_E1BASE + SL11_E0DEV) - -#define SL11_CTRL (0x05) /* Control Register1 */ -#define SL11_IER (0x06) /* Interrupt Enable Register */ -#define SL11_ISR (0x0d) /* Interrupt Status Register */ -#define SL11_DATA (0x0e) /* SOF Counter Low (Write) */ -#define SL11_REV SL11_DATA /* HW Revision Register (Read) */ -#define SL811_CSOF (0x0f) /* SOF Counter High(R), Control2(W) */ -#define SL11_MEM (0x10) /* Memory Buffer (0x10 - 0xff) */ - -#define SL11_EPCTRL_ARM (0x01) -#define SL11_EPCTRL_ENABLE (0x02) -#define SL11_EPCTRL_DIRECTION (0x04) -#define SL11_EPCTRL_ISO (0x10) -#define SL11_EPCTRL_SOF (0x20) -#define SL11_EPCTRL_DATATOGGLE (0x40) -#define SL11_EPCTRL_PREAMBLE (0x80) - -#define SL11_EPPID_PIDMASK (0xf0) -#define SL11_EPPID_EPMASK (0x0f) - -#define SL11_EPSTAT_ACK (0x01) -#define SL11_EPSTAT_ERROR (0x02) -#define SL11_EPSTAT_TIMEOUT (0x04) -#define SL11_EPSTAT_SEQUENCE (0x08) -#define SL11_EPSTAT_SETUP (0x10) -#define SL11_EPSTAT_OVERFLOW (0x20) -#define SL11_EPSTAT_NAK (0x40) -#define SL11_EPSTAT_STALL (0x80) - -#define SL11_CTRL_ENABLESOF (0x01) -#define SL11_CTRL_EOF2 (0x04) -#define SL11_CTRL_RESETENGINE (0x08) -#define SL11_CTRL_JKSTATE (0x10) -#define SL11_CTRL_LOWSPEED (0x20) -#define SL11_CTRL_SUSPEND (0x40) - -#define SL11_IER_USBA (0x01) /* USB-A done */ -#define SL11_IER_USBB (0x02) /* USB-B done */ -#define SL11_IER_BABBLE (0x04) /* Babble detection */ -#define SL11_IER_SOFTIMER (0x10) /* 1ms SOF timer */ -#define SL11_IER_INSERT (0x20) /* Slave Insert/Remove detection */ -#define SL11_IER_RESET (0x40) /* USB Reset/Resume */ - -#define SL11_ISR_USBA (0x01) /* USB-A done */ -#define SL11_ISR_USBB (0x02) /* USB-B done */ -#define SL11_ISR_BABBLE (0x04) /* Babble detection */ -#define SL11_ISR_SOFTIMER (0x10) /* 1ms SOF timer */ -#define SL11_ISR_INSERT (0x20) /* Slave Insert/Remove detection */ -#define SL11_ISR_RESET (0x40) /* USB Reset/Resume */ -#define SL11_ISR_DATA (0x80) /* Value of the Data+ pin */ - -#define SL11_REV_USBA (0x01) /* USB-A */ -#define SL11_REV_USBB (0x02) /* USB-B */ -#define SL11_REV_REVMASK (0xf0) /* HW Revision */ -#define SL11_REV_REVSL11H (0x00) /* HW is SL11H */ -#define SL11_REV_REVSL811HS (0x10) /* HW is SL811HS */ - -#define SL811_CSOF_SOFMASK (0x3f) /* SOF High Counter */ -#define SL811_CSOF_POLARITY (0x40) /* Change polarity */ -#define SL811_CSOF_MASTER (0x80) /* Master/Slave selection */ - diff --git a/sys/dev/usb/sl811hsvar.h b/sys/dev/usb/sl811hsvar.h deleted file mode 100644 index 6f5e6d6..0000000 --- a/sys/dev/usb/sl811hsvar.h +++ /dev/null @@ -1,107 +0,0 @@ -/* $NetBSD$ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Tetsuya Isaki. - * - * 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. - */ - -/* - * ScanLogic SL811HS/T USB Host Controller - */ - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) -#define delay_ms(X) \ - pause("slhci", MS_TO_TICKS(X)) - -#define SL11_PID_OUT (0x1) -#define SL11_PID_IN (0x9) -#define SL11_PID_SOF (0x5) -#define SL11_PID_SETUP (0xd) - -struct slhci_xfer { - usbd_xfer_handle sx_xfer; - usb_callout_t sx_callout_t; -}; - -struct slhci_softc { - struct usbd_bus sc_bus; - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; - -#ifdef __FreeBSD__ - void *ih; - struct resource *io_res; - struct resource *irq_res; -#endif - - void (*sc_enable_power)(void *, int); - void (*sc_enable_intr)(void *, int); - void *sc_arg; - int sc_powerstat; -#define POWER_ON (1) -#define POWER_OFF (0) -#define INTR_ON (1) -#define INTR_OFF (0) - - struct device *sc_parent; /* parent device */ - int sc_sltype; /* revision */ -#define SLTYPE_SL11H (0x00) -#define SLTYPE_SL811HS (0x01) -#define SLTYPE_SL811HS_R12 SLTYPE_SL811HS -#define SLTYPE_SL811HS_R14 (0x02) - - u_int8_t sc_addr; /* device address of root hub */ - u_int8_t sc_conf; - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; - - /* Information for the root hub interrupt pipe */ - int sc_interval; - usbd_xfer_handle sc_intr_xfer; - usb_callout_t sc_poll_handle; - - int sc_flags; -#define SLF_RESET (0x01) -#define SLF_INSERT (0x02) -#define SLF_ATTACHED (0x04) - - /* Root HUB specific members */ - int sc_fullspeed; - int sc_connect; /* XXX */ - int sc_change; -}; - -int sl811hs_find(struct slhci_softc *); -int slhci_attach(struct slhci_softc *); -int slhci_intr(void *); diff --git a/sys/dev/usb/slhci_pccard.c b/sys/dev/usb/slhci_pccard.c deleted file mode 100644 index 794b81d..0000000 --- a/sys/dev/usb/slhci_pccard.c +++ /dev/null @@ -1,206 +0,0 @@ -/*- - * Copyright (C) 2005 Takanori Watanabe. 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 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 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. - * - */ - - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/malloc.h> -#include <sys/sema.h> -#include <sys/taskqueue.h> -#include <vm/uma.h> -#include <machine/stdarg.h> -#include <machine/resource.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <dev/pccard/pccard_cis.h> -#include <dev/pccard/pccardreg.h> -#include <dev/pccard/pccardvar.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_port.h> -#include <dev/usb/sl811hsvar.h> -#include "pccarddevs.h" - -__FBSDID("$FreeBSD$"); - -static void slhci_pccard_intr(void *arg); - -static const struct pccard_product slhci_pccard_products[] = { - PCMCIA_CARD(RATOC, REX_CFU1), - {NULL} -}; - -static int -slhci_pccard_probe(device_t dev) -{ - const struct pccard_product *pp; - u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; - int error = 0; - - if ((error = pccard_get_function(dev, &fcn))) - return error; - - /* if it says its a disk we should register it */ - if (fcn == PCCARD_FUNCTION_DISK) - return 0; - - /* match other devices here, primarily cdrom/dvd rom */ - if ((pp = pccard_product_lookup(dev, slhci_pccard_products, - sizeof(slhci_pccard_products[0]), NULL))) { - if (pp->pp_name) - device_set_desc(dev, pp->pp_name); - return 0; - } - return ENXIO; -} - -static int -slhci_pccard_detach(device_t dev) -{ - struct slhci_softc *sc = device_get_softc(dev); - bus_generic_detach(dev); - - if (sc->ih) - bus_teardown_intr(dev, sc->irq_res, sc->ih); - if (sc->io_res) - bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_res); - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); - if (sc->sc_bus.bdev) - device_delete_child(dev, sc->sc_bus.bdev); - return 0; -} - -static int -slhci_pccard_attach(device_t dev) -{ - struct slhci_softc *sc = device_get_softc(dev); - int error = ENXIO; - int rid = 0; - if ((sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE)) == NULL) { - return ENOMEM; - } - sc->sc_iot = rman_get_bustag(sc->io_res); - sc->sc_ioh = rman_get_bushandle(sc->io_res); - - if (sl811hs_find(sc) == -1) { - error = ENXIO; - goto out; - } - - rid = 0; - if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - printf("CANNOT ALLOC IRQ\n"); - error = ENOMEM; - goto out; - } - sc->sc_iot = rman_get_bustag(sc->io_res); - sc->sc_ioh = rman_get_bushandle(sc->io_res); - sc->sc_bus.bdev = device_add_child(dev, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(dev, "Could not add USB device\n"); - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO, NULL, slhci_pccard_intr, sc, &sc->ih); - if (error) - goto out; -#if 1 - - if (slhci_attach(sc) == -1) { - printf("MI attach NO\n"); - goto out; - } - - error = device_probe_and_attach(sc->sc_bus.bdev); - - if (error) { - printf("Probing USB bus %x\n", error); - goto out; - } -#endif - printf("ATTACHED\n"); - return 0; -out: - slhci_pccard_detach(dev); - return error; -} - -#if 0 -static void -slhci_pccard_enable_power(void *arg, int mode) -{ -#if 0 - struct slhci_softc *sc = arg; - u_int8_t r; -#endif -} - -static void -slhci_pccard_enable_intr(void *arg, int mode) -{ -#if 0 - struct slhci_softc *sc = arg; - u_int8_t r; -#endif -} - -#endif -static void -slhci_pccard_intr(void *arg) -{ -#if 1 - struct slhci_softc *sc = arg; - sc = sc; - slhci_intr(sc); -#endif -} - -static device_method_t slhci_pccard_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, slhci_pccard_probe), - DEVMETHOD(device_attach, slhci_pccard_attach), - DEVMETHOD(device_detach, slhci_pccard_detach), - - {0, 0} -}; - -static driver_t slhci_pccard_driver = { - "slhci", - slhci_pccard_methods, - sizeof(struct slhci_softc), -}; - -devclass_t slhci_devclass; - -DRIVER_MODULE(slhci, pccard, slhci_pccard_driver, slhci_devclass, 0, 0); -MODULE_DEPEND(slhci, usb, 1, 1, 1); diff --git a/sys/dev/usb/u3g.c b/sys/dev/usb/u3g.c deleted file mode 100644 index 8c6f67e..0000000 --- a/sys/dev/usb/u3g.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * Copyright (c) 2008 AnyWi Technologies - * Author: Andrea Guzzo <aguzzo@anywi.com> - * * based on uark.c 1.1 2006/08/14 08:30:22 jsg * - * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk * - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -/* - * Notes: - * - The detour through the tty layer is ridiculously expensive wrt buffering - * due to the high speeds. - * We should consider adding a simple r/w device which allows attaching of PPP - * in a more efficient way. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include <dev/usb/ucomvar.h> - -#if __FreeBSD_version >= 800000 -#include "opt_u3g.h" -#endif -#include "usbdevs.h" - -//#define U3G_DEBUG -#ifdef U3G_DEBUG -#define DPRINTF(x...) do { if (u3gdebug) device_printf(sc->sc_dev, ##x); } while (0) -int u3gdebug = 1; -#else -#define DPRINTF(x...) /* nop */ -#endif - -#define U3G_MAXPORTS 4 -#define U3G_CONFIG_INDEX 0 - -struct u3g_softc { - struct ucom_softc sc_ucom[U3G_MAXPORTS]; - device_t sc_dev; - usbd_device_handle sc_udev; - u_int8_t sc_speed; - u_int8_t sc_flags; - u_char sc_numports; -}; - -static int u3g_open(void *addr, int portno); -static void u3g_close(void *addr, int portno); - -struct ucom_callback u3g_callback = { - NULL, - NULL, - NULL, - NULL, - u3g_open, - u3g_close, - NULL, - NULL, -}; - - -struct u3g_speeds_s { - u_int32_t ispeed; - u_int32_t ospeed; -}; - -static const struct u3g_speeds_s u3g_speeds[] = { -#define U3GSP_GPRS 0 - {64000, 64000}, -#define U3GSP_EDGE 1 - {384000, 64000}, -#define U3GSP_CDMA 2 - {384000, 64000}, -#define U3GSP_UMTS 3 - {384000, 64000}, -#define U3GSP_HSDPA 4 - {1200000, 384000}, -#define U3GSP_HSUPA 5 - {1200000, 384000}, -#define U3GSP_HSPA 6 - {7200000, 384000}, -}; - -#define U3GIBUFSIZE 1024 -#define U3GOBUFSIZE 1024 - -/* - * Various supported device vendors/products. - */ -struct u3g_dev_type_s { - struct usb_devno devno; - u_int8_t speed; - u_int8_t flags; -#define U3GFL_NONE 0x00 -#define U3GFL_HUAWEI_INIT 0x01 // Requires init command (Huawei cards) -#define U3GFL_SCSI_EJECT 0x02 // Requires SCSI eject command (Novatel) -#define U3GFL_SIERRA_INIT 0x04 // Requires init command (Sierra cards) -#define U3GFL_CMOTECH_INIT 0x08 // Requires init command (CMOTECH cards) -#define U3GFL_STUB_WAIT 0x80 // Device reappears after a short delay -}; - -// Note: The entries marked with XXX should be checked for the correct speed -// indication to set the buffer sizes. -static const struct u3g_dev_type_s u3g_devs[] = { - /* OEM: Option */ - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G }, U3GSP_UMTS, U3GFL_NONE }, - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD }, U3GSP_UMTS, U3GFL_NONE }, - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS }, U3GSP_UMTS, U3GFL_NONE }, - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36 }, U3GSP_HSDPA, U3GFL_NONE }, - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA }, U3GSP_HSDPA, U3GFL_NONE }, - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G }, U3GSP_UMTS, U3GFL_NONE }, - /* OEM: Qualcomm, Inc. */ - {{ USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR }, U3GSP_CDMA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM }, U3GSP_CDMA, U3GFL_SCSI_EJECT }, - /* OEM: Huawei */ - {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE }, U3GSP_HSDPA, U3GFL_HUAWEI_INIT }, - {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 }, U3GSP_HSPA, U3GFL_HUAWEI_INIT }, - /* OEM: Novatel */ - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM }, U3GSP_CDMA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D }, U3GSP_HSUPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740 }, U3GSP_HSDPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2 }, U3GSP_HSDPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720 }, U3GSP_UMTS, U3GFL_SCSI_EJECT }, // XXX - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740 }, U3GSP_HSDPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D }, U3GSP_HSUPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870 }, U3GSP_HSDPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD }, U3GSP_HSUPA, U3GFL_SCSI_EJECT }, - {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_U740 }, U3GSP_HSDPA, U3GFL_SCSI_EJECT }, - /* OEM: Merlin */ - {{ USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - /* OEM: Sierra Wireless: */ - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 }, U3GSP_HSDPA, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 }, U3GSP_UMTS, U3GFL_NONE }, // XXX - {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL }, U3GSP_UMTS, U3GFL_SIERRA_INIT }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_HS2300 }, U3GSP_HSDPA, U3GFL_NONE }, - /* OEM: CMOTECH */ - {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CGU628 }, U3GSP_HSDPA, U3GFL_CMOTECH_INIT }, - {{ USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_DISK }, U3GSP_HSDPA, U3GFL_NONE }, -}; -#define u3g_lookup(v, p) ((const struct u3g_dev_type_s *)usb_lookup(u3g_devs, v, p)) - -static int -u3g_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - const struct u3g_dev_type_s *u3g_dev_type; - - if (!uaa->iface) - return UMATCH_NONE; - - u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product); - if (!u3g_dev_type) - return UMATCH_NONE; - - if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT) { - /* If the interface class of the first interface is no longer - * mass storage the card has changed to modem (see u3g_attach() - * below). - */ - usb_interface_descriptor_t *id; - id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass == UICLASS_MASS) - return UMATCH_NONE; - } - - return UMATCH_VENDOR_PRODUCT_CONF_IFACE; -} - -static int -u3g_attach(device_t self) -{ - struct u3g_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - const struct u3g_dev_type_s *u3g_dev_type; - usbd_device_handle dev = uaa->device; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i, n; - usb_config_descriptor_t *cd; - char devnamefmt[32]; - -#if __FreeBSD_version < 700000 - char *devinfo = malloc(1024, M_USBDEV, M_WAITOK); - usbd_devinfo(dev, 0, devinfo); - device_printf(self, "%s\n", devinfo); - free(devinfo, M_USBDEV); -#endif - - /* get the config descriptor */ - cd = usbd_get_config_descriptor(dev); - if (cd == NULL) { - device_printf(self, "failed to get configuration descriptor\n"); - return ENXIO; - } - - sc->sc_dev = self; - sc->sc_udev = dev; - - u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product); - sc->sc_flags = u3g_dev_type->flags; - sc->sc_speed = u3g_dev_type->speed; - - sprintf(devnamefmt,"U%d.%%d", device_get_unit(self)); - int portno = 0; - for (i = 0; i < uaa->nifaces && portno < U3G_MAXPORTS; i++) { - if (uaa->ifaces[i] == NULL) - continue; - - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id && id->bInterfaceClass == UICLASS_MASS) { - /* We attach to the interface instead of the device as - * some devices have a built-in SD card reader. - * Claim the first umass device (cdX) as it contains - * only Windows drivers anyway (CD-ROM), hiding it. - */ -#ifndef U3G_DEBUG - if (!bootverbose) - if (uaa->vendor == USB_VENDOR_HUAWEI) - if (id->bInterfaceNumber == 2) - uaa->ifaces[i] = NULL; -#endif - continue; - } - - int bulkin_no = -1, bulkout_no = -1; - int claim_iface = 0; - for (n = 0; n < id->bNumEndpoints && portno < U3G_MAXPORTS; n++) { - ed = usbd_interface2endpoint_descriptor(uaa->ifaces[i], n); - if (ed == NULL) - continue; - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - bulkout_no = ed->bEndpointAddress; - - /* If we have found a pair of bulk-in/-out endpoints - * create a serial port for it. Note: We assume that - * the bulk-in and bulk-out endpoints appear in pairs. - */ - if (bulkin_no != -1 && bulkout_no != -1) { - struct ucom_softc *ucom = &sc->sc_ucom[portno]; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->ifaces[i]; - ucom->sc_bulkin_no = bulkin_no; - ucom->sc_bulkout_no = bulkout_no; - ucom->sc_ibufsize = U3GIBUFSIZE; - ucom->sc_ibufsizepad = U3GIBUFSIZE; - ucom->sc_obufsize = U3GOBUFSIZE; - ucom->sc_opkthdrlen = 0; - - ucom->sc_callback = &u3g_callback; - ucom->sc_parent = sc; - ucom->sc_portno = portno; - - DPRINTF("port=%d iface=%d in=0x%x out=0x%x\n", - portno, i, - ucom->sc_bulkin_no, - ucom->sc_bulkout_no); -#if __FreeBSD_version < 700000 - ucom_attach_tty(ucom, MINOR_CALLOUT, devnamefmt, portno); -#elif __FreeBSD_version < 800000 - ucom_attach_tty(ucom, TS_CALLOUT, devnamefmt, portno); -#else - ucom_attach_tty(ucom, devnamefmt, portno); -#endif - - claim_iface = 1; - portno++; - bulkin_no = bulkout_no = -1; - } - } - if (claim_iface) - uaa->ifaces[i] = NULL; // claim the interface - } - sc->sc_numports = portno; - - device_printf(self, "configured %d serial ports (%s)\n", - sc->sc_numports, devnamefmt); - return 0; -} - -static int -u3g_detach(device_t self) -{ - struct u3g_softc *sc = device_get_softc(self); - int rv = 0; - int i; - - for (i = 0; i < sc->sc_numports; i++) { - sc->sc_ucom[i].sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom[i]); - if (rv != 0) { - device_printf(self, "ucom_detach(U%d.%d\n", device_get_unit(self), i); - return rv; - } - } - - return 0; -} - -static int -u3g_open(void *addr, int portno) -{ -#if __FreeBSD_version < 800000 - /* Supply generous buffering for these cards to avoid disappointments - * when setting the speed incorrectly. Only do this for the first port - * assuming that the rest of the ports are used for diagnostics only - * anyway. - * Note: We abuse the fact that ucom sets the speed through - * ispeed/ospeed, not through ispeedwat/ospeedwat. - */ - if (portno == 0) { - struct u3g_softc *sc = addr; - struct ucom_softc *ucom = &sc->sc_ucom[portno]; - struct tty *tp = ucom->sc_tty; - - tp->t_ispeedwat = u3g_speeds[sc->sc_speed].ispeed; - tp->t_ospeedwat = u3g_speeds[sc->sc_speed].ospeed; - - /* Avoid excessive buffer sizes. - * XXX The values here should be checked. Lower them and see - * whether 'lost chars' messages appear. - */ - if (tp->t_ispeedwat > 384000) - tp->t_ispeedwat = 384000; - if (tp->t_ospeedwat > 384000) - tp->t_ospeedwat = 384000; - - ttsetwater(tp); - } -#endif - - return 0; -} - -static void -u3g_close(void *addr, int portno) -{ -#if __FreeBSD_version < 800000 - if (portno == 0) { /* see u3g_open() */ - /* Reduce the buffers allocated above again */ - struct u3g_softc *sc = addr; - struct ucom_softc *ucom = &sc->sc_ucom[portno]; - struct tty *tp = ucom->sc_tty; -#ifdef U3G_DEBUG - device_t self = sc->sc_dev; -#endif - - tp->t_ispeedwat = (speed_t)-1; - tp->t_ospeedwat = (speed_t)-1; - - ttsetwater(tp); - } -#endif -} - -static device_method_t u3g_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, u3g_match), - DEVMETHOD(device_attach, u3g_attach), - DEVMETHOD(device_detach, u3g_detach), - - { 0, 0 } -}; - -static driver_t u3g_driver = { - "ucom", - u3g_methods, - sizeof (struct u3g_softc) -}; - -DRIVER_MODULE(u3g, uhub, u3g_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(u3g, usb, 1, 1, 1); -MODULE_DEPEND(u3g, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(u3g, 1); - -/******************************************************************* - ****** Stub driver to hide devices that need to reinitialise ****** - *******************************************************************/ - -struct u3gstub_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_pipe_handle sc_pipe_out, sc_pipe_in; - usbd_xfer_handle sc_xfer; -}; - -static int -u3gstub_huawei_init(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, UHF_PORT_SUSPEND); - USETW(req.wLength, 0); - - (void) usbd_do_request(uaa->device, &req, 0); /* ignore any error */ - - return 1; -} - -static void -u3gstub_BBB_cb(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status err) -{ - struct u3gstub_softc *sc = (struct u3gstub_softc *) priv; - unsigned char cmd[13]; - - if (err) { - device_printf(sc->sc_dev, - "Failed to send CD eject command to " - "change to modem mode\n"); - } else { - usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_in, NULL, cmd, sizeof(cmd), - 0, USBD_DEFAULT_TIMEOUT, NULL); - int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; - if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) - DPRINTF("failed to start transfer (CSW)\n"); - } -} - -static int -u3gstub_scsi_eject(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) -{ - /* See definition of umass_bbb_cbw_t in sys/dev/usb/umass.c and struct - * scsi_start_stop_unit in sys/cam/scsi/scsi_all.h . - */ - unsigned char cmd[31] = { - 0x55, 0x53, 0x42, 0x43, /* 0..3: Command Block Wrapper (CBW) signature */ - 0x01, 0x00, 0x00, 0x00, /* 4..7: CBW Tag, unique 32-bit number */ - 0x00, 0x00, 0x00, 0x00, /* 8..11: CBW Transfer Length, no data here */ - 0x00, /* 12: CBW Flag: output */ - 0x00, /* 13: CBW Lun */ - 0x06, /* 14: CBW Length */ - - 0x1b, /* 15+0: opcode: SCSI START/STOP */ - 0x00, /* 15+1: byte2: Not immediate */ - 0x00, 0x00, /* 15+2..3: reserved */ - 0x02, /* 15+4: Load/Eject command */ - 0x00, /* 15+5: control */ - 0x00, 0x00, 0x00, 0x00, /* 15+6..15: unused */ - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 - }; - - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed = NULL; - int i; - - - /* Find the bulk-out endpoints */ - id = usbd_get_interface_descriptor(uaa->iface); - for (i = 0 ; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (ed != NULL - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { - if (usbd_open_pipe(uaa->iface, - ed->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->sc_pipe_out) - != USBD_NORMAL_COMPLETION) { - DPRINTF("failed to open bulk-out pipe on endpoint %d\n", - ed->bEndpointAddress); - return 0; - } - } else { - if (usbd_open_pipe(uaa->iface, - ed->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->sc_pipe_in) - != USBD_NORMAL_COMPLETION) { - DPRINTF("failed to open bulk-in pipe on endpoint %d\n", - ed->bEndpointAddress); - return 0; - } - } - } - if (sc->sc_pipe_out && sc->sc_pipe_in) - break; - } - - if (i == id->bNumEndpoints) { - DPRINTF("failed to find bulk-out pipe\n"); - return 0; - } - - sc->sc_xfer = usbd_alloc_xfer(uaa->device); - if (sc->sc_xfer == NULL) { - DPRINTF("failed to allocate xfer\n"); - return 0; - } - - usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_out, NULL, cmd, sizeof(cmd), - 0, USBD_DEFAULT_TIMEOUT, u3gstub_BBB_cb); - int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; - if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) { - DPRINTF("failed to start transfer (CBW)\n"); - return 0; - } - - return 1; -} - -static int -u3gstub_cmotech_init(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) -{ - /* See definition of umass_bbb_cbw_t in sys/dev/usb/umass.c - * in sys/cam/scsi/scsi_all.h . - */ - unsigned char cmd[31] = { - 0x55, 0x53, 0x42, 0x43, /* 0..3: Command Block Wrapper (CBW) signature */ - 0x01, 0x00, 0x00, 0x00, /* 4..7: CBW Tag, unique 32-bit number */ - 0x00, 0x00, 0x00, 0x00, /* 8..11: CBW Transfer Length, no data here */ - 0x80, /* 12: CBW Flag: output, so 0 */ - 0x00, /* 13: CBW Lun */ - 0x08, /* 14: CBW Length */ - - 0xff, /* 15+0 */ - 0x52, /* 15+1 */ - 0x44, /* 15+2 */ - 0x45, /* 15+2 */ - 0x56, /* 15+4 */ - 0x43, /* 15+5 */ - 0x48, /* 15+5 */ - 0x47, /* 15+5 */ - 0x00, 0x00, 0x00, 0x00, /* 15+8..15: unused */ - 0x00, 0x00, 0x00, 0x00 - }; - - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed = NULL; - int i; - - - /* Find the bulk-out endpoints */ - id = usbd_get_interface_descriptor(uaa->iface); - for (i = 0 ; i < id->bNumEndpoints ; i++) { - ed = usbd_interface2endpoint_descriptor(uaa->iface, i); - if (ed != NULL - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { - if (usbd_open_pipe(uaa->iface, - ed->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->sc_pipe_out) - != USBD_NORMAL_COMPLETION) { - DPRINTF("failed to open bulk-out pipe on endpoint %d\n", - ed->bEndpointAddress); - return 0; - } - } else { - if (usbd_open_pipe(uaa->iface, - ed->bEndpointAddress, - USBD_EXCLUSIVE_USE, - &sc->sc_pipe_in) - != USBD_NORMAL_COMPLETION) { - DPRINTF("failed to open bulk-in pipe on endpoint %d\n", - ed->bEndpointAddress); - return 0; - } - } - } - if (sc->sc_pipe_out && sc->sc_pipe_in) - break; - } - - if (i == id->bNumEndpoints) { - DPRINTF("failed to find bulk-out pipe\n"); - return 0; - } - - sc->sc_xfer = usbd_alloc_xfer(uaa->device); - if (sc->sc_xfer == NULL) { - DPRINTF("failed to allocate xfer\n"); - return 0; - } - - usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe_out, NULL, cmd, sizeof(cmd), - 0, USBD_DEFAULT_TIMEOUT, u3gstub_BBB_cb); - int err = usbd_transfer(sc->sc_xfer) != USBD_NORMAL_COMPLETION; - if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) { - DPRINTF("failed to start transfer (CBW)\n"); - return 0; - } - - return 1; -} - -static int -u3gstub_sierra_init(struct u3gstub_softc *sc, struct usb_attach_arg *uaa) -{ - usb_device_request_t req; - - req.bmRequestType = UT_VENDOR; - req.bRequest = UR_SET_INTERFACE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, UHF_PORT_CONNECTION); - USETW(req.wLength, 0); - - (void) usbd_do_request(uaa->device, &req, 0); /* ignore any error */ - - return 1; -} - -static int -u3gstub_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - const struct u3g_dev_type_s *u3g_dev_type; - usb_interface_descriptor_t *id; - - /* This stub handles 3G modem devices (E220, Mobile, etc.) with - * auto-install flash disks for Windows/MacOSX on the first interface. - * After some command or some delay they change appearance to a modem. - */ - - if (!uaa->iface) - return UMATCH_NONE; - - u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product); - if (!u3g_dev_type) - return UMATCH_NONE; - - if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT - || u3g_dev_type->flags&U3GFL_SCSI_EJECT - || u3g_dev_type->flags&U3GFL_SIERRA_INIT - || u3g_dev_type->flags&U3GFL_CMOTECH_INIT - || u3g_dev_type->flags&U3GFL_STUB_WAIT) { - /* We assume that if the first interface is still a mass - * storage device the device has not yet changed appearance. - */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id && id->bInterfaceNumber == 0 - && id->bInterfaceClass == UICLASS_MASS) { -#ifndef U3G_DEBUG - if (!bootverbose) - device_quiet(self); -#endif - - return UMATCH_VENDOR_PRODUCT; - } - } - - return UMATCH_NONE; -} - -static int -u3gstub_attach(device_t self) -{ - struct u3gstub_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - const struct u3g_dev_type_s *u3g_dev_type; - int i; - -#ifndef U3G_DEBUG - if (!bootverbose) - device_quiet(self); -#endif - - sc->sc_dev = self; - sc->sc_udev = uaa->device; - - for (i = 0; i < uaa->nifaces; i++) - uaa->ifaces[i] = NULL; // claim all interfaces - - u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product); - if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT) { - if (bootverbose) - device_printf(sc->sc_dev, - "changing Huawei modem to modem mode\n"); - if (!u3gstub_huawei_init(sc, uaa)) - return ENXIO; - } else if (u3g_dev_type->flags&U3GFL_SCSI_EJECT) { - if (bootverbose) - device_printf(sc->sc_dev, "sending CD eject command to " - "change to modem mode\n"); - if (!u3gstub_scsi_eject(sc, uaa)) - return ENXIO; - } else if (u3g_dev_type->flags&U3GFL_SIERRA_INIT) { - if (bootverbose) - device_printf(sc->sc_dev, - "changing Sierra modem to modem mode\n"); - if (!u3gstub_sierra_init(sc, uaa)) - return ENXIO; - } else if (u3g_dev_type->flags&U3GFL_CMOTECH_INIT) { - if (bootverbose) - device_printf(sc->sc_dev, - "changing CMOTECH modem to modem mode\n"); - if (!u3gstub_cmotech_init(sc, uaa)) - return ENXIO; - } else if (u3g_dev_type->flags&U3GFL_STUB_WAIT) { - if (bootverbose) - device_printf(sc->sc_dev, "waiting for modem to change " - "to modem mode\n"); - /* nop */ - } - - return 0; -} - -static int -u3gstub_detach(device_t self) -{ - struct u3gstub_softc *sc = device_get_softc(self); - - if (sc->sc_xfer) - usbd_free_xfer(sc->sc_xfer); - - if (sc->sc_pipe_in) { - usbd_abort_pipe(sc->sc_pipe_in); - usbd_close_pipe(sc->sc_pipe_in); - } - if (sc->sc_pipe_out) { - usbd_abort_pipe(sc->sc_pipe_out); - usbd_close_pipe(sc->sc_pipe_out); - } - - return 0; -} - -static device_method_t u3gstub_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, u3gstub_match), - DEVMETHOD(device_attach, u3gstub_attach), - DEVMETHOD(device_detach, u3gstub_detach), - - { 0, 0 } -}; - -static driver_t u3gstub_driver = { - "u3g", - u3gstub_methods, - sizeof (struct u3gstub_softc) -}; - -DRIVER_MODULE(u3gstub, uhub, u3gstub_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(u3gstub, usb, 1, 1, 1); diff --git a/sys/dev/usb/uark.c b/sys/dev/usb/uark.c deleted file mode 100644 index af85819..0000000 --- a/sys/dev/usb/uark.c +++ /dev/null @@ -1,339 +0,0 @@ -/* $OpenBSD: uark.c,v 1.1 2006/08/14 08:30:22 jsg Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/ucomvar.h> - -#ifdef UARK_DEBUG -#define DPRINTFN(n, x) do { \ - if (uarkdebug > (n)) \ - printf x; \ -} while (0) -int uarkebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UARKBUFSZ 256 -#define UARK_CONFIG_NO 0 -#define UARK_IFACE_NO 0 - -#define UARK_SET_DATA_BITS(x) (x - 5) - -#define UARK_PARITY_NONE 0x00 -#define UARK_PARITY_ODD 0x08 -#define UARK_PARITY_EVEN 0x18 - -#define UARK_STOP_BITS_1 0x00 -#define UARK_STOP_BITS_2 0x04 - -#define UARK_BAUD_REF 3000000 - -#define UARK_WRITE 0x40 -#define UARK_READ 0xc0 - -#define UARK_REQUEST 0xfe - -#define UARK_CONFIG_INDEX 0 -#define UARK_IFACE_INDEX 0 - -struct uark_softc { - struct ucom_softc sc_ucom; - usbd_interface_handle sc_iface; - - u_char sc_msr; - u_char sc_lsr; -}; - -static void uark_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void uark_set(void *, int, int, int); -static int uark_param(void *, int, struct termios *); -static void uark_break(void *, int, int); -static int uark_cmd(struct uark_softc *, uint16_t, uint16_t); - -struct ucom_callback uark_callback = { - uark_get_status, - uark_set, - uark_param, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -static const struct usb_devno uark_devs[] = { - { USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116 } -}; - -static int -uark_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (usb_lookup(uark_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -uark_attach(device_t self) -{ - struct uark_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - struct ucom_softc *ucom = &sc->sc_ucom; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - - if (uaa->iface == NULL) { - /* Move the device into the configured state. */ - error = usbd_set_config_index(dev, UARK_CONFIG_INDEX, 1); - if (error) { - device_printf(ucom->sc_dev, - "failed to set configuration, err=%s\n", - usbd_errstr(error)); - goto bad; - } - error = - usbd_device2interface_handle(dev, UARK_IFACE_INDEX, &iface); - if (error) { - device_printf(ucom->sc_dev, - "failed to get interface, err=%s\n", - usbd_errstr(error)); - goto bad; - } - } else - iface = uaa->iface; - - id = usbd_get_interface_descriptor(iface); - ucom->sc_iface = iface; - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, - "could not read endpoint descriptor\n"); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "missing endpoint\n"); - goto bad; - } - ucom->sc_parent = sc; - ucom->sc_ibufsize = UARKBUFSZ; - ucom->sc_obufsize = UARKBUFSZ; - ucom->sc_ibufsizepad = UARKBUFSZ; - ucom->sc_opkthdrlen = 0; - - ucom->sc_callback = &uark_callback; - - DPRINTF(("uark: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - return 0; - -bad: - DPRINTF(("uark_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uark_detach(device_t self) -{ - struct uark_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uark_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static void -uark_set(void *vsc, int portno, int reg, int onoff) -{ - struct uark_softc *sc = vsc; - - switch (reg) { - case UCOM_SET_BREAK: - uark_break(sc, portno, onoff); - return; - /* NOTREACHED */ - case UCOM_SET_DTR: - case UCOM_SET_RTS: - default: - return; - /* NOTREACHED */ - } -} - -static int -uark_param(void *vsc, int portno, struct termios *t) -{ - struct uark_softc *sc = (struct uark_softc *)vsc; - int data, divisor; - speed_t speed = t->c_ospeed; - - if (speed < 300 || speed > 115200) - return (EINVAL); - divisor = (UARK_BAUD_REF + speed / 2) / speed; - /* Check that we're within 3% of the requested rate. */ - if (speed * divisor < UARK_BAUD_REF * 100 / 103 || - speed * divisor > UARK_BAUD_REF * 100 / 97) - return (EINVAL); - uark_cmd(sc, 3, 0x83); - uark_cmd(sc, 0, divisor & 0xFF); - uark_cmd(sc, 1, divisor >> 8); - uark_cmd(sc, 3, 0x03); - - if (ISSET(t->c_cflag, CSTOPB)) - data = UARK_STOP_BITS_2; - else - data = UARK_STOP_BITS_1; - - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= UARK_PARITY_ODD; - else - data |= UARK_PARITY_EVEN; - } else - data |= UARK_PARITY_NONE; - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= UARK_SET_DATA_BITS(5); - break; - case CS6: - data |= UARK_SET_DATA_BITS(6); - break; - case CS7: - data |= UARK_SET_DATA_BITS(7); - break; - case CS8: - data |= UARK_SET_DATA_BITS(8); - break; - } - uark_cmd(sc, 3, 0x00); - uark_cmd(sc, 3, data); - - return (0); -} - -void -uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uark_softc *sc = vsc; - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -void -uark_break(void *vsc, int portno, int onoff) -{ -#ifdef UARK_DEBUG - struct uark_softc *sc = vsc; - - device_printf(sc->sc_dev, "%s: break %s!\n", onoff ? "on" : "off"); - if (onoff) - /* break on */ - uark_cmd(sc, 4, 0x01); - else - uark_cmd(sc, 4, 0x00); -#endif -} - -int -uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value) -{ - usb_device_request_t req; - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - - req.bmRequestType = UARK_WRITE; - req.bRequest = UARK_REQUEST; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - - if (err) - return (EIO); - - return (0); -} - -static device_method_t uark_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uark_match), - DEVMETHOD(device_attach, uark_attach), - DEVMETHOD(device_detach, uark_detach), - - { 0, 0 } -}; - -static driver_t uark_driver = { - "ucom", - uark_methods, - sizeof (struct uark_softc) -}; - -DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uark, usb, 1, 1, 1); -MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); diff --git a/sys/dev/usb/ubsa.c b/sys/dev/usb/ubsa.c deleted file mode 100644 index b66cce8..0000000 --- a/sys/dev/usb/ubsa.c +++ /dev/null @@ -1,742 +0,0 @@ -/*- - * Copyright (c) 2002, Alexander Kabaev <kan.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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -/*- - * 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. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/taskqueue.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -#ifdef USB_DEBUG -static int ubsadebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ubsa, CTLFLAG_RW, 0, "USB ubsa"); -SYSCTL_INT(_hw_usb_ubsa, OID_AUTO, debug, CTLFLAG_RW, - &ubsadebug, 0, "ubsa debug level"); - -#define DPRINTFN(n, x) do { \ - if (ubsadebug > (n)) \ - printf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UBSA_MODVER 1 /* module version */ - -#define UBSA_CONFIG_INDEX 1 -#define UBSA_IFACE_INDEX 0 - -#define UBSA_INTR_INTERVAL 100 /* ms */ - -#define UBSA_SET_BAUDRATE 0x00 -#define UBSA_SET_STOP_BITS 0x01 -#define UBSA_SET_DATA_BITS 0x02 -#define UBSA_SET_PARITY 0x03 -#define UBSA_SET_DTR 0x0A -#define UBSA_SET_RTS 0x0B -#define UBSA_SET_BREAK 0x0C -#define UBSA_SET_FLOW_CTRL 0x10 - -#define UBSA_PARITY_NONE 0x00 -#define UBSA_PARITY_EVEN 0x01 -#define UBSA_PARITY_ODD 0x02 -#define UBSA_PARITY_MARK 0x03 -#define UBSA_PARITY_SPACE 0x04 - -#define UBSA_FLOW_NONE 0x0000 -#define UBSA_FLOW_OCTS 0x0001 -#define UBSA_FLOW_ODSR 0x0002 -#define UBSA_FLOW_IDSR 0x0004 -#define UBSA_FLOW_IDTR 0x0008 -#define UBSA_FLOW_IRTS 0x0010 -#define UBSA_FLOW_ORTS 0x0020 -#define UBSA_FLOW_UNKNOWN 0x0040 -#define UBSA_FLOW_OXON 0x0080 -#define UBSA_FLOW_IXON 0x0100 - -/* line status register */ -#define UBSA_LSR_TSRE 0x40 /* Transmitter empty: byte sent */ -#define UBSA_LSR_TXRDY 0x20 /* Transmitter buffer empty */ -#define UBSA_LSR_BI 0x10 /* Break detected */ -#define UBSA_LSR_FE 0x08 /* Framing error: bad stop bit */ -#define UBSA_LSR_PE 0x04 /* Parity error */ -#define UBSA_LSR_OE 0x02 /* Overrun, lost incoming byte */ -#define UBSA_LSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ -#define UBSA_LSR_RCV_MASK 0x1f /* Mask for incoming data or error */ - -/* modem status register */ -/* All deltas are from the last read of the MSR. */ -#define UBSA_MSR_DCD 0x80 /* Current Data Carrier Detect */ -#define UBSA_MSR_RI 0x40 /* Current Ring Indicator */ -#define UBSA_MSR_DSR 0x20 /* Current Data Set Ready */ -#define UBSA_MSR_CTS 0x10 /* Current Clear to Send */ -#define UBSA_MSR_DDCD 0x08 /* DCD has changed state */ -#define UBSA_MSR_TERI 0x04 /* RI has toggled low to high */ -#define UBSA_MSR_DDSR 0x02 /* DSR has changed state */ -#define UBSA_MSR_DCTS 0x01 /* CTS has changed state */ - -struct ubsa_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number; /* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* ubsa status register */ - struct task sc_task; -}; - -static void ubsa_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ubsa_notify(void *, int count); - -static void ubsa_get_status(void *, int, u_char *, u_char *); -static void ubsa_set(void *, int, int, int); -static int ubsa_param(void *, int, struct termios *); -static int ubsa_open(void *, int); -static void ubsa_close(void *, int); - -static int ubsa_request(struct ubsa_softc *, u_int8_t, u_int16_t); -static void ubsa_dtr(struct ubsa_softc *, int); -static void ubsa_rts(struct ubsa_softc *, int); -static void ubsa_baudrate(struct ubsa_softc *, speed_t); -static void ubsa_parity(struct ubsa_softc *, tcflag_t); -static void ubsa_databits(struct ubsa_softc *, tcflag_t); -static void ubsa_stopbits(struct ubsa_softc *, tcflag_t); -static void ubsa_flow(struct ubsa_softc *, tcflag_t, tcflag_t); - -struct ucom_callback ubsa_callback = { - ubsa_get_status, - ubsa_set, - ubsa_param, - NULL, - ubsa_open, - ubsa_close, - NULL, - NULL -}; - -static const struct ubsa_product { - uint16_t vendor; - uint16_t product; -} ubsa_products [] = { - /* AnyData ADU-500A */ - { USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_500A }, - /* AnyData ADU-E100A/H */ - { USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_E100X }, - /* Axesstel MV100H */ - { USB_VENDOR_AXESSTEL, USB_PRODUCT_AXESSTEL_DATAMODEM }, - /* BELKIN F5U103 */ - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U103 }, - /* BELKIN F5U120 */ - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U120 }, - /* GoHubs GO-COM232 */ - { USB_VENDOR_ETEK, USB_PRODUCT_ETEK_1COM }, - /* GoHubs GO-COM232 */ - { USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232 }, - /* Peracom */ - { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1 }, - { 0, 0 } -}; - -static device_probe_t ubsa_match; -static device_attach_t ubsa_attach; -static device_detach_t ubsa_detach; - -static device_method_t ubsa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ubsa_match), - DEVMETHOD(device_attach, ubsa_attach), - DEVMETHOD(device_detach, ubsa_detach), - { 0, 0 } -}; - -static driver_t ubsa_driver = { - "ucom", - ubsa_methods, - sizeof (struct ubsa_softc) -}; - -DRIVER_MODULE(ubsa, uhub, ubsa_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(ubsa, usb, 1, 1, 1); -MODULE_DEPEND(ubsa, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(ubsa, UBSA_MODVER); - -static int -ubsa_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - int i; - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - for (i = 0; ubsa_products[i].vendor != 0; i++) { - if (ubsa_products[i].vendor == uaa->vendor && - ubsa_products[i].product == uaa->product) { - return (UMATCH_VENDOR_PRODUCT); - } - } - return (UMATCH_NONE); -} - -static int -ubsa_attach(device_t self) -{ - struct ubsa_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int i; - - dev = uaa->device; - ucom = &sc->sc_ucom; - - /* - * initialize rts, dtr variables to something - * different from boolean 0, 1 - */ - sc->sc_dtr = -1; - sc->sc_rts = -1; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - DPRINTF(("ubsa attach: sc = %p\n", sc)); - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UBSA_CONFIG_INDEX, 1); - if (err) { - device_printf(ucom->sc_dev, "failed to set configuration: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - device_printf(ucom->sc_dev, - "failed to get configuration descriptor\n"); - ucom->sc_dying = 1; - goto error; - } - - /* get the first interface */ - err = usbd_device2interface_handle(dev, UBSA_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* Find the endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, - "no endpoint descriptor for %d\n", i); - ucom->sc_dying = 1; - goto error; - } - - 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); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - ucom->sc_ibufsize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - ucom->sc_obufsize = UGETW(ed->wMaxPacketSize); - } - } - - if (sc->sc_intr_number == -1) { - device_printf(ucom->sc_dev, "Could not find interrupt in\n"); - ucom->sc_dying = 1; - goto error; - } - - /* keep interface for interrupt */ - sc->sc_intr_iface = ucom->sc_iface; - - if (ucom->sc_bulkin_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk in\n"); - ucom->sc_dying = 1; - goto error; - } - - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk out\n"); - ucom->sc_dying = 1; - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = 1024; - ucom->sc_obufsize = 1024; - ucom->sc_ibufsizepad = ucom->sc_ibufsize; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &ubsa_callback; - - DPRINTF(("ubsa: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - TASK_INIT(&sc->sc_task, 0, ubsa_notify, sc); - ucom_attach(ucom); - return 0; - -error: - return ENXIO; -} - -static int -ubsa_detach(device_t self) -{ - struct ubsa_softc *sc = device_get_softc(self); - int rv; - - DPRINTF(("ubsa_detach: sc = %p\n", sc)); - - 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_ucom.sc_dying = 1; -#if 0 - taskqueue_drain(taskqueue_swi_giant); -#endif - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static int -ubsa_request(struct ubsa_softc *sc, u_int8_t request, u_int16_t value) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = request; - USETW(req.wValue, value); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - device_printf(sc->sc_ucom.sc_dev, "ubsa_request(%x, %x): %s\n", - request, value, usbd_errstr(err)); - return (err); -} - -static void -ubsa_dtr(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_dtr: onoff = %d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - ubsa_request(sc, UBSA_SET_DTR, onoff ? 1 : 0); -} - -static void -ubsa_rts(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_rts: onoff = %d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - ubsa_request(sc, UBSA_SET_RTS, onoff ? 1 : 0); -} - -static void -ubsa_break(struct ubsa_softc *sc, int onoff) -{ - - DPRINTF(("ubsa_rts: onoff = %d\n", onoff)); - - ubsa_request(sc, UBSA_SET_BREAK, onoff ? 1 : 0); -} - -static void -ubsa_set(void *addr, int portno, int reg, int onoff) -{ - struct ubsa_softc *sc; - - sc = addr; - switch (reg) { - case UCOM_SET_DTR: - ubsa_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - ubsa_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - ubsa_break(sc, onoff); - break; - default: - break; - } -} - -static void -ubsa_baudrate(struct ubsa_softc *sc, speed_t speed) -{ - u_int16_t value = 0; - - DPRINTF(("ubsa_baudrate: speed = %d\n", speed)); - - switch(speed) { - case B0: - break; - case B300: - case B600: - case B1200: - case B2400: - case B4800: - case B9600: - case B19200: - case B38400: - case B57600: - case B115200: - case B230400: - value = B230400 / speed; - break; - default: - device_printf(sc->sc_ucom.sc_dev, - "ubsa_param: unsupported baud, forcing default of 9600\n"); - value = B230400 / B9600; - break; - }; - - if (speed == B0) { - ubsa_flow(sc, 0, 0); - ubsa_dtr(sc, 0); - ubsa_rts(sc, 0); - } else - ubsa_request(sc, UBSA_SET_BAUDRATE, value); -} - -static void -ubsa_parity(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_parity: cflag = 0x%x\n", cflag)); - - if (cflag & PARENB) - value = (cflag & PARODD) ? UBSA_PARITY_ODD : UBSA_PARITY_EVEN; - else - value = UBSA_PARITY_NONE; - - ubsa_request(sc, UBSA_SET_PARITY, value); -} - -static void -ubsa_databits(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_databits: cflag = 0x%x\n", cflag)); - - switch (cflag & CSIZE) { - case CS5: value = 0; break; - case CS6: value = 1; break; - case CS7: value = 2; break; - case CS8: value = 3; break; - default: - device_printf(sc->sc_ucom.sc_dev, - "ubsa_param: unsupported databits requested, " - "forcing default of 8\n"); - value = 3; - } - - ubsa_request(sc, UBSA_SET_DATA_BITS, value); -} - -static void -ubsa_stopbits(struct ubsa_softc *sc, tcflag_t cflag) -{ - int value; - - DPRINTF(("ubsa_stopbits: cflag = 0x%x\n", cflag)); - - value = (cflag & CSTOPB) ? 1 : 0; - - ubsa_request(sc, UBSA_SET_STOP_BITS, value); -} - -static void -ubsa_flow(struct ubsa_softc *sc, tcflag_t cflag, tcflag_t iflag) -{ - int value; - - DPRINTF(("ubsa_flow: cflag = 0x%x, iflag = 0x%x\n", cflag, iflag)); - - value = 0; - if (cflag & CRTSCTS) - value |= UBSA_FLOW_OCTS | UBSA_FLOW_IRTS; - if (iflag & (IXON|IXOFF)) - value |= UBSA_FLOW_OXON | UBSA_FLOW_IXON; - - ubsa_request(sc, UBSA_SET_FLOW_CTRL, value); -} - -static int -ubsa_param(void *addr, int portno, struct termios *ti) -{ - struct ubsa_softc *sc; - - sc = addr; - - DPRINTF(("ubsa_param: sc = %p\n", sc)); - - ubsa_baudrate(sc, ti->c_ospeed); - ubsa_parity(sc, ti->c_cflag); - ubsa_databits(sc, ti->c_cflag); - ubsa_stopbits(sc, ti->c_cflag); - ubsa_flow(sc, ti->c_cflag, ti->c_iflag); - - return (0); -} - -static int -ubsa_open(void *addr, int portno) -{ - struct ubsa_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("ubsa_open: sc = %p\n", sc)); - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - ubsa_intr, - UBSA_INTR_INTERVAL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, - "cannot open interrupt pipe (addr %d)\n", - sc->sc_intr_number); - return (EIO); - } - } - - return (0); -} - -static void -ubsa_close(void *addr, int portno) -{ - struct ubsa_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("ubsa_close: close\n")); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "abort interrupt pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "close interrupt pipe failed: %s\n", - usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -ubsa_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ubsa_softc *sc; - u_char *buf; - - sc = priv; - buf = sc->sc_intr_buf; - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: ubsa_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - /* incidentally, Belkin adapter status bits match UART 16550 bits */ - sc->sc_lsr = buf[2]; - sc->sc_msr = buf[3]; - - DPRINTF(("%s: ubsa lsr = 0x%02x, msr = 0x%02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), sc->sc_lsr, sc->sc_msr)); - - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); -} - -/* Handle delayed events. */ -static void -ubsa_notify(void *arg, int count) -{ - struct ubsa_softc *sc; - - sc = arg; - ucom_status_change(&sc->sc_ucom); -} - -static void -ubsa_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct ubsa_softc *sc; - - DPRINTF(("ubsa_get_status\n")); - - sc = addr; - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} diff --git a/sys/dev/usb/ubser.c b/sys/dev/usb/ubser.c deleted file mode 100644 index 29994b9..0000000 --- a/sys/dev/usb/ubser.c +++ /dev/null @@ -1,882 +0,0 @@ -/*- - * Copyright (c) 2004 Bernd Walter <ticso@freebsd.org> - * - * $URL: https://devel.bwct.de/svn/projects/ubser/ubser.c $ - * $Date: 2004-02-29 01:53:10 +0100 (Sun, 29 Feb 2004) $ - * $Author: ticso $ - * $Rev: 1127 $ - */ - -/*- - * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.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. - */ - -/*- - * Copyright (c) 2000 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * BWCT serial adapter driver - */ - -#include <sys/cdefs.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/clist.h> -#include <sys/file.h> - -#include <sys/selinfo.h> - -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/ubser.h> - -#ifdef USB_DEBUG -static int ubserdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ubser, CTLFLAG_RW, 0, "USB ubser"); -SYSCTL_INT(_hw_usb_ubser, OID_AUTO, debug, CTLFLAG_RW, - &ubserdebug, 0, "ubser debug level"); -#define DPRINTF(x) do { \ - if (ubserdebug) \ - printf x; \ - } while (0) - -#define DPRINTFN(n, x) do { \ - if (ubserdebug > (n)) \ - printf x; \ - } while (0) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define ISSET(t, f) ((t) & (f)) -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~((unsigned)(f)) - -struct ubser_port { - int p_port; - struct ubser_softc *p_sc; - usbd_xfer_handle p_oxfer; /* write request */ - u_char *p_obuf; /* write buffer */ - struct tty *p_tty; -}; - -struct ubser_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; /* data interface */ - int sc_ifaceno; - - int sc_refcnt; - u_char sc_dying; - u_char sc_opening; - int sc_state; - uint8_t sc_numser; - - int sc_bulkin_no; /* bulk in endpoint address */ - usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_ixfer; /* read request */ - u_char *sc_ibuf; /* read buffer */ - u_int sc_ibufsize; /* read buffer size */ - u_int sc_ibufsizepad; /* read buffer size padded */ - - int sc_bulkout_no; /* bulk out endpoint address */ - usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ - u_int sc_obufsize; /* write buffer size */ - u_int sc_opkthdrlen; /* header length of - output packet */ - - struct ubser_port *sc_port; -}; - -static int ubserparam(struct tty *, struct termios *); -static void ubserstart(struct tty *); -static void ubserstop(struct tty *, int); -static usbd_status ubserstartread(struct ubser_softc *); -static void ubserreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ubserwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ubser_cleanup(struct ubser_softc *sc); - -static t_break_t ubserbreak; -static t_open_t ubseropen; -static t_close_t ubserclose; -static t_modem_t ubsermodem; - -static device_probe_t ubser_match; -static device_attach_t ubser_attach; -static device_detach_t ubser_detach; - -static device_method_t ubser_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ubser_match), - DEVMETHOD(device_attach, ubser_attach), - DEVMETHOD(device_detach, ubser_detach), - - { 0, 0 } -}; - -static driver_t ubser_driver = { - "ubser", - ubser_methods, - sizeof(struct ubser_softc) -}; - -static devclass_t ubser_devclass; - -static int -ubser_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_string_descriptor_t us; - usb_interface_descriptor_t *id; - usb_device_descriptor_t *dd; - int err, size; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - DPRINTFN(20,("ubser: vendor=0x%x, product=0x%x\n", - uaa->vendor, uaa->product)); - - dd = usbd_get_device_descriptor(uaa->device); - if (dd == NULL) { - printf("ubser: failed to get device descriptor\n"); - return (UMATCH_NONE); - } - - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL) { - printf("ubser: failed to get interface descriptor\n"); - return (UMATCH_NONE); - } - - err = usbd_get_string_desc(uaa->device, dd->iManufacturer, 0, &us, - &size); - if (err != 0) - return (UMATCH_NONE); - - /* check if this is a BWCT vendor specific ubser interface */ - if (strcmp((char*)us.bString, "B\0W\0C\0T\0") == 0 && - id->bInterfaceClass == 0xff && id->bInterfaceSubClass == 0x00) - return (UMATCH_VENDOR_IFACESUBCLASS); - - return (UMATCH_NONE); -} - -static int -ubser_attach(device_t self) -{ - struct ubser_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle udev = uaa->device; - usb_endpoint_descriptor_t *ed; - usb_interface_descriptor_t *id; - usb_device_request_t req; - struct tty *tp; - usbd_status err; - int i; - int alen; - uint8_t epcount; - struct ubser_port *pp; - - sc->sc_dev = self; - - DPRINTFN(10,("\nubser_attach: sc=%p\n", sc)); - - sc->sc_udev = udev = uaa->device; - sc->sc_iface = uaa->iface; - sc->sc_numser = 0; - sc->sc_port = NULL; - - /* get interface index */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL) { - printf("ubser: failed to get interface descriptor\n"); - return (UMATCH_NONE); - } - sc->sc_ifaceno = id->bInterfaceNumber; - - /* get number of serials */ - req.bmRequestType = UT_READ_VENDOR_INTERFACE; - req.bRequest = VENDOR_GET_NUMSER; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 1); - err = usbd_do_request_flags(udev, &req, &sc->sc_numser, - USBD_SHORT_XFER_OK, &alen, USBD_DEFAULT_TIMEOUT); - if (err) { - device_printf(self, "failed to get number of serials\n"); - goto bad; - } else if (alen != 1) { - device_printf(self, "bogus answer on get_numser\n"); - goto bad; - } - if (sc->sc_numser > MAX_SER) - sc->sc_numser = MAX_SER; - device_printf(self, "found %i serials\n", sc->sc_numser); - - sc->sc_port = malloc(sizeof(*sc->sc_port) * sc->sc_numser, - M_USBDEV, M_WAITOK); - - /* find our bulk endpoints */ - epcount = 0; - (void)usbd_endpoint_count(sc->sc_iface, &epcount); - sc->sc_bulkin_no = -1; - sc->sc_bulkout_no = -1; - for (i = 0; i < epcount; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == NULL) { - device_printf(self, "couldn't get ep %d\n", i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_bulkin_no = ed->bEndpointAddress; - sc->sc_ibufsizepad = UGETW(ed->wMaxPacketSize); - sc->sc_ibufsizepad = UGETW(ed->wMaxPacketSize) - 1; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_bulkout_no = ed->bEndpointAddress; - sc->sc_obufsize = UGETW(ed->wMaxPacketSize) - 1; - sc->sc_opkthdrlen = 1; - } - } - if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1) { - device_printf(self, "could not find bulk in/out endpoint\n"); - sc->sc_dying = 1; - goto bad; - } - - /* Open the bulk pipes */ - /* Bulk-in pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, - &sc->sc_bulkin_pipe); - if (err) { - device_printf(self, "open bulk in error (addr %d): %s\n", - sc->sc_bulkin_no, usbd_errstr(err)); - goto fail_0; - } - /* Bulk-out pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - device_printf(self, "open bulk out error (addr %d): %s\n", - sc->sc_bulkout_no, usbd_errstr(err)); - goto fail_1; - } - - /* Allocate a request and an input buffer */ - sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_ixfer == NULL) { - goto fail_2; - } - - sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, - sc->sc_ibufsizepad); - if (sc->sc_ibuf == NULL) { - goto fail_3; - } - - for (i = 0; i < sc->sc_numser; i++) { - pp = &sc->sc_port[i]; - pp->p_port = i; - pp->p_sc = sc; - tp = pp->p_tty = ttyalloc(); - tp->t_sc = pp; - DPRINTF(("ubser_attach: tty_attach tp = %p\n", tp)); - tp->t_oproc = ubserstart; - tp->t_param = ubserparam; - tp->t_stop = ubserstop; - tp->t_break = ubserbreak; - tp->t_open = ubseropen; - tp->t_close = ubserclose; - tp->t_modem = ubsermodem; - ttycreate(tp, 0, "y%r%r", device_get_unit(sc->sc_dev), i); - } - - - for (i = 0; i < sc->sc_numser; i++) { - sc->sc_port[i].p_oxfer = NULL; - sc->sc_port[i].p_obuf = NULL; - } - for (i = 0; i < sc->sc_numser; i++) { - sc->sc_port[i].p_oxfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_port[i].p_oxfer == NULL) { - goto fail_4; - } - - sc->sc_port[i].p_obuf = usbd_alloc_buffer(sc->sc_port[i].p_oxfer, - sc->sc_obufsize + - sc->sc_opkthdrlen); - if (sc->sc_port[i].p_obuf == NULL) { - goto fail_4; - } - } - - ubserstartread(sc); - return 0; - -fail_4: - for (i = 0; i < sc->sc_numser; i++) { - if (sc->sc_port[i].p_oxfer != NULL) { - usbd_free_xfer(sc->sc_port[i].p_oxfer); - sc->sc_port[i].p_oxfer = NULL; - } - } -fail_3: - usbd_free_xfer(sc->sc_ixfer); - sc->sc_ixfer = NULL; -fail_2: - usbd_close_pipe(sc->sc_bulkout_pipe); - sc->sc_bulkout_pipe = NULL; -fail_1: - usbd_close_pipe(sc->sc_bulkin_pipe); - sc->sc_bulkin_pipe = NULL; -fail_0: - sc->sc_opening = 0; - wakeup(&sc->sc_opening); - -bad: - ubser_cleanup(sc); - if (sc->sc_port != NULL) { - for (i = 0; i < sc->sc_numser; i++) { - pp = &sc->sc_port[i]; - if (pp->p_tty != NULL) - ttyfree(pp->p_tty); - } - free(sc->sc_port, M_USBDEV); - sc->sc_port = NULL; - } - - DPRINTF(("ubser_attach: ATTACH ERROR\n")); - return ENXIO; -} - -static int -ubser_detach(device_t self) -{ - struct ubser_softc *sc = device_get_softc(self); - int i; - struct ubser_port *pp; - - DPRINTF(("ubser_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - for (i = 0; i < sc->sc_numser; i++) { - pp = &sc->sc_port[i]; - if (pp->p_tty != NULL) - ttygone(pp->p_tty); - } - - if (sc->sc_bulkin_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkout_pipe); - - if (sc->sc_port != NULL) { - for (i = 0; i < sc->sc_numser; i++) { - pp = &sc->sc_port[i]; - if (pp->p_tty != NULL) - ttyfree(pp->p_tty); - } - free(sc->sc_port, M_USBDEV); - sc->sc_port = NULL; - } - - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - - return (0); -} - -static int -ubserparam(struct tty *tp, struct termios *t) -{ - struct ubser_softc *sc; - struct ubser_port *pp; - - pp = tp->t_sc; - sc = pp->p_sc; - - if (sc->sc_dying) - return (EIO); - - DPRINTF(("ubserparam: sc = %p\n", sc)); - - /* - * The firmware on our devices can only do 8n1@9600bps - * without handshake. - * We refuse to accept other configurations. - */ - - /* enshure 9600bps */ - switch (t->c_ospeed) { - case 9600: - break; - default: - return (EINVAL); - } - - /* 2 stop bits not possible */ - if (ISSET(t->c_cflag, CSTOPB)) - return (EINVAL); - - /* XXX parity handling not possible with current firmware */ - if (ISSET(t->c_cflag, PARENB)) - return (EINVAL); - - /* we can only do 8 data bits */ - switch (ISSET(t->c_cflag, CSIZE)) { - case CS8: - break; - default: - return (EINVAL); - } - - /* we can't do any kind of hardware handshaking */ - if ((t->c_cflag & - (CRTS_IFLOW | CDTR_IFLOW |CDSR_OFLOW |CCAR_OFLOW)) != 0) - return (EINVAL); - - /* - * XXX xon/xoff not supported by the firmware! - * This is handled within FreeBSD only and may overflow buffers - * because of delayed reaction due to device buffering. - */ - - ttsetwater(tp); - - return (0); -} - -static void -ubserstart(struct tty *tp) -{ - struct ubser_softc *sc; - struct ubser_port *pp; - struct cblock *cbp; - usbd_status err; - u_char *data; - int cnt; - uint8_t serial; - - pp = tp->t_sc; - sc = pp->p_sc; - serial = pp->p_port; - DPRINTF(("ubserstart: sc = %p, tp = %p\n", sc, tp)); - - if (sc->sc_dying) - return; - - if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - DPRINTF(("ubserstart: stopped\n")); - return; - } - - if (tp->t_outq.c_cc <= tp->t_olowat) { - if (ISSET(tp->t_state, TS_SO_OLOWAT)) { - CLR(tp->t_state, TS_SO_OLOWAT); - wakeup(TSA_OLOWAT(tp)); - } - selwakeuppri(&tp->t_wsel, TTIPRI); - if (tp->t_outq.c_cc == 0) { - if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) == - TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) { - CLR(tp->t_state, TS_SO_OCOMPLETE); - wakeup(TSA_OCOMPLETE(tp)); - } - return; - } - } - - /* Grab the first contiguous region of buffer space. */ - data = tp->t_outq.c_cf; - cbp = (struct cblock *) ((intptr_t) tp->t_outq.c_cf & ~CROUND); - cnt = min((char *) (cbp+1) - tp->t_outq.c_cf, tp->t_outq.c_cc); - - if (cnt == 0) { - DPRINTF(("ubserstart: cnt == 0\n")); - return; - } - - SET(tp->t_state, TS_BUSY); - - if (cnt + sc->sc_opkthdrlen > sc->sc_obufsize) { - DPRINTF(("ubserstart: big buffer %d chars\n", cnt)); - cnt = sc->sc_obufsize; - } - sc->sc_port[serial].p_obuf[0] = serial; - memcpy(sc->sc_port[serial].p_obuf + sc->sc_opkthdrlen, data, cnt); - - - DPRINTF(("ubserstart: %d chars\n", cnt)); - usbd_setup_xfer(sc->sc_port[serial].p_oxfer, sc->sc_bulkout_pipe, - (usbd_private_handle)tp, sc->sc_port[serial].p_obuf, - cnt + sc->sc_opkthdrlen, - USBD_NO_COPY, USBD_NO_TIMEOUT, ubserwritecb); - /* What can we do on error? */ - err = usbd_transfer(sc->sc_port[serial].p_oxfer); - if (err != USBD_IN_PROGRESS) - printf("ubserstart: err=%s\n", usbd_errstr(err)); - - ttwwakeup(tp); -} - -static void -ubserstop(struct tty *tp, int flag) -{ - struct ubser_softc *sc; - - sc = tp->t_sc; - - DPRINTF(("ubserstop: %d\n", flag)); - - if (flag & FWRITE) { - DPRINTF(("ubserstop: write\n")); - if (ISSET(tp->t_state, TS_BUSY)) { - /* XXX do what? */ - if (!ISSET(tp->t_state, TS_TTSTOP)) - SET(tp->t_state, TS_FLUSH); - } - } - - DPRINTF(("ubserstop: done\n")); -} - -static void -ubserwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) -{ - struct tty *tp; - struct ubser_softc *sc; - struct ubser_port *pp; - u_int32_t cc; - - tp = (struct tty *)p; - pp = tp->t_sc; - sc = pp->p_sc; - - DPRINTF(("ubserwritecb: status = %d\n", status)); - - if (status == USBD_CANCELLED || sc->sc_dying) - goto error; - - if (status != USBD_NORMAL_COMPLETION) { - device_printf(sc->sc_dev, "ubserwritecb: %s\n", - usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - /* XXX we should restart after some delay. */ - goto error; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - DPRINTF(("ubserwritecb: cc = %d\n", cc)); - if (cc <= sc->sc_opkthdrlen) { - device_printf(sc->sc_dev, "sent size too small, cc = %d\n", - cc); - goto error; - } - - /* convert from USB bytes to tty bytes */ - cc -= sc->sc_opkthdrlen; - - CLR(tp->t_state, TS_BUSY); - if (ISSET(tp->t_state, TS_FLUSH)) - CLR(tp->t_state, TS_FLUSH); - else - ndflush(&tp->t_outq, cc); - ttyld_start(tp); - - return; - -error: - CLR(tp->t_state, TS_BUSY); - return; -} - -static usbd_status -ubserstartread(struct ubser_softc *sc) -{ - usbd_status err; - - DPRINTF(("ubserstartread: start\n")); - - if (sc->sc_bulkin_pipe == NULL) - return (USBD_NORMAL_COMPLETION); - - usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, - (usbd_private_handle)sc, - sc->sc_ibuf, sc->sc_ibufsizepad, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, ubserreadcb); - - err = usbd_transfer(sc->sc_ixfer); - if (err != USBD_IN_PROGRESS) { - DPRINTF(("ubserstartread: err = %s\n", usbd_errstr(err))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -ubserreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) -{ - struct ubser_softc *sc = (struct ubser_softc *)p; - struct tty *tp; - usbd_status err; - u_int32_t cc; - u_char *cp; - int lostcc; - - if (status == USBD_IOERROR) { - device_printf(sc->sc_dev, "ubserreadcb: %s - restarting\n", - usbd_errstr(status)); - goto resubmit; - } - - DPRINTF(("ubserreadcb: status = %d\n", status)); - - if (status != USBD_NORMAL_COMPLETION) { - if (status != USBD_CANCELLED) { - device_printf(sc->sc_dev, "ubserreadcb: %s\n", - usbd_errstr(status)); - } - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - return; - } - - usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); - - DPRINTF(("ubserreadcb: got %d bytes from device\n", cc)); - if (cc == 0) - goto resubmit; - - if (cc > sc->sc_ibufsizepad) { - device_printf(sc->sc_dev, "invalid receive data size, %d chars\n", - cc); - goto resubmit; - } - - /* parse header */ - if (cc < 1) - goto resubmit; - DPRINTF(("ubserreadcb: got %d chars for serial %d\n", cc - 1, *cp)); - tp = sc->sc_port[*cp].p_tty; - cp++; - cc--; - - if (cc < 1) - goto resubmit; - - if (!(tp->t_state & TS_ISOPEN)) /* drop data for unused serials */ - goto resubmit; - - if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - if (tp->t_rawq.c_cc + cc > tp->t_ihiwat - && (tp->t_iflag & IXOFF) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - lostcc = b_to_q((char *)cp, cc, &tp->t_rawq); - tp->t_rawcc += cc; - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP - && (tp->t_iflag & IXANY - || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - ubserstart(tp); - } - if (lostcc > 0) - device_printf(sc->sc_dev, "lost %d chars\n", lostcc); - } else { - /* Give characters to tty layer. */ - while (cc > 0) { - DPRINTFN(7, ("ubserreadcb: char = 0x%02x\n", *cp)); - if (ttyld_rint(tp, *cp) == -1) { - /* XXX what should we do? */ - device_printf(sc->sc_dev, "lost %d chars\n", - cc); - break; - } - cc--; - cp++; - } - } - -resubmit: - err = ubserstartread(sc); - if (err) { - device_printf(sc->sc_dev, "read start failed\n"); - /* XXX what should we do now? */ - } - -} - -static void -ubser_cleanup(struct ubser_softc *sc) -{ - int i; - struct ubser_port *pp; - - DPRINTF(("ubser_cleanup: closing pipes\n")); - - 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_ixfer != NULL) { - usbd_free_xfer(sc->sc_ixfer); - sc->sc_ixfer = NULL; - } - for (i = 0; i < sc->sc_numser; i++) { - pp = &sc->sc_port[i]; - if (pp->p_oxfer != NULL) { - usbd_free_xfer(pp->p_oxfer); - pp->p_oxfer = NULL; - } - } -} - -static int -ubseropen(struct tty *tp, struct cdev *dev) -{ - struct ubser_softc *sc; - struct ubser_port *pp; - - pp = tp->t_sc; - sc = pp->p_sc; - - sc->sc_refcnt++; /* XXX: wrong refcnt on error later on */ - return (0); -} - -static void -ubserclose(struct tty *tp) -{ - struct ubser_softc *sc; - struct ubser_port *pp; - - pp = tp->t_sc; - sc = pp->p_sc; - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); -} - -static void -ubserbreak(struct tty *tp, int sig) -{ - usb_device_request_t req; - struct ubser_softc *sc; - struct ubser_port *pp; - int error; - int alen; - - pp = tp->t_sc; - sc = pp->p_sc; - if (sig) { - DPRINTF(("ubser_break: TIOCSBRK\n")); - req.bmRequestType = UT_READ_VENDOR_INTERFACE; - req.bRequest = VENDOR_SET_BREAK; - USETW(req.wValue, pp->p_port); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 0); - error = usbd_do_request_flags(sc->sc_udev, &req, &sc->sc_numser, - USBD_SHORT_XFER_OK, &alen, USBD_DEFAULT_TIMEOUT); - } -} - -static int -ubsermodem(struct tty *tp, int sigon, int sigoff) -{ - - return (SER_DTR | SER_RTS | SER_DCD); -} - -MODULE_DEPEND(ubser, usb, 1, 1, 1); -DRIVER_MODULE(ubser, uhub, ubser_driver, ubser_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/ubser.h b/sys/dev/usb/ubser.h deleted file mode 100644 index f256d4a..0000000 --- a/sys/dev/usb/ubser.h +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 2003 Bernd Walter <ticso@freebsd.org> - * - * $URL: https://devel.bwct.de/svn/projects/ubser/ubser.h $ - * $Date: 2004-02-29 01:53:10 +0100 (Sun, 29 Feb 2004) $ - * $Author: ticso $ - * $Rev: 1127 $ - * - * 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$ - */ - -#ifndef UBSER_H -#define UBSER_H - -#define MAX_SER 32 - -/* Vendor Interface Requests */ -#define VENDOR_GET_NUMSER 0x01 -#define VENDOR_SET_BREAK 0x02 -#define VENDOR_CLEAR_BREAK 0x03 - -#endif /* UBSER_H */ diff --git a/sys/dev/usb/uchcom.c b/sys/dev/usb/uchcom.c deleted file mode 100644 index 85b2629..0000000 --- a/sys/dev/usb/uchcom.c +++ /dev/null @@ -1,1036 +0,0 @@ -/* $NetBSD: uchcom.c,v 1.1 2007/09/03 17:57:37 tshiozak Exp $ */ - -/*- - * Copyright (c) 2007, Takanori Watanabe - * 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. - */ - -/* - * Copyright (c) 2007 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/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * driver for WinChipHead CH341/340, the worst USB-serial chip in the world. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/proc.h> -#include <sys/bus.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/usb_quirks.h> - -#include <dev/usb/ucomvar.h> -#include "usbdevs.h" - -#ifdef UCHCOM_DEBUG -#define DPRINTFN(n, x) if (uchcomdebug > (n)) logprintf x -int uchcomdebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UCHCOM_IFACE_INDEX 0 -#define UCHCOM_CONFIG_INDEX 0 - -#define UCHCOM_REV_CH340 0x0250 -#define UCHCOM_INPUT_BUF_SIZE 8 - -#define UCHCOM_REQ_GET_VERSION 0x5F -#define UCHCOM_REQ_READ_REG 0x95 -#define UCHCOM_REQ_WRITE_REG 0x9A -#define UCHCOM_REQ_RESET 0xA1 -#define UCHCOM_REQ_SET_DTRRTS 0xA4 - -#define UCHCOM_REG_STAT1 0x06 -#define UCHCOM_REG_STAT2 0x07 -#define UCHCOM_REG_BPS_PRE 0x12 -#define UCHCOM_REG_BPS_DIV 0x13 -#define UCHCOM_REG_BPS_MOD 0x14 -#define UCHCOM_REG_BPS_PAD 0x0F -#define UCHCOM_REG_BREAK1 0x05 -#define UCHCOM_REG_BREAK2 0x18 -#define UCHCOM_REG_LCR1 0x18 -#define UCHCOM_REG_LCR2 0x25 - -#define UCHCOM_VER_20 0x20 - -#define UCHCOM_BASE_UNKNOWN 0 -#define UCHCOM_BPS_MOD_BASE 20000000 -#define UCHCOM_BPS_MOD_BASE_OFS 1100 - -#define UCHCOM_DTR_MASK 0x20 -#define UCHCOM_RTS_MASK 0x40 - -#define UCHCOM_BRK1_MASK 0x01 -#define UCHCOM_BRK2_MASK 0x40 - -#define UCHCOM_LCR1_MASK 0xAF -#define UCHCOM_LCR2_MASK 0x07 -#define UCHCOM_LCR1_PARENB 0x80 -#define UCHCOM_LCR2_PAREVEN 0x07 -#define UCHCOM_LCR2_PARODD 0x06 -#define UCHCOM_LCR2_PARMARK 0x05 -#define UCHCOM_LCR2_PARSPACE 0x04 - -#define UCHCOM_INTR_STAT1 0x02 -#define UCHCOM_INTR_STAT2 0x03 -#define UCHCOM_INTR_LEAST 4 - -#define UCHCOMIBUFSIZE 256 -#define UCHCOMOBUFSIZE 256 - -struct uchcom_softc -{ - struct ucom_softc sc_ucom; - - /* */ - int sc_intr_endpoint; - int sc_intr_size; - usbd_pipe_handle sc_intr_pipe; - u_char *sc_intr_buf; - /* */ - uint8_t sc_version; - int sc_dtr; - int sc_rts; - u_char sc_lsr; - u_char sc_msr; - int sc_lcr1; - int sc_lcr2; -}; - -struct uchcom_endpoints -{ - int ep_bulkin; - int ep_bulkout; - int ep_intr; - int ep_intr_size; -}; - -struct uchcom_divider -{ - uint8_t dv_prescaler; - uint8_t dv_div; - uint8_t dv_mod; -}; - -struct uchcom_divider_record -{ - uint32_t dvr_high; - uint32_t dvr_low; - uint32_t dvr_base_clock; - struct uchcom_divider dvr_divider; -}; - -static const struct uchcom_divider_record dividers[] = -{ - { 307200, 307200, UCHCOM_BASE_UNKNOWN, { 7, 0xD9, 0 } }, - { 921600, 921600, UCHCOM_BASE_UNKNOWN, { 7, 0xF3, 0 } }, - { 2999999, 23530, 6000000, { 3, 0, 0 } }, - { 23529, 2942, 750000, { 2, 0, 0 } }, - { 2941, 368, 93750, { 1, 0, 0 } }, - { 367, 1, 11719, { 0, 0, 0 } }, -}; -#define NUM_DIVIDERS (sizeof (dividers) / sizeof (dividers[0])) - -static const struct usb_devno uchcom_devs[] = { - { USB_VENDOR_WCH, USB_PRODUCT_WCH_CH341SER }, -}; -#define uchcom_lookup(v, p) usb_lookup(uchcom_devs, v, p) - -static void uchcom_get_status(void *, int, u_char *, u_char *); -static void uchcom_set(void *, int, int, int); -static int uchcom_param(void *, int, struct termios *); -static int uchcom_open(void *, int); -static void uchcom_close(void *, int); -static void uchcom_intr(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -static int set_config(device_t ); -static int find_ifaces(struct uchcom_softc *, usbd_interface_handle *); -static int find_endpoints(struct uchcom_softc *, - struct uchcom_endpoints *); -static void close_intr_pipe(struct uchcom_softc *); - -static int uchcom_match(device_t ); -static int uchcom_attach(device_t ); -static int uchcom_detach(device_t ); - -struct ucom_callback uchcom_callback = { - .ucom_get_status = uchcom_get_status, - .ucom_set = uchcom_set, - .ucom_param = uchcom_param, - .ucom_ioctl = NULL, - .ucom_open = uchcom_open, - .ucom_close = uchcom_close, - .ucom_read = NULL, - .ucom_write = NULL, -}; - - - - -/* ---------------------------------------------------------------------- - * driver entry points - */ - -static int uchcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - return (uchcom_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int uchcom_attach(device_t self) -{ - struct uchcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - - struct uchcom_endpoints endpoints; - struct ucom_softc *ucom = &sc->sc_ucom; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - - ucom->sc_dying = 0; - sc->sc_dtr = sc->sc_rts = -1; - sc->sc_lsr = sc->sc_msr = 0; - - DPRINTF(("\n\nuchcom attach: sc=%p\n", sc)); - - if (set_config(self)) - goto failed; - - switch (uaa->release) { - case UCHCOM_REV_CH340: - device_printf(self, "CH340 detected\n"); - break; - default: - device_printf(self, "CH341 detected\n"); - break; - } - - if (find_ifaces(sc, &ucom->sc_iface)) - goto failed; - - if (find_endpoints(sc, &endpoints)) - goto failed; - - sc->sc_intr_endpoint = endpoints.ep_intr; - sc->sc_intr_size = endpoints.ep_intr_size; - - /* setup ucom layer */ - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_bulkin_no = endpoints.ep_bulkin; - ucom->sc_bulkout_no = endpoints.ep_bulkout; - ucom->sc_ibufsize = UCHCOMIBUFSIZE; - ucom->sc_obufsize = UCHCOMOBUFSIZE; - ucom->sc_ibufsizepad = UCHCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_parent = sc; - - ucom->sc_callback = &uchcom_callback; - - ucom_attach(&sc->sc_ucom); - - return 0; - -failed: - ucom->sc_dying = 1; - return ENXIO; -} - -static int uchcom_detach(device_t self) -{ - struct uchcom_softc *sc = device_get_softc(self); - struct ucom_softc *ucom = &sc->sc_ucom ; - int rv = 0; - - DPRINTF(("uchcom_detach: sc=%p flags=%d\n", sc, flags)); - - close_intr_pipe(sc); - - ucom->sc_dying = 1; - - rv = ucom_detach(ucom); - - return rv; -} -static int -set_config(device_t dev) -{ - struct uchcom_softc *sc = device_get_softc(dev); - struct ucom_softc *ucom = &sc->sc_ucom; - usbd_status err; - - err = usbd_set_config_index(ucom->sc_udev, UCHCOM_CONFIG_INDEX, 1); - if (err) { - device_printf(dev, "failed to set configuration: %s\n", - usbd_errstr(err)); - return -1; - } - - return 0; -} - -static int -find_ifaces(struct uchcom_softc *sc, usbd_interface_handle *riface) -{ - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - - err = usbd_device2interface_handle(ucom->sc_udev, UCHCOM_IFACE_INDEX, - riface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - return -1; - } - - return 0; -} - -static int -find_endpoints(struct uchcom_softc *sc, struct uchcom_endpoints *endpoints) -{ - struct ucom_softc *ucom= &sc->sc_ucom; - int i, bin=-1, bout=-1, intr=-1, isize=0; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, "no endpoint descriptor for %d\n", i); - return -1; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { - intr = ed->bEndpointAddress; - isize = UGETW(ed->wMaxPacketSize); - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - bin = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - bout = ed->bEndpointAddress; - } - } - - if (intr == -1 || bin == -1 || bout == -1) { - if (intr == -1) { - device_printf(ucom->sc_dev, "no interrupt end point\n"); - } - if (bin == -1) { - device_printf(ucom->sc_dev, "no data bulk in end point\n"); - - } - if (bout == -1) { - device_printf(ucom->sc_dev, "no data bulk out end point\n"); - } - return -1; - } - if (isize < UCHCOM_INTR_LEAST) { - device_printf(ucom->sc_dev, "intr pipe is too short"); - return -1; - } - - DPRINTF(("%s: bulkin=%d, bulkout=%d, intr=%d, isize=%d\n", - USBDEVNAME(sc->sc_dev), bin, bout, intr, isize)); - - endpoints->ep_intr = intr; - endpoints->ep_intr_size = isize; - endpoints->ep_bulkin = bin; - endpoints->ep_bulkout = bout; - - return 0; -} - - -/* ---------------------------------------------------------------------- - * low level i/o - */ - -static __inline usbd_status -generic_control_out(struct uchcom_softc *sc, uint8_t reqno, - uint16_t value, uint16_t index) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = reqno; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, 0); - - return usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); -} - -static __inline usbd_status -generic_control_in(struct uchcom_softc *sc, uint8_t reqno, - uint16_t value, uint16_t index, void *buf, int buflen, - int *actlen) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = reqno; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, (uint16_t)buflen); - - return usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, buf, - USBD_SHORT_XFER_OK, actlen, - USBD_DEFAULT_TIMEOUT); -} - -static __inline usbd_status -write_reg(struct uchcom_softc *sc, - uint8_t reg1, uint8_t val1, uint8_t reg2, uint8_t val2) -{ - DPRINTF(("uchcom: write reg 0x%02X<-0x%02X, 0x%02X<-0x%02X\n", - (unsigned)reg1, (unsigned)val1, - (unsigned)reg2, (unsigned)val2)); - return generic_control_out( - sc, UCHCOM_REQ_WRITE_REG, - reg1|((uint16_t)reg2<<8), val1|((uint16_t)val2<<8)); -} - -static __inline usbd_status -read_reg(struct uchcom_softc *sc, - uint8_t reg1, uint8_t *rval1, uint8_t reg2, uint8_t *rval2) -{ - uint8_t buf[UCHCOM_INPUT_BUF_SIZE]; - usbd_status err; - int actin; - - err = generic_control_in( - sc, UCHCOM_REQ_READ_REG, - reg1|((uint16_t)reg2<<8), 0, buf, sizeof buf, &actin); - if (err) - return err; - - DPRINTF(("uchcom: read reg 0x%02X->0x%02X, 0x%02X->0x%02X\n", - (unsigned)reg1, (unsigned)buf[0], - (unsigned)reg2, (unsigned)buf[1])); - - if (rval1) *rval1 = buf[0]; - if (rval2) *rval2 = buf[1]; - - return USBD_NORMAL_COMPLETION; -} - -static __inline usbd_status -get_version(struct uchcom_softc *sc, uint8_t *rver) -{ - uint8_t buf[UCHCOM_INPUT_BUF_SIZE]; - usbd_status err; - int actin; - - err = generic_control_in( - sc, UCHCOM_REQ_GET_VERSION, 0, 0, buf, sizeof buf, &actin); - if (err) - return err; - - if (rver) *rver = buf[0]; - - return USBD_NORMAL_COMPLETION; -} - -static __inline usbd_status -get_status(struct uchcom_softc *sc, uint8_t *rval) -{ - return read_reg(sc, UCHCOM_REG_STAT1, rval, UCHCOM_REG_STAT2, NULL); -} - -static __inline usbd_status -set_dtrrts_10(struct uchcom_softc *sc, uint8_t val) -{ - return write_reg(sc, UCHCOM_REG_STAT1, val, UCHCOM_REG_STAT1, val); -} - -static __inline usbd_status -set_dtrrts_20(struct uchcom_softc *sc, uint8_t val) -{ - return generic_control_out(sc, UCHCOM_REQ_SET_DTRRTS, val, 0); -} - - -/* ---------------------------------------------------------------------- - * middle layer - */ - -static int -update_version(struct uchcom_softc *sc) -{ - usbd_status err; - - err = get_version(sc, &sc->sc_version); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot get version: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static void -convert_status(struct uchcom_softc *sc, uint8_t cur) -{ - sc->sc_dtr = !(cur & UCHCOM_DTR_MASK); - sc->sc_rts = !(cur & UCHCOM_RTS_MASK); - - cur = ~cur & 0x0F; - sc->sc_msr = (cur << 4) | ((sc->sc_msr >> 4) ^ cur); -} - -static int -update_status(struct uchcom_softc *sc) -{ - usbd_status err; - uint8_t cur; - - err = get_status(sc, &cur); - if (err) { - device_printf(sc->sc_ucom.sc_dev, - "cannot update status: %s\n", - usbd_errstr(err)); - return EIO; - } - convert_status(sc, cur); - - return 0; -} - - -static int -set_dtrrts(struct uchcom_softc *sc, int dtr, int rts) -{ - usbd_status err; - uint8_t val = 0; - - if (dtr) val |= UCHCOM_DTR_MASK; - if (rts) val |= UCHCOM_RTS_MASK; - - if (sc->sc_version < UCHCOM_VER_20) - err = set_dtrrts_10(sc, ~val); - else - err = set_dtrrts_20(sc, ~val); - - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot set DTR/RTS: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -set_break(struct uchcom_softc *sc, int onoff) -{ - usbd_status err; - uint8_t brk1, brk2; - - err = read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_BREAK2, &brk2); - if (err) - return EIO; - if (onoff) { - /* on - clear bits */ - brk1 &= ~UCHCOM_BRK1_MASK; - brk2 &= ~UCHCOM_BRK2_MASK; - } else { - /* off - set bits */ - brk1 |= UCHCOM_BRK1_MASK; - brk2 |= UCHCOM_BRK2_MASK; - } - err = write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_BREAK2, brk2); - if (err) - return EIO; - - return 0; -} - -static int -calc_divider_settings(struct uchcom_divider *dp, uint32_t rate) -{ - int i; - const struct uchcom_divider_record *rp; - uint32_t div, rem, mod; - - /* find record */ - for (i=0; i<NUM_DIVIDERS; i++) { - if (dividers[i].dvr_high >= rate && - dividers[i].dvr_low <= rate) { - rp = ÷rs[i]; - goto found; - } - } - return -1; - -found: - dp->dv_prescaler = rp->dvr_divider.dv_prescaler; - if (rp->dvr_base_clock == UCHCOM_BASE_UNKNOWN) - dp->dv_div = rp->dvr_divider.dv_div; - else { - div = rp->dvr_base_clock / rate; - rem = rp->dvr_base_clock % rate; - if (div==0 || div>=0xFF) - return -1; - if ((rem<<1) >= rate) - div += 1; - dp->dv_div = (uint8_t)-div; - } - - mod = UCHCOM_BPS_MOD_BASE/rate + UCHCOM_BPS_MOD_BASE_OFS; - mod = mod + mod/2; - - dp->dv_mod = mod / 0x100; - - return 0; -} - -static int -set_dte_rate(struct uchcom_softc *sc, uint32_t rate) -{ - usbd_status err; - struct uchcom_divider dv; - - if (calc_divider_settings(&dv, rate)) - return EINVAL; - - if ((err = write_reg(sc, - UCHCOM_REG_BPS_PRE, dv.dv_prescaler, - UCHCOM_REG_BPS_DIV, dv.dv_div)) || - (err = write_reg(sc, - UCHCOM_REG_BPS_MOD, dv.dv_mod, - UCHCOM_REG_BPS_PAD, 0))) { - device_printf(sc->sc_ucom.sc_dev, " cannot set DTE rate: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -set_line_control(struct uchcom_softc *sc, tcflag_t cflag) -{ - usbd_status err; - uint8_t lcr1 = 0, lcr2 = 0; - - err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - if (err) { - device_printf(sc->sc_ucom.sc_dev, " cannot get LCR: %s\n", - usbd_errstr(err)); - return EIO; - } - - lcr1 &= ~UCHCOM_LCR1_MASK; - lcr2 &= ~UCHCOM_LCR2_MASK; - - /* - * XXX: it is difficult to handle the line control appropriately: - * - CS8, !CSTOPB and any parity mode seems ok, but - * - the chip doesn't have the function to calculate parity - * in !CS8 mode. - * - it is unclear that the chip supports CS5,6 mode. - * - it is unclear how to handle stop bits. - */ - - switch (ISSET(cflag, CSIZE)) { - case CS5: - case CS6: - case CS7: - return EINVAL; - case CS8: - break; - } - - if (ISSET(cflag, PARENB)) { - lcr1 |= UCHCOM_LCR1_PARENB; - if (ISSET(cflag, PARODD)) - lcr2 |= UCHCOM_LCR2_PARODD; - else - lcr2 |= UCHCOM_LCR2_PAREVEN; - } - - err = write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2, lcr2); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot set LCR: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -clear_chip(struct uchcom_softc *sc) -{ - usbd_status err; - - DPRINTF(("%s: clear\n", USBDEVNAME(sc->sc_dev))); - err = generic_control_out(sc, UCHCOM_REQ_RESET, 0, 0); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "cannot clear: %s\n", - usbd_errstr(err)); - return EIO; - } - - return 0; -} - -static int -reset_chip(struct uchcom_softc *sc) -{ - usbd_status err; - uint8_t lcr1, lcr2, pre, div, mod; - uint16_t val=0, idx=0; - - err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - if (err) - goto failed; - - err = read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV, &div); - if (err) - goto failed; - - err = read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD, NULL); - if (err) - goto failed; - - val |= (uint16_t)(lcr1&0xF0) << 8; - val |= 0x01; - val |= (uint16_t)(lcr2&0x0F) << 8; - val |= 0x02; - idx |= pre & 0x07; - val |= 0x04; - idx |= (uint16_t)div << 8; - val |= 0x08; - idx |= mod & 0xF8; - val |= 0x10; - - DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n", - USBDEVNAME(sc->sc_dev), val, idx)); - - err = generic_control_out(sc, UCHCOM_REQ_RESET, val, idx); - if (err) - goto failed; - - return 0; - -failed: - device_printf(sc->sc_ucom.sc_dev, "cannot reset: %s\n", - usbd_errstr(err)); - return EIO; -} - -static int -setup_comm(struct uchcom_softc *sc) -{ - int ret; - - ret = update_version(sc); - if (ret) - return ret; - - ret = clear_chip(sc); - if (ret) - return ret; - - ret = set_dte_rate(sc, TTYDEF_SPEED); - if (ret) - return ret; - - ret = set_line_control(sc, CS8); - if (ret) - return ret; - - ret = update_status(sc); - if (ret) - return ret; - - ret = reset_chip(sc); - if (ret) - return ret; - - ret = set_dte_rate(sc, TTYDEF_SPEED); /* XXX */ - if (ret) - return ret; - - sc->sc_dtr = sc->sc_rts = 1; - ret = set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - if (ret) - return ret; - - return 0; -} - -static int -setup_intr_pipe(struct uchcom_softc *sc) -{ - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - if (sc->sc_intr_endpoint != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = malloc(sc->sc_intr_size, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(ucom->sc_iface, - sc->sc_intr_endpoint, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, sc, - sc->sc_intr_buf, - sc->sc_intr_size, - uchcom_intr, USBD_DEFAULT_INTERVAL); - if (err) { - device_printf(ucom->sc_dev, - "cannot open interrupt pipe: %s\n", - usbd_errstr(err)); - return EIO; - } - } - return 0; -} - -static void -close_intr_pipe(struct uchcom_softc *sc) -{ - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - if (ucom->sc_dying) - return; - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(ucom->sc_dev, - "abort interrupt pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(ucom->sc_dev, - " close interrupt pipe failed: %s\n", - usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - - -/* ---------------------------------------------------------------------- - * methods for ucom - */ -void -uchcom_get_status(void *arg, int portno, u_char *rlsr, u_char *rmsr) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - *rlsr = sc->sc_lsr; - *rmsr = sc->sc_msr; -} - -void -uchcom_set(void *arg, int portno, int reg, int onoff) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - switch (reg) { - case UCOM_SET_DTR: - sc->sc_dtr = !!onoff; - set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - break; - case UCOM_SET_RTS: - sc->sc_rts = !!onoff; - set_dtrrts(sc, sc->sc_dtr, sc->sc_rts); - break; - case UCOM_SET_BREAK: - set_break(sc, onoff); - break; - } -} - -int -uchcom_param(void *arg, int portno, struct termios *t) -{ - struct uchcom_softc *sc = arg; - int ret; - - if (sc->sc_ucom.sc_dying) - return 0; - - ret = set_line_control(sc, t->c_cflag); - if (ret) - return ret; - - ret = set_dte_rate(sc, t->c_ospeed); - if (ret) - return ret; - - return 0; -} - -int -uchcom_open(void *arg, int portno) -{ - int ret; - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return EIO; - - ret = setup_intr_pipe(sc); - if (ret) - return ret; - - ret = setup_comm(sc); - if (ret) - return ret; - - return 0; -} - -void -uchcom_close(void *arg, int portno) -{ - struct uchcom_softc *sc = arg; - - if (sc->sc_ucom.sc_dying) - return; - - close_intr_pipe(sc); -} - - -/* ---------------------------------------------------------------------- - * callback when the modem status is changed. - */ -void -uchcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - struct uchcom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - - if (sc->sc_ucom.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: intr: 0x%02X 0x%02X 0x%02X 0x%02X " - "0x%02X 0x%02X 0x%02X 0x%02X\n", - USBDEVNAME(sc->sc_dev), - (unsigned)buf[0], (unsigned)buf[1], - (unsigned)buf[2], (unsigned)buf[3], - (unsigned)buf[4], (unsigned)buf[5], - (unsigned)buf[6], (unsigned)buf[7])); - - convert_status(sc, buf[UCHCOM_INTR_STAT1]); - ucom_status_change(&sc->sc_ucom); -} - -static device_method_t uchcom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uchcom_match), - DEVMETHOD(device_attach, uchcom_attach), - DEVMETHOD(device_detach, uchcom_detach), - - { 0, 0 } -}; - -static driver_t uchcom_driver = { - "ucom", - uchcom_methods, - sizeof (struct uchcom_softc) -}; - -DRIVER_MODULE(uchcom, uhub, uchcom_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uchcom, usb, 1, 1, 1); -MODULE_DEPEND(uchcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c deleted file mode 100644 index ae263a0..0000000 --- a/sys/dev/usb/ucom.c +++ /dev/null @@ -1,829 +0,0 @@ -/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ - -/*- - * Copyright (c) 2001-2003, 2005, 2008 - * Shunsuke Akiyama <akiyama@jp.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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998, 2000 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/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -#ifdef USB_DEBUG -static int ucomdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom"); -SYSCTL_INT(_hw_usb_ucom, OID_AUTO, debug, CTLFLAG_RW, - &ucomdebug, 0, "ucom debug level"); -#define DPRINTF(x) do { \ - if (ucomdebug) \ - printf x; \ - } while (0) - -#define DPRINTFN(n, x) do { \ - if (ucomdebug > (n)) \ - printf x; \ - } while (0) -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) -#endif - -static int ucom_modevent(module_t, int, void *); -static void ucom_cleanup(struct ucom_softc *); -static void ucom_shutdown(struct ucom_softc *); -static void ucom_dtr(struct ucom_softc *, int); -static void ucom_rts(struct ucom_softc *, int); -static void ucombreak(struct ucom_softc *, int); -static usbd_status ucomstartread(struct ucom_softc *); -static void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void ucomstopread(struct ucom_softc *); - -static tsw_open_t ucomtty_open; -static tsw_close_t ucomtty_close; -static tsw_outwakeup_t ucomtty_outwakeup; -static tsw_ioctl_t ucomtty_ioctl; -static tsw_param_t ucomtty_param; -static tsw_modem_t ucomtty_modem; -static tsw_free_t ucomtty_free; - -static struct ttydevsw ucomtty_class = { - .tsw_flags = TF_INITLOCK|TF_CALLOUT, - .tsw_open = ucomtty_open, - .tsw_close = ucomtty_close, - .tsw_outwakeup = ucomtty_outwakeup, - .tsw_ioctl = ucomtty_ioctl, - .tsw_param = ucomtty_param, - .tsw_modem = ucomtty_modem, - .tsw_free = ucomtty_free, -}; - -devclass_t ucom_devclass; - -static moduledata_t ucom_mod = { - "ucom", - ucom_modevent, - NULL -}; - -DECLARE_MODULE(ucom, ucom_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); -MODULE_DEPEND(ucom, usb, 1, 1, 1); -MODULE_VERSION(ucom, UCOM_MODVER); - -static int -ucom_modevent(module_t mod, int type, void *data) -{ - switch (type) { - case MOD_LOAD: - case MOD_UNLOAD: - return (0); - default: - return (EOPNOTSUPP); - } -} - -void -ucom_attach_tty(struct ucom_softc *sc, char* fmt, int unit) -{ - struct tty *tp; - - sc->sc_tty = tp = tty_alloc(&ucomtty_class, sc, &Giant); - tty_makedev(tp, NULL, fmt, unit); -} - -int -ucom_attach(struct ucom_softc *sc) -{ - - ucom_attach_tty(sc, "U%d", device_get_unit(sc->sc_dev)); - - DPRINTF(("ucom_attach: ttycreate: tp = %p, %s\n", - sc->sc_tty, sc->sc_tty->t_dev->si_name)); - - return (0); -} - -int -ucom_detach(struct ucom_softc *sc) -{ - DPRINTF(("ucom_detach: sc = %p, tp = %p\n", sc, sc->sc_tty)); - - tty_lock(sc->sc_tty); - sc->sc_dying = 1; - - if (sc->sc_bulkin_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkout_pipe); - - tty_rel_gone(sc->sc_tty); - - return (0); -} - -static void -ucom_shutdown(struct ucom_softc *sc) -{ - struct tty *tp = sc->sc_tty; - - DPRINTF(("ucom_shutdown\n")); - /* - * Hang up if necessary. Wait a bit, so the other side has time to - * notice even if we immediately open the port again. - */ - if (tp->t_termios.c_cflag & HUPCL) { - (void)ucomtty_modem(tp, 0, SER_DTR); -#if 0 - (void)tsleep(sc, TTIPRI, "ucomsd", hz); -#endif - } -} - -static int -ucomtty_open(struct tty *tp) -{ - struct ucom_softc *sc = tty_softc(tp); - usbd_status err; - int error; - - if (sc->sc_dying) - return (ENXIO); - - DPRINTF(("%s: ucomtty_open: tp = %p\n", device_get_nameunit(sc->sc_dev), tp)); - - sc->sc_poll = 0; - sc->sc_lsr = sc->sc_msr = sc->sc_mcr = 0; - - (void)ucomtty_modem(tp, SER_DTR | SER_RTS, 0); - - /* Device specific open */ - if (sc->sc_callback->ucom_open != NULL) { - error = sc->sc_callback->ucom_open(sc->sc_parent, - sc->sc_portno); - if (error) { - ucom_cleanup(sc); - return (error); - } - } - - DPRINTF(("ucomtty_open: open pipes in = %d out = %d\n", - sc->sc_bulkin_no, sc->sc_bulkout_no)); - - /* Open the bulk pipes */ - /* Bulk-in pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, - &sc->sc_bulkin_pipe); - if (err) { - printf("%s: open bulk in error (addr %d): %s\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkin_no, - usbd_errstr(err)); - error = EIO; - goto fail; - } - /* Bulk-out pipe */ - err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - printf("%s: open bulk out error (addr %d): %s\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkout_no, - usbd_errstr(err)); - error = EIO; - goto fail; - } - - /* Allocate a request and an input buffer and start reading. */ - sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_ixfer == NULL) { - error = ENOMEM; - goto fail; - } - - sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, - sc->sc_ibufsizepad); - if (sc->sc_ibuf == NULL) { - error = ENOMEM; - goto fail; - } - - sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_oxfer == NULL) { - error = ENOMEM; - goto fail; - } - - sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, - sc->sc_obufsize + - sc->sc_opkthdrlen); - if (sc->sc_obuf == NULL) { - error = ENOMEM; - goto fail; - } - - sc->sc_state |= UCS_RXSTOP; - ucomstartread(sc); - - sc->sc_poll = 1; - - return (0); - -fail: - ucom_cleanup(sc); - return (error); -} - -static void -ucomtty_close(struct tty *tp) -{ - struct ucom_softc *sc = tty_softc(tp); - - DPRINTF(("%s: ucomtty_close \n", device_get_nameunit(sc->sc_dev))); - - ucom_cleanup(sc); - - if (sc->sc_callback->ucom_close != NULL) - sc->sc_callback->ucom_close(sc->sc_parent, sc->sc_portno); -} - -static int -ucomtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *p) -{ - struct ucom_softc *sc = tty_softc(tp); - int error; - - if (sc->sc_dying) - return (EIO); - - DPRINTF(("ucomioctl: cmd = 0x%08lx\n", cmd)); - - switch (cmd) { - case TIOCSBRK: - ucombreak(sc, 1); - return (0); - case TIOCCBRK: - ucombreak(sc, 0); - return (0); - } - - error = ENOIOCTL; - if (sc->sc_callback->ucom_ioctl != NULL) - error = sc->sc_callback->ucom_ioctl(sc->sc_parent, - sc->sc_portno, - cmd, data, p); - return (error); -} - -static int -ucomtty_modem(struct tty *tp, int sigon, int sigoff) -{ - struct ucom_softc *sc = tty_softc(tp); - int mcr; - int msr; - int onoff; - - if (sigon == 0 && sigoff == 0) { - mcr = sc->sc_mcr; - if (ISSET(mcr, SER_DTR)) - sigon |= SER_DTR; - if (ISSET(mcr, SER_RTS)) - sigon |= SER_RTS; - - msr = sc->sc_msr; - if (ISSET(msr, SER_CTS)) - sigon |= SER_CTS; - if (ISSET(msr, SER_DCD)) - sigon |= SER_DCD; - if (ISSET(msr, SER_DSR)) - sigon |= SER_DSR; - if (ISSET(msr, SER_RI)) - sigon |= SER_RI; - return (sigon); - } - - mcr = sc->sc_mcr; - if (ISSET(sigon, SER_DTR)) - mcr |= SER_DTR; - if (ISSET(sigoff, SER_DTR)) - mcr &= ~SER_DTR; - if (ISSET(sigon, SER_RTS)) - mcr |= SER_RTS; - if (ISSET(sigoff, SER_RTS)) - mcr &= ~SER_RTS; - sc->sc_mcr = mcr; - - onoff = ISSET(sc->sc_mcr, SER_DTR) ? 1 : 0; - ucom_dtr(sc, onoff); - - onoff = ISSET(sc->sc_mcr, SER_RTS) ? 1 : 0; - ucom_rts(sc, onoff); - - return (0); -} - -static void -ucombreak(struct ucom_softc *sc, int onoff) -{ - DPRINTF(("ucombreak: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_BREAK, onoff); -} - -static void -ucom_dtr(struct ucom_softc *sc, int onoff) -{ - DPRINTF(("ucom_dtr: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_DTR, onoff); -} - -static void -ucom_rts(struct ucom_softc *sc, int onoff) -{ - DPRINTF(("ucom_rts: onoff = %d\n", onoff)); - - if (sc->sc_callback->ucom_set == NULL) - return; - sc->sc_callback->ucom_set(sc->sc_parent, sc->sc_portno, - UCOM_SET_RTS, onoff); -} - -void -ucom_status_change(struct ucom_softc *sc) -{ - struct tty *tp = sc->sc_tty; - u_char old_msr; - int onoff; - - if (sc->sc_callback->ucom_get_status == NULL) { - sc->sc_lsr = 0; - sc->sc_msr = 0; - return; - } - - old_msr = sc->sc_msr; - sc->sc_callback->ucom_get_status(sc->sc_parent, sc->sc_portno, - &sc->sc_lsr, &sc->sc_msr); - if (ISSET((sc->sc_msr ^ old_msr), SER_DCD)) { - if (sc->sc_poll == 0) - return; - onoff = ISSET(sc->sc_msr, SER_DCD) ? 1 : 0; - DPRINTF(("ucom_status_change: DCD changed to %d\n", onoff)); - ttydisc_modem(tp, onoff); - } -} - -static int -ucomtty_param(struct tty *tp, struct termios *t) -{ - struct ucom_softc *sc = tty_softc(tp); - int error; - usbd_status uerr; - - if (sc->sc_dying) - return (EIO); - - DPRINTF(("ucomtty_param: sc = %p\n", sc)); - - /* Check requested parameters. */ - if (t->c_ospeed < 0) { - DPRINTF(("ucomtty_param: negative ospeed\n")); - return (EINVAL); - } - if (t->c_ispeed && t->c_ispeed != t->c_ospeed) { - DPRINTF(("ucomtty_param: mismatch ispeed and ospeed\n")); - return (EINVAL); - } - t->c_ispeed = t->c_ospeed; - - if (sc->sc_callback->ucom_param == NULL) - return (0); - - ucomstopread(sc); - - error = sc->sc_callback->ucom_param(sc->sc_parent, sc->sc_portno, t); - if (error) { - DPRINTF(("ucomtty_param: callback: error = %d\n", error)); - return (error); - } - -#if 0 - ttsetwater(tp); -#endif - - if (t->c_cflag & CRTS_IFLOW) { - sc->sc_state |= UCS_RTS_IFLOW; - } else if (sc->sc_state & UCS_RTS_IFLOW) { - sc->sc_state &= ~UCS_RTS_IFLOW; - (void)ucomtty_modem(tp, SER_RTS, 0); - } - -#if 0 - ttyldoptim(tp); -#endif - - uerr = ucomstartread(sc); - if (uerr != USBD_NORMAL_COMPLETION) - return (EIO); - - return (0); -} - -static void -ucomtty_free(void *sc) -{ - /* - * Our softc gets deallocated earlier on. - * XXX: we should make sure the TTY device name doesn't get - * recycled before we end up here! - */ -} - -static void -ucomtty_outwakeup(struct tty *tp) -{ - struct ucom_softc *sc = tty_softc(tp); - usbd_status err; - size_t cnt; - - DPRINTF(("ucomtty_outwakeup: sc = %p\n", sc)); - - if (sc->sc_dying) - return; - - /* - * If there's no sc_oxfer, then ucomclose has removed it. The buffer - * has just been flushed in the ttyflush() in ttyclose(). ttyflush() - * then calls tt_stop(). ucomstop calls ucomstart, so the right thing - * to do here is just abort if sc_oxfer is NULL, as everything else - * is cleaned up elsewhere. - */ - if (sc->sc_oxfer == NULL) - return; - - /* XXX: hardware flow control. We should use inwakeup here. */ -#if 0 - if (tp->t_state & TS_TBLOCK) { - if (ISSET(sc->sc_mcr, SER_RTS) && - ISSET(sc->sc_state, UCS_RTS_IFLOW)) { - DPRINTF(("ucomtty_outwakeup: clear RTS\n")); - (void)ucomtty_modem(tp, 0, SER_RTS); - } - } else { - if (!ISSET(sc->sc_mcr, SER_RTS) && - tp->t_rawq.c_cc <= tp->t_ilowat && - ISSET(sc->sc_state, UCS_RTS_IFLOW)) { - DPRINTF(("ucomtty_outwakeup: set RTS\n")); - (void)ucomtty_modem(tp, SER_RTS, 0); - } - } -#endif - - if (sc->sc_state & UCS_TXBUSY) - return; - - sc->sc_state |= UCS_TXBUSY; - if (sc->sc_callback->ucom_write != NULL) - cnt = sc->sc_callback->ucom_write(sc->sc_parent, - sc->sc_portno, tp, sc->sc_obuf, sc->sc_obufsize); - else - cnt = ttydisc_getc(tp, sc->sc_obuf, sc->sc_obufsize); - - if (cnt == 0) { - DPRINTF(("ucomtty_outwakeup: cnt == 0\n")); - sc->sc_state &= ~UCS_TXBUSY; - return; - } - sc->sc_obufactive = cnt; - - DPRINTF(("ucomtty_outwakeup: %zu chars\n", cnt)); - usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, - (usbd_private_handle)sc, sc->sc_obuf, cnt, - USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); - /* What can we do on error? */ - err = usbd_transfer(sc->sc_oxfer); - if (err != USBD_IN_PROGRESS) { - printf("ucomtty_outwakeup: err=%s\n", usbd_errstr(err)); - sc->sc_state &= ~UCS_TXBUSY; - } -} - -#if 0 -static void -ucomstop(struct tty *tp, int flag) -{ - struct ucom_softc *sc = tty_softc(tp); - int s; - - DPRINTF(("ucomstop: %d\n", flag)); - - if ((flag & FREAD) && (sc->sc_state & UCS_RXSTOP) == 0) { - DPRINTF(("ucomstop: read\n")); - ucomstopread(sc); - ucomstartread(sc); - } - - if (flag & FWRITE) { - DPRINTF(("ucomstop: write\n")); - if (ISSET(tp->t_state, TS_BUSY)) { - /* XXX do what? */ - if (!ISSET(tp->t_state, TS_TTSTOP)) - SET(tp->t_state, TS_FLUSH); - } - } - - ucomtty_outwakeup(tp); - - DPRINTF(("ucomstop: done\n")); -} -#endif - -static void -ucomwritecb(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; - u_int32_t cc; - - DPRINTF(("ucomwritecb: status = %d\n", status)); - - if (status == USBD_CANCELLED || sc->sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - printf("%s: ucomwritecb: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - /* XXX we should restart after some delay. */ - return; - } - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - DPRINTF(("ucomwritecb: cc = %d\n", cc)); - if (cc <= sc->sc_opkthdrlen) { - printf("%s: sent size too small, cc = %d\n", - device_get_nameunit(sc->sc_dev), cc); - return; - } - - /* convert from USB bytes to tty bytes */ - cc -= sc->sc_opkthdrlen; - if (cc != sc->sc_obufactive) - panic("Partial write of %d of %d bytes, not supported\n", - cc, sc->sc_obufactive); - - sc->sc_state &= ~UCS_TXBUSY; -#if 0 - CLR(tp->t_state, TS_BUSY); - if (ISSET(tp->t_state, TS_FLUSH)) - CLR(tp->t_state, TS_FLUSH); - else - ndflush(&tp->t_outq, cc); -#endif - ucomtty_outwakeup(tp); -} - -static usbd_status -ucomstartread(struct ucom_softc *sc) -{ - usbd_status err; - - DPRINTF(("ucomstartread: start\n")); - - if (sc->sc_bulkin_pipe == NULL || (sc->sc_state & UCS_RXSTOP) == 0) - return (USBD_NORMAL_COMPLETION); - sc->sc_state &= ~UCS_RXSTOP; - - usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, - (usbd_private_handle)sc, - sc->sc_ibuf, sc->sc_ibufsize, - USBD_SHORT_XFER_OK | USBD_NO_COPY, - USBD_NO_TIMEOUT, ucomreadcb); - - err = usbd_transfer(sc->sc_ixfer); - if (err && err != USBD_IN_PROGRESS) { - sc->sc_state |= UCS_RXSTOP; - DPRINTF(("ucomstartread: err = %s\n", usbd_errstr(err))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -void -ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc) -{ - struct tty *tp = sc->sc_tty; - - /* Give characters to tty layer. */ - if (ttydisc_can_bypass(tp)) { - DPRINTFN(7, ("ucomreadcb: buf = %*D\n", cc, cp, "")); - cc -= ttydisc_rint_bypass(tp, cp, cc); - } else { - while (cc > 0) { - DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp)); - if (ttydisc_rint(tp, *cp, 0) == -1) - break; - cc--; - cp++; - } - } - if (cc > 0) - device_printf(sc->sc_dev, "lost %d chars\n", cc); - ttydisc_rint_done(tp); -} - -static void -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; - usbd_status err; - u_int32_t cc; - u_char *cp; - - (void)tp; /* Used for debugging */ - DPRINTF(("ucomreadcb: status = %d\n", status)); - - if (status != USBD_NORMAL_COMPLETION) { - if (!(sc->sc_state & UCS_RXSTOP)) - printf("%s: ucomreadcb: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(status)); - sc->sc_state |= UCS_RXSTOP; - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); - /* XXX we should restart after some delay. */ - return; - } - sc->sc_state |= UCS_RXSTOP; - - usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); - DPRINTF(("ucomreadcb: got %d chars, tp = %p\n", cc, tp)); - if (cc == 0) - goto resubmit; - - if (sc->sc_callback->ucom_read != NULL) - sc->sc_callback->ucom_read(sc->sc_parent, sc->sc_portno, - &cp, &cc); - - if (cc > sc->sc_ibufsize) { - printf("%s: invalid receive data size, %d chars\n", - device_get_nameunit(sc->sc_dev), cc); - goto resubmit; - } - if (cc > 0) - ucomrxchars(sc, cp, cc); - - resubmit: - err = ucomstartread(sc); - if (err) { - printf("%s: read start failed\n", device_get_nameunit(sc->sc_dev)); - /* XXX what should we dow now? */ - } - -#if 0 - if ((sc->sc_state & UCS_RTS_IFLOW) && !ISSET(sc->sc_mcr, SER_RTS) - && !(tp->t_state & TS_TBLOCK)) - ucomtty_modem(tp, SER_RTS, 0); -#endif -} - -static void -ucom_cleanup(struct ucom_softc *sc) -{ - DPRINTF(("ucom_cleanup: closing pipes\n")); - - ucom_shutdown(sc); - if (sc->sc_bulkin_pipe != NULL) { - sc->sc_state |= UCS_RXSTOP; - 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_ixfer != NULL) { - usbd_free_xfer(sc->sc_ixfer); - sc->sc_ixfer = NULL; - } - if (sc->sc_oxfer != NULL) { - usbd_free_xfer(sc->sc_oxfer); - sc->sc_oxfer = NULL; - } -} - -static void -ucomstopread(struct ucom_softc *sc) -{ - usbd_status err; - - DPRINTF(("ucomstopread: enter\n")); - - if (!(sc->sc_state & UCS_RXSTOP)) { - sc->sc_state |= UCS_RXSTOP; - if (sc->sc_bulkin_pipe == NULL) { - DPRINTF(("ucomstopread: bulkin pipe NULL\n")); - return; - } - err = usbd_abort_pipe(sc->sc_bulkin_pipe); - if (err) { - DPRINTF(("ucomstopread: err = %s\n", - usbd_errstr(err))); - } - } - - DPRINTF(("ucomstopread: leave\n")); -} diff --git a/sys/dev/usb/ucomvar.h b/sys/dev/usb/ucomvar.h deleted file mode 100644 index 4433a1a..0000000 --- a/sys/dev/usb/ucomvar.h +++ /dev/null @@ -1,169 +0,0 @@ -/* $NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama@jp.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. - */ - -/*- - * Copyright (c) 1999 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. - */ - -/* Module interface related macros */ -#define UCOM_MODVER 1 - -#define UCOM_MINVER 1 -#define UCOM_PREFVER UCOM_MODVER -#define UCOM_MAXVER 1 - -/* Macros to clear/set/test flags. */ -#define SET(t, f) (t) |= (f) -#define CLR(t, f) (t) &= ~((unsigned)(f)) -#define ISSET(t, f) ((t) & (f)) - -#define UCOM_CALLOUT_MASK 0x80 - -#define UCOMUNIT_MASK 0x3ff7f -#define UCOMDIALOUT_MASK 0x80000 -#define UCOMCALLUNIT_MASK 0x40000 - -#define UCOMUNIT(x) (dev2unit(x) & UCOMUNIT_MASK) -#define UCOMDIALOUT(x) (dev2unit(x) & UCOMDIALOUT_MASK) -#define UCOMCALLUNIT(x) (dev2unit(x) & UCOMCALLUNIT_MASK) - -#define UCOM_UNK_PORTNO -1 /* XXX */ - -struct tty; -struct ucom_softc; - -struct ucom_callback { - void (*ucom_get_status)(void *, int, u_char *, u_char *); - void (*ucom_set)(void *, int, int, int); -#define UCOM_SET_DTR 1 -#define UCOM_SET_RTS 2 -#define UCOM_SET_BREAK 3 - int (*ucom_param)(void *, int, struct termios *); - int (*ucom_ioctl)(void *, int, u_long, caddr_t, struct thread *); - int (*ucom_open)(void *, int); - void (*ucom_close)(void *, int); - void (*ucom_read)(void *, int, u_char **, u_int32_t *); - size_t (*ucom_write)(void *, int, struct tty *, u_char *, u_int32_t); -}; - -/* line status register */ -#define ULSR_RCV_FIFO 0x80 -#define ULSR_TSRE 0x40 /* Transmitter empty: byte sent */ -#define ULSR_TXRDY 0x20 /* Transmitter buffer empty */ -#define ULSR_BI 0x10 /* Break detected */ -#define ULSR_FE 0x08 /* Framing error: bad stop bit */ -#define ULSR_PE 0x04 /* Parity error */ -#define ULSR_OE 0x02 /* Overrun, lost incoming byte */ -#define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */ -#define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */ - -/* ucom state declarations */ -#define UCS_RXSTOP 0x0001 /* Rx stopped */ -#define UCS_TXBUSY 0x0002 /* Tx busy */ -#define UCS_RTS_IFLOW 0x0008 /* use RTS input flow control */ - -struct ucom_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - usbd_interface_handle sc_iface; /* data interface */ - - int sc_bulkin_no; /* bulk in endpoint address */ - usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_ixfer; /* read request */ - u_char *sc_ibuf; /* read buffer */ - u_int sc_ibufsize; /* read buffer size */ - u_int sc_ibufsizepad; /* read buffer size padded */ - - int sc_bulkout_no; /* bulk out endpoint address */ - usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ - usbd_xfer_handle sc_oxfer; /* write request */ - u_char *sc_obuf; /* write buffer */ - u_int sc_obufsize; /* write buffer size */ - u_int sc_opkthdrlen; /* header length of - output packet */ - u_int sc_obufactive; /* Active bytes in buffer */ - - struct ucom_callback *sc_callback; - void *sc_parent; - int sc_portno; - - struct tty *sc_tty; /* our tty */ - - int sc_state; - - int sc_poll; - - u_char sc_lsr; - u_char sc_msr; - u_char sc_mcr; - - u_char sc_dying; /* disconnecting */ - -}; - -extern devclass_t ucom_devclass; - -void ucom_attach_tty(struct ucom_softc *, char*, int); -int ucom_attach(struct ucom_softc *); -int ucom_detach(struct ucom_softc *); -void ucom_status_change(struct ucom_softc *); -void ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc); diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c deleted file mode 100644 index ecf115f..0000000 --- a/sys/dev/usb/ucycom.c +++ /dev/null @@ -1,543 +0,0 @@ -/*- - * Copyright (c) 2004 Dag-Erling Coïdan Smørgrav - * 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 - * in this position and unchanged. - * 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. 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. - * - * $FreeBSD$ - */ - -/* - * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to - * RS232 bridges. - * - * Normally, a driver for a USB-to-serial chip would hang off the ucom(4) - * driver, but ucom(4) was written under the assumption that all USB-to- - * serial chips use bulk pipes for I/O, while the Cypress parts use HID - * reports. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/sysctl.h> -#include <sys/bus.h> -#include <sys/tty.h> - -#include "usbdevs.h" -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbhid.h> -#include <dev/usb/hid.h> - -#define UCYCOM_EP_INPUT 0 -#define UCYCOM_EP_OUTPUT 1 - -#define UCYCOM_MAX_IOLEN 32U - -struct ucycom_softc { - device_t sc_dev; - struct tty *sc_tty; - int sc_error; - unsigned long sc_cintr; - unsigned long sc_cin; - unsigned long sc_clost; - unsigned long sc_cout; - - /* usb parameters */ - usbd_device_handle sc_usbdev; - usbd_interface_handle sc_iface; - usbd_pipe_handle sc_pipe; - uint8_t sc_iep; /* input endpoint */ - uint8_t sc_fid; /* feature report id*/ - uint8_t sc_iid; /* input report id */ - uint8_t sc_oid; /* output report id */ - size_t sc_flen; /* feature report length */ - size_t sc_ilen; /* input report length */ - size_t sc_olen; /* output report length */ - uint8_t sc_ibuf[UCYCOM_MAX_IOLEN]; - - /* model and settings */ - uint32_t sc_model; -#define MODEL_CY7C63743 0x63743 -#define MODEL_CY7C64013 0x64013 - uint32_t sc_baud; - uint8_t sc_cfg; -#define UCYCOM_CFG_RESET 0x80 -#define UCYCOM_CFG_PARODD 0x20 -#define UCYCOM_CFG_PAREN 0x10 -#define UCYCOM_CFG_STOPB 0x08 -#define UCYCOM_CFG_DATAB 0x03 - uint8_t sc_ist; /* status flags from last input */ - uint8_t sc_ost; /* status flags for next output */ - - /* flags */ - char sc_dying; -}; - -static device_probe_t ucycom_probe; -static device_attach_t ucycom_attach; -static device_detach_t ucycom_detach; -static t_open_t ucycom_open; -static t_close_t ucycom_close; -static void ucycom_start(struct tty *); -static void ucycom_stop(struct tty *, int); -static int ucycom_param(struct tty *, struct termios *); -static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); -static void ucycom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static device_method_t ucycom_methods[] = { - DEVMETHOD(device_probe, ucycom_probe), - DEVMETHOD(device_attach, ucycom_attach), - DEVMETHOD(device_detach, ucycom_detach), - { 0, 0 } -}; - -static driver_t ucycom_driver = { - "ucycom", - ucycom_methods, - sizeof(struct ucycom_softc), -}; - -static devclass_t ucycom_devclass; - -DRIVER_MODULE(ucycom, uhub, ucycom_driver, ucycom_devclass, usbd_driver_load, 0); -MODULE_VERSION(ucycom, 1); -MODULE_DEPEND(ucycom, usb, 1, 1, 1); - -/* - * Supported devices - */ - -static struct ucycom_device { - uint16_t vendor; - uint16_t product; - uint32_t model; -} ucycom_devices[] = { - { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, MODEL_CY7C64013 }, - { 0, 0, 0 }, -}; - -#define UCYCOM_DEFAULT_RATE 4800 -#define UCYCOM_DEFAULT_CFG 0x03 /* N-8-1 */ - -/***************************************************************************** - * - * Driver interface - * - */ - -static int -ucycom_probe(device_t dev) -{ - struct usb_attach_arg *uaa; - struct ucycom_device *ud; - - uaa = device_get_ivars(dev); - if (uaa->iface != NULL) - return (UMATCH_NONE); - for (ud = ucycom_devices; ud->model != 0; ++ud) - if (ud->vendor == uaa->vendor && ud->product == uaa->product) - return (UMATCH_VENDOR_PRODUCT); - return (UMATCH_NONE); -} - -static int -ucycom_attach(device_t dev) -{ - struct usb_attach_arg *uaa; - struct ucycom_softc *sc; - struct ucycom_device *ud; - usb_endpoint_descriptor_t *ued; - void *urd; - int error, urdlen; - - /* get arguments and softc */ - uaa = device_get_ivars(dev); - sc = device_get_softc(dev); - bzero(sc, sizeof *sc); - sc->sc_dev = dev; - sc->sc_usbdev = uaa->device; - - /* get chip model */ - for (ud = ucycom_devices; ud->model != 0; ++ud) - if (ud->vendor == uaa->vendor && ud->product == uaa->product) - sc->sc_model = ud->model; - if (sc->sc_model == 0) { - device_printf(dev, "unsupported device\n"); - return (ENXIO); - } - device_printf(dev, "Cypress CY7C%X USB to RS232 bridge\n", sc->sc_model); - - /* select configuration */ - error = usbd_set_config_index(sc->sc_usbdev, 0, 1 /* verbose */); - if (error != 0) { - device_printf(dev, "failed to select configuration: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get first interface handle */ - error = usbd_device2interface_handle(sc->sc_usbdev, 0, &sc->sc_iface); - if (error != 0) { - device_printf(dev, "failed to get interface handle: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get report descriptor */ - error = usbd_read_report_desc(sc->sc_iface, &urd, &urdlen, M_USBDEV); - if (error != 0) { - device_printf(dev, "failed to get report descriptor: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - /* get report sizes */ - sc->sc_flen = hid_report_size(urd, urdlen, hid_feature, &sc->sc_fid); - sc->sc_ilen = hid_report_size(urd, urdlen, hid_input, &sc->sc_iid); - sc->sc_olen = hid_report_size(urd, urdlen, hid_output, &sc->sc_oid); - - if (sc->sc_ilen > UCYCOM_MAX_IOLEN || sc->sc_olen > UCYCOM_MAX_IOLEN) { - device_printf(dev, "I/O report size too big (%zu, %zu, %u)\n", - sc->sc_ilen, sc->sc_olen, UCYCOM_MAX_IOLEN); - return (ENXIO); - } - - /* get and verify input endpoint descriptor */ - ued = usbd_interface2endpoint_descriptor(sc->sc_iface, UCYCOM_EP_INPUT); - if (ued == NULL) { - device_printf(dev, "failed to get input endpoint descriptor\n"); - return (ENXIO); - } - if (UE_GET_DIR(ued->bEndpointAddress) != UE_DIR_IN) { - device_printf(dev, "not an input endpoint\n"); - return (ENXIO); - } - if ((ued->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - device_printf(dev, "not an interrupt endpoint\n"); - return (ENXIO); - } - sc->sc_iep = ued->bEndpointAddress; - - /* set up tty */ - sc->sc_tty = ttyalloc(); - sc->sc_tty->t_sc = sc; - sc->sc_tty->t_oproc = ucycom_start; - sc->sc_tty->t_stop = ucycom_stop; - sc->sc_tty->t_param = ucycom_param; - sc->sc_tty->t_open = ucycom_open; - sc->sc_tty->t_close = ucycom_close; - - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "intr", CTLFLAG_RD, &sc->sc_cintr, 0, - "interrupt count"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "in", CTLFLAG_RD, &sc->sc_cin, 0, - "input bytes read"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "lost", CTLFLAG_RD, &sc->sc_clost, 0, - "input bytes lost"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), - OID_AUTO, "out", CTLFLAG_RD, &sc->sc_cout, 0, - "output bytes"); - - /* create character device node */ - ttycreate(sc->sc_tty, 0, "y%r", device_get_unit(sc->sc_dev)); - - return (0); -} - -static int -ucycom_detach(device_t dev) -{ - struct ucycom_softc *sc; - - sc = device_get_softc(dev); - - ttyfree(sc->sc_tty); - - return (0); -} - -/***************************************************************************** - * - * Device interface - * - */ - -static int -ucycom_open(struct tty *tp, struct cdev *cdev) -{ - struct ucycom_softc *sc = tp->t_sc; - int error; - - /* set default configuration */ - ucycom_configure(sc, UCYCOM_DEFAULT_RATE, UCYCOM_DEFAULT_CFG); - - /* open interrupt pipe */ - error = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep, 0, - &sc->sc_pipe, sc, sc->sc_ibuf, sc->sc_ilen, - ucycom_intr, USBD_DEFAULT_INTERVAL); - if (error != 0) { - device_printf(sc->sc_dev, "failed to open interrupt pipe: %s\n", - usbd_errstr(error)); - return (ENXIO); - } - - if (bootverbose) - device_printf(sc->sc_dev, "%s bypass l_rint()\n", - (sc->sc_tty->t_state & TS_CAN_BYPASS_L_RINT) ? - "can" : "can't"); - - /* done! */ - return (0); -} - -static void -ucycom_close(struct tty *tp) -{ - struct ucycom_softc *sc = tp->t_sc; - - /* stop interrupts and close the interrupt pipe */ - usbd_abort_pipe(sc->sc_pipe); - usbd_close_pipe(sc->sc_pipe); - sc->sc_pipe = 0; - - return; -} - -/***************************************************************************** - * - * TTY interface - * - */ - -static void -ucycom_start(struct tty *tty) -{ - struct ucycom_softc *sc = tty->t_sc; - uint8_t report[sc->sc_olen]; - int error, len; - - while (sc->sc_error == 0 && sc->sc_tty->t_outq.c_cc > 0) { - switch (sc->sc_model) { - case MODEL_CY7C63743: - len = q_to_b(&sc->sc_tty->t_outq, - report + 1, sc->sc_olen - 1); - sc->sc_cout += len; - report[0] = len; - len += 1; - break; - case MODEL_CY7C64013: - len = q_to_b(&sc->sc_tty->t_outq, - report + 2, sc->sc_olen - 2); - sc->sc_cout += len; - report[0] = 0; - report[1] = len; - len += 2; - break; - default: - panic("unsupported model (driver error)"); - } - - while (len < sc->sc_olen) - report[len++] = 0; - error = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT, - sc->sc_oid, report, sc->sc_olen); -#if 0 - if (error != 0) { - device_printf(sc->sc_dev, - "failed to set output report: %s\n", - usbd_errstr(error)); - sc->sc_error = error; - } -#endif - } -} - -static void -ucycom_stop(struct tty *tty, int flags) -{ - struct ucycom_softc *sc; - - sc = tty->t_sc; - if (bootverbose) - device_printf(sc->sc_dev, "%s()\n", __func__); -} - -static int -ucycom_param(struct tty *tty, struct termios *t) -{ - struct ucycom_softc *sc; - uint32_t baud; - uint8_t cfg; - int error; - - sc = tty->t_sc; - - if (t->c_ispeed != t->c_ospeed) - return (EINVAL); - baud = t->c_ispeed; - - if (t->c_cflag & CIGNORE) { - cfg = sc->sc_cfg; - } else { - cfg = 0; - switch (t->c_cflag & CSIZE) { - case CS8: - ++cfg; - case CS7: - ++cfg; - case CS6: - ++cfg; - case CS5: - break; - default: - return (EINVAL); - } - if (t->c_cflag & CSTOPB) - cfg |= UCYCOM_CFG_STOPB; - if (t->c_cflag & PARENB) - cfg |= UCYCOM_CFG_PAREN; - if (t->c_cflag & PARODD) - cfg |= UCYCOM_CFG_PARODD; - } - - error = ucycom_configure(sc, baud, cfg); - return (error); -} - -/***************************************************************************** - * - * Hardware interface - * - */ - -static int -ucycom_configure(struct ucycom_softc *sc, uint32_t baud, uint8_t cfg) -{ - uint8_t report[sc->sc_flen]; - int error; - - switch (baud) { - case 600: - case 1200: - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: -#if 0 - /* - * Stock chips only support standard baud rates in the 600 - 57600 - * range, but higher rates can be achieved using custom firmware. - */ - case 115200: - case 153600: - case 192000: -#endif - break; - default: - return (EINVAL); - } - - if (bootverbose) - device_printf(sc->sc_dev, "%d baud, %c-%d-%d\n", baud, - (cfg & UCYCOM_CFG_PAREN) ? - ((cfg & UCYCOM_CFG_PARODD) ? 'O' : 'E') : 'N', - 5 + (cfg & UCYCOM_CFG_DATAB), - (cfg & UCYCOM_CFG_STOPB) ? 2 : 1); - report[0] = baud & 0xff; - report[1] = (baud >> 8) & 0xff; - report[2] = (baud >> 16) & 0xff; - report[3] = (baud >> 24) & 0xff; - report[4] = cfg; - error = usbd_set_report(sc->sc_iface, UHID_FEATURE_REPORT, - sc->sc_fid, report, sc->sc_flen); - if (error != 0) { - device_printf(sc->sc_dev, "%s\n", usbd_errstr(error)); - return (EIO); - } - sc->sc_baud = baud; - sc->sc_cfg = cfg; - return (0); -} - -static void -ucycom_intr(usbd_xfer_handle xfer, usbd_private_handle scp, usbd_status status) -{ - struct ucycom_softc *sc = scp; - uint8_t *data; - int i, len, lost; - - sc->sc_cintr++; - - switch (sc->sc_model) { - case MODEL_CY7C63743: - sc->sc_ist = sc->sc_ibuf[0] & ~0x07; - len = sc->sc_ibuf[0] & 0x07; - data = sc->sc_ibuf + 1; - break; - case MODEL_CY7C64013: - sc->sc_ist = sc->sc_ibuf[0] & ~0x07; - len = sc->sc_ibuf[1]; - data = sc->sc_ibuf + 2; - break; - default: - panic("unsupported model (driver error)"); - } - - switch (status) { - case USBD_NORMAL_COMPLETION: - break; - default: - /* XXX */ - return; - } - - if (sc->sc_tty->t_state & TS_CAN_BYPASS_L_RINT) { - /* XXX flow control! */ - lost = b_to_q(data, len, &sc->sc_tty->t_rawq); - sc->sc_tty->t_rawcc += len - lost; - ttwakeup(sc->sc_tty); - } else { - for (i = 0, lost = len; i < len; ++i, --lost) - if (ttyld_rint(sc->sc_tty, data[i]) != 0) - break; - } - sc->sc_cin += len - lost; - sc->sc_clost += lost; -} diff --git a/sys/dev/usb/udbp.c b/sys/dev/usb/udbp.c deleted file mode 100644 index 523184f..0000000 --- a/sys/dev/usb/udbp.c +++ /dev/null @@ -1,860 +0,0 @@ -/*- - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * 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. Neither the name of author 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 NICK HIBMA 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. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* Driver for arbitrary double bulk pipe devices. - * The driver assumes that there will be the same driver on the other side. - * - * XXX Some more information on what the framing of the IP packets looks like. - * - * To take full advantage of bulk transmission, packets should be chosen - * between 1k and 5k in size (1k to make sure the sending side starts - * straming, and <5k to avoid overflowing the system with small TDs). - */ - - -/* probe/attach/detach: - * Connect the driver to the hardware and netgraph - * - * udbp_setup_out_transfer(sc); - * Setup an outbound transfer. Only one transmit can be active at the same - * time. - * XXX If it is required that the driver is able to queue multiple requests - * let me know. That is slightly difficult, due to the fact that we - * cannot call usbd_alloc_xfer in int context. - * - * udbp_setup_in_transfer(sc) - * Prepare an in transfer that will be waiting for data to come in. It - * is submitted and sits there until data is available. - * The callback resubmits a new transfer on completion. - * - * The reason we submit a bulk in transfer is that USB does not know about - * interrupts. The bulk transfer continuously polls the device for data. - * While the device has no data available, the device NAKs the TDs. As soon - * as there is data, the transfer happens and the data comes flowing in. - * - * In case you were wondering, interrupt transfers happen exactly that way. - * It therefore doesn't make sense to use the interrupt pipe to signal - * 'data ready' and then schedule a bulk transfer to fetch it. That would - * incur a 2ms delay at least, without reducing bandwidth requirements. - * - */ - - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/poll.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/ctype.h> -#include <sys/errno.h> -#include <sys/sysctl.h> -#include <net/if.h> -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usbhid.h> - -#include "usbdevs.h" - - -#include <netgraph/ng_message.h> -#include <netgraph/ng_parse.h> -#include <dev/usb/udbp.h> -#include <netgraph/netgraph.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (udbpdebug) printf x -#define DPRINTFN(n,x) if (udbpdebug>(n)) printf x -int udbpdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp"); -SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW, - &udbpdebug, 0, "udbp debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#define UDBP_TIMEOUT 2000 /* timeout on outbound transfers, in msecs */ -#define UDBP_BUFFERSIZE 2048 /* maximum number of bytes in one transfer */ - - -struct udbp_softc { - device_t sc_dev; /* base device */ - usbd_interface_handle sc_iface; - - usbd_pipe_handle sc_bulkin_pipe; - int sc_bulkin; - usbd_xfer_handle sc_bulkin_xfer; - void *sc_bulkin_buffer; - int sc_bulkin_bufferlen; - int sc_bulkin_datalen; - - usbd_pipe_handle sc_bulkout_pipe; - int sc_bulkout; - usbd_xfer_handle sc_bulkout_xfer; - void *sc_bulkout_buffer; - int sc_bulkout_bufferlen; - int sc_bulkout_datalen; - - int flags; -# define DISCONNECTED 0x01 -# define OUT_BUSY 0x02 -# define NETGRAPH_INITIALISED 0x04 - node_p node; /* back pointer to node */ - hook_p hook; /* pointer to the hook */ - u_int packets_in; /* packets in from downstream */ - u_int packets_out; /* packets out towards downstream */ - struct ifqueue xmitq_hipri; /* hi-priority transmit queue */ - struct ifqueue xmitq; /* low-priority transmit queue */ - -}; -typedef struct udbp_softc *udbp_p; - - - -static ng_constructor_t ng_udbp_constructor; -static ng_rcvmsg_t ng_udbp_rcvmsg; -static ng_shutdown_t ng_udbp_rmnode; -static ng_newhook_t ng_udbp_newhook; -static ng_connect_t ng_udbp_connect; -static ng_rcvdata_t ng_udbp_rcvdata; -static ng_disconnect_t ng_udbp_disconnect; - -/* Parse type for struct ngudbpstat */ -static const struct ng_parse_struct_field - ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO; -static const struct ng_parse_type ng_udbp_stat_type = { - &ng_parse_struct_type, - &ng_udbp_stat_type_fields -}; - -/* List of commands and how to convert arguments to/from ASCII */ -static const struct ng_cmdlist ng_udbp_cmdlist[] = { - { - NGM_UDBP_COOKIE, - NGM_UDBP_GET_STATUS, - "getstatus", - NULL, - &ng_udbp_stat_type, - }, - { - NGM_UDBP_COOKIE, - NGM_UDBP_SET_FLAG, - "setflag", - &ng_parse_int32_type, - NULL - }, - { 0 } -}; - -/* Netgraph node type descriptor */ -static struct ng_type ng_udbp_typestruct = { - .version = NG_ABI_VERSION, - .name = NG_UDBP_NODE_TYPE, - .constructor = ng_udbp_constructor, - .rcvmsg = ng_udbp_rcvmsg, - .shutdown = ng_udbp_rmnode, - .newhook = ng_udbp_newhook, - .connect = ng_udbp_connect, - .rcvdata = ng_udbp_rcvdata, - .disconnect = ng_udbp_disconnect, - .cmdlist = ng_udbp_cmdlist, -}; - -static int udbp_setup_in_transfer (udbp_p sc); -static void udbp_in_transfer_cb (usbd_xfer_handle xfer, - usbd_private_handle priv, - usbd_status err); - -static int udbp_setup_out_transfer (udbp_p sc); -static void udbp_out_transfer_cb (usbd_xfer_handle xfer, - usbd_private_handle priv, - usbd_status err); - -static device_probe_t udbp_match; -static device_attach_t udbp_attach; -static device_detach_t udbp_detach; - -static device_method_t udbp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, udbp_match), - DEVMETHOD(device_attach, udbp_attach), - DEVMETHOD(device_detach, udbp_detach), - - { 0, 0 } -}; - -static driver_t udbp_driver = { - "udbp", - udbp_methods, - sizeof(struct udbp_softc) -}; - -static devclass_t udbp_devclass; - -static int -udbp_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - if (!uaa->iface) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - - /* XXX Julian, add the id of the device if you have one to test - * things with. run 'usbdevs -v' and note the 3 ID's that appear. - * The Vendor Id and Product Id are in hex and the Revision Id is in - * bcd. But as usual if the revision is 0x101 then you should compare - * the revision id in the device descriptor with 0x101 - * Or go search the file usbdevs.h. Maybe the device is already in - * there. - */ - if ((uaa->vendor == USB_VENDOR_NETCHIP && - uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT)) - return (UMATCH_VENDOR_PRODUCT); - - if ((uaa->vendor == USB_VENDOR_PROLIFIC && - (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 || - uaa->product == USB_PRODUCT_PROLIFIC_PL2302))) - return (UMATCH_VENDOR_PRODUCT); - - if ((uaa->vendor == USB_VENDOR_ANCHOR && - uaa->product == USB_PRODUCT_ANCHOR_EZLINK)) - return (UMATCH_VENDOR_PRODUCT); - - if ((uaa->vendor == USB_VENDOR_GENESYS && - uaa->product == USB_PRODUCT_GENESYS_GL620USB)) - return (UMATCH_VENDOR_PRODUCT); - - return (UMATCH_NONE); -} - -static int -udbp_attach(device_t self) -{ - struct udbp_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL; - usbd_status err; - int i; - static int ngudbp_done_init=0; - - sc->flags |= DISCONNECTED; - /* fetch the interface handle for the first interface */ - (void) usbd_device2interface_handle(uaa->device, 0, &iface); - id = usbd_get_interface_descriptor(iface); - sc->sc_dev = self; - - /* Find the two first bulk endpoints */ - for (i = 0 ; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (!ed) { - device_printf(self, "could not read endpoint descriptor\n"); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkin = ed; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkout = ed; - } - - if (ed_bulkin && ed_bulkout) /* found all we need */ - break; - } - - /* Verify that we goething sensible */ - if (ed_bulkin == NULL || ed_bulkout == NULL) { - device_printf(self, "bulk-in and/or bulk-out endpoint not found\n"); - return ENXIO; - } - - if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] || - ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) { - device_printf(self, - "bulk-in and bulk-out have different packet sizes %d %d %d %d\n", - ed_bulkin->wMaxPacketSize[0], - ed_bulkout->wMaxPacketSize[0], - ed_bulkin->wMaxPacketSize[1], - ed_bulkout->wMaxPacketSize[1]); - return ENXIO; - } - - sc->sc_bulkin = ed_bulkin->bEndpointAddress; - sc->sc_bulkout = ed_bulkout->bEndpointAddress; - - DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n", - device_get_nameunit(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout, - ed_bulkin->wMaxPacketSize[0])); - - /* Allocate the in transfer struct */ - sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device); - if (!sc->sc_bulkin_xfer) { - goto bad; - } - sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device); - if (!sc->sc_bulkout_xfer) { - goto bad; - } - sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK); - if (!sc->sc_bulkin_buffer) { - goto bad; - } - sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK); - if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) { - goto bad; - } - sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE; - sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE; - - /* We have decided on which endpoints to use, now open the pipes */ - err = usbd_open_pipe(iface, sc->sc_bulkin, - USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); - if (err) { - device_printf(self, "cannot open bulk-in pipe (addr %d)\n", - sc->sc_bulkin); - goto bad; - } - err = usbd_open_pipe(iface, sc->sc_bulkout, - USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); - if (err) { - device_printf(self, "cannot open bulk-out pipe (addr %d)\n", - sc->sc_bulkout); - goto bad; - } - - if (!ngudbp_done_init){ - ngudbp_done_init=1; - if (ng_newtype(&ng_udbp_typestruct)) { - printf("ngudbp install failed\n"); - goto bad; - } - } - - if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) { - char nodename[128]; - sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev)); - if ((err = ng_name_node(sc->node, nodename))) { - NG_NODE_UNREF(sc->node); - sc->node = NULL; - goto bad; - } else { - NG_NODE_SET_PRIVATE(sc->node, sc); - sc->xmitq.ifq_maxlen = IFQ_MAXLEN; - sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN; - mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL, - MTX_DEF); - mtx_init(&sc->xmitq_hipri.ifq_mtx, - "usb_xmitq_hipri", NULL, MTX_DEF); - } - } - sc->flags = NETGRAPH_INITIALISED; - /* sc->flags &= ~DISCONNECTED; */ /* XXX */ - - - /* the device is now operational */ - - - /* schedule the first incoming xfer */ - err = udbp_setup_in_transfer(sc); - if (err) { - goto bad; - } - return 0; -bad: -#if 0 /* probably done in udbp_detach() */ - if (sc->sc_bulkout_buffer) { - free(sc->sc_bulkout_buffer, M_USBDEV); - } - if (sc->sc_bulkin_buffer) { - free(sc->sc_bulkin_buffer, M_USBDEV); - } - if (sc->sc_bulkout_xfer) { - usbd_free_xfer(sc->sc_bulkout_xfer); - } - if (sc->sc_bulkin_xfer) { - usbd_free_xfer(sc->sc_bulkin_xfer); - } -#endif - udbp_detach(self); - return ENXIO; -} - - -static int -udbp_detach(device_t self) -{ - struct udbp_softc *sc = device_get_softc(self); - - sc->flags |= DISCONNECTED; - - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - - if (sc->sc_bulkin_pipe) { - usbd_abort_pipe(sc->sc_bulkin_pipe); - usbd_close_pipe(sc->sc_bulkin_pipe); - } - if (sc->sc_bulkout_pipe) { - usbd_abort_pipe(sc->sc_bulkout_pipe); - usbd_close_pipe(sc->sc_bulkout_pipe); - } - - if (sc->flags & NETGRAPH_INITIALISED) { - ng_rmnode_self(sc->node); - NG_NODE_SET_PRIVATE(sc->node, NULL); - NG_NODE_UNREF(sc->node); - sc->node = NULL; /* Paranoid */ - } - - if (sc->sc_bulkin_xfer) - usbd_free_xfer(sc->sc_bulkin_xfer); - if (sc->sc_bulkout_xfer) - usbd_free_xfer(sc->sc_bulkout_xfer); - - if (sc->sc_bulkin_buffer) - free(sc->sc_bulkin_buffer, M_USBDEV); - if (sc->sc_bulkout_buffer) - free(sc->sc_bulkout_buffer, M_USBDEV); - return 0; -} - - -static int -udbp_setup_in_transfer(udbp_p sc) -{ - void *priv = sc; /* XXX this should probably be some pointer to - * struct describing the transfer (mbuf?) - * See also below. - */ - usbd_status err; - - /* XXX - * How should we arrange for 2 extra bytes at the start of the - * packet? - */ - - /* Initialise a USB transfer and then schedule it */ - - (void) usbd_setup_xfer( sc->sc_bulkin_xfer, - sc->sc_bulkin_pipe, - priv, - sc->sc_bulkin_buffer, - sc->sc_bulkin_bufferlen, - USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, - udbp_in_transfer_cb); - - err = usbd_transfer(sc->sc_bulkin_xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(("%s: failed to setup in-transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - udbp_p sc = priv; /* XXX see priv above */ - int s; - int len; - struct mbuf *m; - - if (err) { - if (err != USBD_CANCELLED) { - DPRINTF(("%s: bulk-out transfer failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - } else { - /* USBD_CANCELLED happens at unload of the driver */ - return; - } - - /* Transfer has failed, packet is not received */ - } else { - - len = xfer->actlen; - - s = splimp(); /* block network stuff too */ - if (sc->hook) { - /* get packet from device and send on */ - m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL); - NG_SEND_DATA_ONLY(err, sc->hook, m); - } - splx(s); - - } - /* schedule the next in transfer */ - udbp_setup_in_transfer(sc); -} - - -static int -udbp_setup_out_transfer(udbp_p sc) -{ - void *priv = sc; /* XXX this should probably be some pointer to - * struct describing the transfer (mbuf?) - * See also below. - */ - int pktlen; - usbd_status err; - int s, s1; - struct mbuf *m; - - - s = splusb(); - if (sc->flags & OUT_BUSY) - panic("out transfer already in use, we should add queuing"); - sc->flags |= OUT_BUSY; - splx(s); - s1 = splimp(); /* Queueing happens at splnet */ - IF_DEQUEUE(&sc->xmitq_hipri, m); - if (m == NULL) { - IF_DEQUEUE(&sc->xmitq, m); - } - splx(s1); - - if (!m) { - sc->flags &= ~OUT_BUSY; - return (USBD_NORMAL_COMPLETION); - } - - pktlen = m->m_pkthdr.len; - if (pktlen > sc->sc_bulkout_bufferlen) { - device_printf(sc->sc_dev, "Packet too large, %d > %d\n", - pktlen, sc->sc_bulkout_bufferlen); - return (USBD_IOERROR); - } - - m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer); - m_freem(m); - - /* Initialise a USB transfer and then schedule it */ - - (void) usbd_setup_xfer( sc->sc_bulkout_xfer, - sc->sc_bulkout_pipe, - priv, - sc->sc_bulkout_buffer, - pktlen, - USBD_SHORT_XFER_OK, - UDBP_TIMEOUT, - udbp_out_transfer_cb); - - err = usbd_transfer(sc->sc_bulkout_xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(("%s: failed to setup out-transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - udbp_p sc = priv; /* XXX see priv above */ - int s; - - if (err) { - DPRINTF(("%s: bulk-out transfer failed: %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - /* Transfer has failed, packet is not transmitted */ - /* XXX Invalidate packet */ - return; - } - - /* packet has been transmitted */ - - s = splusb(); /* mark the buffer available */ - sc->flags &= ~OUT_BUSY; - udbp_setup_out_transfer(sc); - splx(s); -} - -DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0); -MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); -MODULE_DEPEND(udbp, usb, 1, 1, 1); - - -/*********************************************************************** - * Start of Netgraph methods - **********************************************************************/ - -/* - * If this is a device node so this work is done in the attach() - * routine and the constructor will return EINVAL as you should not be able - * to create nodes that depend on hardware (unless you can add the hardware :) - */ -static int -ng_udbp_constructor(node_p node) -{ - return (EINVAL); -} - -/* - * Give our ok for a hook to be added... - * If we are not running this might kick a device into life. - * Possibly decode information out of the hook name. - * Add the hook's private info to the hook structure. - * (if we had some). In this example, we assume that there is a - * an array of structs, called 'channel' in the private info, - * one for each active channel. The private - * pointer of each hook points to the appropriate UDBP_hookinfo struct - * so that the source of an input packet is easily identified. - */ -static int -ng_udbp_newhook(node_p node, hook_p hook, const char *name) -{ - const udbp_p sc = NG_NODE_PRIVATE(node); - -#if 0 - /* Possibly start up the device if it's not already going */ - if ((sc->flags & SCF_RUNNING) == 0) { - ng_udbp_start_hardware(sc); - } -#endif - - if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) { - sc->hook = hook; - NG_HOOK_SET_PRIVATE(hook, NULL); - } else { - return (EINVAL); /* not a hook we know about */ - } - return(0); -} - -/* - * Get a netgraph control message. - * Check it is one we understand. If needed, send a response. - * We could save the address for an async action later, but don't here. - * Always free the message. - * The response should be in a malloc'd region that the caller can 'free'. - * A response is not required. - * Theoretically you could respond defferently to old message types if - * the cookie in the header didn't match what we consider to be current - * (so that old userland programs could continue to work). - */ -static int -ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook) -{ - const udbp_p sc = NG_NODE_PRIVATE(node); - struct ng_mesg *resp = NULL; - int error = 0; - struct ng_mesg *msg; - - NGI_GET_MSG(item, msg); - /* Deal with message according to cookie and command */ - switch (msg->header.typecookie) { - case NGM_UDBP_COOKIE: - switch (msg->header.cmd) { - case NGM_UDBP_GET_STATUS: - { - struct ngudbpstat *stats; - - NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); - if (!resp) { - error = ENOMEM; - break; - } - stats = (struct ngudbpstat *) resp->data; - stats->packets_in = sc->packets_in; - stats->packets_out = sc->packets_out; - break; - } - case NGM_UDBP_SET_FLAG: - if (msg->header.arglen != sizeof(u_int32_t)) { - error = EINVAL; - break; - } - sc->flags = *((u_int32_t *) msg->data); - break; - default: - error = EINVAL; /* unknown command */ - break; - } - break; - default: - error = EINVAL; /* unknown cookie type */ - break; - } - - /* Take care of synchronous response, if any */ - NG_RESPOND_MSG(error, node, item, resp); - NG_FREE_MSG(msg); - return(error); -} - -/* - * Accept data from the hook and queue it for output. - */ -static int -ng_udbp_rcvdata(hook_p hook, item_p item) -{ - const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - int error; - struct ifqueue *xmitq_p; - int s; - struct mbuf *m; - struct ng_tag_prio *ptag; - - NGI_GET_M(item, m); - NG_FREE_ITEM(item); - - /* - * Now queue the data for when it can be sent - */ - if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, - NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) - xmitq_p = (&sc->xmitq_hipri); - else - xmitq_p = (&sc->xmitq); - - s = splusb(); - IF_LOCK(xmitq_p); - if (_IF_QFULL(xmitq_p)) { - _IF_DROP(xmitq_p); - IF_UNLOCK(xmitq_p); - splx(s); - error = ENOBUFS; - goto bad; - } - _IF_ENQUEUE(xmitq_p, m); - IF_UNLOCK(xmitq_p); - if (!(sc->flags & OUT_BUSY)) - udbp_setup_out_transfer(sc); - splx(s); - return (0); - -bad: /* - * It was an error case. - * check if we need to free the mbuf, and then return the error - */ - NG_FREE_M(m); - return (error); -} - -/* - * Do local shutdown processing.. - * We are a persistant device, we refuse to go away, and - * only remove our links and reset ourself. - */ -static int -ng_udbp_rmnode(node_p node) -{ - const udbp_p sc = NG_NODE_PRIVATE(node); - int err; - - if (sc->flags & DISCONNECTED) { - /* - * WE are really going away.. hardware must have gone. - * Assume that the hardware drive part will clear up the - * sc, in fact it may already have done so.. - * In which case we may have just segfaulted..XXX - */ - return (0); - } - - /* stolen from attach routine */ - /* Drain the queues */ - IF_DRAIN(&sc->xmitq_hipri); - IF_DRAIN(&sc->xmitq); - - sc->packets_in = 0; /* reset stats */ - sc->packets_out = 0; - NG_NODE_UNREF(node); /* forget it ever existed */ - - if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) { - char nodename[128]; - sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev)); - if ((err = ng_name_node(sc->node, nodename))) { - NG_NODE_UNREF(sc->node); /* out damned spot! */ - sc->flags &= ~NETGRAPH_INITIALISED; - sc->node = NULL; - } else { - NG_NODE_SET_PRIVATE(sc->node, sc); - } - } - return (err); -} - -/* - * This is called once we've already connected a new hook to the other node. - * It gives us a chance to balk at the last minute. - */ -static int -ng_udbp_connect(hook_p hook) -{ - /* probably not at splnet, force outward queueing */ - NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); - /* be really amiable and just say "YUP that's OK by me! " */ - return (0); -} - -/* - * Dook disconnection - * - * For this type, removal of the last link destroys the node - */ -static int -ng_udbp_disconnect(hook_p hook) -{ - const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - sc->hook = NULL; - - if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) - && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) - ng_rmnode_self(NG_HOOK_NODE(hook)); - return (0); -} - diff --git a/sys/dev/usb/udbp.h b/sys/dev/usb/udbp.h deleted file mode 100644 index 97ef945..0000000 --- a/sys/dev/usb/udbp.h +++ /dev/null @@ -1,80 +0,0 @@ -/*- - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * All rights reserved. - * - * Subject to the following obligations and disclaimer of warranty, use and - * redistribution of this software, in source or object code forms, with or - * without modifications are expressly permitted by Whistle Communications; - * provided, however, that: - * 1. Any and all reproductions of the source or object code must include the - * copyright notice above and the following disclaimer of warranties; and - * 2. No rights are granted, in any manner or form, to use Whistle - * Communications, Inc. trademarks, including the mark "WHISTLE - * COMMUNICATIONS" on advertising, endorsements, or otherwise except as - * such appears in the above copyright notice or in the software. - * - * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, - * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY - * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS - * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. - * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES - * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING - * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file was derived from src/sys/netgraph/ng_sample.h, revision 1.1 - * written by Julian Elischer, Whistle Communications. - * - * $FreeBSD$ - */ - -#ifndef _NETGRAPH_UDBP_H_ -#define _NETGRAPH_UDBP_H_ - -/* Node type name. This should be unique among all netgraph node types */ -#define NG_UDBP_NODE_TYPE "udbp" - -/* Node type cookie. Should also be unique. This value MUST change whenever - an incompatible change is made to this header file, to insure consistency. - The de facto method for generating cookies is to take the output of the - date command: date -u +'%s' */ -#define NGM_UDBP_COOKIE 944609300 - - -#define NG_UDBP_HOOK_NAME "data" - -/* Netgraph commands understood by this node type */ -enum { - NGM_UDBP_SET_FLAG = 1, - NGM_UDBP_GET_STATUS, -}; - -/* This structure is returned by the NGM_UDBP_GET_STATUS command */ -struct ngudbpstat { - u_int packets_in; /* packets in from downstream */ - u_int packets_out; /* packets out towards downstream */ -}; - -/* - * This is used to define the 'parse type' for a struct ngudbpstat, which - * is bascially a description of how to convert a binary struct ngudbpstat - * to an ASCII string and back. See ng_parse.h for more info. - * - * This needs to be kept in sync with the above structure definition - */ -#define NG_UDBP_STATS_TYPE_INFO { \ - { "packets_in", &ng_parse_int32_type }, \ - { "packets_out", &ng_parse_int32_type }, \ - { NULL }, \ -} - -#endif /* _NETGRAPH_UDBP_H_ */ diff --git a/sys/dev/usb/ufm.c b/sys/dev/usb/ufm.c deleted file mode 100644 index 2635827..0000000 --- a/sys/dev/usb/ufm.c +++ /dev/null @@ -1,376 +0,0 @@ -/*- - * Copyright (c) 2001-2007 M. Warner Losh - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/conf.h> -#include <sys/uio.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/poll.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include "usbdevs.h" -#include <dev/usb/dsbr100io.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ufmdebug) printf x -#define DPRINTFN(n,x) if (ufmdebug>(n)) printf x -int ufmdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ufm, CTLFLAG_RW, 0, "USB ufm"); -SYSCTL_INT(_hw_usb_ufm, OID_AUTO, debug, CTLFLAG_RW, - &ufmdebug, 0, "ufm debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -d_open_t ufmopen; -d_close_t ufmclose; -d_ioctl_t ufmioctl; - -static struct cdevsw ufm_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ufmopen, - .d_close = ufmclose, - .d_ioctl = ufmioctl, - .d_name = "ufm", -}; - -#define FM_CMD0 0x00 -#define FM_CMD_SET_FREQ 0x01 -#define FM_CMD2 0x02 - -struct ufm_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - int sc_opened; - int sc_epaddr; - int sc_freq; - - int sc_refcnt; -}; - -#define UFMUNIT(n) (dev2unit(n)) - -static device_probe_t ufm_match; -static device_attach_t ufm_attach; -static device_detach_t ufm_detach; - -static device_method_t ufm_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ufm_match), - DEVMETHOD(device_attach, ufm_attach), - DEVMETHOD(device_detach, ufm_detach), - - { 0, 0 } -}; - -static driver_t ufm_driver = { - "ufm", - ufm_methods, - sizeof(struct ufm_softc) -}; - -static devclass_t ufm_devclass; - -static int -ufm_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd; - - DPRINTFN(10,("ufm_match\n")); - if (!uaa->iface) - return UMATCH_NONE; - - dd = usbd_get_device_descriptor(uaa->device); - - if (dd && - ((UGETW(dd->idVendor) == USB_VENDOR_CYPRESS && - UGETW(dd->idProduct) == USB_PRODUCT_CYPRESS_FMRADIO))) - return UMATCH_VENDOR_PRODUCT; - else - return UMATCH_NONE; -} - -static int -ufm_attach(device_t self) -{ - struct ufm_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_endpoint_descriptor_t *edesc; - usbd_device_handle udev; - usbd_interface_handle iface; - u_int8_t epcount; - usbd_status r; - char * ermsg = "<none>"; - - DPRINTFN(10,("ufm_attach: sc=%p\n", sc)); - sc->sc_dev = self; - sc->sc_udev = udev = uaa->device; - - if ((!uaa->device) || (!uaa->iface)) { - ermsg = "device or iface"; - goto nobulk; - } - sc->sc_iface = iface = uaa->iface; - sc->sc_opened = 0; - sc->sc_refcnt = 0; - - r = usbd_endpoint_count(iface, &epcount); - if (r != USBD_NORMAL_COMPLETION) { - ermsg = "endpoints"; - goto nobulk; - } - - edesc = usbd_interface2endpoint_descriptor(iface, 0); - if (!edesc) { - ermsg = "interface endpoint"; - goto nobulk; - } - sc->sc_epaddr = edesc->bEndpointAddress; - - /* XXX no error trapping, no storing of struct cdev **/ - (void) make_dev(&ufm_cdevsw, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "ufm%d", device_get_unit(self)); - DPRINTFN(10, ("ufm_attach: %p\n", sc->sc_udev)); - return 0; - - nobulk: - device_printf(sc->sc_dev, "could not find %s\n", ermsg); - return ENXIO; -} - - -int -ufmopen(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - sc = devclass_get_softc(ufm_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("ufmopen: flag=%d, mode=%d, unit=%d\n", - flag, mode, unit)); - - if (sc->sc_opened) - return (EBUSY); - - if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD)) - return (EACCES); - - sc->sc_opened = 1; - return (0); -} - -int -ufmclose(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - sc = devclass_get_softc(ufm_devclass, unit); - - DPRINTFN(5, ("ufmclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit)); - sc->sc_opened = 0; - sc->sc_refcnt = 0; - return 0; -} - -static int -ufm_do_req(struct ufm_softc *sc, u_int8_t reqtype, u_int8_t request, - u_int16_t value, u_int16_t index, u_int8_t len, void *retbuf) -{ - int s; - usb_device_request_t req; - usbd_status err; - - s = splusb(); - req.bmRequestType = reqtype; - req.bRequest = request; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, len); - err = usbd_do_request_flags(sc->sc_udev, &req, retbuf, 0, NULL, - USBD_DEFAULT_TIMEOUT); - splx(s); - if (err) - return (EIO); - return (0); -} - -static int -ufm_set_freq(struct ufm_softc *sc, caddr_t addr) -{ - int freq = *(int *)addr; - u_int8_t ret; - - /* - * 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. - */ - sc->sc_freq = freq; - freq = (freq + 10700001) / 12500; - /* This appears to set the frequency */ - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD_SET_FREQ, freq >> 8, - freq, 1, &ret) != 0) - return (EIO); - /* Not sure what this does */ - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x96, 0xb7, 1, - &ret) != 0) - return (EIO); - return (0); -} - -static int -ufm_get_freq(struct ufm_softc *sc, caddr_t addr) -{ - int *valp = (int *)addr; - *valp = sc->sc_freq; - return (0); -} - -static int -ufm_start(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x00, 0xc7, - 1, &ret)) - return (EIO); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD2, 0x01, 0x00, - 1, &ret)) - return (EIO); - if (ret & 0x1) - return (EIO); - return (0); -} - -static int -ufm_stop(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x16, 0x1C, - 1, &ret)) - return (EIO); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD2, 0x00, 0x00, - 1, &ret)) - return (EIO); - return (0); -} - -static int -ufm_get_stat(struct ufm_softc *sc, caddr_t addr) -{ - u_int8_t ret; - - /* - * Note, there's a 240ms settle time before the status - * will be valid, so tsleep that amount. hz/4 is a good - * approximation of that. Since this is a short sleep - * we don't try to catch any signals to keep things - * simple. - */ - tsleep(sc, 0, "ufmwait", hz/4); - if (ufm_do_req(sc, UT_READ_VENDOR_DEVICE, FM_CMD0, 0x00, 0x24, - 1, &ret)) - return (EIO); - *(int *)addr = ret; - - return (0); -} - -int -ufmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) -{ - struct ufm_softc *sc; - - int unit = UFMUNIT(dev); - int error = 0; - - sc = devclass_get_softc(ufm_devclass, unit); - - switch (cmd) { - case FM_SET_FREQ: - error = ufm_set_freq(sc, addr); - break; - case FM_GET_FREQ: - error = ufm_get_freq(sc, addr); - break; - case FM_START: - error = ufm_start(sc, addr); - break; - case FM_STOP: - error = ufm_stop(sc, addr); - break; - case FM_GET_STAT: - error = ufm_get_stat(sc, addr); - break; - default: - return ENOTTY; - break; - } - return error; -} - -static int -ufm_detach(device_t self) -{ - return 0; -} - -MODULE_DEPEND(ufm, usb, 1, 1, 1); -DRIVER_MODULE(ufm, uhub, ufm_driver, ufm_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/ufoma.c b/sys/dev/usb/ufoma.c deleted file mode 100644 index e5704a7..0000000 --- a/sys/dev/usb/ufoma.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */ -#define UFOMA_HANDSFREE -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 2005, Takanori Watanabe - * Copyright (c) 2003, M. Warner Losh <imp@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. - */ - -/*- - * Copyright (c) 1998 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. - */ - -/* - * Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf - * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf - */ - -/* - * TODO: - * - Add error recovery in various places; the big problem is what - * to do in a callback if there is an error. - * - Implement a Call Device for modems without multiplexed commands. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/ioccom.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#include <sys/bus.h> -#include <sys/sbuf.h> -#include <sys/poll.h> -#include <sys/uio.h> -#include <sys/taskqueue.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/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -#include "usbdevs.h" - -typedef struct ufoma_mobile_acm_descriptor{ - uByte bFunctionLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bType; - uByte bMode[1]; -}usb_mcpc_acm_descriptor; - -#define UISUBCLASS_MCPC 0x88 - -#define UDESC_VS_INTERFACE 0x44 -#define UDESCSUB_MCPC_ACM 0x11 - -#define UMCPC_ACM_TYPE_AB1 0x1 -#define UMCPC_ACM_TYPE_AB2 0x2 -#define UMCPC_ACM_TYPE_AB5 0x5 -#define UMCPC_ACM_TYPE_AB6 0x6 - -#define UMCPC_ACM_MODE_DEACTIVATED 0x0 -#define UMCPC_ACM_MODE_MODEM 0x1 -#define UMCPC_ACM_MODE_ATCOMMAND 0x2 -#define UMCPC_ACM_MODE_OBEX 0x60 -#define UMCPC_ACM_MODE_VENDOR1 0xc0 -#define UMCPC_ACM_MODE_VENDOR2 0xfe -#define UMCPC_ACM_MODE_UNLINKED 0xff - -#define UMCPC_CM_MOBILE_ACM 0x0 - -#define UMCPC_ACTIVATE_MODE 0x60 -#define UMCPC_GET_MODETABLE 0x61 -#define UMCPC_SET_LINK 0x62 -#define UMCPC_CLEAR_LINK 0x63 - -#define UMCPC_REQUEST_ACKNOLEDGE 0x31 - -#define UFOMA_MAX_TIMEOUT 15 /*Standard says 10(sec)*/ -#define UFOMA_CMD_BUF_SIZE 64 - -#define UMODEMIBUFSIZE 1024 -#define UMODEMOBUFSIZE 1024 -#define DPRINTF(a) - -struct ufoma_softc{ - struct ucom_softc sc_ucom; - int sc_is_ucom; - int sc_isopen; - - struct mtx sc_mtx; - int sc_ctl_iface_no; - usbd_interface_handle sc_ctl_iface; - usbd_interface_handle sc_data_iface; - int sc_data_iface_no; - int sc_cm_cap; - int sc_acm_cap; - usb_cdc_line_state_t sc_line_state; /* current line state */ - usb_cdc_line_state_t sc_line_state_init; /* pre open line state*/ - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - usbd_pipe_handle sc_notify_pipe; - usb_cdc_notification_t sc_notify_buf; - u_char sc_lsr; - u_char sc_msr; - - struct task sc_task; - uByte *sc_modetable; - uByte sc_modetoactivate; - uByte sc_currentmode; - char sc_resbuffer[UFOMA_CMD_BUF_SIZE+1]; - int sc_cmdbp; - int sc_nummsg; - usbd_xfer_handle sc_msgxf; -}; -static usbd_status -ufoma_set_line_coding(struct ufoma_softc *sc, usb_cdc_line_state_t *state); -static device_probe_t ufoma_match; -static device_attach_t ufoma_attach; -static device_detach_t ufoma_detach; -static void *ufoma_get_intconf(usb_config_descriptor_t *cd, usb_interface_descriptor_t *id,int type, int subtype); -static void ufoma_notify(void * ,int count); -static void ufoma_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static char *ufoma_mode_to_str(int); -static int ufoma_str_to_mode(char *); - -#ifdef UFOMA_HANDSFREE -/*Pseudo ucom stuff(for Handsfree interface)*/ -static int ufoma_init_pseudo_ucom(struct ufoma_softc *); -static tsw_open_t ufoma_open; -static tsw_close_t ufoma_close; -static tsw_outwakeup_t ufoma_outwakeup; -static tsw_free_t ufoma_free; -#endif - -/*umodem like stuff*/ -static int ufoma_init_modem(struct ufoma_softc *, struct usb_attach_arg *); -static void ufoma_get_status(void *, int portno, u_char *lst, u_char *msr); -static void ufoma_set(void *, int portno, int reg, int onoff); -static int ufoma_param(void *, int portno, struct termios *); -static int ufoma_ucom_open(void *, int portno); -static void ufoma_ucom_close(void *, int portno); -static void ufoma_break(struct ufoma_softc *sc, int onoff); -static void ufoma_dtr(struct ufoma_softc *sc, int onoff); -static void ufoma_rts(struct ufoma_softc *sc, int onoff); - -/*sysctl stuff*/ -static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS); -static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS); -static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS); -static void ufoma_set_line_state(struct ufoma_softc *sc); - -static struct ucom_callback ufoma_callback = { - .ucom_get_status = ufoma_get_status, - .ucom_set = ufoma_set, - .ucom_param = ufoma_param, - .ucom_open = ufoma_ucom_open, - .ucom_close = ufoma_ucom_close, -}; - - -static device_method_t ufoma_methods[] = { - /**/ - DEVMETHOD(device_probe, ufoma_match), - DEVMETHOD(device_attach, ufoma_attach), - DEVMETHOD(device_detach, ufoma_detach), - {0, 0} -}; -struct umcpc_modetostr_tab{ - int mode; - char *str; -}umcpc_modetostr_tab[]={ - {UMCPC_ACM_MODE_DEACTIVATED, "deactivated"}, - {UMCPC_ACM_MODE_MODEM, "modem"}, - {UMCPC_ACM_MODE_ATCOMMAND, "handsfree"}, - {UMCPC_ACM_MODE_OBEX, "obex"}, - {UMCPC_ACM_MODE_VENDOR1, "vendor1"}, - {UMCPC_ACM_MODE_VENDOR2, "vendor2"}, - {UMCPC_ACM_MODE_UNLINKED, "unlinked"}, - {0, NULL} -}; - -static driver_t ufoma_driver = { - "ucom", - ufoma_methods, - sizeof(struct ufoma_softc) -}; - - -DRIVER_MODULE(ufoma, uhub, ufoma_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(ufoma, usb, 1, 1, 1); -MODULE_DEPEND(ufoma, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); - -static int -ufoma_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - usb_config_descriptor_t *cd; - usb_mcpc_acm_descriptor *mad; - int ret; - - ret = UMATCH_NONE; - - if(uaa->iface == NULL) - return(UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - cd = usbd_get_config_descriptor(uaa->device); - - if(id == NULL || cd == NULL) - return (UMATCH_NONE); - - if( id->bInterfaceClass == UICLASS_CDC && - id->bInterfaceSubClass == UISUBCLASS_MCPC){ - ret = (UMATCH_IFACECLASS_IFACESUBCLASS); - }else{ - return UMATCH_NONE; - } - - mad = ufoma_get_intconf(cd, id , UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM); - if(mad == NULL){ - return (UMATCH_NONE); - } - -#ifndef UFOMA_HANDSFREE - if((mad->bType == UMCPC_ACM_TYPE_AB5)|| - (mad->bType == UMCPC_ACM_TYPE_AB6)){ - return UMATCH_NONE; - } -#endif - return ret; -} - -static int -ufoma_attach(device_t self) -{ - struct ufoma_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usb_config_descriptor_t *cd; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usb_mcpc_acm_descriptor *mad; - struct ucom_softc *ucom = &sc->sc_ucom; - const char *devname,*modename; - int ctl_notify; - int i,err; - int elements; - uByte *mode; - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - sc->sc_ctl_iface = uaa->iface; - mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF); - - cd = usbd_get_config_descriptor(ucom->sc_udev); - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); - sc->sc_ctl_iface_no = id->bInterfaceNumber; - - devname = device_get_nameunit(self); - device_printf(self, "iclass %d/%d ifno:%d\n", - id->bInterfaceClass, id->bInterfaceSubClass, sc->sc_ctl_iface_no); - - ctl_notify = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); - if (ed == NULL) - continue; - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - ctl_notify = ed->bEndpointAddress; - } - } - - if(ctl_notify== -1){ - /*NOTIFY is mandatory.*/ - printf("NOTIFY interface not found\n"); - goto error; - } - - err = usbd_open_pipe_intr(sc->sc_ctl_iface, ctl_notify, - USBD_SHORT_XFER_OK, &sc->sc_notify_pipe, sc, &sc->sc_notify_buf, - sizeof(sc->sc_notify_buf), ufoma_intr, USBD_DEFAULT_INTERVAL); - if(err){ - printf("PIPE open error %d\n", err); - goto error; - } - mad = ufoma_get_intconf(cd, id , UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM); - if(mad ==NULL){ - goto error; - } - - printf("%s:Supported Mode:", devname); - for(mode = mad->bMode; - mode < ((uByte *)mad + mad->bFunctionLength); mode++){ - modename = ufoma_mode_to_str(*mode); - if(modename){ - printf("%s", ufoma_mode_to_str(*mode)); - }else{ - printf("(%x)", *mode); - } - if(mode != ((uByte*)mad + mad->bFunctionLength-1)){ - printf(","); - } - } - printf("\n"); - if((mad->bType == UMCPC_ACM_TYPE_AB5) - ||(mad->bType == UMCPC_ACM_TYPE_AB6)){ -#ifdef UFOMA_HANDSFREE - /*These does not have data interface*/ - sc->sc_is_ucom = 0; - ufoma_init_pseudo_ucom(sc); -#else - /*Should not happen*/ - goto error; -#endif - - }else{ - if(ufoma_init_modem(sc, uaa)){ - goto error; - } - } - elements = mad->bFunctionLength - sizeof(*mad)+1; - sc->sc_msgxf = usbd_alloc_xfer(ucom->sc_udev); - sc->sc_nummsg = 0; - - /*Initialize Mode vars.*/ - sc->sc_modetable = malloc(elements + 1, M_USBDEV, M_WAITOK); - sc->sc_modetable[0] = elements + 1; - bcopy(mad->bMode, &sc->sc_modetable[1], elements); - sc->sc_currentmode = UMCPC_ACM_MODE_UNLINKED; - sc->sc_modetoactivate = mad->bMode[0]; - - /*Sysctls*/ - sctx = device_get_sysctl_ctx(self); - soid = device_get_sysctl_tree(self); - - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "supportmode", - CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_support, - "A", "Supporting port role"); - - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "currentmode", - CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_current, - "A", "Current port role"); - - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "openmode", - CTLFLAG_RW|CTLTYPE_STRING, sc, 0, ufoma_sysctl_open, - "A", "Mode to transit when port is opened"); - - return 0; - error: - if(sc->sc_modetable) - free(sc->sc_modetable, M_USBDEV); - return EIO; -} - -static int -ufoma_detach(device_t self) -{ - struct ufoma_softc *sc = device_get_softc(self); - int rv = 0; - - usbd_free_xfer(sc->sc_msgxf); - sc->sc_ucom.sc_dying = 1; - usbd_abort_pipe(sc->sc_notify_pipe); - usbd_close_pipe(sc->sc_notify_pipe); - if(sc->sc_is_ucom){ - ucom_detach(&sc->sc_ucom); - } -#ifdef UFOMA_HANDSFREE - else{ - tty_lock(sc->sc_ucom.sc_tty); - tty_rel_gone(sc->sc_ucom.sc_tty); - } - -#endif - free(sc->sc_modetable, M_USBDEV); - return rv; -} - - -static char *ufoma_mode_to_str(int mode) -{ - int i; - for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){ - if(umcpc_modetostr_tab[i].mode == mode){ - return umcpc_modetostr_tab[i].str; - } - } - return NULL; -} - -static int ufoma_str_to_mode(char *str) -{ - int i; - for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){ - if(strcmp(str, umcpc_modetostr_tab[i].str)==0){ - return umcpc_modetostr_tab[i].mode; - } - } - return -1; -} - -static void *ufoma_get_intconf( usb_config_descriptor_t *cd, - usb_interface_descriptor_t *id, int type, int subtype) -{ - uByte *p, *end; - usb_descriptor_t *ud=NULL; - int flag=0; - - - for(p = (uByte *)cd,end = p + UGETW(cd->wTotalLength); p < end; - p += ud->bLength){ - ud = (usb_descriptor_t *)p; - if(flag && ud->bDescriptorType==UDESC_INTERFACE){ - return NULL; - } - /*Read through this interface desc.*/ - if(bcmp(p, id, sizeof(*id))==0){ - flag=1; - continue; - } - if(flag==0) - continue; - if(ud->bDescriptorType == type - && ud->bDescriptorSubtype == subtype){ - break; - } - } - return ud; -} - - - -static int ufoma_link_state(struct ufoma_softc *sc) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - int err; - - req.bmRequestType = UT_WRITE_VENDOR_INTERFACE; - req.bRequest = UMCPC_SET_LINK; - USETW(req.wValue, UMCPC_CM_MOBILE_ACM); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, sc->sc_modetable[0]); - - err = usbd_do_request(ucom->sc_udev, &req, sc->sc_modetable); - if(err){ - printf("SET_LINK:%s\n",usbd_errstr(err)); - return EIO; - } - err = tsleep(&sc->sc_currentmode, PZERO|PCATCH, "fmalnk", hz); - if(err){ - printf("NO response"); - return EIO; - } - if(sc->sc_currentmode != UMCPC_ACM_MODE_DEACTIVATED){ - return EIO; - } - return 0; -} - -static int ufoma_activate_state(struct ufoma_softc *sc, int state) -{ - usb_device_request_t req; - int err; - struct ucom_softc *ucom = &sc->sc_ucom; - - req.bmRequestType = UT_WRITE_VENDOR_INTERFACE; - req.bRequest = UMCPC_ACTIVATE_MODE; - USETW(req.wValue, state); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if(err){ - printf("%s:ACTIVATE(%x):%s\n", - device_get_nameunit(ucom->sc_dev), state, - usbd_errstr(err)); - return EIO; - } - - err = tsleep(&sc->sc_currentmode, PZERO|PCATCH, "fmaact", UFOMA_MAX_TIMEOUT*hz); - if(err){ - printf("%s:NO response", device_get_nameunit(ucom->sc_dev)); - return EIO; - } - if(sc->sc_currentmode != state){ - return EIO; - } - return 0; -} - -#ifdef UFOMA_HANDSFREE -static inline void ufoma_setup_msg_req(struct ufoma_softc *sc, usb_device_request_t *req) -{ - req->bmRequestType = UT_READ_CLASS_INTERFACE; - req->bRequest = UCDC_GET_ENCAPSULATED_RESPONSE; - USETW(req->wIndex, sc->sc_ctl_iface_no); - USETW(req->wValue, 0); - USETW(req->wLength, UFOMA_CMD_BUF_SIZE); -} - - -static void ufoma_msg(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - usb_device_request_t req; - struct ufoma_softc *sc = priv; - int actlen,i; - struct ucom_softc *ucom= &sc->sc_ucom; - usbd_get_xfer_status(xfer, NULL, NULL, &actlen ,NULL); - ufoma_setup_msg_req(sc, &req); - mtx_lock(&sc->sc_mtx); - for(i = 0;i < actlen; i++){ - - if(ttydisc_rint(sc->sc_ucom.sc_tty, sc->sc_resbuffer[i], 0) - == -1){ - break; - } - } - - ttydisc_rint_done(sc->sc_ucom.sc_tty); - - sc->sc_nummsg--; - if(sc->sc_nummsg){ - usbd_setup_default_xfer(sc->sc_msgxf, ucom->sc_udev, - priv, USBD_DEFAULT_TIMEOUT, &req, - sc->sc_resbuffer, - UFOMA_CMD_BUF_SIZE, - 0, ufoma_msg); - usbd_transfer(sc->sc_msgxf); - } - mtx_unlock(&sc->sc_mtx); - -} -#endif -static void ufoma_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ufoma_softc *sc = priv; - unsigned int a; - struct ucom_softc *ucom =&sc->sc_ucom; - u_char mstatus; - -#ifdef UFOMA_HANDSFREE - usb_device_request_t req; - - ufoma_setup_msg_req(sc, &req); -#endif - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - printf("%s: abnormal status: %s\n", device_get_nameunit(ucom->sc_dev), - usbd_errstr(status)); - return; - } - if((sc->sc_notify_buf.bmRequestType == UT_READ_VENDOR_INTERFACE)&& - (sc->sc_notify_buf.bNotification == UMCPC_REQUEST_ACKNOLEDGE)){ - a = UGETW(sc->sc_notify_buf.wValue); - sc->sc_currentmode = a>>8; - if(!(a&0xff)){ - printf("%s:Mode change Failed\n", device_get_nameunit(ucom->sc_dev)); - } - wakeup(&sc->sc_currentmode); - } - if(sc->sc_notify_buf.bmRequestType != UCDC_NOTIFICATION){ - return; - } - switch(sc->sc_notify_buf.bNotification){ -#ifdef UFOMA_HANDSFREE - case UCDC_N_RESPONSE_AVAILABLE: - if(sc->sc_is_ucom){ - printf("%s:wrong response request?\n", device_get_nameunit(ucom->sc_dev)); - break; - } - mtx_lock(&sc->sc_mtx); - if(!sc->sc_nummsg){ - usbd_setup_default_xfer(sc->sc_msgxf, ucom->sc_udev, - priv, USBD_DEFAULT_TIMEOUT, &req, sc->sc_resbuffer, - UFOMA_CMD_BUF_SIZE, - 0, ufoma_msg); - usbd_transfer(sc->sc_msgxf); - } - sc->sc_nummsg++; - mtx_unlock(&sc->sc_mtx); - break; -#endif - case UCDC_N_SERIAL_STATE: - if(!sc->sc_is_ucom){ - printf("%s:wrong sereal request?\n",device_get_nameunit(ucom->sc_dev)); - break; - } - - /* - * Set the serial state in ucom driver based on - * the bits from the notify message - */ - if (UGETW(sc->sc_notify_buf.wLength) != 2) { - printf("%s: Invalid notification length! (%d)\n", - device_get_nameunit(ucom->sc_dev), - UGETW(sc->sc_notify_buf.wLength)); - break; - } - DPRINTF(("%s: notify bytes = %02x%02x\n", - device_get_nameunit(ucom->sc_dev), - sc->sc_notify_buf.data[0], - sc->sc_notify_buf.data[1])); - /* Currently, lsr is always zero. */ - sc->sc_lsr = sc->sc_msr = 0; - mstatus = sc->sc_notify_buf.data[0]; - - if (ISSET(mstatus, UCDC_N_SERIAL_RI)) - sc->sc_msr |= SER_RI; - if (ISSET(mstatus, UCDC_N_SERIAL_DSR)) - sc->sc_msr |= SER_DSR; - if (ISSET(mstatus, UCDC_N_SERIAL_DCD)) - sc->sc_msr |= SER_DCD; - /* Deferred notifying to the ucom layer */ - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); - break; - default: - break; - } -} - -#ifdef UFOMA_HANDSFREE -struct ttydevsw ufomatty_class ={ - .tsw_flags = TF_INITLOCK|TF_CALLOUT, - .tsw_open = ufoma_open, - .tsw_close = ufoma_close, - .tsw_outwakeup = ufoma_outwakeup, - .tsw_free = ufoma_free -}; -static void ufoma_free(void *sc) -{ - -} -static int ufoma_init_pseudo_ucom(struct ufoma_softc *sc) -{ - struct tty *tp; - struct ucom_softc *ucom = &sc->sc_ucom; - tp = ucom->sc_tty = tty_alloc(&ufomatty_class, sc, &Giant); - tty_makedev(tp, NULL, "U%d", device_get_unit(ucom->sc_dev)); - - return 0; -} - - -static int ufoma_open(struct tty * tty) -{ - - struct ufoma_softc *sc = tty_softc(tty); - - if(sc->sc_ucom.sc_dying) - return (ENXIO); - - mtx_lock(&sc->sc_mtx); - if(sc->sc_isopen){ - mtx_unlock(&sc->sc_mtx); - return EBUSY; - } - mtx_unlock(&sc->sc_mtx); - - return ufoma_ucom_open(sc, 0); -} - -static void ufoma_close(struct tty *tty) -{ - struct ufoma_softc *sc = tty_softc(tty); - - ufoma_ucom_close(sc, 0); -} - -static void ufoma_outwakeup(struct tty *tp) -{ - struct ufoma_softc *sc = tty_softc(tp); - struct ucom_softc *ucom = &sc->sc_ucom; - usb_device_request_t req; - int len,i; - unsigned char buf[128]; - - uByte c; - if(ucom->sc_dying) - return; - if(ucom->sc_state &UCS_TXBUSY) - return; - - ucom->sc_state |= UCS_TXBUSY; - for(;;){ - len = ttydisc_getc(tp, buf, sizeof(buf)); - if(len == 0){ - break; - } - - for(i=0; i < len; i++){ - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - c = buf[i]; - req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND; - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wValue, 0); - USETW(req.wLength, 1); - usbd_do_request(ucom->sc_udev, &req, &c); - } - } - ucom->sc_state &= ~(UCS_TXBUSY); - -} -#endif - - -static int ufoma_ucom_open(void *p, int portno) -{ - struct ufoma_softc *sc = p; - int res; - - if(sc->sc_currentmode == UMCPC_ACM_MODE_UNLINKED){ - if((res = ufoma_link_state(sc))){ - return res; - } - } - - sc->sc_cmdbp = 0; - if(sc->sc_currentmode == UMCPC_ACM_MODE_DEACTIVATED){ - if((res = ufoma_activate_state(sc, sc->sc_modetoactivate))){ - return res; - } - } - mtx_lock(&sc->sc_mtx); - sc->sc_isopen = 1; - mtx_unlock(&sc->sc_mtx); - /*Now line coding should be set.*/ - if(sc->sc_is_ucom){ - ufoma_set_line_state(sc); - ufoma_set_line_coding(sc, NULL); - } - return 0; -} - -static void ufoma_ucom_close(void *p, int portno) -{ - struct ufoma_softc *sc = p; - ufoma_activate_state(sc, UMCPC_ACM_MODE_DEACTIVATED); - mtx_lock(&sc->sc_mtx); - sc->sc_isopen = 0; - mtx_unlock(&sc->sc_mtx); - return ; -} - -void -ufoma_break(struct ufoma_softc *sc, int onoff) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - DPRINTF(("ufoma_break: onoff=%d\n", onoff)); - - if (!(sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK)) - return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(ucom->sc_udev, &req, 0); -} - -void -ufoma_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct ufoma_softc *sc = addr; - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -static void ufoma_set(void * addr, int portno, int reg, int onoff) -{ - struct ufoma_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - ufoma_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - ufoma_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - ufoma_break(sc, onoff); - break; - default: - break; - } - -} - -static void -ufoma_set_line_state(struct ufoma_softc *sc) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - int ls; - int err; - - if(!sc->sc_isopen){ - return ; /*Set it later*/ - } - - /*Don't send line state emulation request for OBEX port*/ - if(sc->sc_currentmode == UMCPC_ACM_MODE_OBEX){ - return; - } - - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - err = usbd_do_request(ucom->sc_udev, &req, 0); - if(err){ - printf("LINE_STATE:%s\n", usbd_errstr(err)); - } - - -} - -void -ufoma_dtr(struct ufoma_softc *sc, int onoff) -{ - DPRINTF(("ufoma_foma: onoff=%d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - ufoma_set_line_state(sc); -} - -void -ufoma_rts(struct ufoma_softc *sc, int onoff) -{ - DPRINTF(("ufoma_foma: onoff=%d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - ufoma_set_line_state(sc); -} - -usbd_status -ufoma_set_line_coding(struct ufoma_softc *sc, usb_cdc_line_state_t *state) -{ - - usbd_status err; - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - if(!sc->sc_isopen){ - sc->sc_line_state_init = *state; - return (USBD_NORMAL_COMPLETION); - } - - DPRINTF(("ufoma_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n", - UGETDW(state->dwDTERate), state->bCharFormat, - state->bParityType, state->bDataBits)); - if(state == NULL){ - state = &sc->sc_line_state_init; - }else if (memcmp(state, &sc->sc_line_state, - UCDC_LINE_STATE_LENGTH) == 0) { - DPRINTF(("ufoma_set_line_coding: already set\n")); - return (USBD_NORMAL_COMPLETION); - } - - /*Don't send line state emulation request for OBEX port*/ - if(sc->sc_currentmode == UMCPC_ACM_MODE_OBEX){ - sc->sc_line_state = *state; - return (USBD_NORMAL_COMPLETION); - } - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_LINE_CODING; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, UCDC_LINE_STATE_LENGTH); - - err = usbd_do_request(ucom->sc_udev, &req, state); - if (err) { - DPRINTF(("ufoma_set_line_coding: failed, err=%s\n", - usbd_errstr(err))); - return (err); - } - - sc->sc_line_state = *state; - - return (USBD_NORMAL_COMPLETION); -} - -static int -ufoma_param(void *addr, int portno, struct termios *t) -{ - - struct ufoma_softc *sc = addr; - usbd_status err; - usb_cdc_line_state_t ls; - - DPRINTF(("ufoma_param: sc=%p\n", sc)); - - USETDW(ls.dwDTERate, t->c_ospeed); - if (ISSET(t->c_cflag, CSTOPB)) - ls.bCharFormat = UCDC_STOP_BIT_2; - else - ls.bCharFormat = UCDC_STOP_BIT_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - ls.bParityType = UCDC_PARITY_ODD; - else - ls.bParityType = UCDC_PARITY_EVEN; - } else - ls.bParityType = UCDC_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - ls.bDataBits = 5; - break; - case CS6: - ls.bDataBits = 6; - break; - case CS7: - ls.bDataBits = 7; - break; - case CS8: - ls.bDataBits = 8; - break; - } - - err = ufoma_set_line_coding(sc, &ls); - if (err) { - DPRINTF(("ufoma_param: err=%s\n", usbd_errstr(err))); - return (EIO); - } - - return (0); -} - -static int ufoma_init_modem(struct ufoma_softc *sc,struct usb_attach_arg *uaa) -{ - struct ucom_softc *ucom = &sc->sc_ucom; - usb_config_descriptor_t *cd; - usb_cdc_acm_descriptor_t *acm; - usb_cdc_cm_descriptor_t *cmd; - usb_endpoint_descriptor_t *ed; - usb_interface_descriptor_t *id; - const char *devname = device_get_nameunit(ucom->sc_dev); - int i; - cd = usbd_get_config_descriptor(ucom->sc_udev); - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); - - sc->sc_is_ucom = 1; - - cmd = ufoma_get_intconf(cd, id, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); - if(cmd == NULL) - return -1; - sc->sc_cm_cap = cmd->bmCapabilities; - - acm = ufoma_get_intconf(cd, id, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM); - if(acm == NULL) - return -1; - sc->sc_acm_cap = acm->bmCapabilities; - - sc->sc_data_iface_no = cmd->bDataInterface; - printf("%s: data interface %d, has %sCM over data, has %sbreak\n", - devname, sc->sc_data_iface_no, - sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ", - sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no "); - - for(i = 0; i < uaa->nifaces; i++){ - if(!uaa->ifaces[i]) - continue; - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if(id != NULL && - id->bInterfaceNumber == sc->sc_data_iface_no){ - sc->sc_data_iface = uaa->ifaces[i]; - //uaa->ifaces[i] = NULL; - } - } - - ucom->sc_iface = sc->sc_data_iface; - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - id = usbd_get_interface_descriptor(sc->sc_data_iface); - for(i = 0 ; i < id->bNumEndpoints; i++){ - ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i); - if(ed == NULL){ - printf("%s: endpoint descriptor for %d\n", - devname,i); - return -1; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - printf("%s: Could not find data bulk in\n", devname); - return -1; - } - if (ucom->sc_bulkout_no == -1) { - printf("%s: Could not find data bulk out\n", devname); - return -1; - } - - sc->sc_dtr = -1; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UMODEMIBUFSIZE; - ucom->sc_obufsize = UMODEMOBUFSIZE; - ucom->sc_ibufsizepad = UMODEMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &ufoma_callback; - TASK_INIT(&sc->sc_task, 0, ufoma_notify, sc); - ucom_attach(&sc->sc_ucom); - - return 0; -} - -static void -ufoma_notify(void *arg, int count) -{ - struct ufoma_softc *sc; - - sc = (struct ufoma_softc *)arg; - if (sc->sc_ucom.sc_dying) - return; - ucom_status_change(&sc->sc_ucom); -} -static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS) -{ - struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1; - struct sbuf sb; - int i; - char *mode; - - sbuf_new(&sb, NULL, 1, SBUF_AUTOEXTEND); - for(i = 1; i < sc->sc_modetable[0]; i++){ - mode = ufoma_mode_to_str(sc->sc_modetable[i]); - if(mode !=NULL){ - sbuf_cat(&sb, mode); - }else{ - sbuf_printf(&sb, "(%02x)", sc->sc_modetable[i]); - } - if(i < (sc->sc_modetable[0]-1)) - sbuf_cat(&sb, ","); - } - sbuf_trim(&sb); - sbuf_finish(&sb); - sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req); - sbuf_delete(&sb); - - return 0; -} -static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS) -{ - struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1; - char *mode; - char subbuf[]="(XXX)"; - mode = ufoma_mode_to_str(sc->sc_currentmode); - if(!mode){ - mode = subbuf; - snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_currentmode); - } - sysctl_handle_string(oidp, mode, strlen(mode), req); - - return 0; - -} -static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS) -{ - struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1; - char *mode; - char subbuf[40]; - int newmode; - int error; - int i; - - mode = ufoma_mode_to_str(sc->sc_modetoactivate); - if(mode){ - strncpy(subbuf, mode, sizeof(subbuf)); - }else{ - snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_modetoactivate); - } - error = sysctl_handle_string(oidp, subbuf, sizeof(subbuf), req); - if(error != 0 || req->newptr == NULL){ - return error; - } - - if((newmode = ufoma_str_to_mode(subbuf)) == -1){ - return EINVAL; - } - - for(i = 1 ; i < sc->sc_modetable[0] ; i++){ - if(sc->sc_modetable[i] == newmode){ - sc->sc_modetoactivate = newmode; - return 0; - } - } - - return EINVAL; -} diff --git a/sys/dev/usb/uftdi.c b/sys/dev/usb/uftdi.c deleted file mode 100644 index c652977..0000000 --- a/sys/dev/usb/uftdi.c +++ /dev/null @@ -1,793 +0,0 @@ -/* $NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $ */ - -/*- - * Copyright (c) 2000 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * FTDI FT8U100AX serial adapter driver - */ - -#include <sys/cdefs.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/file.h> - -#include <sys/selinfo.h> - -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/ucomvar.h> - -#include <dev/usb/uftdireg.h> - -#ifdef USB_DEBUG -static int uftdidebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi"); -SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW, - &uftdidebug, 0, "uftdi debug level"); -#define DPRINTF(x) do { \ - if (uftdidebug) \ - printf x; \ - } while (0) - -#define DPRINTFN(n, x) do { \ - if (uftdidebug > (n)) \ - printf x; \ - } while (0) - -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UFTDI_CONFIG_INDEX 0 -#define UFTDI_IFACE_INDEX 0 - - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UFTDIIBUFSIZE 256 -#define UFTDIOBUFSIZE 64 - -struct uftdi_softc { - struct ucom_softc sc_ucom; - usbd_interface_handle sc_iface; /* interface */ - enum uftdi_type sc_type; - u_int sc_hdrlen; - u_char sc_msr; - u_char sc_lsr; - 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 size_t uftdi_write(void *sc, int portno, struct tty *, - u_char *to, u_int32_t count); -static void uftdi_break(void *sc, int portno, int onoff); -static int uftdi_8u232am_getrate(speed_t speed, int *rate); - -struct ucom_callback uftdi_callback = { - uftdi_get_status, - uftdi_set, - uftdi_param, - NULL, - uftdi_open, - NULL, - uftdi_read, - uftdi_write, -}; - -static int -uftdi_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) { - if (uaa->vendor == USB_VENDOR_FTDI && - (uaa->product == USB_PRODUCT_FTDI_SERIAL_2232C)) - return (UMATCH_VENDOR_IFACESUBCLASS); - return (UMATCH_NONE); - } - - DPRINTFN(20,("uftdi: vendor=0x%x, product=0x%x\n", - uaa->vendor, uaa->product)); - - if (uaa->vendor == USB_VENDOR_FTDI && - (uaa->product == USB_PRODUCT_FTDI_SERIAL_8U100AX || - uaa->product == USB_PRODUCT_FTDI_SERIAL_8U232AM || - uaa->product == USB_PRODUCT_FTDI_SEMC_DSS20 || - uaa->product == USB_PRODUCT_FTDI_CFA_631 || - uaa->product == USB_PRODUCT_FTDI_CFA_632 || - uaa->product == USB_PRODUCT_FTDI_CFA_633 || - uaa->product == USB_PRODUCT_FTDI_CFA_634 || - uaa->product == USB_PRODUCT_FTDI_CFA_635 || - uaa->product == USB_PRODUCT_FTDI_USBSERIAL || - uaa->product == USB_PRODUCT_FTDI_MX2_3 || - uaa->product == USB_PRODUCT_FTDI_MX4_5 || - uaa->product == USB_PRODUCT_FTDI_LK202 || - uaa->product == USB_PRODUCT_FTDI_LK204 || - uaa->product == USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M || - uaa->product == USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S || - uaa->product == USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U || - uaa->product == USB_PRODUCT_FTDI_EISCOU || - uaa->product == USB_PRODUCT_FTDI_UOPTBR || - uaa->product == USB_PRODUCT_FTDI_EMCU2D || - uaa->product == USB_PRODUCT_FTDI_PCMSFU || - uaa->product == USB_PRODUCT_FTDI_EMCU2H || - uaa->product == USB_PRODUCT_FTDI_MAXSTREAM )) - return (UMATCH_VENDOR_PRODUCT); - if (uaa->vendor == USB_VENDOR_SIIG2 && - (uaa->product == USB_PRODUCT_SIIG2_US2308)) - return (UMATCH_VENDOR_PRODUCT); - if (uaa->vendor == USB_VENDOR_INTREPIDCS && - (uaa->product == USB_PRODUCT_INTREPIDCS_VALUECAN || - uaa->product == USB_PRODUCT_INTREPIDCS_NEOVI)) - return (UMATCH_VENDOR_PRODUCT); - if (uaa->vendor == USB_VENDOR_BBELECTRONICS && - (uaa->product == USB_PRODUCT_BBELECTRONICS_USOTL4)) - return (UMATCH_VENDOR_PRODUCT); - if (uaa->vendor == USB_VENDOR_MELCO && - (uaa->product == USB_PRODUCT_MELCO_PCOPRS1)) - return (UMATCH_VENDOR_PRODUCT); - if (uaa->vendor == USB_VENDOR_DRESDENELEKTRONIK && - (uaa->product == USB_PRODUCT_DRESDENELEKTRONIK_SENSORTERMINALBOARD)) - return (UMATCH_VENDOR_PRODUCT); - - return (UMATCH_NONE); -} - -static int -uftdi_attach(device_t self) -{ - struct uftdi_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc)); - - ucom->sc_dev = self; - ucom->sc_udev = dev; - - if (uaa->iface == NULL) { - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UFTDI_CONFIG_INDEX, 1); - if (err) { - device_printf(ucom->sc_dev, - "failed to set configuration, err=%s\n", - usbd_errstr(err)); - goto bad; - } - - err = usbd_device2interface_handle(dev, UFTDI_IFACE_INDEX, &iface); - if (err) { - device_printf(ucom->sc_dev, - "failed to get interface, err=%s\n", usbd_errstr(err)); - goto bad; - } - } else { - iface = uaa->iface; - } - - id = usbd_get_interface_descriptor(iface); - ucom->sc_iface = iface; - switch( uaa->vendor ){ - case USB_VENDOR_FTDI: - switch( uaa->product ){ - case USB_PRODUCT_FTDI_SERIAL_8U100AX: - sc->sc_type = UFTDI_TYPE_SIO; - sc->sc_hdrlen = 1; - break; - case USB_PRODUCT_FTDI_SEMC_DSS20: - case USB_PRODUCT_FTDI_SERIAL_8U232AM: - case USB_PRODUCT_FTDI_SERIAL_2232C: - case USB_PRODUCT_FTDI_CFA_631: - case USB_PRODUCT_FTDI_CFA_632: - case USB_PRODUCT_FTDI_CFA_633: - case USB_PRODUCT_FTDI_CFA_634: - case USB_PRODUCT_FTDI_CFA_635: - case USB_PRODUCT_FTDI_USBSERIAL: - case USB_PRODUCT_FTDI_MX2_3: - case USB_PRODUCT_FTDI_MX4_5: - case USB_PRODUCT_FTDI_LK202: - case USB_PRODUCT_FTDI_LK204: - case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M: - case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S: - case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U: - case USB_PRODUCT_FTDI_EISCOU: - case USB_PRODUCT_FTDI_UOPTBR: - case USB_PRODUCT_FTDI_EMCU2D: - case USB_PRODUCT_FTDI_PCMSFU: - case USB_PRODUCT_FTDI_EMCU2H: - case USB_PRODUCT_FTDI_MAXSTREAM: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - case USB_VENDOR_INTREPIDCS: - switch( uaa->product ){ - case USB_PRODUCT_INTREPIDCS_VALUECAN: - case USB_PRODUCT_INTREPIDCS_NEOVI: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - case USB_VENDOR_SIIG2: - switch( uaa->product ){ - case USB_PRODUCT_SIIG2_US2308: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - case USB_VENDOR_BBELECTRONICS: - switch( uaa->product ){ - case USB_PRODUCT_BBELECTRONICS_USOTL4: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - case USB_VENDOR_MELCO: - switch( uaa->product ){ - case USB_PRODUCT_MELCO_PCOPRS1: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - case USB_VENDOR_DRESDENELEKTRONIK: - switch( uaa->product ){ - case USB_PRODUCT_DRESDENELEKTRONIK_SENSORTERMINALBOARD: - sc->sc_type = UFTDI_TYPE_8U232AM; - sc->sc_hdrlen = 0; - break; - - default: /* Can't happen */ - goto bad; - } - break; - - default: /* Can't happen */ - goto bad; - } - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - - for (i = 0; i < id->bNumEndpoints; i++) { - int addr, dir, attr; - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, - "could not read endpoint descriptor\n"); - goto bad; - } - - addr = ed->bEndpointAddress; - dir = UE_GET_DIR(ed->bEndpointAddress); - attr = ed->bmAttributes & UE_XFERTYPE; - if (dir == UE_DIR_IN && attr == UE_BULK) - ucom->sc_bulkin_no = addr; - else if (dir == UE_DIR_OUT && attr == UE_BULK) - ucom->sc_bulkout_no = addr; - else { - device_printf(ucom->sc_dev, "unexpected endpoint\n"); - goto bad; - } - } - if (ucom->sc_bulkin_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk in\n"); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, "Could not find data bulk out\n"); - goto bad; - } - ucom->sc_parent = sc; - if (uaa->iface == NULL) - ucom->sc_portno = FTDI_PIT_SIOA; - else - ucom->sc_portno = FTDI_PIT_SIOA + id->bInterfaceNumber; - /* bulkin, bulkout set above */ - - ucom->sc_ibufsize = UFTDIIBUFSIZE; - ucom->sc_obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen; - ucom->sc_ibufsizepad = UFTDIIBUFSIZE; - ucom->sc_opkthdrlen = sc->sc_hdrlen; - - - ucom->sc_callback = &uftdi_callback; -#if 0 - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); -#endif - DPRINTF(("uftdi: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - return 0; - -bad: - DPRINTF(("uftdi_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return ENXIO; -} -#if 0 -int -uftdi_activate(device_t self, enum devact act) -{ - struct uftdi_softc *sc = (struct uftdi_softc *)self; - int rv = 0; - - switch (act) { - case DVACT_ACTIVATE: - return (EOPNOTSUPP); - - case DVACT_DEACTIVATE: - if (sc->sc_subdev != NULL) - rv = config_deactivate(sc->sc_subdev); - sc->sc_ucom.sc_dying = 1; - break; - } - return (rv); -} -#endif - -static int -uftdi_detach(device_t self) -{ - struct uftdi_softc *sc = device_get_softc(self); - - int rv = 0; - - DPRINTF(("uftdi_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - return rv; -} - -static int -uftdi_open(void *vsc, int portno) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = &sc->sc_ucom; - usb_device_request_t req; - usbd_status err; - struct termios t; - - DPRINTF(("uftdi_open: sc=%p\n", sc)); - - if (ucom->sc_dying) - return (EIO); - - /* Perform a full reset on the device */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_RESET; - USETW(req.wValue, FTDI_SIO_RESET_SIO); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - /* Set 9600 baud, 2 stop bits, no parity, 8 bits */ - t.c_ospeed = 9600; - t.c_cflag = CSTOPB | CS8; - (void)uftdi_param(sc, portno, &t); - - /* Turn on RTS/CTS flow control */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_FLOW_CTRL; - USETW(req.wValue, 0); - USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -static void -uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count) -{ - struct uftdi_softc *sc = vsc; - u_char msr, lsr; - unsigned l; - - DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", - sc, portno, *count)); - while (*count > 0) { - l = *count; - if (l > 64) - l = 64; - - msr = FTDI_GET_MSR(*ptr); - lsr = FTDI_GET_LSR(*ptr); - - if (sc->sc_msr != msr || - (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) { - DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) " - "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr, - lsr, sc->sc_lsr)); - sc->sc_msr = msr; - sc->sc_lsr = lsr; - ucom_status_change(&sc->sc_ucom); - } - - if (l > 2) - ucomrxchars(&sc->sc_ucom, (*ptr) + 2, l - 2); - *ptr += l; - *count -= l; - } -} - -static size_t -uftdi_write(void *vsc, int portno, struct tty *tp, u_char *to, u_int32_t count) -{ - struct uftdi_softc *sc = vsc; - size_t l; - - DPRINTFN(10,("uftdi_write: sc=%p, port=%d tp=%p, count=%u\n", - vsc, portno, tp, count)); - - /* Leave space for the length tag. */ - l = ttydisc_getc(tp, to + sc->sc_hdrlen, count - sc->sc_hdrlen); - if (l == 0) - return (0); - - /* Make length tag. */ - if (sc->sc_hdrlen > 0) - *to = FTDI_OUT_TAG(l, portno); - - return (l + sc->sc_hdrlen); -} - -static void -uftdi_set(void *vsc, int portno, int reg, int onoff) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = vsc; - usb_device_request_t req; - int ctl; - - DPRINTF(("uftdi_set: sc=%p, port=%d reg=%d onoff=%d\n", vsc, portno, - reg, onoff)); - - switch (reg) { - case UCOM_SET_DTR: - ctl = onoff ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; - break; - case UCOM_SET_RTS: - ctl = onoff ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; - break; - case UCOM_SET_BREAK: - uftdi_break(sc, portno, onoff); - return; - default: - return; - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_MODEM_CTRL; - USETW(req.wValue, ctl); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_set: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - (void)usbd_do_request(ucom->sc_udev, &req, NULL); -} - -static int -uftdi_param(void *vsc, int portno, struct termios *t) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = &sc->sc_ucom; - usb_device_request_t req; - usbd_status err; - int rate=0, data, flow; - - DPRINTF(("uftdi_param: sc=%p\n", sc)); - - if (ucom->sc_dying) - return (EIO); - - switch (sc->sc_type) { - case UFTDI_TYPE_SIO: - switch (t->c_ospeed) { - case 300: rate = ftdi_sio_b300; break; - case 600: rate = ftdi_sio_b600; break; - case 1200: rate = ftdi_sio_b1200; break; - case 2400: rate = ftdi_sio_b2400; break; - case 4800: rate = ftdi_sio_b4800; break; - case 9600: rate = ftdi_sio_b9600; break; - case 19200: rate = ftdi_sio_b19200; break; - case 38400: rate = ftdi_sio_b38400; break; - case 57600: rate = ftdi_sio_b57600; break; - case 115200: rate = ftdi_sio_b115200; break; - default: - return (EINVAL); - } - break; - - case UFTDI_TYPE_8U232AM: - if (uftdi_8u232am_getrate(t->c_ospeed, &rate) == -1) - return (EINVAL); - break; - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_BAUD_RATE; - USETW(req.wValue, rate); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CSTOPB)) - data = FTDI_SIO_SET_DATA_STOP_BITS_2; - else - data = FTDI_SIO_SET_DATA_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= FTDI_SIO_SET_DATA_PARITY_ODD; - else - data |= FTDI_SIO_SET_DATA_PARITY_EVEN; - } else - data |= FTDI_SIO_SET_DATA_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= FTDI_SIO_SET_DATA_BITS(5); - break; - case CS6: - data |= FTDI_SIO_SET_DATA_BITS(6); - break; - case CS7: - data |= FTDI_SIO_SET_DATA_BITS(7); - break; - case CS8: - 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); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " - "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, - UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - flow = FTDI_SIO_RTS_CTS_HS; - USETW(req.wValue, 0); - } else if (ISSET(t->c_iflag, IXON|IXOFF)) { - flow = FTDI_SIO_XON_XOFF_HS; - USETW2(req.wValue, t->c_cc[VSTOP], t->c_cc[VSTART]); - } else { - flow = FTDI_SIO_DISABLE_FLOW_CTRL; - USETW(req.wValue, 0); - } - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = FTDI_SIO_SET_FLOW_CTRL; - USETW2(req.wIndex, flow, portno); - USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -void -uftdi_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uftdi_softc *sc = vsc; - - DPRINTF(("uftdi_status: msr=0x%02x lsr=0x%02x\n", - sc->sc_msr, sc->sc_lsr)); - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -void -uftdi_break(void *vsc, int portno, int onoff) -{ - struct uftdi_softc *sc = vsc; - struct ucom_softc *ucom = 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(ucom->sc_udev, &req, NULL); -} - -static int -uftdi_8u232am_getrate(speed_t speed, int *rate) -{ - /* Table of the nearest even powers-of-2 for values 0..15. */ - static const unsigned char roundoff[16] = { - 0, 2, 2, 4, 4, 4, 8, 8, - 8, 8, 8, 8, 16, 16, 16, 16, - }; - - unsigned int d, freq; - int result; - - if (speed <= 0) - return (-1); - - /* Special cases for 2M and 3M. */ - if (speed >= 3000000 * 100 / 103 && - speed <= 3000000 * 100 / 97) { - result = 0; - goto done; - } - if (speed >= 2000000 * 100 / 103 && - speed <= 2000000 * 100 / 97) { - result = 1; - goto done; - } - - d = (FTDI_8U232AM_FREQ << 4) / speed; - d = (d & ~15) + roundoff[d & 15]; - - if (d < FTDI_8U232AM_MIN_DIV) - d = FTDI_8U232AM_MIN_DIV; - else if (d > FTDI_8U232AM_MAX_DIV) - d = FTDI_8U232AM_MAX_DIV; - - /* - * Calculate the frequency needed for d to exactly divide down - * to our target speed, and check that the actual frequency is - * within 3% of this. - */ - freq = speed * d; - if (freq < (quad_t)(FTDI_8U232AM_FREQ << 4) * 100 / 103 || - freq > (quad_t)(FTDI_8U232AM_FREQ << 4) * 100 / 97) - return (-1); - - /* - * Pack the divisor into the resultant value. The lower - * 14-bits hold the integral part, while the upper 2 bits - * encode the fractional component: either 0, 0.5, 0.25, or - * 0.125. - */ - result = d >> 4; - if (d & 8) - result |= 0x4000; - else if (d & 4) - result |= 0x8000; - else if (d & 2) - result |= 0xc000; - -done: - *rate = result; - return (0); -} - -static device_method_t uftdi_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uftdi_match), - DEVMETHOD(device_attach, uftdi_attach), - DEVMETHOD(device_detach, uftdi_detach), - - { 0, 0 } -}; - -static driver_t uftdi_driver = { - "ucom", - uftdi_methods, - sizeof (struct uftdi_softc) -}; - -DRIVER_MODULE(uftdi, uhub, uftdi_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uftdi, usb, 1, 1, 1); -MODULE_DEPEND(uftdi, ucom,UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); diff --git a/sys/dev/usb/uftdireg.h b/sys/dev/usb/uftdireg.h deleted file mode 100644 index 78c9349..0000000 --- a/sys/dev/usb/uftdireg.h +++ /dev/null @@ -1,338 +0,0 @@ -/* $NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ */ -/* $FreeBSD$ */ - -/* - * Definitions for the FTDI USB Single Port Serial Converter - - * known as FTDI_SIO (Serial Input/Output application of the chipset) - * - * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, - * USB on the other. - * - * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details - * of the protocol required to talk to the device and ongoing assistence - * during development. - * - * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc. is the original - * author of this file. - */ -/* Modified by Lennart Augustsson */ - -/* Vendor Request Interface */ -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ - -/* Port Identifier Table */ -#define FTDI_PIT_DEFAULT 0 /* SIOA */ -#define FTDI_PIT_SIOA 1 /* SIOA */ -#define FTDI_PIT_SIOB 2 /* SIOB */ -#define FTDI_PIT_PARALLEL 3 /* Parallel */ - -enum uftdi_type { - UFTDI_TYPE_SIO, - UFTDI_TYPE_8U232AM -}; - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_RESET - * wValue: Control Value - * 0 = Reset SIO - * 1 = Purge RX buffer - * 2 = Purge TX buffer - * wIndex: Port - * wLength: 0 - * Data: None - * - * The Reset SIO command has this effect: - * - * Sets flow control set to 'none' - * Event char = 0x0d - * Event trigger = disabled - * Purge RX buffer - * Purge TX buffer - * Clear DTR - * Clear RTS - * baud and data format not reset - * - * The Purge RX and TX buffer commands affect nothing except the buffers - * - */ -/* FTDI_SIO_RESET */ -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 - - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_BAUDRATE - * wValue: BaudRate value - see below - * wIndex: Port - * wLength: 0 - * Data: None - */ -/* FTDI_SIO_SET_BAUDRATE */ -enum { - ftdi_sio_b300 = 0, - ftdi_sio_b600 = 1, - ftdi_sio_b1200 = 2, - ftdi_sio_b2400 = 3, - ftdi_sio_b4800 = 4, - ftdi_sio_b9600 = 5, - ftdi_sio_b19200 = 6, - ftdi_sio_b38400 = 7, - ftdi_sio_b57600 = 8, - ftdi_sio_b115200 = 9 -}; - -#define FTDI_8U232AM_FREQ 3000000 - -/* Bounds for normal divisors as 4-bit fixed precision ints. */ -#define FTDI_8U232AM_MIN_DIV 0x20 -#define FTDI_8U232AM_MAX_DIV 0x3fff8 - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_DATA - * wValue: Data characteristics (see below) - * wIndex: Port - * wLength: 0 - * Data: No - * - * Data characteristics - * - * B0..7 Number of data bits - * B8..10 Parity - * 0 = None - * 1 = Odd - * 2 = Even - * 3 = Mark - * 4 = Space - * B11..13 Stop Bits - * 0 = 1 - * 1 = 1.5 - * 2 = 2 - * B14..15 Reserved - * - */ -/* FTDI_SIO_SET_DATA */ -#define FTDI_SIO_SET_DATA_BITS(n) (n) -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#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) - - -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_MODEM_CTRL - * wValue: ControlValue (see below) - * wIndex: Port - * wLength: 0 - * Data: None - * - * NOTE: If the device is in RTS/CTS flow control, the RTS set by this - * command will be IGNORED without an error being returned - * Also - you can not set DTR and RTS with one control message - * - * ControlValue - * B0 DTR state - * 0 = reset - * 1 = set - * B1 RTS state - * 0 = reset - * 1 = set - * B2..7 Reserved - * B8 DTR state enable - * 0 = ignore - * 1 = use DTR state - * B9 RTS state enable - * 0 = ignore - * 1 = use RTS state - * B10..15 Reserved - */ -/* FTDI_SIO_MODEM_CTRL */ -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8)) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8)) -#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8)) - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_FLOW_CTRL - * wValue: Xoff/Xon - * wIndex: Protocol/Port - hIndex is protocl / lIndex is port - * wLength: 0 - * Data: None - * - * hIndex protocol is: - * B0 Output handshaking using RTS/CTS - * 0 = disabled - * 1 = enabled - * B1 Output handshaking using DTR/DSR - * 0 = disabled - * 1 = enabled - * B2 Xon/Xoff handshaking - * 0 = disabled - * 1 = enabled - * - * A value of zero in the hIndex field disables handshaking - * - * If Xon/Xoff handshaking is specified, the hValue field should contain the - * XOFF character and the lValue field contains the XON character. - */ -/* FTDI_SIO_SET_FLOW_CTRL */ -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS 0x1 -#define FTDI_SIO_DTR_DSR_HS 0x2 -#define FTDI_SIO_XON_XOFF_HS 0x4 - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_EVENT_CHAR - * wValue: Event Char - * wIndex: Port - * wLength: 0 - * Data: None - * - * wValue: - * B0..7 Event Character - * B8 Event Character Processing - * 0 = disabled - * 1 = enabled - * B9..15 Reserved - * - * FTDI_SIO_SET_EVENT_CHAR - * - * Set the special event character for the specified communications port. - * If the device sees this character it will immediately return the - * data read so far - rather than wait 40ms or until 62 bytes are read - * which is what normally happens. - */ - - - -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_ERROR_CHAR - * wValue: Error Char - * wIndex: Port - * wLength: 0 - * Data: None - * - * Error Char - * B0..7 Error Character - * B8 Error Character Processing - * 0 = disabled - * 1 = enabled - * B9..15 Reserved - * - * - * FTDI_SIO_SET_ERROR_CHAR - * Set the parity error replacement character for the specified communications - * port. - */ - - -/* - * BmRequestType: 1100 0000b - * bRequest: FTDI_SIO_GET_MODEM_STATUS - * wValue: zero - * wIndex: Port - * wLength: 1 - * Data: Status - * - * One byte of data is returned - * B0..3 0 - * B4 CTS - * 0 = inactive - * 1 = active - * B5 DSR - * 0 = inactive - * 1 = active - * B6 Ring Indicator (RI) - * 0 = inactive - * 1 = active - * B7 Receive Line Signal Detect (RLSD) - * 0 = inactive - * 1 = active - * - * FTDI_SIO_GET_MODEM_STATUS - * Retrieve the current value of the modem status register. - */ -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 - - - -/* - * - * DATA FORMAT - * - * IN Endpoint - * - * The device reserves the first two bytes of data on this endpoint to contain - * the current values of the modem and line status registers. In the absence of - * data, the device generates a message consisting of these two status bytes - * every 40 ms. - * - * Byte 0: Modem Status - * NOTE: 4 upper bits have same layout as the MSR register in a 16550 - * - * Offset Description - * B0..3 Port - * B4 Clear to Send (CTS) - * B5 Data Set Ready (DSR) - * B6 Ring Indicator (RI) - * B7 Receive Line Signal Detect (RLSD) - * - * Byte 1: Line Status - * NOTE: same layout as the LSR register in a 16550 - * - * Offset Description - * B0 Data Ready (DR) - * B1 Overrun Error (OE) - * B2 Parity Error (PE) - * B3 Framing Error (FE) - * B4 Break Interrupt (BI) - * B5 Transmitter Holding Register (THRE) - * B6 Transmitter Empty (TEMT) - * B7 Error in RCVR FIFO - * - * - * OUT Endpoint - * - * This device reserves the first bytes of data on this endpoint contain the - * length and port identifier of the message. For the FTDI USB Serial converter - * the port identifier is always 1. - * - * Byte 0: Port & length - * - * Offset Description - * B0..1 Port - * B2..7 Length of message - (not including Byte 0) - * - */ -#define FTDI_PORT_MASK 0x0f -#define FTDI_MSR_MASK 0xf0 -#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK) -#define FTDI_GET_LSR(p) ((p)[1]) -#define FTDI_LSR_MASK (~0x60) /* interesting bits */ -#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port)) diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c deleted file mode 100644 index 4f03cfb..0000000 --- a/sys/dev/usb/ugen.c +++ /dev/null @@ -1,1590 +0,0 @@ -/* $NetBSD: ugen.c,v 1.79 2006/03/01 12:38:13 yamt Exp $ */ - -/* Also already merged from NetBSD: - * $NetBSD: ugen.c,v 1.61 2002/09/23 05:51:20 simonb Exp $ - * $NetBSD: ugen.c,v 1.64 2003/06/28 14:21:46 darrenr Exp $ - * $NetBSD: ugen.c,v 1.65 2003/06/29 22:30:56 fvdl Exp $ - * $NetBSD: ugen.c,v 1.68 2004/06/23 02:30:52 mycroft Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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/param.h> -#include <sys/systm.h> -#include <sys/clist.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ugendebug) printf x -#define DPRINTFN(n,x) if (ugendebug>(n)) printf x -int ugendebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB ugen"); -SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW, - &ugendebug, 0, "ugen debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UGEN_CHUNK 128 /* chunk size for read */ -#define UGEN_IBSIZE 1020 /* buffer size */ -#define UGEN_BBSIZE 1024 - -#define UGEN_NISOFRAMES 500 /* 0.5 seconds worth */ -#define UGEN_NISOREQS 6 /* number of outstanding xfer requests */ -#define UGEN_NISORFRMS 4 /* number of frames (miliseconds) per req */ - -struct ugen_endpoint { - struct ugen_softc *sc; - struct cdev *dev; - usb_endpoint_descriptor_t *edesc; - usbd_interface_handle iface; - int state; -#define UGEN_ASLP 0x02 /* waiting for data */ -#define UGEN_SHORT_OK 0x04 /* short xfers are OK */ - usbd_pipe_handle pipeh; - struct clist q; - struct selinfo rsel; - u_char *ibuf; /* start of buffer (circular for isoc) */ - u_char *fill; /* location for input (isoc) */ - u_char *limit; /* end of circular buffer (isoc) */ - u_char *cur; /* current read location (isoc) */ - u_int32_t timeout; - struct isoreq { - struct ugen_endpoint *sce; - usbd_xfer_handle xfer; - void *dmabuf; - u_int16_t sizes[UGEN_NISORFRMS]; - } isoreqs[UGEN_NISOREQS]; -}; - -struct ugen_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; - struct cdev *dev; - - char sc_is_open[USB_MAX_ENDPOINTS]; - struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; -#define OUT 0 -#define IN 1 - -#define UGEN_DEV_REF(dev, sc) \ - if ((sc)->sc_dying || dev_refthread(dev) == NULL) \ - return (ENXIO) -#define UGEN_DEV_RELE(dev, sc) \ - dev_relthread(dev) -#define UGEN_DEV_OPEN(dev, sc) \ - /* handled by dev layer */ -#define UGEN_DEV_CLOSE(dev, sc) \ - /* handled by dev layer */ - u_char sc_dying; -}; - -d_open_t ugenopen; -d_close_t ugenclose; -d_read_t ugenread; -d_write_t ugenwrite; -d_ioctl_t ugenioctl; -d_poll_t ugenpoll; -d_purge_t ugenpurge; - -static struct cdevsw ugenctl_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ugenopen, - .d_close = ugenclose, - .d_ioctl = ugenioctl, - .d_purge = ugenpurge, - .d_name = "ugenctl", -}; - -static struct cdevsw ugen_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ugenopen, - .d_close = ugenclose, - .d_read = ugenread, - .d_write = ugenwrite, - .d_ioctl = ugenioctl, - .d_poll = ugenpoll, - .d_purge = ugenpurge, - .d_name = "ugen", -}; - -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, struct thread *); -static void ugen_make_devnodes(struct ugen_softc *sc); -static void ugen_destroy_devnodes(struct ugen_softc *sc); -static int ugen_set_config(struct ugen_softc *sc, int configno); -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); - -#define UGENUNIT(n) ((dev2unit(n) >> 4) & 0xf) -#define UGENENDPOINT(n) (dev2unit(n) & 0xf) -#define UGENMINOR(u, e) (((u) << 4) | (e)) - -static device_probe_t ugen_match; -static device_attach_t ugen_attach; -static device_detach_t ugen_detach; - -static devclass_t ugen_devclass; - -static device_method_t ugen_methods[] = { - DEVMETHOD(device_probe, ugen_match), - DEVMETHOD(device_attach, ugen_attach), - DEVMETHOD(device_detach, ugen_detach), - {0,0}, - {0,0} -}; - -static driver_t ugen_driver = { - "ugen", - ugen_methods, - sizeof(struct ugen_softc) -}; - -MODULE_DEPEND(ugen, usb, 1, 1, 1); - -static int -ugen_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - -#if 0 - if (uaa->matchlvl) - return (uaa->matchlvl); -#endif - if (uaa->usegeneric) - return (UMATCH_GENERIC); - else - return (UMATCH_NONE); -} - -static int -ugen_attach(device_t self) -{ - struct ugen_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle udev; - usbd_status err; - int conf; - - sc->sc_dev = self; - sc->sc_udev = udev = uaa->device; - - memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); - - /* 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", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return (ENXIO); - } - conf = usbd_get_config_descriptor(udev)->bConfigurationValue; - - /* Set up all the local state for this configuration. */ - err = ugen_set_config(sc, conf); - if (err) { - printf("%s: setting configuration %d failed\n", - device_get_nameunit(sc->sc_dev), conf); - sc->sc_dying = 1; - return (ENXIO); - } - - /* the main device, ctrl endpoint */ - sc->dev = make_dev(&ugenctl_cdevsw, - UGENMINOR(device_get_unit(sc->sc_dev), 0), UID_ROOT, GID_OPERATOR, 0644, - "%s", device_get_nameunit(sc->sc_dev)); - ugen_make_devnodes(sc); - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); - return (0); -} - -static void -ugen_make_devnodes(struct ugen_softc *sc) -{ - int endptno; - struct cdev *dev; - - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) { - if (sc->sc_endpoints[endptno][IN].sc != NULL || - sc->sc_endpoints[endptno][OUT].sc != NULL ) { - /* endpt can be 0x81 and 0x01, representing - * endpoint address 0x01 and IN/OUT directions. - * We map both endpts to the same device, - * IN is reading from it, OUT is writing to it. - * - * In the if clause above we check whether one - * of the structs is populated. - */ - dev = make_dev(&ugen_cdevsw, - UGENMINOR(device_get_unit(sc->sc_dev), endptno), - UID_ROOT, GID_OPERATOR, 0644, - "%s.%d", - device_get_nameunit(sc->sc_dev), endptno); - dev_depends(sc->dev, dev); - if (sc->sc_endpoints[endptno][IN].sc != NULL) - sc->sc_endpoints[endptno][IN].dev = dev; - if (sc->sc_endpoints[endptno][OUT].sc != NULL) - sc->sc_endpoints[endptno][OUT].dev = dev; - } - } -} - -static void -ugen_destroy_devnodes(struct ugen_softc *sc) -{ - int endptno, prev_sc_dying; - struct cdev *dev; - - prev_sc_dying = sc->sc_dying; - sc->sc_dying = 1; - /* destroy all devices for the other (existing) endpoints as well */ - for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) { - if (sc->sc_endpoints[endptno][IN].sc != NULL || - sc->sc_endpoints[endptno][OUT].sc != NULL ) { - /* endpt can be 0x81 and 0x01, representing - * endpoint address 0x01 and IN/OUT directions. - * We map both endpoint addresses to the same device, - * IN is reading from it, OUT is writing to it. - * - * In the if clause above we check whether one - * of the structs is populated. - */ - if (sc->sc_endpoints[endptno][IN].sc != NULL) - dev = sc->sc_endpoints[endptno][IN].dev; - else - dev = sc->sc_endpoints[endptno][OUT].dev; - - KASSERT(dev != NULL, - ("ugen_destroy_devnodes: NULL dev")); - if(dev != NULL) - destroy_dev(dev); - - sc->sc_endpoints[endptno][IN].sc = NULL; - sc->sc_endpoints[endptno][OUT].sc = NULL; - } - } - sc->sc_dying = prev_sc_dying; -} - -static int -ugen_set_config(struct ugen_softc *sc, int configno) -{ - usbd_device_handle dev = sc->sc_udev; - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - struct ugen_endpoint *sce, **sce_cache, ***sce_cache_arr; - u_int8_t niface, niface_cache, nendpt, *nendpt_cache; - int ifaceno, endptno, endpt; - usbd_status err; - int dir; - - DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", - device_get_nameunit(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", - device_get_nameunit(sc->sc_dev), endptno)); - return (USBD_IN_USE); - } - - err = usbd_interface_count(dev, &niface); - if (err) - return (err); - /* store an array of endpoint descriptors to clear if the configuration - * change succeeds - these aren't available afterwards */ - nendpt_cache = malloc(sizeof(u_int8_t) * niface, M_TEMP, M_WAITOK | - M_ZERO); - sce_cache_arr = malloc(sizeof(struct ugen_endpoint **) * niface, M_TEMP, - M_WAITOK | M_ZERO); - niface_cache = niface; - - for (ifaceno = 0; ifaceno < niface; ifaceno++) { - DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); - err = usbd_device2interface_handle(dev, ifaceno, &iface); - if (err) - panic("ugen_set_config: can't obtain interface handle"); - err = usbd_endpoint_count(iface, &nendpt); - if (err) - panic("ugen_set_config: endpoint count failed"); - - /* store endpoint descriptors for each interface */ - nendpt_cache[ifaceno] = nendpt; - sce_cache = malloc(sizeof(struct ugen_endpoint *) * nendpt, M_TEMP, - M_WAITOK); - sce_cache_arr[ifaceno] = sce_cache; - - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce_cache[endptno] = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - } - } - - /* Avoid setting the current value. */ - if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { - /* attempt to perform the configuration change */ - err = usbd_set_config_no(dev, configno, 1); - if (err) { - for(ifaceno = 0; ifaceno < niface_cache; ifaceno++) - free(sce_cache_arr[ifaceno], M_TEMP); - free(sce_cache_arr, M_TEMP); - free(nendpt_cache, M_TEMP); - return (err); - } - } - - ugen_destroy_devnodes(sc); - - /* now we can clear the old interface's ugen_endpoints */ - for(ifaceno = 0; ifaceno < niface_cache; ifaceno++) { - sce_cache = sce_cache_arr[ifaceno]; - for(endptno = 0; endptno < nendpt_cache[ifaceno]; endptno++) { - sce = sce_cache[endptno]; - sce->sc = 0; - sce->edesc = 0; - sce->iface = 0; - } - } - - /* and free the cache storing them */ - for(ifaceno = 0; ifaceno < niface_cache; ifaceno++) - free(sce_cache_arr[ifaceno], M_TEMP); - free(sce_cache_arr, M_TEMP); - free(nendpt_cache, M_TEMP); - - /* no endpoints if the device is in the unconfigured state */ - if (configno != USB_UNCONFIG_NO) - { - /* set the new configuration's ugen_endpoints */ - err = usbd_interface_count(dev, &niface); - if (err) - panic("ugen_set_config: interface count failed"); - - memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); - for (ifaceno = 0; ifaceno < niface; ifaceno++) { - DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); - err = usbd_device2interface_handle(dev, ifaceno, &iface); - if (err) - panic("ugen_set_config: can't obtain interface handle"); - err = usbd_endpoint_count(iface, &nendpt); - if (err) - panic("ugen_set_config: endpoint count failed"); - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x" - "(%d,%d), sce=%p\n", - endptno, endpt, UE_GET_ADDR(endpt), - UE_GET_DIR(endpt), sce)); - sce->sc = sc; - sce->edesc = ed; - sce->iface = iface; - } - } - } - - return (USBD_NORMAL_COMPLETION); -} - -int -ugenopen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct ugen_softc *sc; - int unit = UGENUNIT(dev); - int endpt = UGENENDPOINT(dev); - usb_endpoint_descriptor_t *edesc; - struct ugen_endpoint *sce; - int dir, isize; - usbd_status err; - usbd_xfer_handle xfer; - void *buf; - int i, j; - - sc = devclass_get_softc(ugen_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", - flag, mode, unit, endpt)); - - if (sc == NULL || sc->sc_dying) - return (ENXIO); - - if (sc->sc_is_open[endpt]) - return (EBUSY); - - if (endpt == USB_CONTROL_ENDPOINT) { - sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; - UGEN_DEV_OPEN(dev, sc); - return (0); - } - - /* Make sure there are pipes for all directions. */ - for (dir = OUT; dir <= IN; dir++) { - if (flag & (dir == OUT ? FWRITE : FREAD)) { - sce = &sc->sc_endpoints[endpt][dir]; - if (sce->edesc == 0) - return (ENXIO); - } - } - - /* Actually open the pipes. */ - /* XXX Should back out properly if it fails. */ - for (dir = OUT; dir <= IN; dir++) { - if (!(flag & (dir == OUT ? FWRITE : FREAD))) - continue; - 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", - sc, endpt, dir, sce)); - edesc = sce->edesc; - switch (edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - if (dir == OUT) { - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) - return (EIO); - break; - } - isize = UGETW(edesc->wMaxPacketSize); - 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", - endpt, isize)); - if ((clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, - 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); - clist_free_cblocks(&sce->q); - return (EIO); - } - DPRINTFN(5, ("ugenopen: interrupt open done\n")); - break; - case UE_BULK: - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) - return (EIO); - break; - case UE_ISOCHRONOUS: - if (dir == OUT) - return (EINVAL); - isize = UGETW(edesc->wMaxPacketSize); - if (isize == 0) /* shouldn't happen */ - return (EINVAL); - sce->ibuf = malloc(isize * UGEN_NISOFRAMES, - 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", - endpt, isize)); - err = usbd_open_pipe(sce->iface, - edesc->bEndpointAddress, 0, &sce->pipeh); - if (err) { - free(sce->ibuf, M_USBDEV); - return (EIO); - } - for(i = 0; i < UGEN_NISOREQS; ++i) { - sce->isoreqs[i].sce = sce; - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - goto bad; - sce->isoreqs[i].xfer = xfer; - buf = usbd_alloc_buffer - (xfer, isize * UGEN_NISORFRMS); - if (buf == 0) { - i++; - goto bad; - } - sce->isoreqs[i].dmabuf = buf; - for(j = 0; j < UGEN_NISORFRMS; ++j) - sce->isoreqs[i].sizes[j] = isize; - usbd_setup_isoc_xfer - (xfer, sce->pipeh, &sce->isoreqs[i], - sce->isoreqs[i].sizes, - UGEN_NISORFRMS, USBD_NO_COPY, - ugen_isoc_rintr); - (void)usbd_transfer(xfer); - } - DPRINTFN(5, ("ugenopen: isoc open done\n")); - break; - bad: - while (--i >= 0) /* implicit buffer free */ - usbd_free_xfer(sce->isoreqs[i].xfer); - return (ENOMEM); - case UE_CONTROL: - sce->timeout = USBD_DEFAULT_TIMEOUT; - return (EINVAL); - } - } - sc->sc_is_open[endpt] = 1; - UGEN_DEV_OPEN(dev, sc); - return (0); -} - -int -ugenclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - struct ugen_endpoint *sce; - int dir; - int i; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", - flag, mode, UGENUNIT(dev), endpt)); - -#ifdef DIAGNOSTIC - if (!sc->sc_is_open[endpt]) { - printf("ugenclose: not open\n"); - return (EINVAL); - } -#endif - - if (endpt == USB_CONTROL_ENDPOINT) { - DPRINTFN(5, ("ugenclose: close control\n")); - sc->sc_is_open[endpt] = 0; - UGEN_DEV_CLOSE(dev, sc); - return (0); - } - - for (dir = OUT; dir <= IN; dir++) { - if (!(flag & (dir == OUT ? FWRITE : FREAD))) - continue; - sce = &sc->sc_endpoints[endpt][dir]; - if (sce->pipeh == NULL) - continue; - DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", - endpt, dir, sce)); - - usbd_abort_pipe(sce->pipeh); - usbd_close_pipe(sce->pipeh); - sce->pipeh = NULL; - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - ndflush(&sce->q, sce->q.c_cc); - clist_free_cblocks(&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; - clist_free_cblocks(&sce->q); - } - } - sc->sc_is_open[endpt] = 0; - UGEN_DEV_CLOSE(dev, sc); - - return (0); -} - -static int -ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) -{ - struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; - u_int32_t n, tn; - char buf[UGEN_BBSIZE]; - usbd_xfer_handle xfer; - usbd_status err; - int s; - int error = 0, doneone = 0; - u_char buffer[UGEN_CHUNK]; - - DPRINTFN(5, ("%s: ugenread: %d\n", device_get_nameunit(sc->sc_dev), endpt)); - - if (sc->sc_dying) - return (EIO); - - if (endpt == USB_CONTROL_ENDPOINT) - return (ENODEV); - -#ifdef DIAGNOSTIC - if (sce->edesc == NULL) { - printf("ugenread: no edesc\n"); - return (EIO); - } - if (sce->pipeh == NULL) { - printf("ugenread: no pipe\n"); - return (EIO); - } -#endif - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - /* Block until activity occurred. */ - s = splusb(); - while (sce->q.c_cc == 0) { - if (flag & O_NONBLOCK) { - splx(s); - return (EWOULDBLOCK); - } - sce->state |= UGEN_ASLP; - DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); - error = tsleep(sce, PZERO | PCATCH, "ugenri", - (sce->timeout * hz + 999) / 1000); - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error == EAGAIN) { - error = 0; /* timeout, return 0 bytes */ - break; - } - if (error) - break; - } - splx(s); - - /* Transfer as many chunks as possible. */ - while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { - n = min(sce->q.c_cc, uio->uio_resid); - if (n > sizeof(buffer)) - n = sizeof(buffer); - - /* Remove a small chunk from the input queue. */ - q_to_b(&sce->q, buffer, n); - DPRINTFN(5, ("ugenread: got %d chars\n", n)); - - /* Copy the data to the user process. */ - error = uiomove(buffer, n, uio); - if (error) - break; - } - break; - case UE_BULK: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - return (ENOMEM); - while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0 || - !doneone) { - DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); - tn = n; - doneone = 1; - err = usbd_bulk_transfer( - xfer, sce->pipeh, - sce->state & UGEN_SHORT_OK ? - USBD_SHORT_XFER_OK : 0, - sce->timeout, buf, &tn, "ugenrb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); - error = uiomove(buf, tn, uio); - if (error || tn < n) - break; - } - usbd_free_xfer(xfer); - break; - case UE_ISOCHRONOUS: - s = splusb(); - while (sce->cur == sce->fill) { - if (flag & O_NONBLOCK) { - splx(s); - return (EWOULDBLOCK); - } - sce->state |= UGEN_ASLP; - DPRINTFN(5, ("ugenread: sleep on %p\n", sce)); - error = tsleep(sce, PZERO | PCATCH, "ugenri", - (sce->timeout * hz + 999) / 1000); - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error == EAGAIN) { - error = 0; /* timeout, return 0 bytes */ - break; - } - if (error) - break; - } - - while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) { - if (sce->fill > sce->cur) - n = min(sce->fill - sce->cur, uio->uio_resid); - else - n = min(sce->limit - sce->cur, uio->uio_resid); - - DPRINTFN(5, ("ugenread: isoc got %d chars\n", n)); - - /* Copy the data to the user process. */ - error = uiomove(sce->cur, n, uio); - if (error) - break; - sce->cur += n; - if(sce->cur >= sce->limit) - sce->cur = sce->ibuf; - } - splx(s); - break; - - - default: - return (ENXIO); - } - return (error); -} - -int -ugenread(struct cdev *dev, struct uio *uio, int flag) -{ - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - UGEN_DEV_REF(dev, sc); - error = ugen_do_read(sc, endpt, uio, flag); - UGEN_DEV_RELE(dev, sc); - return (error); -} - -static int -ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) -{ - struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; - u_int32_t n; - int error = 0, doneone = 0; - char buf[UGEN_BBSIZE]; - usbd_xfer_handle xfer; - usbd_status err; - - DPRINTFN(5, ("%s: ugenwrite: %d\n", device_get_nameunit(sc->sc_dev), endpt)); - - if (sc->sc_dying) - return (EIO); - - if (endpt == USB_CONTROL_ENDPOINT) - return (ENODEV); - -#ifdef DIAGNOSTIC - if (sce->edesc == NULL) { - printf("ugenwrite: no edesc\n"); - return (EIO); - } - if (sce->pipeh == NULL) { - printf("ugenwrite: no pipe\n"); - return (EIO); - } -#endif - - switch (sce->edesc->bmAttributes & UE_XFERTYPE) { - case UE_BULK: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - return (EIO); - while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0 || - !doneone) { - doneone = 1; - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sce->pipeh, 0, - sce->timeout, buf, &n,"ugenwb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - } - usbd_free_xfer(xfer); - break; - case UE_INTERRUPT: - xfer = usbd_alloc_xfer(sc->sc_udev); - if (xfer == 0) - return (EIO); - while ((n = min(UGETW(sce->edesc->wMaxPacketSize), - uio->uio_resid)) != 0 || !doneone) { - doneone = 1; - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); - err = usbd_intr_transfer(xfer, sce->pipeh, 0, - sce->timeout, buf, &n, "ugenwi"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - } - usbd_free_xfer(xfer); - break; - default: - return (ENXIO); - } - return (error); -} - -int -ugenwrite(struct cdev *dev, struct uio *uio, int flag) -{ - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - UGEN_DEV_REF(dev, sc); - error = ugen_do_write(sc, endpt, uio, flag); - UGEN_DEV_RELE(dev, sc); - return (error); -} - -void -ugenpurge(struct cdev *dev) -{ - int endpt = UGENENDPOINT(dev); - struct ugen_endpoint *sce; - struct ugen_softc *sc; - - if (endpt == USB_CONTROL_ENDPOINT) - return; - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - sce = &sc->sc_endpoints[endpt][IN]; - if (sce->pipeh) - usbd_abort_pipe(sce->pipeh); - if (sce->state & UGEN_ASLP) { - DPRINTFN(5, ("ugenpurge: waking %p\n", sce)); - wakeup(sce); - } - selwakeuppri(&sce->rsel, PZERO); - - sce = &sc->sc_endpoints[endpt][OUT]; - if (sce->pipeh) - usbd_abort_pipe(sce->pipeh); - if (sce->state & UGEN_ASLP) { - DPRINTFN(5, ("ugenpurge: waking %p\n", sce)); - wakeup(sce); - } - selwakeuppri(&sce->rsel, PZERO); -} - -static int -ugen_detach(device_t self) -{ - struct ugen_softc *sc = device_get_softc(self); - struct ugen_endpoint *sce; - int i, dir; - - DPRINTF(("ugen_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - /* Abort all pipes. Causes processes waiting for transfer to wake. */ - for (i = 0; i < USB_MAX_ENDPOINTS; i++) { - for (dir = OUT; dir <= IN; dir++) { - sce = &sc->sc_endpoints[i][dir]; - if (sce->pipeh) - usbd_abort_pipe(sce->pipeh); - selwakeuppri(&sce->rsel, PZERO); - } - } - - /* destroy the device for the control endpoint */ - destroy_dev(sc->dev); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - return (0); -} - -static void -ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct ugen_endpoint *sce = addr; - /*struct ugen_softc *sc = sce->sc;*/ - u_int32_t count; - u_char *ibuf; - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ugenintr: status=%d\n", status)); - if (status == USBD_STALLED) - 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", - xfer, status, count)); - DPRINTFN(5, (" data = %02x %02x %02x\n", - ibuf[0], ibuf[1], ibuf[2])); - - (void)b_to_q(ibuf, count, &sce->q); - - if (sce->state & UGEN_ASLP) { - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugen_intr: waking %p\n", sce)); - wakeup(sce); - } - selwakeuppri(&sce->rsel, PZERO); -} - -static void -ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr, - usbd_status status) -{ - struct isoreq *req = addr; - struct ugen_endpoint *sce = req->sce; - u_int32_t count, n; - int i, isize; - - /* Return if we are aborting. */ - if (status == USBD_CANCELLED) - return; - - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - DPRINTFN(5,("ugen_isoc_rintr: xfer %td, count=%d\n", req - sce->isoreqs, - count)); - - /* throw away oldest input if the buffer is full */ - if(sce->fill < sce->cur && sce->cur <= sce->fill + count) { - sce->cur += count; - if(sce->cur >= sce->limit) - sce->cur = sce->ibuf + (sce->limit - sce->cur); - DPRINTF(("ugen_isoc_rintr: throwing away %d bytes\n", - count)); - } - - isize = UGETW(sce->edesc->wMaxPacketSize); - for (i = 0; i < UGEN_NISORFRMS; i++) { - u_int32_t actlen = req->sizes[i]; - char const *buf = (char const *)req->dmabuf + isize * i; - - /* copy data to buffer */ - while (actlen > 0) { - n = min(actlen, sce->limit - sce->fill); - memcpy(sce->fill, buf, n); - - buf += n; - actlen -= n; - sce->fill += n; - if(sce->fill == sce->limit) - sce->fill = sce->ibuf; - } - - /* setup size for next transfer */ - req->sizes[i] = isize; - } - - usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS, - USBD_NO_COPY, ugen_isoc_rintr); - (void)usbd_transfer(xfer); - - if (sce->state & UGEN_ASLP) { - sce->state &= ~UGEN_ASLP; - DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce)); - wakeup(sce); - } - selwakeuppri(&sce->rsel, PZERO); -} - -static usbd_status -ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno) -{ - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - usbd_status err; - struct ugen_endpoint *sce, **sce_cache; - u_int8_t niface, nendpt, nendpt_cache, endptno, endpt; - int dir; - - DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); - - err = usbd_interface_count(sc->sc_udev, &niface); - if (err) - return (err); - if (ifaceidx < 0 || ifaceidx >= niface) - return (USBD_INVAL); - - err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (err) - return (err); - err = usbd_endpoint_count(iface, &nendpt); - if (err) - return (err); - - /* store an array of endpoint descriptors to clear if the interface - * change succeeds - these aren't available afterwards */ - sce_cache = malloc(sizeof(struct ugen_endpoint *) * nendpt, M_TEMP, - M_WAITOK); - nendpt_cache = nendpt; - - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce_cache[endptno] = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - } - - /* change setting */ - err = usbd_set_interface(iface, altno); - if (err) { - free(sce_cache, M_TEMP); - return (err); - } - err = usbd_endpoint_count(iface, &nendpt); - if (err) - panic("ugen_set_interface: endpoint count failed"); - - /* destroy the existing devices, we remake the new ones in a moment */ - ugen_destroy_devnodes(sc); - - /* now we can clear the old interface's ugen_endpoints */ - for (endptno = 0; endptno < nendpt_cache; endptno++) { - sce = sce_cache[endptno]; - sce->sc = 0; - sce->edesc = 0; - sce->iface = 0; - } - free(sce_cache, M_TEMP); - - /* set the new interface's ugen_endpoints */ - for (endptno = 0; endptno < nendpt; endptno++) { - ed = usbd_interface2endpoint_descriptor(iface,endptno); - endpt = ed->bEndpointAddress; - dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; - sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; - sce->sc = sc; - sce->edesc = ed; - sce->iface = iface; - } - - /* make the new devices */ - ugen_make_devnodes(sc); - - return (0); -} - -/* Retrieve a complete descriptor for a certain device and index. */ -static usb_config_descriptor_t * -ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp) -{ - usb_config_descriptor_t *cdesc, *tdesc, cdescr; - int len; - usbd_status err; - - if (index == USB_CURRENT_CONFIG_INDEX) { - tdesc = usbd_get_config_descriptor(sc->sc_udev); - len = UGETW(tdesc->wTotalLength); - if (lenp) - *lenp = len; - cdesc = malloc(len, M_TEMP, M_WAITOK); - memcpy(cdesc, tdesc, len); - DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); - } else { - err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); - if (err) - return (0); - len = UGETW(cdescr.wTotalLength); - DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); - if (lenp) - *lenp = len; - cdesc = malloc(len, M_TEMP, M_WAITOK); - err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len); - if (err) { - free(cdesc, M_TEMP); - return (0); - } - } - return (cdesc); -} - -static int -ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx) -{ - usbd_interface_handle iface; - usbd_status err; - - err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); - if (err) - return (-1); - return (usbd_get_interface_altindex(iface)); -} - -static int -ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, - caddr_t addr, int flag, struct thread *p) -{ - struct ugen_endpoint *sce; - usbd_status err; - usbd_interface_handle iface; - struct usb_config_desc *cd; - usb_config_descriptor_t *cdesc; - struct usb_interface_desc *id; - usb_interface_descriptor_t *idesc; - struct usb_endpoint_desc *ed; - usb_endpoint_descriptor_t *edesc; - struct usb_alt_interface *ai; - struct usb_string_desc *si; - u_int8_t conf, alt; - - DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); - if (sc->sc_dying) - return (EIO); - - switch (cmd) { - case FIONBIO: - case FIOASYNC: - /* All handled in the upper FS layer. */ - return (0); - case USB_SET_SHORT_XFER: - if (endpt == USB_CONTROL_ENDPOINT) - return (EINVAL); - /* This flag only affects read */ - sce = &sc->sc_endpoints[endpt][IN]; - - if (sce->pipeh == NULL) { - printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); - return (EIO); - } - - if (*(int *)addr) - sce->state |= UGEN_SHORT_OK; - else - sce->state &= ~UGEN_SHORT_OK; - return (0); - case USB_SET_TIMEOUT: - sce = &sc->sc_endpoints[endpt][IN]; - sce->timeout = *(int *)addr; - sce = &sc->sc_endpoints[endpt][OUT]; - sce->timeout = *(int *)addr; - return (0); - default: - break; - } - - if (endpt != USB_CONTROL_ENDPOINT) - return (EINVAL); - - switch (cmd) { -#ifdef USB_DEBUG - case USB_SETDEBUG: - ugendebug = *(int *)addr; - break; -#endif - case USB_GET_CONFIG: - err = usbd_get_config(sc->sc_udev, &conf); - if (err) - return (EIO); - *(int *)addr = conf; - break; - case USB_SET_CONFIG: - if (!(flag & FWRITE)) - return (EPERM); - err = ugen_set_config(sc, *(int *)addr); - switch (err) { - case USBD_NORMAL_COMPLETION: - ugen_make_devnodes(sc); - break; - case USBD_IN_USE: - return (EBUSY); - default: - 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); - if (err) - return (EINVAL); - idesc = usbd_get_interface_descriptor(iface); - if (idesc == NULL) - return (EIO); - ai->uai_alt_no = idesc->bAlternateSetting; - break; - case USB_SET_ALTINTERFACE: - if (!(flag & FWRITE)) - return (EPERM); - ai = (struct usb_alt_interface *)addr; - 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); - if (err) - return (EINVAL); - break; - case USB_GET_NO_ALT: - ai = (struct usb_alt_interface *)addr; - cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0); - if (idesc == NULL) { - free(cdesc, M_TEMP); - return (EINVAL); - } - ai->uai_alt_no = usbd_get_no_alts(cdesc, - idesc->bInterfaceNumber); - free(cdesc, M_TEMP); - break; - case USB_GET_DEVICE_DESC: - *(usb_device_descriptor_t *)addr = - *usbd_get_device_descriptor(sc->sc_udev); - break; - case USB_GET_CONFIG_DESC: - cd = (struct usb_config_desc *)addr; - cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - cd->ucd_desc = *cdesc; - free(cdesc, M_TEMP); - break; - case USB_GET_INTERFACE_DESC: - id = (struct usb_interface_desc *)addr; - cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX && - id->uid_alt_index == USB_CURRENT_ALT_INDEX) - alt = ugen_get_alt_index(sc, id->uid_interface_index); - else - alt = id->uid_alt_index; - idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt); - if (idesc == NULL) { - free(cdesc, M_TEMP); - return (EINVAL); - } - id->uid_desc = *idesc; - free(cdesc, M_TEMP); - break; - case USB_GET_ENDPOINT_DESC: - ed = (struct usb_endpoint_desc *)addr; - cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0); - if (cdesc == NULL) - return (EINVAL); - if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX && - ed->ued_alt_index == USB_CURRENT_ALT_INDEX) - 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, - alt, ed->ued_endpoint_index); - if (edesc == NULL) { - free(cdesc, M_TEMP); - return (EINVAL); - } - ed->ued_desc = *edesc; - free(cdesc, M_TEMP); - break; - case USB_GET_FULL_DESC: - { - int len; - struct iovec iov; - struct uio uio; - struct usb_full_desc *fd = (struct usb_full_desc *)addr; - int error; - - cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len); - if (len > fd->ufd_size) - len = fd->ufd_size; - iov.iov_base = (caddr_t)fd->ufd_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = UIO_READ; - uio.uio_td = p; - error = uiomove((void *)cdesc, len, &uio); - free(cdesc, M_TEMP); - return (error); - } - case USB_GET_STRING_DESC: { - int len; - si = (struct usb_string_desc *)addr; - err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index, - si->usd_language_id, &si->usd_desc, &len); - if (err) - return (EINVAL); - break; - } - case USB_DO_REQUEST: - { - struct usb_ctl_request *ur = (void *)addr; - int len = UGETW(ur->ucr_request.wLength); - struct iovec iov; - struct uio uio; - void *ptr = 0; - int error = 0; - - if (!(flag & FWRITE)) - return (EPERM); - /* Avoid requests that would damage the bus integrity. */ - if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && - ur->ucr_request.bRequest == UR_SET_ADDRESS) || - (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && - ur->ucr_request.bRequest == UR_SET_CONFIG) || - (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE && - ur->ucr_request.bRequest == UR_SET_INTERFACE)) - return (EINVAL); - - if (len < 0 || len > 32767) - return (EINVAL); - if (len != 0) { - iov.iov_base = (caddr_t)ur->ucr_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = p; - ptr = malloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - 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); - if (err) { - error = EIO; - goto ret; - } - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - ret: - if (ptr) - free(ptr, M_TEMP); - return (error); - } - case USB_GET_DEVICEINFO: - usbd_fill_deviceinfo(sc->sc_udev, - (struct usb_device_info *)addr, 1); - break; - case USB_RESET_DEVICE: - err = usbd_reset_device(sc->sc_udev); - if (err) - return EIO; - break; - default: - return (EINVAL); - } - return (0); -} - -int -ugenioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, - struct thread *p) -{ - int endpt = UGENENDPOINT(dev); - struct ugen_softc *sc; - int error; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - UGEN_DEV_REF(dev, sc); - error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); - UGEN_DEV_RELE(dev, sc); - return (error); -} - -int -ugenpoll(struct cdev *dev, int events, struct thread *p) -{ - struct ugen_softc *sc; - struct ugen_endpoint *sce_in, *sce_out; - usb_endpoint_descriptor_t *edesc; - int revents = 0; - int s; - - sc = devclass_get_softc(ugen_devclass, UGENUNIT(dev)); - - if (sc->sc_dying) - return ((events & (POLLIN | POLLOUT | POLLRDNORM | - POLLWRNORM)) | POLLHUP); - /* Do not allow to poll a control endpoint */ - if (UGENENDPOINT(dev) == USB_CONTROL_ENDPOINT) - return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); - - sce_in = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; - sce_out = &sc->sc_endpoints[UGENENDPOINT(dev)][OUT]; - edesc = (sce_in->edesc != NULL) ? sce_in->edesc : sce_out->edesc; - KASSERT(edesc != NULL, ("ugenpoll: NULL edesc")); - if (sce_in->edesc == NULL || sce_in->pipeh == NULL) - sce_in = NULL; - if (sce_out->edesc == NULL || sce_out->pipeh == NULL) - sce_out = NULL; - - s = splusb(); - switch (edesc->bmAttributes & UE_XFERTYPE) { - case UE_INTERRUPT: - if (sce_in != NULL && (events & (POLLIN | POLLRDNORM))) { - if (sce_in->q.c_cc > 0) - revents |= events & (POLLIN | POLLRDNORM); - else - selrecord(p, &sce_in->rsel); - } - if (sce_out != NULL && (events & (POLLOUT | POLLWRNORM))) { - if (sce_out->q.c_cc > 0) - revents |= events & (POLLOUT | POLLWRNORM); - else - selrecord(p, &sce_out->rsel); - } - break; - case UE_ISOCHRONOUS: - if (sce_in != NULL && (events & (POLLIN | POLLRDNORM))) { - if (sce_in->cur != sce_in->fill) - revents |= events & (POLLIN | POLLRDNORM); - else - selrecord(p, &sce_in->rsel); - } - if (sce_out != NULL && (events & (POLLOUT | POLLWRNORM))) { - if (sce_out->cur != sce_out->fill) - revents |= events & (POLLOUT | POLLWRNORM); - else - selrecord(p, &sce_out->rsel); - } - 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 & - (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM); - break; - default: - break; - } - splx(s); - return (revents); -} - -DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/ugraphire_rdesc.h b/sys/dev/usb/ugraphire_rdesc.h deleted file mode 100644 index 9c5a0c1..0000000 --- a/sys/dev/usb/ugraphire_rdesc.h +++ /dev/null @@ -1,176 +0,0 @@ -/* $NetBSD: usb/ugraphire_rdesc.h,v 1.1 2000/12/29 01:47:49 augustss Exp $ */ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2000 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. - */ - -static const uByte uhid_graphire_report_descr[] = { - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Digitizer) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Digitizer) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x09, 0x33, /* USAGE (Touch) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x44, /* USAGE (Barrel Switch) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ - 0x09, 0x3c, /* USAGE (Invert) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x38, /* USAGE (Transducer Index) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x32, /* USAGE (In Range) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x30, /* USAGE (Tip Pressure) */ - 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x03, /* REPORT_ID (3) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ -}; - -static const uByte uhid_graphire3_4x5_report_descr[] = { - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x02, /* USAGE (Mouse) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x85, 0x01, /* REPORT_ID (1) */ - 0x09, 0x01, /* USAGE (Pointer) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x05, 0x09, /* USAGE_PAGE (Button) */ - 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ - 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x05, /* REPORT_SIZE (5) */ - 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x38, /* USAGE (Wheel) */ - 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ - 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - 0xc0, /* END_COLLECTION */ - 0xc0, /* END_COLLECTION */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Pointer) */ - 0xa1, 0x01, /* COLLECTION (Applicaption) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x01, /* USAGE (Digitizer) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x09, 0x33, /* USAGE (Touch) */ - 0x09, 0x44, /* USAGE (Barrel Switch) */ - 0x09, 0x44, /* USAGE (Barrel Switch) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x01, /* INPUT (Cnst,Ary,Abs) */ - 0x09, 0x3c, /* USAGE (Invert) */ - 0x09, 0x38, /* USAGE (Transducer Index) */ - 0x09, 0x32, /* USAGE (In Range) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x26, 0xde, 0x27, /* LOGICAL_MAXIMUM (10206) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x26, 0xfe, 0x1c, /* LOGICAL_MAXIMUM (7422) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x30, /* USAGE (Tip Pressure) */ - 0x26, 0xff, 0x01, /* LOGICAL_MAXIMUM (511) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0x09, 0x00, /* USAGE (Undefined) */ - 0x85, 0x03, /* REPORT_ID (3) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ - 0xc0 /* END_COLLECTION */ -}; diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c deleted file mode 100644 index 4d4c61b..0000000 --- a/sys/dev/usb/uhci.c +++ /dev/null @@ -1,3704 +0,0 @@ -/* $NetBSD: uhci.c,v 1.170 2003/02/19 01:35:04 augustss Exp $ */ - -/* Also already incorporated from NetBSD: - * $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ - * $NetBSD: uhci.c,v 1.173 2003/05/13 04:41:59 gson Exp $ - * $NetBSD: uhci.c,v 1.175 2003/09/12 16:18:08 mycroft Exp $ - * $NetBSD: uhci.c,v 1.176 2003/11/04 19:11:21 mycroft Exp $ - * $NetBSD: uhci.c,v 1.177 2003/12/29 08:17:10 toshii Exp $ - * $NetBSD: uhci.c,v 1.178 2004/03/02 16:32:05 martin Exp $ - * $NetBSD: uhci.c,v 1.180 2004/07/17 20:12:03 mycroft Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - - -/*- - * Copyright (c) 1998 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. - */ - -/* - * USB Universal Host Controller driver. - * Handles e.g. PIIX3 and PIIX4. - * - * UHCI spec: http://developer.intel.com/design/USB/UHCI11D.htm - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf - * ftp://download.intel.com/design/intarch/datashts/29056201.pdf - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/endian.h> -#include <sys/module.h> -#include <sys/bus.h> -#if defined(DIAGNOSTIC) && defined(__i386__) -#include <machine/cpu.h> -#endif -#include <sys/proc.h> -#include <sys/queue.h> -#include <sys/sysctl.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/uhcireg.h> -#include <dev/usb/uhcivar.h> - -/* Use bandwidth reclamation for control transfers. Some devices choke on it. */ -/*#define UHCI_CTL_LOOP */ - -#define delay(d) DELAY(d) - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#ifdef USB_DEBUG -uhci_softc_t *thesc; -#define DPRINTF(x) if (uhcidebug) printf x -#define DPRINTFN(n,x) if (uhcidebug>(n)) printf x -int uhcidebug = 0; -int uhcinoloop = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhci, CTLFLAG_RW, 0, "USB uhci"); -SYSCTL_INT(_hw_usb_uhci, OID_AUTO, debug, CTLFLAG_RW, - &uhcidebug, 0, "uhci debug level"); -SYSCTL_INT(_hw_usb_uhci, OID_AUTO, loop, CTLFLAG_RW, - &uhcinoloop, 0, "uhci noloop"); -#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f)) -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uhci_pipe { - struct usbd_pipe pipe; - int nexttoggle; - - u_char aborting; - usbd_xfer_handle abortstart, abortend; - - /* Info needed for different pipe kinds. */ - union { - /* Control pipe */ - struct { - uhci_soft_qh_t *sqh; - usb_dma_t reqdma; - uhci_soft_td_t *setup, *stat; - u_int length; - } ctl; - /* Interrupt pipe */ - struct { - int npoll; - int isread; - uhci_soft_qh_t **qhs; - } intr; - /* Bulk pipe */ - struct { - uhci_soft_qh_t *sqh; - u_int length; - int isread; - } bulk; - /* Iso pipe */ - struct iso { - uhci_soft_td_t **stds; - int next, inuse; - } iso; - } u; -}; - -static void uhci_globalreset(uhci_softc_t *); -static usbd_status uhci_portreset(uhci_softc_t*, int); -static void uhci_reset(uhci_softc_t *); -#if defined(__NetBSD__) || defined(__OpenBSD__) -static void uhci_shutdown(void *v); -static void uhci_power(int, void *); -#endif -static usbd_status uhci_run(uhci_softc_t *, int run); -static uhci_soft_td_t *uhci_alloc_std(uhci_softc_t *); -static void uhci_free_std(uhci_softc_t *, uhci_soft_td_t *); -static uhci_soft_qh_t *uhci_alloc_sqh(uhci_softc_t *); -static void uhci_free_sqh(uhci_softc_t *, uhci_soft_qh_t *); -static usbd_status uhci_aux_dma_alloc(uhci_softc_t *, uhci_soft_td_t *, - void *data, int len); -static uhci_physaddr_t uhci_aux_dma_prepare(uhci_soft_td_t *, int); -static void uhci_aux_dma_complete(uhci_soft_td_t *, int); -#if 0 -static void uhci_enter_ctl_q(uhci_softc_t *, uhci_soft_qh_t *, - uhci_intr_info_t *); -static void uhci_exit_ctl_q(uhci_softc_t *, uhci_soft_qh_t *); -#endif - -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, - usbd_xfer_handle xfer, - uhci_soft_td_t **, uhci_soft_td_t **); -static void uhci_poll_hub(void *); -static void uhci_waitintr(uhci_softc_t *, usbd_xfer_handle); -static void uhci_check_intr(uhci_softc_t *, uhci_intr_info_t *); -static void uhci_idone(uhci_intr_info_t *); - -static void uhci_abort_xfer(usbd_xfer_handle, usbd_status status); -static void uhci_transfer_complete(usbd_xfer_handle xfer); - -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 *); -static void uhci_remove_ls_ctrl(uhci_softc_t *,uhci_soft_qh_t *); -static void uhci_remove_hs_ctrl(uhci_softc_t *,uhci_soft_qh_t *); -static void uhci_remove_bulk(uhci_softc_t *,uhci_soft_qh_t *); -static int uhci_str(usb_string_descriptor_t *, int, char *); -static void uhci_add_loop(uhci_softc_t *sc); -static void uhci_rem_loop(uhci_softc_t *sc); - -static usbd_status uhci_setup_isoc(usbd_pipe_handle pipe); -static void uhci_device_isoc_enter(usbd_xfer_handle); - -static usbd_status uhci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); -static void uhci_freem(struct usbd_bus *, usb_dma_t *); - -static usbd_xfer_handle uhci_allocx(struct usbd_bus *); -static void uhci_freex(struct usbd_bus *, usbd_xfer_handle); - -static usbd_status uhci_device_ctrl_transfer(usbd_xfer_handle); -static usbd_status uhci_device_ctrl_start(usbd_xfer_handle); -static void uhci_device_ctrl_abort(usbd_xfer_handle); -static void uhci_device_ctrl_close(usbd_pipe_handle); -static void uhci_device_ctrl_done(usbd_xfer_handle); - -static usbd_status uhci_device_intr_transfer(usbd_xfer_handle); -static usbd_status uhci_device_intr_start(usbd_xfer_handle); -static void uhci_device_intr_abort(usbd_xfer_handle); -static void uhci_device_intr_close(usbd_pipe_handle); -static void uhci_device_intr_done(usbd_xfer_handle); - -static usbd_status uhci_device_bulk_transfer(usbd_xfer_handle); -static usbd_status uhci_device_bulk_start(usbd_xfer_handle); -static void uhci_device_bulk_abort(usbd_xfer_handle); -static void uhci_device_bulk_close(usbd_pipe_handle); -static void uhci_device_bulk_done(usbd_xfer_handle); - -static usbd_status uhci_device_isoc_transfer(usbd_xfer_handle); -static usbd_status uhci_device_isoc_start(usbd_xfer_handle); -static void uhci_device_isoc_abort(usbd_xfer_handle); -static void uhci_device_isoc_close(usbd_pipe_handle); -static void uhci_device_isoc_done(usbd_xfer_handle); - -static usbd_status uhci_root_ctrl_transfer(usbd_xfer_handle); -static usbd_status uhci_root_ctrl_start(usbd_xfer_handle); -static void uhci_root_ctrl_abort(usbd_xfer_handle); -static void uhci_root_ctrl_close(usbd_pipe_handle); -static void uhci_root_ctrl_done(usbd_xfer_handle); - -static usbd_status uhci_root_intr_transfer(usbd_xfer_handle); -static usbd_status uhci_root_intr_start(usbd_xfer_handle); -static void uhci_root_intr_abort(usbd_xfer_handle); -static void uhci_root_intr_close(usbd_pipe_handle); -static void uhci_root_intr_done(usbd_xfer_handle); - -static usbd_status uhci_open(usbd_pipe_handle); -static void uhci_poll(struct usbd_bus *); -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, - struct uhci_pipe *pipe, int ival); - -static void uhci_device_clear_toggle(usbd_pipe_handle pipe); -static void uhci_noop(usbd_pipe_handle pipe); - -static __inline uhci_soft_qh_t *uhci_find_prev_qh(uhci_soft_qh_t *, - uhci_soft_qh_t *); - -#ifdef USB_DEBUG -static void uhci_dump_all(uhci_softc_t *); -static void uhci_dumpregs(uhci_softc_t *); -static void uhci_dump_qhs(uhci_soft_qh_t *); -static void uhci_dump_qh(uhci_soft_qh_t *); -static void uhci_dump_tds(uhci_soft_td_t *); -static void uhci_dump_td(uhci_soft_td_t *); -static void uhci_dump_ii(uhci_intr_info_t *ii); -void uhci_dump(void); -#endif - -#define UBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \ - BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) -#define UWRITE1(sc, r, x) \ - do { UBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UWRITE2(sc, r, x) \ - do { UBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UWRITE4(sc, r, x) \ - do { UBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); \ - } while (/*CONSTCOND*/0) -#define UREAD1(sc, r) (UBARR(sc), bus_space_read_1((sc)->iot, (sc)->ioh, (r))) -#define UREAD2(sc, r) (UBARR(sc), bus_space_read_2((sc)->iot, (sc)->ioh, (r))) -#define UREAD4(sc, r) (UBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r))) - -#define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) -#define UHCISTS(sc) UREAD2(sc, UHCI_STS) - -#define UHCI_RESET_TIMEOUT 100 /* ms, reset timeout */ - -#define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK) - -#define UHCI_INTR_ENDPT 1 - -struct usbd_bus_methods uhci_bus_methods = { - uhci_open, - uhci_softintr, - uhci_poll, - uhci_allocm, - uhci_freem, - uhci_allocx, - uhci_freex, -}; - -struct usbd_pipe_methods uhci_root_ctrl_methods = { - uhci_root_ctrl_transfer, - uhci_root_ctrl_start, - uhci_root_ctrl_abort, - uhci_root_ctrl_close, - uhci_noop, - uhci_root_ctrl_done, -}; - -struct usbd_pipe_methods uhci_root_intr_methods = { - uhci_root_intr_transfer, - uhci_root_intr_start, - uhci_root_intr_abort, - uhci_root_intr_close, - uhci_noop, - uhci_root_intr_done, -}; - -struct usbd_pipe_methods uhci_device_ctrl_methods = { - uhci_device_ctrl_transfer, - uhci_device_ctrl_start, - uhci_device_ctrl_abort, - uhci_device_ctrl_close, - uhci_noop, - uhci_device_ctrl_done, -}; - -struct usbd_pipe_methods uhci_device_intr_methods = { - uhci_device_intr_transfer, - uhci_device_intr_start, - uhci_device_intr_abort, - uhci_device_intr_close, - uhci_device_clear_toggle, - uhci_device_intr_done, -}; - -struct usbd_pipe_methods uhci_device_bulk_methods = { - uhci_device_bulk_transfer, - uhci_device_bulk_start, - uhci_device_bulk_abort, - uhci_device_bulk_close, - uhci_device_clear_toggle, - uhci_device_bulk_done, -}; - -struct usbd_pipe_methods uhci_device_isoc_methods = { - uhci_device_isoc_transfer, - uhci_device_isoc_start, - uhci_device_isoc_abort, - uhci_device_isoc_close, - uhci_noop, - uhci_device_isoc_done, -}; - -#define uhci_add_intr_info(sc, ii) \ - LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ii), list) -#define uhci_del_intr_info(ii) \ - do { \ - LIST_REMOVE((ii), list); \ - (ii)->list.le_prev = NULL; \ - } while (0) -#define uhci_active_intr_info(ii) ((ii)->list.le_prev != NULL) - -static __inline uhci_soft_qh_t * -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(USB_DEBUG) - if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) { - printf("uhci_find_prev_qh: QH not found\n"); - return (NULL); - } -#endif - } - return (pqh); -} - -void -uhci_globalreset(uhci_softc_t *sc) -{ - UHCICMD(sc, UHCI_CMD_GRESET); /* global reset */ - usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* wait a little */ - UHCICMD(sc, 0); /* do nothing */ -} - -usbd_status -uhci_init(uhci_softc_t *sc) -{ - usbd_status err; - int i, j; - uhci_soft_qh_t *clsqh, *chsqh, *bsqh, *sqh, *lsqh; - uhci_soft_td_t *std; - - DPRINTFN(1,("uhci_init: start\n")); - -#ifdef USB_DEBUG - thesc = sc; - - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - - 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, - UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t), - UHCI_FRAMELIST_ALIGN, &sc->sc_dma); - if (err) - return (err); - sc->sc_pframes = KERNADDR(&sc->sc_dma, 0); - UWRITE2(sc, UHCI_FRNUM, 0); /* set frame number to 0 */ - UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); /* 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. - */ - std = uhci_alloc_std(sc); - if (std == NULL) - return (USBD_NOMEM); - std->link.std = NULL; - std->td.td_link = htole32(UHCI_PTR_T); - std->td.td_status = htole32(0); /* inactive */ - std->td.td_token = htole32(0); - std->td.td_buffer = htole32(0); - - /* Allocate the dummy QH marking the end and used for looping the QHs.*/ - lsqh = uhci_alloc_sqh(sc); - if (lsqh == NULL) - return (USBD_NOMEM); - lsqh->hlink = NULL; - lsqh->qh.qh_hlink = htole32(UHCI_PTR_T); /* end of QH chain */ - lsqh->elink = std; - lsqh->qh.qh_elink = htole32(std->physaddr | UHCI_PTR_TD); - sc->sc_last_qh = lsqh; - - /* Allocate the dummy QH where bulk traffic will be queued. */ - bsqh = uhci_alloc_sqh(sc); - if (bsqh == NULL) - return (USBD_NOMEM); - bsqh->hlink = lsqh; - bsqh->qh.qh_hlink = htole32(lsqh->physaddr | UHCI_PTR_QH); - bsqh->elink = NULL; - bsqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_bulk_start = sc->sc_bulk_end = bsqh; - - /* Allocate dummy QH where high speed control traffic will be queued. */ - chsqh = uhci_alloc_sqh(sc); - if (chsqh == NULL) - return (USBD_NOMEM); - chsqh->hlink = bsqh; - chsqh->qh.qh_hlink = htole32(bsqh->physaddr | UHCI_PTR_QH); - chsqh->elink = NULL; - chsqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_hctl_start = sc->sc_hctl_end = chsqh; - - /* Allocate dummy QH where control traffic will be queued. */ - clsqh = uhci_alloc_sqh(sc); - if (clsqh == NULL) - return (USBD_NOMEM); - clsqh->hlink = chsqh; - clsqh->qh.qh_hlink = htole32(chsqh->physaddr | UHCI_PTR_QH); - clsqh->elink = NULL; - 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. - */ - for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = uhci_alloc_std(sc); - sqh = uhci_alloc_sqh(sc); - if (std == NULL || sqh == NULL) - return (USBD_NOMEM); - std->link.sqh = sqh; - std->td.td_link = htole32(sqh->physaddr | UHCI_PTR_QH); - std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */ - std->td.td_token = htole32(0); - std->td.td_buffer = htole32(0); - sqh->hlink = clsqh; - sqh->qh.qh_hlink = htole32(clsqh->physaddr | UHCI_PTR_QH); - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - sc->sc_vframes[i].htd = std; - 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; - j += UHCI_VFRAMELIST_COUNT) - sc->sc_pframes[j] = htole32(std->physaddr); - } - - LIST_INIT(&sc->sc_intrhead); - - STAILQ_INIT(&sc->sc_free_xfers); - - callout_init(&sc->sc_poll_handle, 0); - - /* Set up the bus struct. */ - sc->sc_bus.methods = &uhci_bus_methods; - sc->sc_bus.pipe_size = sizeof(struct uhci_pipe); - -#if defined(__NetBSD__) || defined(__OpenBSD__) - sc->sc_suspend = PWR_RESUME; - sc->sc_powerhook = powerhook_establish(uhci_power, sc); - sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc); -#endif - - DPRINTFN(1,("uhci_init: enabling\n")); - UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | - UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */ - - UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */ - - return (uhci_run(sc, 1)); /* and here we go... */ -} - -int -uhci_detach(struct uhci_softc *sc, int flags) -{ - usbd_xfer_handle xfer; - int rv = 0; - - sc->sc_dying = 1; - - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - uhci_run(sc, 0); - -#if defined(__NetBSD__) || defined(__OpenBSD__) - powerhook_disestablish(sc->sc_powerhook); - shutdownhook_disestablish(sc->sc_shutdownhook); -#endif - - /* Free all xfers associated with this HC. */ - for (;;) { - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer == NULL) - break; - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next); - free(xfer, M_USB); - } - - /* XXX free other data structures XXX */ - usb_freemem(&sc->sc_bus, &sc->sc_dma); - - return (rv); -} - -usbd_status -uhci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size) -{ - return (usb_allocmem(bus, size, 0, dma)); -} - -void -uhci_freem(struct usbd_bus *bus, usb_dma_t *dma) -{ - usb_freemem(bus, dma); -} - -usbd_xfer_handle -uhci_allocx(struct usbd_bus *bus) -{ - struct uhci_softc *sc = (struct uhci_softc *)bus; - usbd_xfer_handle xfer; - - xfer = STAILQ_FIRST(&sc->sc_free_xfers); - if (xfer != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, 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 uhci_xfer), M_USB, M_NOWAIT); - } - if (xfer != NULL) { - memset(xfer, 0, sizeof (struct uhci_xfer)); - UXFER(xfer)->iinfo.sc = sc; - usb_init_task(&UXFER(xfer)->abort_task, uhci_timeout_task, - xfer); - UXFER(xfer)->uhci_xfer_flags = 0; -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; - xfer->busy_free = XFER_BUSY; -#endif - } - return (xfer); -} - -void -uhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) -{ - struct uhci_softc *sc = (struct uhci_softc *)bus; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("uhci_freex: xfer=%p not busy, 0x%08x\n", xfer, - xfer->busy_free); - return; - } - xfer->busy_free = XFER_FREE; - if (!UXFER(xfer)->iinfo.isdone) { - printf("uhci_freex: !isdone\n"); - return; - } -#endif - STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); -} - -/* - * Shut down the controller when the system is going down. - */ -void -uhci_shutdown(void *v) -{ - uhci_softc_t *sc = v; - - DPRINTF(("uhci_shutdown: stopping the HC\n")); - uhci_run(sc, 0); /* stop the controller */ -} - -/* - * Handle suspend/resume. - * - * We need to switch to polling mode here, because this routine is - * called from an interrupt context. This is all right since we - * are almost suspended anyway. - */ -void -uhci_power(int why, void *v) -{ - uhci_softc_t *sc = v; - int cmd; - int s; - - s = splhardusb(); - cmd = UREAD2(sc, UHCI_CMD); - - DPRINTF(("uhci_power: sc=%p, why=%d (was %d), cmd=0x%x\n", - sc, why, sc->sc_suspend, cmd)); - - if (why != PWR_RESUME) { -#ifdef USB_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - if (sc->sc_intr_xfer != NULL) - callout_stop(&sc->sc_poll_handle); - sc->sc_bus.use_polling++; - uhci_run(sc, 0); /* stop the controller */ - cmd &= ~UHCI_CMD_RS; - - /* save some state if BIOS doesn't */ - sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); - sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); - - UWRITE2(sc, UHCI_INTR, 0); /* disable intrs */ - - UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); - sc->sc_suspend = why; - sc->sc_bus.use_polling--; - DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); - } else { -#ifdef DIAGNOSTIC - if (sc->sc_suspend == PWR_RESUME) - printf("uhci_power: weird, resume without suspend.\n"); -#endif - sc->sc_bus.use_polling++; - sc->sc_suspend = why; - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - uhci_globalreset(sc); /* reset the controller */ - uhci_reset(sc); - if (cmd & UHCI_CMD_RS) - uhci_run(sc, 0); /* in case BIOS has started it */ - - uhci_globalreset(sc); - uhci_reset(sc); - - /* restore saved state */ - UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); - UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); - UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); - - UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); - UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ - UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | - UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* re-enable intrs */ - UHCICMD(sc, UHCI_CMD_MAXP); - uhci_run(sc, 1); /* and start traffic again */ - usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); - sc->sc_bus.use_polling--; - if (sc->sc_intr_xfer != NULL) - callout_reset(&sc->sc_poll_handle, sc->sc_ival, - uhci_poll_hub, sc->sc_intr_xfer); -#ifdef USB_DEBUG - if (uhcidebug > 2) - uhci_dumpregs(sc); -#endif - } - splx(s); -} - -#ifdef USB_DEBUG -static void -uhci_dumpregs(uhci_softc_t *sc) -{ - DPRINTFN(-1,("%s regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, " - "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n", - device_get_nameunit(sc->sc_bus.bdev), - UREAD2(sc, UHCI_CMD), - UREAD2(sc, UHCI_STS), - UREAD2(sc, UHCI_INTR), - UREAD2(sc, UHCI_FRNUM), - UREAD4(sc, UHCI_FLBASEADDR), - UREAD1(sc, UHCI_SOF), - UREAD2(sc, UHCI_PORTSC1), - UREAD2(sc, UHCI_PORTSC2))); -} - -void -uhci_dump_td(uhci_soft_td_t *p) -{ - char sbuf[128], sbuf2[128]; - - DPRINTFN(-1,("TD(%p) at %08lx = link=0x%08lx status=0x%08lx " - "token=0x%08lx buffer=0x%08lx\n", - p, (long)p->physaddr, - (long)le32toh(p->td.td_link), - (long)le32toh(p->td.td_status), - (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", - sbuf, sizeof(sbuf)); - bitmask_snprintf((u_int32_t)le32toh(p->td.td_status), - "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" - "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD", - sbuf2, sizeof(sbuf2)); - - DPRINTFN(-1,(" %s %s,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d," - "D=%d,maxlen=%d\n", sbuf, sbuf2, - UHCI_TD_GET_ERRCNT(le32toh(p->td.td_status)), - UHCI_TD_GET_ACTLEN(le32toh(p->td.td_status)), - UHCI_TD_GET_PID(le32toh(p->td.td_token)), - UHCI_TD_GET_DEVADDR(le32toh(p->td.td_token)), - UHCI_TD_GET_ENDPT(le32toh(p->td.td_token)), - UHCI_TD_GET_DT(le32toh(p->td.td_token)), - UHCI_TD_GET_MAXLEN(le32toh(p->td.td_token)))); -} - -void -uhci_dump_qh(uhci_soft_qh_t *sqh) -{ - DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh, - (int)sqh->physaddr, le32toh(sqh->qh.qh_hlink), - le32toh(sqh->qh.qh_elink))); -} - - -#if 1 -void -uhci_dump(void) -{ - uhci_dump_all(thesc); -} -#endif - -void -uhci_dump_all(uhci_softc_t *sc) -{ - uhci_dumpregs(sc); - printf("intrs=%d\n", sc->sc_bus.no_intrs); - /*printf("framelist[i].link = %08x\n", sc->sc_framelist[0].link);*/ - uhci_dump_qh(sc->sc_lctl_start); -} - - -void -uhci_dump_qhs(uhci_soft_qh_t *sqh) -{ - uhci_dump_qh(sqh); - - /* uhci_dump_qhs displays all the QHs and TDs from the given QH onwards - * Traverses sideways first, then down. - * - * QH1 - * QH2 - * No QH - * TD2.1 - * TD2.2 - * TD1.1 - * etc. - * - * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1. - */ - - - if (sqh->hlink != NULL && !(le32toh(sqh->qh.qh_hlink) & UHCI_PTR_T)) - uhci_dump_qhs(sqh->hlink); - else - DPRINTF(("No QH\n")); - - if (sqh->elink != NULL && !(le32toh(sqh->qh.qh_elink) & UHCI_PTR_T)) - uhci_dump_tds(sqh->elink); - else - DPRINTF(("No TD\n")); -} - -void -uhci_dump_tds(uhci_soft_td_t *std) -{ - uhci_soft_td_t *td; - - for(td = std; td != NULL; td = td->link.std) { - uhci_dump_td(td); - - /* Check whether the link pointer in this TD marks - * the link pointer as end of queue. This avoids - * printing the free list in case the queue/TD has - * already been moved there (seatbelt). - */ - if (le32toh(td->td.td_link) & UHCI_PTR_T || - le32toh(td->td.td_link) == 0) - break; - } -} - -static void -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 -#define DONE 0 -#endif - if (ii == NULL) { - printf("ii NULL\n"); - return; - } - if (ii->xfer == NULL) { - printf("ii %p: done=%d xfer=NULL\n", - ii, DONE); - return; - } - pipe = ii->xfer->pipe; - if (pipe == NULL) { - printf("ii %p: done=%d xfer=%p pipe=NULL\n", - ii, DONE, ii->xfer); - return; - } - if (pipe->endpoint == NULL) { - printf("ii %p: done=%d xfer=%p pipe=%p pipe->endpoint=NULL\n", - ii, DONE, ii->xfer, pipe); - return; - } - if (pipe->device == NULL) { - printf("ii %p: done=%d xfer=%p pipe=%p pipe->device=NULL\n", - ii, DONE, ii->xfer, pipe); - return; - } - 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, - UGETW(dev->ddesc.idVendor), - UGETW(dev->ddesc.idProduct), - dev->address, pipe, - ed->bEndpointAddress, ed->bmAttributes); -#undef DONE -} - -void uhci_dump_iis(struct uhci_softc *sc); -void -uhci_dump_iis(struct uhci_softc *sc) -{ - uhci_intr_info_t *ii; - - printf("intr_info list:\n"); - for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) - uhci_dump_ii(ii); -} - -void iidump(void); -void iidump(void) { uhci_dump_iis(thesc); } - -#endif - -/* - * This routine is executed periodically and simulates interrupts - * from the root controller interrupt pipe for port status change. - */ -void -uhci_poll_hub(void *addr) -{ - usbd_xfer_handle xfer = addr; - usbd_pipe_handle pipe = xfer->pipe; - usbd_device_handle dev = pipe->device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - int s; - u_char *p; - - DPRINTFN(20, ("uhci_poll_hub\n")); - - callout_reset(&sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, xfer); - - p = xfer->buffer; - p[0] = 0; - if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) - p[0] |= 1<<1; - if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC)) - p[0] |= 1<<2; - if (p[0] == 0) - /* No change, try again in a while */ - return; - - xfer->actlen = 1; - xfer->status = USBD_NORMAL_COMPLETION; - s = splusb(); - dev->bus->intr_context++; - uhci_transfer_complete(xfer); - dev->bus->intr_context--; - splx(s); -} - -void -uhci_root_intr_done(usbd_xfer_handle xfer) -{ -} - -void -uhci_root_ctrl_done(usbd_xfer_handle xfer) -{ -} - -/* - * Let the last QH loop back to the high speed control transfer QH. - * This is what intel calls "bandwidth reclamation" and improves - * USB performance a lot for some devices. - * If we are already looping, just count it. - */ -void -uhci_add_loop(uhci_softc_t *sc) { -#ifdef USB_DEBUG - if (uhcinoloop) - return; -#endif - 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 = - htole32(sc->sc_hctl_start->physaddr | UHCI_PTR_QH); - } -} - -void -uhci_rem_loop(uhci_softc_t *sc) { -#ifdef USB_DEBUG - if (uhcinoloop) - return; -#endif - if (--sc->sc_loops == 0) { - DPRINTFN(5,("uhci_end_loop: remove\n")); - sc->sc_last_qh->qh.qh_hlink = htole32(UHCI_PTR_T); - } -} - -/* Add high speed control QH, called at splusb(). */ -void -uhci_add_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_add_ctrl: sqh=%p\n", sqh)); - eqh = sc->sc_hctl_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_hctl_end = sqh; -#ifdef UHCI_CTL_LOOP - uhci_add_loop(sc); -#endif -} - -/* Remove high speed control QH, called at splusb(). */ -void -uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh)); -#ifdef UHCI_CTL_LOOP - uhci_rem_loop(sc); -#endif - /* - * The T bit should be set in the elink of the QH so that the HC - * doesn't follow the pointer. This condition may fail if the - * the transferred packet was short so that the QH still points - * at the last used TD. - * In this case we set the T bit and wait a little for the HC - * to stop looking at the TD. - */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - - pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_hctl_end == sqh) - sc->sc_hctl_end = pqh; -} - -/* Add low speed control QH, called at splusb(). */ -void -uhci_add_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_add_ls_ctrl: sqh=%p\n", sqh)); - eqh = sc->sc_lctl_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_lctl_end = sqh; -} - -/* Remove low speed control QH, called at splusb(). */ -void -uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh)); - /* See comment in uhci_remove_hs_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_lctl_end == sqh) - sc->sc_lctl_end = pqh; -} - -/* Add bulk QH, called at splusb(). */ -void -uhci_add_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *eqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_add_bulk: sqh=%p\n", sqh)); - eqh = sc->sc_bulk_end; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - sc->sc_bulk_end = sqh; - uhci_add_loop(sc); -} - -/* Remove bulk QH, called at splusb(). */ -void -uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - uhci_soft_qh_t *pqh; - - SPLUSBCHECK; - - DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh)); - uhci_rem_loop(sc); - /* See comment in uhci_remove_hs_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - pqh = uhci_find_prev_qh(sc->sc_bulk_start, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (sc->sc_bulk_end == sqh) - sc->sc_bulk_end = pqh; -} - -static int uhci_intr1(uhci_softc_t *); - -int -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 - printf("uhci_intr: ignored interrupt while polling\n"); -#endif - return (0); - } - return (uhci_intr1(sc)); -} - -int -uhci_intr1(uhci_softc_t *sc) -{ - - int status; - int ack; - - /* - * It can happen that an interrupt will be delivered to - * us before the device has been fully attached and the - * softc struct has been configured. Usually this happens - * when kldloading the USB support as a module after the - * system has been booted. If we detect this condition, - * we need to squelch the unwanted interrupts until we're - * ready for them. - */ - if (sc->sc_bus.bdev == NULL) { - UWRITE2(sc, UHCI_STS, 0xFFFF); /* ack pending interrupts */ - uhci_run(sc, 0); /* stop the controller */ - UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */ - return(0); - } - -#ifdef USB_DEBUG - if (uhcidebug > 15) { - DPRINTF(("%s: uhci_intr1\n", device_get_nameunit(sc->sc_bus.bdev))); - uhci_dumpregs(sc); - } -#endif - status = UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS; - 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", - device_get_nameunit(sc->sc_bus.bdev)); - UWRITE2(sc, UHCI_STS, status); /* acknowledge the ints */ - return (0); - } - - ack = 0; - if (status & UHCI_STS_USBINT) - ack |= UHCI_STS_USBINT; - if (status & UHCI_STS_USBEI) - ack |= UHCI_STS_USBEI; - if (status & UHCI_STS_RD) { - ack |= UHCI_STS_RD; -#ifdef USB_DEBUG - printf("%s: resume detect\n", device_get_nameunit(sc->sc_bus.bdev)); -#endif - } - if (status & UHCI_STS_HSE) { - ack |= UHCI_STS_HSE; - printf("%s: host system error\n", device_get_nameunit(sc->sc_bus.bdev)); - } - if (status & UHCI_STS_HCPE) { - ack |= UHCI_STS_HCPE; - printf("%s: host controller process error\n", - device_get_nameunit(sc->sc_bus.bdev)); - } - if (status & UHCI_STS_HCH) { - /* no acknowledge needed */ - if (!sc->sc_dying) { - printf("%s: host controller halted\n", - device_get_nameunit(sc->sc_bus.bdev)); -#ifdef USB_DEBUG - uhci_dump_all(sc); -#endif - } - sc->sc_dying = 1; - } - - if (!ack) - return (0); /* nothing to acknowledge */ - UWRITE2(sc, UHCI_STS, ack); /* acknowledge the ints */ - - sc->sc_bus.no_intrs++; - usb_schedsoftintr(&sc->sc_bus); - - DPRINTFN(15, ("%s: uhci_intr: exit\n", device_get_nameunit(sc->sc_bus.bdev))); - - return (1); -} - -void -uhci_softintr(void *v) -{ - uhci_softc_t *sc = v; - uhci_intr_info_t *ii, *nextii; - - DPRINTFN(10,("%s: uhci_softintr (%d)\n", device_get_nameunit(sc->sc_bus.bdev), - sc->sc_bus.intr_context)); - - sc->sc_bus.intr_context++; - - /* - * Interrupts on UHCI really suck. When the host controller - * interrupts because a transfer is completed there is no - * way of knowing which transfer it was. You can scan down - * the TDs and QHs of the previous frame to limit the search, - * but that assumes that the interrupt was not delayed by more - * than 1 ms, which may not always be true (e.g. after debug - * output on a slow console). - * We scan all interrupt descriptors to see if any have - * completed. - */ - LIST_FOREACH_SAFE(ii, &sc->sc_intrhead, list, nextii) - uhci_check_intr(sc, ii); - -#ifdef USB_USE_SOFTINTR - if (sc->sc_softwake) { - sc->sc_softwake = 0; - wakeup(&sc->sc_softwake); - } -#endif /* USB_USE_SOFTINTR */ - - sc->sc_bus.intr_context--; -} - -/* Check for an interrupt. */ -void -uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) -{ - uhci_soft_td_t *std, *lstd; - u_int32_t status; - - DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii)); -#ifdef DIAGNOSTIC - if (ii == NULL) { - printf("uhci_check_intr: no ii? %p\n", 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; -#ifdef DIAGNOSTIC - if (lstd == NULL) { - printf("uhci_check_intr: std==0\n"); - return; - } -#endif - /* - * If the last TD is still active we need to check whether there - * is an error somewhere in the middle, or whether there was a - * short packet (SPD and not ACTIVE). - */ - if (le32toh(lstd->td.td_status) & UHCI_TD_ACTIVE) { - DPRINTFN(12, ("uhci_check_intr: active ii=%p\n", ii)); - for (std = ii->stdstart; std != lstd; std = std->link.std) { - status = le32toh(std->td.td_status); - /* If there's an active TD the xfer isn't done. */ - if (status & UHCI_TD_ACTIVE) - break; - /* Any kind of error makes the xfer done. */ - if (status & UHCI_TD_STALLED) - goto done; - /* We want short packets, and it is short: it's done */ - if ((status & UHCI_TD_SPD) && - UHCI_TD_GET_ACTLEN(status) < - UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) - goto done; - } - DPRINTFN(12, ("uhci_check_intr: ii=%p std=%p still active\n", - ii, ii->stdstart)); - return; - } - done: - DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii)); - callout_stop(&ii->xfer->timeout_handle); - usb_rem_task(ii->xfer->pipe->device, &UXFER(ii->xfer)->abort_task); - uhci_idone(ii); -} - -/* Called at splusb() */ -void -uhci_idone(uhci_intr_info_t *ii) -{ - usbd_xfer_handle xfer = ii->xfer; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_td_t *std; - u_int32_t status = 0, nstatus; - int actlen; - - DPRINTFN(12, ("uhci_idone: ii=%p\n", ii)); -#ifdef DIAGNOSTIC - { - int s = splhigh(); - if (ii->isdone) { - splx(s); -#ifdef USB_DEBUG - printf("uhci_idone: ii is done!\n "); - uhci_dump_ii(ii); -#else - printf("uhci_idone: ii=%p is done!\n", ii); -#endif - return; - } - ii->isdone = 1; - splx(s); - } -#endif - - if (xfer->nframes != 0) { - /* Isoc transfer, do things differently. */ - uhci_soft_td_t **stds = upipe->u.iso.stds; - int i, n, nframes, len; - - DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii)); - - nframes = xfer->nframes; - actlen = 0; - n = UXFER(xfer)->curframe; - for (i = 0; i < nframes; i++) { - std = stds[n]; -#ifdef USB_DEBUG - if (uhcidebug > 5) { - DPRINTFN(-1,("uhci_idone: isoc TD %d\n", i)); - uhci_dump_td(std); - } -#endif - if (++n >= UHCI_VFRAMELIST_COUNT) - n = 0; - status = le32toh(std->td.td_status); - len = UHCI_TD_GET_ACTLEN(status); - xfer->frlengths[i] = len; - actlen += len; - } - upipe->u.iso.inuse -= nframes; - xfer->actlen = actlen; - xfer->status = USBD_NORMAL_COMPLETION; - goto end; - } - -#ifdef USB_DEBUG - DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n", - ii, xfer, upipe)); - if (uhcidebug > 10) - uhci_dump_tds(ii->stdstart); -#endif - - /* The transfer is done, compute actual length and status. */ - actlen = 0; - for (std = ii->stdstart; std != NULL; std = std->link.std) { - nstatus = le32toh(std->td.td_status); - if (nstatus & UHCI_TD_ACTIVE) - break; - - status = nstatus; - if (UHCI_TD_GET_PID(le32toh(std->td.td_token)) != - UHCI_TD_PID_SETUP) - actlen += UHCI_TD_GET_ACTLEN(status); - else { - /* - * UHCI will report CRCTO in addition to a STALL or NAK - * for a SETUP transaction. See section 3.2.2, "TD - * CONTROL AND STATUS". - */ - if (status & (UHCI_TD_STALLED | UHCI_TD_NAK)) - status &= ~UHCI_TD_CRCTO; - } - } - /* If there are left over TDs we need to update the toggle. */ - if (std != NULL) - 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", - actlen, status)); - xfer->actlen = actlen; - if (status != 0) { -#ifdef USB_DEBUG - char sbuf[128]; - - bitmask_snprintf((u_int32_t)status, - "\20\22BITSTUFF\23CRCTO\24NAK\25" - "BABBLE\26DBUFFER\27STALLED\30ACTIVE", - sbuf, sizeof(sbuf)); - - DPRINTFN((status == UHCI_TD_STALLED)*10, - ("uhci_idone: error, addr=%d, endpt=0x%02x, " - "status 0x%s\n", - xfer->pipe->device->address, - xfer->pipe->endpoint->edesc->bEndpointAddress, - sbuf)); -#endif - - if (status == UHCI_TD_STALLED) - xfer->status = USBD_STALLED; - else - xfer->status = USBD_IOERROR; /* more info XXX */ - } else { - xfer->status = USBD_NORMAL_COMPLETION; - } - - end: - uhci_transfer_complete(xfer); - DPRINTFN(12, ("uhci_idone: ii=%p done\n", ii)); -} - -/* - * Called when a request does not complete. - */ -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_add_task(uxfer->xfer.pipe->device, &uxfer->abort_task, - USB_TASKQ_HC); -} - -void -uhci_timeout_task(void *addr) -{ - usbd_xfer_handle xfer = addr; - int s; - - DPRINTF(("uhci_timeout_task: xfer=%p\n", xfer)); - - s = splusb(); - uhci_abort_xfer(xfer, USBD_TIMEOUT); - splx(s); -} - -/* - * Wait here until controller claims to have an interrupt. - * Then call uhci_intr and return. Use timeout to avoid waiting - * too long. - * Only used during boot when interrupts are not enabled yet. - */ -void -uhci_waitintr(uhci_softc_t *sc, usbd_xfer_handle xfer) -{ - int timo = xfer->timeout; - uhci_intr_info_t *ii; - - DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo)); - - xfer->status = USBD_IN_PROGRESS; - for (; timo >= 0; timo--) { - usb_delay_ms(&sc->sc_bus, 1); - DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS))); - if (UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS) - uhci_intr1(sc); - if (xfer->status != USBD_IN_PROGRESS) - return; - } - - /* Timeout */ - DPRINTF(("uhci_waitintr: timeout\n")); - for (ii = LIST_FIRST(&sc->sc_intrhead); - ii != NULL && ii->xfer != xfer; - ii = LIST_NEXT(ii, list)) - ; -#ifdef DIAGNOSTIC - if (ii == NULL) - panic("uhci_waitintr: lost intr_info"); -#endif - uhci_idone(ii); -} - -void -uhci_poll(struct usbd_bus *bus) -{ - uhci_softc_t *sc = (uhci_softc_t *)bus; - - if (UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS) - uhci_intr1(sc); -} - -void -uhci_reset(uhci_softc_t *sc) -{ - int n; - - UHCICMD(sc, UHCI_CMD_HCRESET); - /* The reset bit goes low when the controller is done. */ - 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", - device_get_nameunit(sc->sc_bus.bdev)); -} - -usbd_status -uhci_run(uhci_softc_t *sc, int run) -{ - int s, n, running; - u_int16_t cmd; - - run = run != 0; - s = splhardusb(); - DPRINTF(("uhci_run: setting run=%d\n", run)); - cmd = UREAD2(sc, UHCI_CMD); - if (run) - cmd |= UHCI_CMD_RS; - else - cmd &= ~UHCI_CMD_RS; - UHCICMD(sc, cmd); - for(n = 0; n < 10; n++) { - running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH); - /* return when we've entered the state we want */ - if (run == running) { - splx(s); - DPRINTF(("uhci_run: done cmd=0x%x sts=0x%x\n", - UREAD2(sc, UHCI_CMD), UREAD2(sc, UHCI_STS))); - return (USBD_NORMAL_COMPLETION); - } - usb_delay_ms(&sc->sc_bus, 1); - } - splx(s); - printf("%s: cannot %s\n", device_get_nameunit(sc->sc_bus.bdev), - run ? "start" : "stop"); - return (USBD_IOERROR); -} - -/* - * Memory management routines. - * uhci_alloc_std allocates TDs - * uhci_alloc_sqh allocates QHs - * These two routines do their own free list management, - * partly for speed, partly because allocating DMAable memory - * has page size granularaity so much memory would be wasted if - * only one TD/QH (32 bytes) was placed in each allocated chunk. - */ - -uhci_soft_td_t * -uhci_alloc_std(uhci_softc_t *sc) -{ - uhci_soft_td_t *std; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freetds == NULL) { - DPRINTFN(2,("uhci_alloc_std: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK, - UHCI_TD_ALIGN, &dma); - if (err) - return (0); - for(i = 0; i < UHCI_STD_CHUNK; i++) { - offs = i * UHCI_STD_SIZE; - std = KERNADDR(&dma, offs); - std->physaddr = DMAADDR(&dma, offs); - std->link.std = sc->sc_freetds; - std->aux_dma.block = NULL; - std->aux_data = NULL; - std->aux_len = 0; - sc->sc_freetds = std; - } - } - std = sc->sc_freetds; - sc->sc_freetds = std->link.std; - memset(&std->td, 0, sizeof(uhci_td_t)); - return std; -} - -void -uhci_free_std(uhci_softc_t *sc, uhci_soft_td_t *std) -{ -#ifdef DIAGNOSTIC -#define TD_IS_FREE 0x12345678 - if (le32toh(std->td.td_token) == TD_IS_FREE) { - printf("uhci_free_std: freeing free TD %p\n", std); - return; - } - std->td.td_token = htole32(TD_IS_FREE); -#endif - if (std->aux_dma.block != NULL) { - usb_freemem(&sc->sc_bus, &std->aux_dma); - std->aux_dma.block = NULL; - std->aux_data = NULL; - std->aux_len = 0; - } - std->link.std = sc->sc_freetds; - sc->sc_freetds = std; -} - -uhci_soft_qh_t * -uhci_alloc_sqh(uhci_softc_t *sc) -{ - uhci_soft_qh_t *sqh; - usbd_status err; - int i, offs; - usb_dma_t dma; - - if (sc->sc_freeqhs == NULL) { - DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n")); - err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK, - UHCI_QH_ALIGN, &dma); - if (err) - return (0); - for(i = 0; i < UHCI_SQH_CHUNK; i++) { - offs = i * UHCI_SQH_SIZE; - sqh = KERNADDR(&dma, offs); - sqh->physaddr = DMAADDR(&dma, offs); - sqh->hlink = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; - } - } - sqh = sc->sc_freeqhs; - sc->sc_freeqhs = sqh->hlink; - memset(&sqh->qh, 0, sizeof(uhci_qh_t)); - return (sqh); -} - -void -uhci_free_sqh(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - sqh->hlink = sc->sc_freeqhs; - sc->sc_freeqhs = sqh; -} - -void -uhci_free_std_chain(uhci_softc_t *sc, uhci_soft_td_t *std, - uhci_soft_td_t *stdend) -{ - uhci_soft_td_t *p; - - for (; std != stdend; std = p) { - p = std->link.std; - uhci_free_std(sc, std); - } -} - -usbd_status -uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len, - int rd, u_int16_t flags, usbd_xfer_handle xfer, - uhci_soft_td_t **sp, uhci_soft_td_t **ep) -{ - struct usb_dma_mapping *dma = &xfer->dmamap; - uhci_soft_td_t *p, *prevp, *startp; - int err, i, ntd, l, tog, maxp, seg, segoff; - u_int32_t status; - 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)); - maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize); - if (maxp == 0) { - printf("uhci_alloc_std_chain: maxp=0\n"); - return (USBD_INVAL); - } - ntd = (len + maxp - 1) / maxp; - if (len == 0) - flags |= USBD_FORCE_SHORT_XFER; - if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0) - ntd++; - DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd)); - KASSERT(ntd > 0, ("uhci_alloc_std_chain: ntd=0")); - tog = upipe->nexttoggle; - prevp = NULL; - startp = NULL; - status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); - if (upipe->pipe.device->speed == USB_SPEED_LOW) - status |= UHCI_TD_LS; - if (flags & USBD_SHORT_XFER_OK) - status |= UHCI_TD_SPD; - seg = 0; - segoff = 0; - for (i = 0; i < ntd; i++) { - p = uhci_alloc_std(sc); - if (p == NULL) { - uhci_free_std_chain(sc, startp, NULL); - return (USBD_NOMEM); - } - p->link.std = NULL; - if (prevp != NULL) { - prevp->link.std = p; - prevp->td.td_link = htole32(p->physaddr | UHCI_PTR_VF | - UHCI_PTR_TD); - } else { - startp = p; - } - p->td.td_status = htole32(status); - if (i == ntd - 1) { - /* last TD */ - l = len % maxp; - if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER)) - l = maxp; - *ep = p; - } else - l = maxp; - p->td.td_token = - htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) : - UHCI_TD_OUT(l, endpt, addr, tog)); - - KASSERT(seg < dma->nsegs || l == 0, - ("uhci_alloc_std_chain: too few segments")); - if (l == 0) { - p->td.td_buffer = 0; - } else if (l > dma->segs[seg].ds_len - segoff) { - /* UHCI can't handle non-contiguous data. */ - err = uhci_aux_dma_alloc(sc, p, (char *)xfer->buffer + - i * maxp, l); - if (err) { - uhci_free_std_chain(sc, startp, NULL); - return (err); - } - p->td.td_buffer = htole32(uhci_aux_dma_prepare(p, rd)); - l -= dma->segs[seg].ds_len - segoff; - seg++; - KASSERT(seg < dma->nsegs, - ("uhci_alloc_std_chain: too few segments 2")); - segoff = 0; - } else { - p->td.td_buffer = htole32(dma->segs[seg].ds_addr + - segoff); - } - segoff += l; - if (l > 0 && segoff >= dma->segs[seg].ds_len) { - KASSERT(segoff == dma->segs[seg].ds_len, - ("uhci_alloc_std_chain: overlap")); - if (i * maxp + l != len) { - seg++; - segoff = 0; - } - } - prevp = p; - tog ^= 1; - } - prevp->td.td_link = htole32(UHCI_PTR_T | UHCI_PTR_VF | UHCI_PTR_TD); - upipe->nexttoggle = tog; - *sp = startp; - DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n", - upipe->nexttoggle)); - return (USBD_NORMAL_COMPLETION); -} - -/* - * Allocate a physically contiguous buffer to handle cases where UHCI - * cannot handle a packet because it is not physically contiguous. - * If the usb_dma_t was already allocated this just ensures it is - * large enough for the specified size. - */ -static usbd_status -uhci_aux_dma_alloc(uhci_softc_t *sc, uhci_soft_td_t *std, void *data, int len) -{ - int err, align; - - if (std->aux_dma.block == NULL || std->aux_dma.block->size < len) { - /* Align to avoid crossing a page boundary. */ - if (powerof2(len)) - align = len; - else - align = 1 << fls(len); - - if (std->aux_dma.block != NULL) - usb_freemem(&sc->sc_bus, &std->aux_dma); - std->aux_dma.block = NULL; - err = usb_allocmem(&sc->sc_bus, len, align, &std->aux_dma); - if (err) - return (err); - } - std->aux_data = data; - std->aux_len = len; - - return (USBD_NORMAL_COMPLETION); -} - -static uhci_physaddr_t -uhci_aux_dma_prepare(uhci_soft_td_t *std, int isread) -{ - if (!isread) { - bcopy(std->aux_data, KERNADDR(&std->aux_dma, 0), std->aux_len); - bus_dmamap_sync(std->aux_dma.block->tag, - std->aux_dma.block->map, BUS_DMASYNC_PREWRITE); - } - - return (DMAADDR(&std->aux_dma, 0)); -} - -static void -uhci_aux_dma_complete(uhci_soft_td_t *std, int isread) -{ - if (isread) { - bus_dmamap_sync(std->aux_dma.block->tag, - std->aux_dma.block->map, BUS_DMASYNC_POSTREAD); - bcopy(KERNADDR(&std->aux_dma, 0), std->aux_data, std->aux_len); - } -} - -void -uhci_device_clear_toggle(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - upipe->nexttoggle = 0; -} - -void -uhci_noop(usbd_pipe_handle pipe) -{ -} - -usbd_status -uhci_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_bulk_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *data, *dataend; - uhci_soft_qh_t *sqh; - usbd_status err; - int len, isread, endpt; - int s; - - DPRINTFN(3, ("uhci_device_bulk_start: xfer=%p len=%d flags=%d ii=%p\n", - xfer, xfer->length, xfer->flags, ii)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("uhci_device_bulk_transfer: a request"); -#endif - - len = xfer->length; - endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = upipe->u.bulk.sqh; - - upipe->u.bulk.isread = isread; - upipe->u.bulk.length = len; - - err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, xfer, - &data, &dataend); - if (err) - return (err); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 8) { - DPRINTF(("uhci_device_bulk_transfer: data(1)\n")); - uhci_dump_tds(data); - } -#endif - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - - s = splusb(); - uhci_add_bulk(sc, sqh); - uhci_add_intr_info(sc, ii); - - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - uhci_timeout, ii); - } - xfer->status = USBD_IN_PROGRESS; - splx(s); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_bulk_transfer: data(2)\n")); - uhci_dump_tds(data); - } -#endif - - if (sc->sc_bus.use_polling) - uhci_waitintr(sc, xfer); - - return (USBD_IN_PROGRESS); -} - -/* Abort a device bulk request. */ -void -uhci_device_bulk_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("uhci_device_bulk_abort:\n")); - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* - * 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. - */ -void -uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) -{ - struct uhci_xfer *uxfer = UXFER(xfer); - uhci_intr_info_t *ii = &uxfer->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 */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); - uhci_transfer_complete(xfer); - splx(s); - return; - } - - if (xfer->device->bus->intr_context || !curproc) - panic("uhci_abort_xfer: not in process context"); - - /* - * If an abort is already in progress then just wait for it to - * complete and return. - */ - if (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) { - DPRINTFN(2, ("uhci_abort_xfer: already aborting\n")); - /* No need to wait if we're aborting from a timeout. */ - if (status == USBD_TIMEOUT) - return; - /* Override the status which might be USBD_TIMEOUT. */ - xfer->status = status; - DPRINTFN(2, ("uhci_abort_xfer: waiting for abort to finish\n")); - uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTWAIT; - while (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) - tsleep(&uxfer->uhci_xfer_flags, PZERO, "uhciaw", 0); - return; - } - - /* - * Step 1: Make interrupt routine and hardware ignore xfer. - */ - s = splusb(); - uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTING; - xfer->status = status; /* make software ignore it */ - callout_stop(&xfer->timeout_handle); - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); - DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii)); - 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(); -#ifdef USB_USE_SOFTINTR - sc->sc_softwake = 1; -#endif /* USB_USE_SOFTINTR */ - usb_schedsoftintr(&sc->sc_bus); -#ifdef USB_USE_SOFTINTR - DPRINTFN(1,("uhci_abort_xfer: tsleep\n")); - tsleep(&sc->sc_softwake, PZERO, "uhciab", 0); -#endif /* USB_USE_SOFTINTR */ - splx(s); - - /* - * Step 3: Execute callback. - */ - DPRINTFN(1,("uhci_abort_xfer: callback\n")); - s = splusb(); -#ifdef DIAGNOSTIC - ii->isdone = 1; -#endif - /* Do the wakeup first to avoid touching the xfer after the callback. */ - uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTING; - if (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTWAIT) { - uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTWAIT; - wakeup(&uxfer->uhci_xfer_flags); - } - uhci_transfer_complete(xfer); - splx(s); -} - -/* - * Perform any UHCI-specific transfer completion operations, then - * call usb_transfer_complete(). - */ -static void -uhci_transfer_complete(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_td_t *p; - int i, isread, n; - - /* XXX, must be an easier way to detect reads... */ - isread = ((xfer->rqflags & URQ_REQUEST) && - (xfer->request.bmRequestType & UT_READ)) || - (xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN); - - /* Copy back from any auxillary buffers after a read operation. */ - if (xfer->nframes == 0) { - for (p = ii->stdstart; p != NULL; p = p->link.std) { - if (p->aux_data != NULL) - uhci_aux_dma_complete(p, isread); - } - } else { - if (xfer->nframes != 0) { - /* Isoc transfer, do things differently. */ - n = UXFER(xfer)->curframe; - for (i = 0; i < xfer->nframes; i++) { - p = upipe->u.iso.stds[n]; - if (p->aux_data != NULL) - uhci_aux_dma_complete(p, isread); - if (++n >= UHCI_VFRAMELIST_COUNT) - n = 0; - } - } - } - - usb_transfer_complete(xfer); -} - -/* Close a device bulk pipe. */ -void -uhci_device_bulk_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - - uhci_free_sqh(sc, upipe->u.bulk.sqh); - pipe->endpoint->savedtoggle = upipe->nexttoggle; -} - -usbd_status -uhci_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_ctrl_start(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_device_ctrl_transfer: not a request"); -#endif - - err = uhci_device_request(xfer); - if (err) - return (err); - - if (sc->sc_bus.use_polling) - uhci_waitintr(sc, xfer); - return (USBD_IN_PROGRESS); -} - -usbd_status -uhci_device_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_device_intr_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *data, *dataend; - uhci_soft_qh_t *sqh; - usbd_status err; - int isread, endpt; - int i, s; - - if (sc->sc_dying) - return (USBD_IOERROR); - - DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_REQUEST) - panic("uhci_device_intr_transfer: a request"); -#endif - - endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - isread = UE_GET_DIR(endpt) == UE_DIR_IN; - sqh = upipe->u.bulk.sqh; - - upipe->u.intr.isread = isread; - - err = uhci_alloc_std_chain(upipe, sc, xfer->length, isread, xfer->flags, - xfer, &data, &dataend); - if (err) - return (err); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: data(1)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - s = splusb(); - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - printf("uhci_device_intr_transfer: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - 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]; - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - } - uhci_add_intr_info(sc, ii); - xfer->status = USBD_IN_PROGRESS; - splx(s); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_transfer: data(2)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - return (USBD_IN_PROGRESS); -} - -/* Abort a device control request. */ -void -uhci_device_ctrl_abort(usbd_xfer_handle xfer) -{ - DPRINTF(("uhci_device_ctrl_abort:\n")); - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device control pipe. */ -void -uhci_device_ctrl_close(usbd_pipe_handle pipe) -{ -} - -/* Abort a device interrupt request. */ -void -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; - } - uhci_abort_xfer(xfer, USBD_CANCELLED); -} - -/* Close a device interrupt pipe. */ -void -uhci_device_intr_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - int i, npoll; - int s; - - /* Unlink descriptors from controller data structures. */ - npoll = upipe->u.intr.npoll; - s = splusb(); - for (i = 0; i < npoll; i++) - 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. - */ - usb_delay_ms(&sc->sc_bus, 2); - - for(i = 0; i < npoll; i++) - uhci_free_sqh(sc, upipe->u.intr.qhs[i]); - free(upipe->u.intr.qhs, M_USBHC); - - /* XXX free other resources */ -} - -usbd_status -uhci_device_request(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usb_device_request_t *req = &xfer->request; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - int addr = dev->address; - int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *setup, *data, *stat, *next, *dataend; - uhci_soft_qh_t *sqh; - int len; - u_int32_t ls; - usbd_status err; - int isread; - int s; - - DPRINTFN(3,("uhci_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), UGETW(req->wLength), - addr, endpt)); - - ls = dev->speed == USB_SPEED_LOW ? UHCI_TD_LS : 0; - isread = req->bmRequestType & UT_READ; - len = UGETW(req->wLength); - - setup = upipe->u.ctl.setup; - stat = upipe->u.ctl.stat; - sqh = upipe->u.ctl.sqh; - - /* Set up data transaction */ - if (len != 0) { - upipe->nexttoggle = 1; - err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, - xfer, &data, &dataend); - if (err) - return (err); - next = data; - dataend->link.std = stat; - dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); - } else { - next = stat; - } - upipe->u.ctl.length = len; - - memcpy(KERNADDR(&upipe->u.ctl.reqdma, 0), req, sizeof *req); - - setup->link.std = next; - setup->td.td_link = htole32(next->physaddr | UHCI_PTR_VF | UHCI_PTR_TD); - setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE); - setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof *req, endpt, addr)); - setup->td.td_buffer = htole32(DMAADDR(&upipe->u.ctl.reqdma, 0)); - - stat->link.std = NULL; - stat->td.td_link = htole32(UHCI_PTR_T); - stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE | UHCI_TD_IOC); - 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); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_request: before transfer\n")); - uhci_dump_tds(setup); - } -#endif - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = setup; - ii->stdend = stat; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - printf("uhci_device_request: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - - sqh->elink = setup; - sqh->qh.qh_elink = htole32(setup->physaddr | UHCI_PTR_TD); - - s = splusb(); - if (dev->speed == USB_SPEED_LOW) - uhci_add_ls_ctrl(sc, sqh); - else - uhci_add_hs_ctrl(sc, sqh); - uhci_add_intr_info(sc, ii); -#ifdef USB_DEBUG - if (uhcidebug > 12) { - uhci_soft_td_t *std; - uhci_soft_qh_t *xqh; - uhci_soft_qh_t *sxqh; - int maxqh = 0; - uhci_physaddr_t link; - DPRINTF(("uhci_enter_ctl_q: follow from [0]\n")); - for (std = sc->sc_vframes[0].htd, link = 0; - (link & UHCI_PTR_QH) == 0; - std = std->link.std) { - link = le32toh(std->td.td_link); - uhci_dump_td(std); - } - sxqh = (uhci_soft_qh_t *)std; - uhci_dump_qh(sxqh); - for (xqh = sxqh; - xqh != NULL; - xqh = (maxqh++ == 5 || xqh->hlink == sxqh || - xqh->hlink == xqh ? NULL : xqh->hlink)) { - uhci_dump_qh(xqh); - } - DPRINTF(("Enqueued QH:\n")); - uhci_dump_qh(sqh); - uhci_dump_tds(sqh->elink); - } -#endif - if (xfer->timeout && !sc->sc_bus.use_polling) { - callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout), - uhci_timeout, ii); - } - xfer->status = USBD_IN_PROGRESS; - splx(s); - - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -uhci_device_isoc_transfer(usbd_xfer_handle xfer) -{ - usbd_status err; - - DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer)); - - /* Put it on our queue, */ - err = usb_insert_transfer(xfer); - - /* bail out on error, */ - if (err && err != USBD_IN_PROGRESS) - return (err); - - /* XXX should check inuse here */ - - /* insert into schedule, */ - uhci_device_isoc_enter(xfer); - - /* and start if the pipe wasn't running */ - if (!err) - uhci_device_isoc_start(STAILQ_FIRST(&xfer->pipe->queue)); - - return (err); -} - -void -uhci_device_isoc_enter(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - struct iso *iso = &upipe->u.iso; - uhci_soft_td_t *std; - void *dataptr; - u_int32_t len, status; - int err, s, i, isread, next, nframes, seg, segoff; - - DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p " - "nframes=%d\n", - iso->inuse, iso->next, xfer, xfer->nframes)); - - if (sc->sc_dying) - return; - - if (xfer->status == USBD_IN_PROGRESS) { - /* This request has already been entered into the frame list */ - printf("uhci_device_isoc_enter: xfer=%p in frame list\n", xfer); - /* XXX */ - } - -#ifdef DIAGNOSTIC - if (iso->inuse >= UHCI_VFRAMELIST_COUNT) - printf("uhci_device_isoc_enter: overflow!\n"); -#endif - - next = iso->next; - if (next == -1) { - /* Not in use yet, schedule it a few frames ahead. */ - next = (UREAD2(sc, UHCI_FRNUM) + 3) % UHCI_VFRAMELIST_COUNT; - DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next)); - } - - xfer->status = USBD_IN_PROGRESS; - UXFER(xfer)->curframe = next; - - seg = 0; - segoff = 0; - dataptr = xfer->allocbuf; /* Normal buffers not possible for isoc? */ - isread = xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN; - status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) | - UHCI_TD_ACTIVE | - UHCI_TD_IOS); - nframes = xfer->nframes; - s = splusb(); - for (i = 0; i < nframes; i++) { - std = iso->stds[next]; - if (++next >= UHCI_VFRAMELIST_COUNT) - next = 0; - len = xfer->frlengths[i]; - KASSERT(seg < xfer->dmamap.nsegs, - ("uhci_device_isoc_enter: too few segments")); - if (len + segoff > xfer->dmamap.segs[seg].ds_len) { - /* UHCI can't handle non-contiguous data. */ - err = uhci_aux_dma_alloc(sc, std, dataptr, len); - /* XXX */ - if (err) - printf("uhci_device_isoc_enter: aux alloc\n"); - std->td.td_buffer = htole32(uhci_aux_dma_prepare(std, - isread)); - segoff += len; - while (segoff >= xfer->dmamap.segs[seg].ds_len) { - KASSERT(seg < xfer->dmamap.nsegs - 1 || - segoff == xfer->dmamap.segs[seg].ds_len, - ("uhci_device_isoc_enter: overlap2")); - segoff -= xfer->dmamap.segs[seg].ds_len; - seg++; - } - } else { - std->td.td_buffer = - htole32(xfer->dmamap.segs[seg].ds_addr + segoff); - segoff += len; - if (segoff >= xfer->dmamap.segs[seg].ds_len) { - KASSERT(segoff == xfer->dmamap.segs[seg].ds_len, - ("uhci_device_isoc_enter: overlap")); - segoff = 0; - seg++; - } - } - if (i == nframes - 1) - status |= UHCI_TD_IOC; - std->td.td_status = htole32(status); - std->td.td_token &= htole32(~UHCI_TD_MAXLEN_MASK); - std->td.td_token |= htole32(UHCI_TD_SET_MAXLEN(len)); -#ifdef USB_DEBUG - if (uhcidebug > 5) { - DPRINTFN(5,("uhci_device_isoc_enter: TD %d\n", i)); - uhci_dump_td(std); - } -#endif - dataptr = (char *)dataptr + len; - } - iso->next = next; - iso->inuse += xfer->nframes; - - splx(s); -} - -usbd_status -uhci_device_isoc_start(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_soft_td_t *end; - int s, i; - - DPRINTFN(5,("uhci_device_isoc_start: xfer=%p\n", xfer)); - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (xfer->status != USBD_IN_PROGRESS) - printf("uhci_device_isoc_start: not in progress %p\n", xfer); -#endif - - /* Find the last TD */ - i = UXFER(xfer)->curframe + xfer->nframes; - if (i >= UHCI_VFRAMELIST_COUNT) - i -= UHCI_VFRAMELIST_COUNT; - end = upipe->u.iso.stds[i]; - -#ifdef DIAGNOSTIC - if (end == NULL) { - printf("uhci_device_isoc_start: end == NULL\n"); - return (USBD_INVAL); - } -#endif - - s = splusb(); - - /* Set up interrupt info. */ - ii->xfer = xfer; - ii->stdstart = end; - ii->stdend = end; -#ifdef DIAGNOSTIC - if (!ii->isdone) - printf("uhci_device_isoc_start: not done, ii=%p\n", ii); - ii->isdone = 0; -#endif - uhci_add_intr_info(sc, ii); - - splx(s); - - return (USBD_IN_PROGRESS); -} - -void -uhci_device_isoc_abort(usbd_xfer_handle xfer) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_td_t **stds = upipe->u.iso.stds; - uhci_soft_td_t *std; - int i, n, s, nframes, maxlen, len; - - s = splusb(); - - /* Transfer is already done. */ - if (xfer->status != USBD_NOT_STARTED && - xfer->status != USBD_IN_PROGRESS) { - splx(s); - return; - } - - /* Give xfer the requested abort code. */ - xfer->status = USBD_CANCELLED; - - /* make hardware ignore it, */ - nframes = xfer->nframes; - n = UXFER(xfer)->curframe; - maxlen = 0; - for (i = 0; i < nframes; i++) { - std = stds[n]; - std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); - len = UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token)); - if (len > maxlen) - maxlen = len; - if (++n >= UHCI_VFRAMELIST_COUNT) - n = 0; - } - - /* and wait until we are sure the hardware has finished. */ - delay(maxlen); - -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; -#endif - /* Run callback and remove from interrupt list. */ - uhci_transfer_complete(xfer); - - splx(s); -} - -void -uhci_device_isoc_close(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - uhci_soft_td_t *std, *vstd; - struct iso *iso; - int i, s; - - /* - * Make sure all TDs are marked as inactive. - * Wait for completion. - * Unschedule. - * Deallocate. - */ - iso = &upipe->u.iso; - - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) - iso->stds[i]->td.td_status &= htole32(~UHCI_TD_ACTIVE); - usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */ - - s = splusb(); - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = iso->stds[i]; - for (vstd = sc->sc_vframes[i].htd; - vstd != NULL && vstd->link.std != std; - vstd = vstd->link.std) - ; - if (vstd == NULL) { - /*panic*/ - printf("uhci_device_isoc_close: %p not found\n", std); - splx(s); - return; - } - vstd->link = std->link; - vstd->td.td_link = std->td.td_link; - uhci_free_std(sc, std); - } - splx(s); - - free(iso->stds, M_USBHC); -} - -usbd_status -uhci_setup_isoc(usbd_pipe_handle pipe) -{ - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usbd_device_handle dev = upipe->pipe.device; - uhci_softc_t *sc = (uhci_softc_t *)dev->bus; - int addr = upipe->pipe.device->address; - int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress; - int rd = UE_GET_DIR(endpt) == UE_DIR_IN; - uhci_soft_td_t *std, *vstd; - u_int32_t token; - struct iso *iso; - int i, s; - - iso = &upipe->u.iso; - iso->stds = malloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *), - M_USBHC, M_WAITOK); - - token = rd ? UHCI_TD_IN (0, endpt, addr, 0) : - UHCI_TD_OUT(0, endpt, addr, 0); - - /* Allocate the TDs and mark as inactive; */ - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = uhci_alloc_std(sc); - if (std == 0) - goto bad; - std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */ - std->td.td_token = htole32(token); - iso->stds[i] = std; - } - - /* Insert TDs into schedule. */ - s = splusb(); - for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) { - std = iso->stds[i]; - vstd = sc->sc_vframes[i].htd; - std->link = vstd->link; - std->td.td_link = vstd->td.td_link; - vstd->link.std = std; - vstd->td.td_link = htole32(std->physaddr | UHCI_PTR_TD); - } - splx(s); - - iso->next = -1; - iso->inuse = 0; - - return (USBD_NORMAL_COMPLETION); - - bad: - while (--i >= 0) - uhci_free_std(sc, iso->stds[i]); - free(iso->stds, M_USBHC); - return (USBD_NOMEM); -} - -void -uhci_device_isoc_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - - DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen)); - - if (ii->xfer != xfer) - /* Not on interrupt list, ignore it. */ - return; - - if (!uhci_active_intr_info(ii)) - return; - -#ifdef DIAGNOSTIC - if (xfer->busy_free != XFER_BUSY) { - printf("uhci_device_isoc_done: xfer=%p not busy 0x%08x\n", - xfer, xfer->busy_free); - return; - } - - if (ii->stdend == NULL) { - printf("uhci_device_isoc_done: xfer=%p stdend==NULL\n", xfer); -#ifdef USB_DEBUG - uhci_dump_ii(ii); -#endif - return; - } -#endif - - /* Turn off the interrupt since it is active even if the TD is not. */ - ii->stdend->td.td_status &= htole32(~UHCI_TD_IOC); - - uhci_del_intr_info(ii); /* remove from active list */ - -#ifdef DIAGNOSTIC - if (ii->stdend == NULL) { - printf("uhci_device_isoc_done: xfer=%p stdend==NULL\n", xfer); -#ifdef USB_DEBUG - uhci_dump_ii(ii); -#endif - return; - } -#endif - ii->stdstart = NULL; - ii->stdend = NULL; -} - -void -uhci_device_intr_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - uhci_soft_qh_t *sqh; - int i, npoll; - - DPRINTFN(5, ("uhci_device_intr_done: length=%d\n", xfer->actlen)); - - npoll = upipe->u.intr.npoll; - for(i = 0; i < npoll; i++) { - sqh = upipe->u.intr.qhs[i]; - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - } - uhci_free_std_chain(sc, ii->stdstart, NULL); - - /* XXX Wasteful. */ - if (xfer->pipe->repeat) { - uhci_soft_td_t *data, *dataend; - - DPRINTFN(5,("uhci_device_intr_done: requeing\n")); - - /* This alloc cannot fail since we freed the chain above. */ - uhci_alloc_std_chain(upipe, sc, xfer->length, - upipe->u.intr.isread, xfer->flags, xfer, - &data, &dataend); - dataend->td.td_status |= htole32(UHCI_TD_IOC); - -#ifdef USB_DEBUG - if (uhcidebug > 10) { - DPRINTF(("uhci_device_intr_done: data(1)\n")); - uhci_dump_tds(data); - uhci_dump_qh(upipe->u.intr.qhs[0]); - } -#endif - - ii->stdstart = data; - ii->stdend = dataend; -#ifdef DIAGNOSTIC - if (!ii->isdone) { - printf("uhci_device_intr_done: not done, ii=%p\n", ii); - } - ii->isdone = 0; -#endif - for (i = 0; i < npoll; i++) { - sqh = upipe->u.intr.qhs[i]; - sqh->elink = data; - sqh->qh.qh_elink = htole32(data->physaddr | UHCI_PTR_TD); - } - xfer->status = USBD_IN_PROGRESS; - /* The ii is already on the examined list, just leave it. */ - } else { - DPRINTFN(5,("uhci_device_intr_done: removing\n")); - if (uhci_active_intr_info(ii)) { - uhci_del_intr_info(ii); - ii->stdstart = NULL; - ii->stdend = NULL; - } - } -} - -/* Deallocate request data structures */ -void -uhci_device_ctrl_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_device_ctrl_done: not a request"); -#endif - - if (!uhci_active_intr_info(ii)) - return; - - uhci_del_intr_info(ii); /* remove from active list */ - - if (upipe->pipe.device->speed == USB_SPEED_LOW) - uhci_remove_ls_ctrl(sc, upipe->u.ctl.sqh); - else - uhci_remove_hs_ctrl(sc, upipe->u.ctl.sqh); - - if (upipe->u.ctl.length != 0) - uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend); - ii->stdstart = NULL; - ii->stdend = NULL; - - DPRINTFN(5, ("uhci_device_ctrl_done: length=%d\n", xfer->actlen)); -} - -/* Deallocate request data structures */ -void -uhci_device_bulk_done(usbd_xfer_handle xfer) -{ - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; - uhci_softc_t *sc = ii->sc; - struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; - - DPRINTFN(5,("uhci_device_bulk_done: xfer=%p ii=%p sc=%p upipe=%p\n", - xfer, ii, sc, upipe)); - - if (!uhci_active_intr_info(ii)) - return; - - uhci_del_intr_info(ii); /* remove from active list */ - - uhci_remove_bulk(sc, upipe->u.bulk.sqh); - - uhci_free_std_chain(sc, ii->stdstart, NULL); - ii->stdstart = NULL; - ii->stdend = NULL; - - DPRINTFN(5, ("uhci_device_bulk_done: length=%d\n", xfer->actlen)); -} - -/* Add interrupt QH, called with vflock. */ -void -uhci_add_intr(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - struct uhci_vframe *vf = &sc->sc_vframes[sqh->pos]; - uhci_soft_qh_t *eqh; - - DPRINTFN(4, ("uhci_add_intr: n=%d sqh=%p\n", sqh->pos, sqh)); - - eqh = vf->eqh; - sqh->hlink = eqh->hlink; - sqh->qh.qh_hlink = eqh->qh.qh_hlink; - eqh->hlink = sqh; - eqh->qh.qh_hlink = htole32(sqh->physaddr | UHCI_PTR_QH); - vf->eqh = sqh; - vf->bandwidth++; -} - -/* Remove interrupt QH. */ -void -uhci_remove_intr(uhci_softc_t *sc, uhci_soft_qh_t *sqh) -{ - struct uhci_vframe *vf = &sc->sc_vframes[sqh->pos]; - uhci_soft_qh_t *pqh; - - DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", sqh->pos, sqh)); - - /* See comment in uhci_remove_ctrl() */ - if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) { - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - delay(UHCI_QH_REMOVE_DELAY); - } - - pqh = uhci_find_prev_qh(vf->hqh, sqh); - pqh->hlink = sqh->hlink; - pqh->qh.qh_hlink = sqh->qh.qh_hlink; - delay(UHCI_QH_REMOVE_DELAY); - if (vf->eqh == sqh) - vf->eqh = pqh; - vf->bandwidth--; -} - -usbd_status -uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) -{ - uhci_soft_qh_t *sqh; - int i, npoll, s; - u_int bestbw, bw, bestoffs, offs; - - DPRINTFN(2, ("uhci_device_setintr: pipe=%p\n", upipe)); - if (ival == 0) { - printf("uhci_setintr: 0 interval\n"); - return (USBD_INVAL); - } - - if (ival > UHCI_VFRAMELIST_COUNT) - ival = UHCI_VFRAMELIST_COUNT; - npoll = (UHCI_VFRAMELIST_COUNT + ival - 1) / ival; - DPRINTFN(2, ("uhci_device_setintr: ival=%d npoll=%d\n", ival, npoll)); - - upipe->u.intr.npoll = npoll; - 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. - */ -#define MOD(i) ((i) & (UHCI_VFRAMELIST_COUNT-1)) - for (bestoffs = offs = 0, bestbw = ~0; offs < ival; offs++) { - for (bw = i = 0; i < npoll; i++) - bw += sc->sc_vframes[MOD(i * ival + offs)].bandwidth; - if (bw < bestbw) { - bestbw = bw; - bestoffs = offs; - } - } - DPRINTFN(1, ("uhci_device_setintr: bw=%d offs=%d\n", bestbw, bestoffs)); - - for(i = 0; i < npoll; i++) { - upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc); - sqh->elink = NULL; - sqh->qh.qh_elink = htole32(UHCI_PTR_T); - sqh->pos = MOD(i * ival + bestoffs); - } -#undef MOD - - s = splusb(); - /* Enter QHs into the controller data structures. */ - for(i = 0; i < npoll; i++) - uhci_add_intr(sc, upipe->u.intr.qhs[i]); - splx(s); - - DPRINTFN(5, ("uhci_device_setintr: returns %p\n", upipe)); - return (USBD_NORMAL_COMPLETION); -} - -/* Open a new pipe. */ -usbd_status -uhci_open(usbd_pipe_handle pipe) -{ - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - struct uhci_pipe *upipe = (struct uhci_pipe *)pipe; - usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; - usbd_status err; - int ival; - - DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", - pipe, pipe->device->address, - ed->bEndpointAddress, sc->sc_addr)); - - upipe->aborting = 0; - upipe->nexttoggle = pipe->endpoint->savedtoggle; - - if (pipe->device->address == sc->sc_addr) { - switch (ed->bEndpointAddress) { - case USB_CONTROL_ENDPOINT: - pipe->methods = &uhci_root_ctrl_methods; - break; - case UE_DIR_IN | UHCI_INTR_ENDPT: - pipe->methods = &uhci_root_intr_methods; - break; - default: - return (USBD_INVAL); - } - } else { - switch (ed->bmAttributes & UE_XFERTYPE) { - case UE_CONTROL: - pipe->methods = &uhci_device_ctrl_methods; - upipe->u.ctl.sqh = uhci_alloc_sqh(sc); - if (upipe->u.ctl.sqh == NULL) - goto bad; - upipe->u.ctl.setup = uhci_alloc_std(sc); - if (upipe->u.ctl.setup == NULL) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - goto bad; - } - upipe->u.ctl.stat = uhci_alloc_std(sc); - if (upipe->u.ctl.stat == NULL) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - uhci_free_std(sc, upipe->u.ctl.setup); - goto bad; - } - err = usb_allocmem(&sc->sc_bus, - sizeof(usb_device_request_t), - 0, &upipe->u.ctl.reqdma); - if (err) { - uhci_free_sqh(sc, upipe->u.ctl.sqh); - uhci_free_std(sc, upipe->u.ctl.setup); - uhci_free_std(sc, upipe->u.ctl.stat); - goto bad; - } - break; - case UE_INTERRUPT: - pipe->methods = &uhci_device_intr_methods; - ival = pipe->interval; - if (ival == USBD_DEFAULT_INTERVAL) - ival = ed->bInterval; - return (uhci_device_setintr(sc, upipe, ival)); - case UE_ISOCHRONOUS: - pipe->methods = &uhci_device_isoc_methods; - return (uhci_setup_isoc(pipe)); - case UE_BULK: - pipe->methods = &uhci_device_bulk_methods; - upipe->u.bulk.sqh = uhci_alloc_sqh(sc); - if (upipe->u.bulk.sqh == NULL) - goto bad; - break; - } - } - return (USBD_NORMAL_COMPLETION); - - bad: - return (USBD_NOMEM); -} - -/* - * Data structures and routines to emulate the root hub. - */ -usb_device_descriptor_t uhci_devd = { - USB_DEVICE_DESCRIPTOR_SIZE, - UDESC_DEVICE, /* type */ - {0x00, 0x01}, /* USB version */ - UDCLASS_HUB, /* class */ - UDSUBCLASS_HUB, /* subclass */ - UDPROTO_FSHUB, /* protocol */ - 64, /* max packet */ - {0},{0},{0x00,0x01}, /* device id */ - 1,2,0, /* string indicies */ - 1 /* # of configurations */ -}; - -usb_config_descriptor_t uhci_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 */ -}; - -usb_interface_descriptor_t uhci_ifcd = { - USB_INTERFACE_DESCRIPTOR_SIZE, - UDESC_INTERFACE, - 0, - 0, - 1, - UICLASS_HUB, - UISUBCLASS_HUB, - UIPROTO_FSHUB, - 0 -}; - -usb_endpoint_descriptor_t uhci_endpd = { - USB_ENDPOINT_DESCRIPTOR_SIZE, - UDESC_ENDPOINT, - UE_DIR_IN | UHCI_INTR_ENDPT, - UE_INTERRUPT, - {8}, - 255 -}; - -usb_hub_descriptor_t uhci_hubd_piix = { - USB_HUB_DESCRIPTOR_SIZE, - UDESC_HUB, - 2, - { UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL, 0 }, - 50, /* power on to power good */ - 0, - { 0x00 }, /* both ports are removable */ -}; - -int -uhci_str(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); -} - -/* - * The USB hub protocol requires that SET_FEATURE(PORT_RESET) also - * enables the port, and also states that SET_FEATURE(PORT_ENABLE) - * should not be used by the USB subsystem. As we cannot issue a - * SET_FEATURE(PORT_ENABLE) externally, we must ensure that the port - * will be enabled as part of the reset. - * - * On the VT83C572, the port cannot be successfully enabled until the - * outstanding "port enable change" and "connection status change" - * events have been reset. - */ -static usbd_status -uhci_portreset(uhci_softc_t *sc, int index) -{ - int lim, port, x; - - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else - return (USBD_IOERROR); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PR); - - usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY); - - DPRINTFN(3,("uhci port %d reset, status0 = 0x%04x\n", - index, UREAD2(sc, port))); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PR); - - delay(100); - - DPRINTFN(3,("uhci port %d reset, status1 = 0x%04x\n", - index, UREAD2(sc, port))); - - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PE); - - for (lim = 10; --lim > 0;) { - usb_delay_ms(&sc->sc_bus, USB_PORT_RESET_DELAY); - - x = UREAD2(sc, port); - - DPRINTFN(3,("uhci port %d iteration %u, status = 0x%04x\n", - index, lim, x)); - - if (!(x & UHCI_PORTSC_CCS)) { - /* - * No device is connected (or was disconnected - * during reset). Consider the port reset. - * The delay must be long enough to ensure on - * the initial iteration that the device - * connection will have been registered. 50ms - * appears to be sufficient, but 20ms is not. - */ - DPRINTFN(3,("uhci port %d loop %u, device detached\n", - index, lim)); - break; - } - - if (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC)) { - /* - * Port enabled changed and/or connection - * status changed were set. Reset either or - * both raised flags (by writing a 1 to that - * bit), and wait again for state to settle. - */ - UWRITE2(sc, port, URWMASK(x) | - (x & (UHCI_PORTSC_POEDC | UHCI_PORTSC_CSC))); - continue; - } - - if (x & UHCI_PORTSC_PE) - /* Port is enabled */ - break; - - UWRITE2(sc, port, URWMASK(x) | UHCI_PORTSC_PE); - } - - DPRINTFN(3,("uhci port %d reset, status2 = 0x%04x\n", - index, UREAD2(sc, port))); - - if (lim <= 0) { - DPRINTFN(1,("uhci port %d reset timed out\n", index)); - return (USBD_TIMEOUT); - } - - sc->sc_isreset = 1; - return (USBD_NORMAL_COMPLETION); -} - -/* - * Simulate a hardware hub by handling all the necessary requests. - */ -usbd_status -uhci_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -usbd_status -uhci_root_ctrl_start(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - usb_device_request_t *req; - void *buf = NULL; - int port, x; - int s, len, value, index, status, change, l, totlen = 0; - usb_port_status_t ps; - usbd_status err; - - if (sc->sc_dying) - return (USBD_IOERROR); - -#ifdef DIAGNOSTIC - if (!(xfer->rqflags & URQ_REQUEST)) - panic("uhci_root_ctrl_transfer: not a request"); -#endif - req = &xfer->request; - - DPRINTFN(2,("uhci_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 = xfer->buffer; - -#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(2,("uhci_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(uhci_devd.idVendor, sc->sc_id_vendor); - memcpy(buf, &uhci_devd, l); - break; - case UDESC_CONFIG: - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE); - memcpy(buf, &uhci_confd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &uhci_ifcd, l); - buf = (char *)buf + l; - len -= l; - l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); - totlen += l; - memcpy(buf, &uhci_endpd, l); - break; - case UDESC_STRING: - if (len == 0) - break; - *(u_int8_t *)buf = 0; - totlen = 1; - switch (value & 0xff) { - case 1: /* Vendor */ - totlen = uhci_str(buf, len, sc->sc_vendor); - break; - case 2: /* Product */ - totlen = uhci_str(buf, len, "UHCI 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(3, ("uhci_root_ctrl_control: UR_CLEAR_PORT_FEATURE " - "port=%d feature=%d\n", - index, value)); - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - switch(value) { - case UHF_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PE); - break; - case UHF_PORT_SUSPEND: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_SUSP); - break; - case UHF_PORT_RESET: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x & ~UHCI_PORTSC_PR); - break; - case UHF_C_PORT_CONNECTION: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_CSC); - break; - case UHF_C_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_POEDC); - break; - case UHF_C_PORT_OVER_CURRENT: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_OCIC); - break; - case UHF_C_PORT_RESET: - sc->sc_isreset = 0; - err = USBD_NORMAL_COMPLETION; - goto ret; - case UHF_PORT_CONNECTION: - case UHF_PORT_OVER_CURRENT: - case UHF_PORT_POWER: - case UHF_PORT_LOW_SPEED: - case UHF_C_PORT_SUSPEND: - default: - err = USBD_IOERROR; - goto ret; - } - break; - case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER): - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - if (len > 0) { - *(u_int8_t *)buf = - (UREAD2(sc, port) & UHCI_PORTSC_LS) >> - UHCI_PORTSC_LS_SHIFT; - totlen = 1; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): - if ((value & 0xff) != 0) { - err = USBD_IOERROR; - goto ret; - } - l = min(len, USB_HUB_DESCRIPTOR_SIZE); - totlen = l; - memcpy(buf, &uhci_hubd_piix, l); - break; - case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - memset(buf, 0, len); - totlen = len; - break; - case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): - if (index == 1) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - if (len != 4) { - err = USBD_IOERROR; - goto ret; - } - x = UREAD2(sc, port); - status = change = 0; - if (x & UHCI_PORTSC_CCS) - status |= UPS_CURRENT_CONNECT_STATUS; - if (x & UHCI_PORTSC_CSC) - change |= UPS_C_CONNECT_STATUS; - if (x & UHCI_PORTSC_PE) - status |= UPS_PORT_ENABLED; - if (x & UHCI_PORTSC_POEDC) - change |= UPS_C_PORT_ENABLED; - if (x & UHCI_PORTSC_OCI) - status |= UPS_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_OCIC) - change |= UPS_C_OVERCURRENT_INDICATOR; - if (x & UHCI_PORTSC_SUSP) - status |= UPS_SUSPEND; - if (x & UHCI_PORTSC_LSDA) - status |= UPS_LOW_SPEED; - status |= UPS_PORT_POWER; - if (sc->sc_isreset) - change |= UPS_C_PORT_RESET; - USETW(ps.wPortStatus, status); - USETW(ps.wPortChange, change); - 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) - port = UHCI_PORTSC1; - else if (index == 2) - port = UHCI_PORTSC2; - else { - err = USBD_IOERROR; - goto ret; - } - switch(value) { - case UHF_PORT_ENABLE: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_PE); - break; - case UHF_PORT_SUSPEND: - x = URWMASK(UREAD2(sc, port)); - UWRITE2(sc, port, x | UHCI_PORTSC_SUSP); - break; - case UHF_PORT_RESET: - err = uhci_portreset(sc, index); - goto ret; - case UHF_PORT_POWER: - /* Pretend we turned on power */ - err = USBD_NORMAL_COMPLETION; - goto ret; - case UHF_C_PORT_CONNECTION: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_OVER_CURRENT: - case UHF_PORT_CONNECTION: - case UHF_PORT_OVER_CURRENT: - case UHF_PORT_LOW_SPEED: - case UHF_C_PORT_SUSPEND: - case UHF_C_PORT_RESET: - default: - err = USBD_IOERROR; - goto ret; - } - break; - default: - err = USBD_IOERROR; - goto ret; - } - xfer->actlen = totlen; - err = USBD_NORMAL_COMPLETION; - ret: - xfer->status = err; - s = splusb(); - uhci_transfer_complete(xfer); - splx(s); - return (USBD_IN_PROGRESS); -} - -/* Abort a root control request. */ -void -uhci_root_ctrl_abort(usbd_xfer_handle xfer) -{ - /* Nothing to do, all transfers are synchronous. */ -} - -/* Close the root pipe. */ -void -uhci_root_ctrl_close(usbd_pipe_handle pipe) -{ - DPRINTF(("uhci_root_ctrl_close\n")); -} - -/* Abort a root interrupt request. */ -void -uhci_root_intr_abort(usbd_xfer_handle xfer) -{ - uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus; - - callout_stop(&sc->sc_poll_handle); - sc->sc_intr_xfer = NULL; - - if (xfer->pipe->intrxfer == xfer) { - DPRINTF(("uhci_root_intr_abort: remove\n")); - xfer->pipe->intrxfer = 0; - } - xfer->status = USBD_CANCELLED; -#ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; -#endif - uhci_transfer_complete(xfer); -} - -usbd_status -uhci_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 (otherwise err would be USBD_INPROG), - * so start it first. - */ - return (uhci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue))); -} - -/* Start a transfer on the root interrupt pipe */ -usbd_status -uhci_root_intr_start(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - - DPRINTFN(3, ("uhci_root_intr_start: xfer=%p len=%d flags=%d\n", - xfer, xfer->length, xfer->flags)); - - if (sc->sc_dying) - return (USBD_IOERROR); - - sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval); - callout_reset(&sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, xfer); - sc->sc_intr_xfer = xfer; - return (USBD_IN_PROGRESS); -} - -/* Close the root interrupt pipe. */ -void -uhci_root_intr_close(usbd_pipe_handle pipe) -{ - uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus; - - callout_stop(&sc->sc_poll_handle); - sc->sc_intr_xfer = NULL; - DPRINTF(("uhci_root_intr_close\n")); -} diff --git a/sys/dev/usb/uhci_pci.c b/sys/dev/usb/uhci_pci.c deleted file mode 100644 index 4ee19d6..0000000 --- a/sys/dev/usb/uhci_pci.c +++ /dev/null @@ -1,524 +0,0 @@ -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) 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> -__FBSDID("$FreeBSD$"); - -/* Universal Host Controller Interface - * - * UHCI spec: http://www.intel.com/ - */ - -/* The low level controller code for UHCI has been split into - * PCI probes and UHCI specific code. This was done to facilitate the - * sharing of code between *BSD's - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/queue.h> -#include <sys/bus.h> - -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.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/uhcireg.h> -#include <dev/usb/uhcivar.h> - -#define PCI_UHCI_VENDORID_INTEL 0x8086 -#define PCI_UHCI_VENDORID_VIA 0x1106 - -#define PCI_UHCI_DEVICEID_PIIX3 0x70208086 -static const char *uhci_device_piix3 = "Intel 82371SB (PIIX3) USB controller"; - -#define PCI_UHCI_DEVICEID_PIIX4 0x71128086 -#define PCI_UHCI_DEVICEID_PIIX4E 0x71128086 /* no separate stepping */ -static const char *uhci_device_piix4 = "Intel 82371AB/EB (PIIX4) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH 0x24128086 -static const char *uhci_device_ich = "Intel 82801AA (ICH) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH0 0x24228086 -static const char *uhci_device_ich0 = "Intel 82801AB (ICH0) USB controller"; - -#define PCI_UHCI_DEVICEID_ICH2_A 0x24428086 -static const char *uhci_device_ich2_a = "Intel 82801BA/BAM (ICH2) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH2_B 0x24448086 -static const char *uhci_device_ich2_b = "Intel 82801BA/BAM (ICH2) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH3_A 0x24828086 -static const char *uhci_device_ich3_a = "Intel 82801CA/CAM (ICH3) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH3_B 0x24848086 -static const char *uhci_device_ich3_b = "Intel 82801CA/CAM (ICH3) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH3_C 0x24878086 -static const char *uhci_device_ich3_c = "Intel 82801CA/CAM (ICH3) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH4_A 0x24c28086 -static const char *uhci_device_ich4_a = "Intel 82801DB (ICH4) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH4_B 0x24c48086 -static const char *uhci_device_ich4_b = "Intel 82801DB (ICH4) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH4_C 0x24c78086 -static const char *uhci_device_ich4_c = "Intel 82801DB (ICH4) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH5_A 0x24d28086 -static const char *uhci_device_ich5_a = "Intel 82801EB (ICH5) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH5_B 0x24d48086 -static const char *uhci_device_ich5_b = "Intel 82801EB (ICH5) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH5_C 0x24d78086 -static const char *uhci_device_ich5_c = "Intel 82801EB (ICH5) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH5_D 0x24de8086 -static const char *uhci_device_ich5_d = "Intel 82801EB (ICH5) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_ICH6_A 0x26588086 -static const char *uhci_device_ich6_a = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH6_B 0x26598086 -static const char *uhci_device_ich6_b = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH6_C 0x265a8086 -static const char *uhci_device_ich6_c = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH6_D 0x265b8086 -static const char *uhci_device_ich6_d = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_63XXESB_1 0x26888086 -static const char *uhci_device_esb_1 = "Intel 631XESB/632XESB/3100 USB controller USB-1"; - -#define PCI_UHCI_DEVICEID_63XXESB_2 0x26898086 -static const char *uhci_device_esb_2 = "Intel 631XESB/632XESB/3100 USB controller USB-2"; - -#define PCI_UHCI_DEVICEID_63XXESB_3 0x268a8086 -static const char *uhci_device_esb_3 = "Intel 631XESB/632XESB/3100 USB controller USB-3"; - -#define PCI_UHCI_DEVICEID_63XXESB_4 0x268b8086 -static const char *uhci_device_esb_4 = "Intel 631XESB/632XESB/3100 USB controller USB-4"; - -#define PCI_UHCI_DEVICEID_ICH8_A 0x28308086 -static const char *uhci_device_ich8_a = "Intel 82801H (ICH8) USB controller USB-A"; - -#define PCI_UHCI_DEVICEID_ICH8_B 0x28318086 -static const char *uhci_device_ich8_b = "Intel 82801H (ICH8) USB controller USB-B"; - -#define PCI_UHCI_DEVICEID_ICH8_C 0x28328086 -static const char *uhci_device_ich8_c = "Intel 82801H (ICH8) USB controller USB-C"; - -#define PCI_UHCI_DEVICEID_ICH8_D 0x28348086 -static const char *uhci_device_ich8_d = "Intel 82801H (ICH8) USB controller USB-D"; - -#define PCI_UHCI_DEVICEID_ICH8_E 0x28358086 -static const char *uhci_device_ich8_e = "Intel 82801H (ICH8) USB controller USB-E"; - -#define PCI_UHCI_DEVICEID_ICH9_A 0x29348086 -#define PCI_UHCI_DEVICEID_ICH9_B 0x29358086 -#define PCI_UHCI_DEVICEID_ICH9_C 0x29368086 -#define PCI_UHCI_DEVICEID_ICH9_D 0x29378086 -#define PCI_UHCI_DEVICEID_ICH9_E 0x29388086 -#define PCI_UHCI_DEVICEID_ICH9_F 0x29398086 -static const char *uhci_device_ich9 = "Intel 82801I (ICH9) USB controller"; - -#define PCI_UHCI_DEVICEID_440MX 0x719a8086 -static const char *uhci_device_440mx = "Intel 82443MX USB controller"; - -#define PCI_UHCI_DEVICEID_460GX 0x76028086 -static const char *uhci_device_460gx = "Intel 82372FB/82468GX USB controller"; - -#define PCI_UHCI_DEVICEID_VT83C572 0x30381106 -static const char *uhci_device_vt83c572 = "VIA 83C572 USB controller"; - -static const char *uhci_device_generic = "UHCI (generic) USB controller"; - -#define PCI_UHCI_BASE_REG 0x20 - - -static device_attach_t uhci_pci_attach; -static device_detach_t uhci_pci_detach; -static device_suspend_t uhci_pci_suspend; -static device_resume_t uhci_pci_resume; - -static int -uhci_pci_suspend(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - int err; - - err = bus_generic_suspend(self); - if (err) - return err; - uhci_power(PWR_SUSPEND, sc); - - return 0; -} - -static int -uhci_pci_resume(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - - pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); - - uhci_power(PWR_RESUME, sc); - bus_generic_resume(self); - - return 0; -} - -static const char * -uhci_pci_match(device_t self) -{ - u_int32_t device_id = pci_get_devid(self); - - if (device_id == PCI_UHCI_DEVICEID_PIIX3) { - return (uhci_device_piix3); - } else if (device_id == PCI_UHCI_DEVICEID_PIIX4) { - return (uhci_device_piix4); - } else if (device_id == PCI_UHCI_DEVICEID_ICH) { - return (uhci_device_ich); - } else if (device_id == PCI_UHCI_DEVICEID_ICH0) { - return (uhci_device_ich0); - } else if (device_id == PCI_UHCI_DEVICEID_ICH2_A) { - return (uhci_device_ich2_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH2_B) { - return (uhci_device_ich2_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_A) { - return (uhci_device_ich3_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_B) { - return (uhci_device_ich3_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH3_C) { - return (uhci_device_ich3_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_A) { - return (uhci_device_ich4_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_B) { - return (uhci_device_ich4_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH4_C) { - return (uhci_device_ich4_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_A) { - return (uhci_device_ich5_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_B) { - return (uhci_device_ich5_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_C) { - return (uhci_device_ich5_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH5_D) { - return (uhci_device_ich5_d); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_A) { - return (uhci_device_ich6_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_B) { - return (uhci_device_ich6_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_C) { - return (uhci_device_ich6_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH6_D) { - return (uhci_device_ich6_d); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_1) { - return (uhci_device_esb_1); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_2) { - return (uhci_device_esb_2); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_3) { - return (uhci_device_esb_3); - } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_4) { - return (uhci_device_esb_4); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_A) { - return (uhci_device_ich8_a); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_B) { - return (uhci_device_ich8_b); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_C) { - return (uhci_device_ich8_c); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_D) { - return (uhci_device_ich8_d); - } else if (device_id == PCI_UHCI_DEVICEID_ICH8_E) { - return (uhci_device_ich8_e); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_A) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_B) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_C) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_D) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_E) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_ICH9_F) { - return (uhci_device_ich9); - } else if (device_id == PCI_UHCI_DEVICEID_440MX) { - return (uhci_device_440mx); - } else if (device_id == PCI_UHCI_DEVICEID_460GX) { - return (uhci_device_460gx); - } else if (device_id == PCI_UHCI_DEVICEID_VT83C572) { - return (uhci_device_vt83c572); - } else { - if (pci_get_class(self) == PCIC_SERIALBUS - && pci_get_subclass(self) == PCIS_SERIALBUS_USB - && pci_get_progif(self) == PCI_INTERFACE_UHCI) { - return (uhci_device_generic); - } - } - - return NULL; /* dunno... */ -} - -static int -uhci_pci_probe(device_t self) -{ - const char *desc = uhci_pci_match(self); - - if (desc) { - device_set_desc(self, desc); - return BUS_PROBE_DEFAULT; - } else { - return ENXIO; - } -} - -static int -uhci_pci_attach(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - int rid; - int err; - - pci_enable_busmaster(self); - - rid = PCI_UHCI_BASE_REG; - sc->io_res = bus_alloc_resource_any(self, SYS_RES_IOPORT, &rid, - RF_ACTIVE); - if (!sc->io_res) { - device_printf(self, "Could not map ports\n"); - return ENXIO; - } - sc->iot = rman_get_bustag(sc->io_res); - sc->ioh = rman_get_bushandle(sc->io_res); - - /* disable interrupts */ - bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0); - - rid = 0; - sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->irq_res == NULL) { - device_printf(self, "Could not allocate irq\n"); - uhci_pci_detach(self); - return ENXIO; - } - sc->sc_bus.bdev = device_add_child(self, "usb", -1); - if (!sc->sc_bus.bdev) { - device_printf(self, "Could not add USB device\n"); - uhci_pci_detach(self); - return ENOMEM; - } - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - /* uhci_pci_match must never return NULL if uhci_pci_probe succeeded */ - device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self)); - switch (pci_get_vendor(self)) { - case PCI_UHCI_VENDORID_INTEL: - sprintf(sc->sc_vendor, "Intel"); - break; - case PCI_UHCI_VENDORID_VIA: - sprintf(sc->sc_vendor, "VIA"); - break; - default: - if (bootverbose) - device_printf(self, "(New UHCI DeviceId=0x%08x)\n", - pci_get_devid(self)); - sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); - } - - switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) { - case PCI_USBREV_PRE_1_0: - sc->sc_bus.usbrev = USBREV_PRE_1_0; - break; - case PCI_USBREV_1_0: - sc->sc_bus.usbrev = USBREV_1_0; - break; - default: - sc->sc_bus.usbrev = USBREV_UNKNOWN; - break; - } - - /* - * Quirk for Parallels Desktop 4.0. - */ - if (pci_get_devid(self) == PCI_UHCI_DEVICEID_ICH6_A) - sc->sc_bus.usbrev = USBREV_2_0; - - err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, - NULL, (driver_intr_t *) uhci_intr, sc, &sc->ih); - if (err) { - device_printf(self, "Could not setup irq, %d\n", err); - sc->ih = NULL; - uhci_pci_detach(self); - return ENXIO; - } - /* - * Set the PIRQD enable bit and switch off all the others. We don't - * want legacy support to interfere with us XXX Does this also mean - * that the BIOS won't touch the keyboard anymore if it is connected - * to the ports of the root hub? - */ -#ifdef USB_DEBUG - if (pci_read_config(self, PCI_LEGSUP, 2) != PCI_LEGSUP_USBPIRQDEN) - device_printf(self, "LegSup = 0x%04x\n", - pci_read_config(self, PCI_LEGSUP, 2)); -#endif - pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2); - - /* Allocate a parent dma tag for DMA maps */ - err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - NULL, NULL, &sc->sc_bus.parent_dmatag); - if (err) { - device_printf(self, "Could not allocate parent DMA tag (%d)\n", - err); - uhci_pci_detach(self); - return ENXIO; - } - /* Allocate a dma tag for transfer buffers */ - err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0, - busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag); - if (err) { - device_printf(self, "Could not allocate transfer tag (%d)\n", - err); - uhci_pci_detach(self); - return ENXIO; - } - - err = uhci_init(sc); - if (!err) { - sc->sc_flags |= UHCI_SCFLG_DONEINIT; - err = device_probe_and_attach(sc->sc_bus.bdev); - } - - if (err) { - device_printf(self, "USB init failed\n"); - uhci_pci_detach(self); - return EIO; - } - return 0; /* success */ -} - -int -uhci_pci_detach(device_t self) -{ - uhci_softc_t *sc = device_get_softc(self); - - if (sc->sc_flags & UHCI_SCFLG_DONEINIT) { - uhci_detach(sc, 0); - sc->sc_flags &= ~UHCI_SCFLG_DONEINIT; - } - - if (sc->sc_bus.parent_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.parent_dmatag); - if (sc->sc_bus.buffer_dmatag != NULL) - bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag); - - if (sc->irq_res && sc->ih) { - int err = bus_teardown_intr(self, sc->irq_res, sc->ih); - - if (err) - /* XXX or should we panic? */ - device_printf(self, "Could not tear down irq, %d\n", - err); - sc->ih = NULL; - } - if (sc->sc_bus.bdev) { - device_delete_child(self, sc->sc_bus.bdev); - sc->sc_bus.bdev = NULL; - } - if (sc->irq_res) { - bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); - sc->irq_res = NULL; - } - if (sc->io_res) { - bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG, - sc->io_res); - sc->io_res = NULL; - sc->iot = 0; - sc->ioh = 0; - } - return 0; -} - - -static device_method_t uhci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uhci_pci_probe), - DEVMETHOD(device_attach, uhci_pci_attach), - DEVMETHOD(device_detach, uhci_pci_detach), - DEVMETHOD(device_suspend, uhci_pci_suspend), - DEVMETHOD(device_resume, uhci_pci_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - {0, 0} -}; - -static driver_t uhci_driver = { - "uhci", - uhci_methods, - sizeof(uhci_softc_t), -}; - -static devclass_t uhci_devclass; - -DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0); -DRIVER_MODULE(uhci, cardbus, uhci_driver, uhci_devclass, 0, 0); -MODULE_DEPEND(uhci, usb, 1, 1, 1); diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h deleted file mode 100644 index 512dd2d..0000000 --- a/sys/dev/usb/uhcireg.h +++ /dev/null @@ -1,193 +0,0 @@ -/* $NetBSD: uhcireg.h,v 1.15 2002/02/11 11:41:30 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _DEV_PCI_UHCIREG_H_ -#define _DEV_PCI_UHCIREG_H_ - -/*** PCI config registers ***/ - -#define PCI_USBREV 0x60 /* 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_LEGSUP 0xc0 /* Legacy Support register */ -#define PCI_LEGSUP_USBPIRQDEN 0x2000 /* USB PIRQ D Enable */ - -#define PCI_CBIO 0x20 /* configuration base IO */ - -#define PCI_INTERFACE_UHCI 0x00 - -/*** UHCI registers ***/ - -#define UHCI_CMD 0x00 -#define UHCI_CMD_RS 0x0001 -#define UHCI_CMD_HCRESET 0x0002 -#define UHCI_CMD_GRESET 0x0004 -#define UHCI_CMD_EGSM 0x0008 -#define UHCI_CMD_FGR 0x0010 -#define UHCI_CMD_SWDBG 0x0020 -#define UHCI_CMD_CF 0x0040 -#define UHCI_CMD_MAXP 0x0080 - -#define UHCI_STS 0x02 -#define UHCI_STS_USBINT 0x0001 -#define UHCI_STS_USBEI 0x0002 -#define UHCI_STS_RD 0x0004 -#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 -#define UHCI_INTR_RIE 0x0002 -#define UHCI_INTR_IOCE 0x0004 -#define UHCI_INTR_SPIE 0x0008 - -#define UHCI_FRNUM 0x06 -#define UHCI_FRNUM_MASK 0x03ff - -#define UHCI_FLBASEADDR 0x08 - -#define UHCI_SOF 0x0c -#define UHCI_SOF_MASK 0x7f - -#define UHCI_PORTSC1 0x010 -#define UHCI_PORTSC2 0x012 -#define UHCI_PORTSC_CCS 0x0001 -#define UHCI_PORTSC_CSC 0x0002 -#define UHCI_PORTSC_PE 0x0004 -#define UHCI_PORTSC_POEDC 0x0008 -#define UHCI_PORTSC_LS 0x0030 -#define UHCI_PORTSC_LS_SHIFT 4 -#define UHCI_PORTSC_RD 0x0040 -#define UHCI_PORTSC_LSDA 0x0100 -#define UHCI_PORTSC_PR 0x0200 -#define UHCI_PORTSC_OCI 0x0400 -#define UHCI_PORTSC_OCIC 0x0800 -#define UHCI_PORTSC_SUSP 0x1000 - -#define URWMASK(x) \ - ((x) & (UHCI_PORTSC_SUSP | UHCI_PORTSC_PR | UHCI_PORTSC_RD | UHCI_PORTSC_PE)) - -#define UHCI_FRAMELIST_COUNT 1024 -#define UHCI_FRAMELIST_ALIGN 4096 - -#define UHCI_TD_ALIGN 16 -#define UHCI_QH_ALIGN 16 - -typedef u_int32_t uhci_physaddr_t; -#define UHCI_PTR_T 0x00000001 -#define UHCI_PTR_TD 0x00000000 -#define UHCI_PTR_QH 0x00000002 -#define UHCI_PTR_VF 0x00000004 - -/* - * Wait this long after a QH has been removed. This gives that HC a - * chance to stop looking at it before it's recycled. - */ -#define UHCI_QH_REMOVE_DELAY 5 - -/* - * The Queue Heads and Transfer Descriptors are accessed - * by both the CPU and the USB controller which run - * concurrently. This means that they have to be accessed - * with great care. As long as the data structures are - * not linked into the controller's frame list they cannot - * be accessed by it and anything goes. As soon as a - * TD is accessible by the controller it "owns" the td_status - * field; it will not be written by the CPU. Similarly - * the controller "owns" the qh_elink field. - */ - -typedef struct { - uhci_physaddr_t td_link; - u_int32_t td_status; -#define UHCI_TD_GET_ACTLEN(s) (((s) + 1) & 0x3ff) -#define UHCI_TD_ZERO_ACTLEN(t) ((t) | 0x3ff) -#define UHCI_TD_BITSTUFF 0x00020000 -#define UHCI_TD_CRCTO 0x00040000 -#define UHCI_TD_NAK 0x00080000 -#define UHCI_TD_BABBLE 0x00100000 -#define UHCI_TD_DBUFFER 0x00200000 -#define UHCI_TD_STALLED 0x00400000 -#define UHCI_TD_ACTIVE 0x00800000 -#define UHCI_TD_IOC 0x01000000 -#define UHCI_TD_IOS 0x02000000 -#define UHCI_TD_LS 0x04000000 -#define UHCI_TD_GET_ERRCNT(s) (((s) >> 27) & 3) -#define UHCI_TD_SET_ERRCNT(n) ((n) << 27) -#define UHCI_TD_SPD 0x20000000 - u_int32_t td_token; -#define UHCI_TD_PID_IN 0x00000069 -#define UHCI_TD_PID_OUT 0x000000e1 -#define UHCI_TD_PID_SETUP 0x0000002d -#define UHCI_TD_GET_PID(s) ((s) & 0xff) -#define UHCI_TD_SET_DEVADDR(a) ((a) << 8) -#define UHCI_TD_GET_DEVADDR(s) (((s) >> 8) & 0x7f) -#define UHCI_TD_SET_ENDPT(e) (((e)&0xf) << 15) -#define UHCI_TD_GET_ENDPT(s) (((s) >> 15) & 0xf) -#define UHCI_TD_SET_DT(t) ((t) << 19) -#define UHCI_TD_GET_DT(s) (((s) >> 19) & 1) -#define UHCI_TD_SET_MAXLEN(l) (((l)-1) << 21) -#define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff) -#define UHCI_TD_MAXLEN_MASK 0xffe00000 - u_int32_t td_buffer; -} uhci_td_t; - -#define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED) - -#define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP) -#define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | \ - UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt)) -#define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \ - UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | \ - UHCI_TD_SET_DT(dt)) - -typedef struct { - uhci_physaddr_t qh_hlink; - uhci_physaddr_t qh_elink; -} uhci_qh_t; - -#endif /* _DEV_PCI_UHCIREG_H_ */ diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h deleted file mode 100644 index 0df23f1..0000000 --- a/sys/dev/usb/uhcivar.h +++ /dev/null @@ -1,206 +0,0 @@ -/* $NetBSD: uhcivar.h,v 1.33 2002/02/11 11:41:30 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -/* - * To avoid having 1024 TDs for each isochronous transfer we introduce - * a virtual frame list. Every UHCI_VFRAMELIST_COUNT entries in the real - * frame list points to a non-active TD. These, in turn, form the - * starts of the virtual frame list. This also has the advantage that it - * simplifies linking in/out of TDs/QHs in the schedule. - * Furthermore, initially each of the inactive TDs point to an inactive - * QH that forms the start of the interrupt traffic for that slot. - * Each of these QHs point to the same QH that is the start of control - * traffic. This QH points at another QH which is the start of the - * bulk traffic. - * - * UHCI_VFRAMELIST_COUNT should be a power of 2 and <= UHCI_FRAMELIST_COUNT. - */ -#define UHCI_VFRAMELIST_COUNT 128 - -typedef struct uhci_soft_qh uhci_soft_qh_t; -typedef struct uhci_soft_td uhci_soft_td_t; - -typedef union { - struct uhci_soft_qh *sqh; - struct uhci_soft_td *std; -} uhci_soft_td_qh_t; - -/* - * An interrupt info struct contains the information needed to - * execute a requested routine when the controller generates an - * interrupt. Since we cannot know which transfer generated - * the interrupt all structs are linked together so they can be - * searched at interrupt time. - */ -typedef struct uhci_intr_info { - struct uhci_softc *sc; - usbd_xfer_handle xfer; - uhci_soft_td_t *stdstart; - uhci_soft_td_t *stdend; - LIST_ENTRY(uhci_intr_info) list; -#ifdef DIAGNOSTIC - int isdone; -#endif -} uhci_intr_info_t; - -struct uhci_xfer { - struct usbd_xfer xfer; - uhci_intr_info_t iinfo; - struct usb_task abort_task; - int curframe; - u_int32_t uhci_xfer_flags; -}; - -#define UHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ -#define UHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ - -#define UXFER(xfer) ((struct uhci_xfer *)(xfer)) - -/* - * Extra information that we need for a TD. - */ -struct uhci_soft_td { - uhci_td_t td; /* The real TD, must be first */ - uhci_soft_td_qh_t link; /* soft version of the td_link field */ - uhci_physaddr_t physaddr; /* TD's physical address. */ - usb_dma_t aux_dma; /* Auxillary storage if needed. */ - void *aux_data; /* Original aux data virtual address. */ - int aux_len; /* Auxillary storage size. */ -}; -/* - * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way - * we can pack a number of soft TD together and have the real TD well - * aligned. - * NOTE: Minimum size is 32 bytes. - */ -#define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN) -#define UHCI_STD_CHUNK (PAGE_SIZE / UHCI_STD_SIZE) - -/* - * Extra information that we need for a QH. - */ -struct uhci_soft_qh { - uhci_qh_t qh; /* The real QH, must be first */ - uhci_soft_qh_t *hlink; /* soft version of qh_hlink */ - uhci_soft_td_t *elink; /* soft version of qh_elink */ - uhci_physaddr_t physaddr; /* QH's physical address. */ - int pos; /* Timeslot position */ -}; -/* See comment about UHCI_STD_SIZE. */ -#define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN) -#define UHCI_SQH_CHUNK (PAGE_SIZE / UHCI_SQH_SIZE) - -/* - * Information about an entry in the virtual frame list. - */ -struct uhci_vframe { - uhci_soft_td_t *htd; /* pointer to dummy TD */ - uhci_soft_td_t *etd; /* pointer to last TD */ - uhci_soft_qh_t *hqh; /* pointer to dummy QH */ - uhci_soft_qh_t *eqh; /* pointer to last QH */ - u_int bandwidth; /* max bandwidth used by this frame */ -}; - -#define UHCI_SCFLG_DONEINIT 0x0001 /* uhci_init() done */ - -typedef struct uhci_softc { - struct usbd_bus sc_bus; /* base device */ - int sc_flags; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_size_t sc_size; - void *ih; - - struct resource *io_res; - struct resource *irq_res; - uhci_physaddr_t *sc_pframes; - usb_dma_t sc_dma; - struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT]; - - uhci_soft_qh_t *sc_lctl_start; /* dummy QH for low speed control */ - uhci_soft_qh_t *sc_lctl_end; /* last control QH */ - uhci_soft_qh_t *sc_hctl_start; /* dummy QH for high speed control */ - uhci_soft_qh_t *sc_hctl_end; /* last control QH */ - uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */ - uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */ - uhci_soft_qh_t *sc_last_qh; /* dummy QH at the end */ - u_int32_t sc_loops; /* number of QHs that wants looping */ - - uhci_soft_td_t *sc_freetds; /* TD free list */ - uhci_soft_qh_t *sc_freeqhs; /* QH free list */ - - STAILQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */ - - u_int8_t sc_addr; /* device address */ - u_int8_t sc_conf; /* device configuration */ - - u_int8_t sc_saved_sof; - u_int16_t sc_saved_frnum; - -#ifdef USB_USE_SOFTINTR - char sc_softwake; -#endif /* USB_USE_SOFTINTR */ - - char sc_isreset; - char sc_suspend; - char sc_dying; - - LIST_HEAD(, uhci_intr_info) sc_intrhead; - - /* Info for the root hub interrupt channel. */ - int sc_ival; /* time between root hub intrs */ - usbd_xfer_handle sc_intr_xfer; /* root hub interrupt transfer */ - struct callout sc_poll_handle; - - char sc_vendor[16]; /* vendor string for root hub */ - int sc_id_vendor; /* vendor ID for root hub */ - -#if defined(__NetBSD__) - void *sc_powerhook; /* cookie from power hook */ - void *sc_shutdownhook; /* cookie from shutdown hook */ -#endif -} uhci_softc_t; - -usbd_status uhci_init(uhci_softc_t *); -int uhci_intr(void *); -int uhci_detach(uhci_softc_t *, int); -void uhci_shutdown(void *v); -void uhci_power(int state, void *priv); - diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c deleted file mode 100644 index d821c01..0000000 --- a/sys/dev/usb/uhid.c +++ /dev/null @@ -1,755 +0,0 @@ -/* $NetBSD: uhid.c,v 1.46 2001/11/13 06:24:55 lukem Exp $ */ - -/* Also already merged from NetBSD: - * $NetBSD: uhid.c,v 1.54 2002/09/23 05:51:21 simonb Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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/devclass_docs/HID1_11.pdf - */ - -/* - * XXX TODO: Convert this driver to use si_drv[12] rather than the - * devclass_get_softc junk - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/clist.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/signalvar.h> -#include <sys/fcntl.h> -#include <sys/ioccom.h> -#include <sys/filio.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/conf.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/ttycom.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include "usbdevs.h" -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/hid.h> - -/* Replacement report descriptors for devices shipped with broken ones */ -#include <dev/usb/ugraphire_rdesc.h> -#include <dev/usb/uxb360gp_rdesc.h> - -/* For hid blacklist quirk */ -#include <dev/usb/usb_quirks.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uhiddebug) printf x -#define DPRINTFN(n,x) if (uhiddebug>(n)) printf x -int uhiddebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhid, CTLFLAG_RW, 0, "USB uhid"); -SYSCTL_INT(_hw_usb_uhid, OID_AUTO, debug, CTLFLAG_RW, - &uhiddebug, 0, "uhid debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct uhid_softc { - device_t 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; - struct proc *sc_async; /* process that wants SIGIO */ - u_char sc_state; /* driver state */ -#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; - - struct cdev *dev; -}; - -#define UHIDUNIT(dev) (dev2unit(dev)) -#define UHID_CHUNK 128 /* chunk size for read */ -#define UHID_BSIZE 1020 /* buffer size */ - -d_open_t uhidopen; -d_close_t uhidclose; -d_read_t uhidread; -d_write_t uhidwrite; -d_ioctl_t uhidioctl; -d_poll_t uhidpoll; - - -static struct cdevsw uhid_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = uhidopen, - .d_close = uhidclose, - .d_read = uhidread, - .d_write = uhidwrite, - .d_ioctl = uhidioctl, - .d_poll = uhidpoll, - .d_name = "uhid", -}; - -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, - struct thread *); - -MODULE_DEPEND(uhid, usb, 1, 1, 1); - -static device_probe_t uhid_match; -static device_attach_t uhid_attach; -static device_detach_t uhid_detach; - -static device_method_t uhid_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uhid_match), - DEVMETHOD(device_attach, uhid_attach), - DEVMETHOD(device_detach, uhid_detach), - - { 0, 0 } -}; - -static driver_t uhid_driver = { - "uhid", - uhid_methods, - sizeof(struct uhid_softc) -}; - -static devclass_t uhid_devclass; - -DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0); - -static int -uhid_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL) - return (UMATCH_NONE); - if (id->bInterfaceClass != UICLASS_HID) { - /* The Xbox 360 gamepad doesn't use the HID class. */ - if (id->bInterfaceClass != UICLASS_VENDOR || - id->bInterfaceSubClass != UISUBCLASS_XBOX360_CONTROLLER || - id->bInterfaceProtocol != UIPROTO_XBOX360_GAMEPAD) - return (UMATCH_NONE); - } - if (usbd_get_quirks(uaa->device)->uq_flags & UQ_HID_IGNORE) - return (UMATCH_NONE); -#if 0 - if (uaa->matchlvl) - return (uaa->matchlvl); -#endif - - return (UMATCH_IFACECLASS_GENERIC); -} - -static int -uhid_attach(device_t self) -{ - struct uhid_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int size; - void *desc; - const void *descptr; - usbd_status err; - - sc->sc_dev = self; - sc->sc_udev = uaa->device; - sc->sc_iface = iface; - id = usbd_get_interface_descriptor(iface); - - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == NULL) { - printf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - 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", device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - sc->sc_ep_addr = ed->bEndpointAddress; - - descptr = NULL; - if (uaa->vendor == USB_VENDOR_WACOM) { - /* The report descriptor for the Wacom Graphire is broken. */ - if (uaa->product == USB_PRODUCT_WACOM_GRAPHIRE) { - size = sizeof uhid_graphire_report_descr; - descptr = uhid_graphire_report_descr; - } else if (uaa->product == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) { - static uByte reportbuf[] = {2, 2, 2}; - - /* - * The Graphire3 needs 0x0202 to be written to - * feature report ID 2 before it'll start - * returning digitizer data. - */ - usbd_set_report(uaa->iface, UHID_FEATURE_REPORT, 2, - &reportbuf, sizeof reportbuf); - - size = sizeof uhid_graphire3_4x5_report_descr; - descptr = uhid_graphire3_4x5_report_descr; - } - } else if (id->bInterfaceClass == UICLASS_VENDOR && - id->bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER && - id->bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD) { - static uByte reportbuf[] = {1, 3, 0}; - - /* The LEDs on the gamepad are blinking by default, turn off. */ - usbd_set_report(uaa->iface, UHID_OUTPUT_REPORT, 0, - &reportbuf, sizeof reportbuf); - - /* The Xbox 360 gamepad has no report descriptor. */ - size = sizeof uhid_xb360gp_report_descr; - descptr = uhid_xb360gp_report_descr; - } - - if (descptr) { - desc = malloc(size, M_USBDEV, M_NOWAIT); - if (desc == NULL) - err = USBD_NOMEM; - else { - err = USBD_NORMAL_COMPLETION; - memcpy(desc, descptr, size); - } - } else { - desc = NULL; - err = usbd_read_report_desc(uaa->iface, &desc, &size,M_USBDEV); - } - - if (err) { - printf("%s: no report descriptor\n", device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - (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); - - sc->sc_repdesc = desc; - sc->sc_repdesc_size = size; - sc->dev = make_dev(&uhid_cdevsw, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "uhid%d", device_get_unit(self)); - return 0; -} - -static int -uhid_detach(device_t self) -{ - struct uhid_softc *sc = device_get_softc(self); - int s; - - DPRINTF(("uhid_detach: sc=%p\n", sc)); - sc->sc_dying = 1; - if (sc->sc_intrpipe != NULL) - usbd_abort_pipe(sc->sc_intrpipe); - - 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(sc->sc_dev); - } - splx(s); - } - destroy_dev(sc->dev); - - if (sc->sc_repdesc) - free(sc->sc_repdesc, M_USBDEV); - - return (0); -} - -void -uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct uhid_softc *sc = addr; - -#ifdef USB_DEBUG - if (uhiddebug > 5) { - u_int32_t cc, i; - - usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); - DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc)); - DPRINTF(("uhid_intr: data =")); - for (i = 0; i < cc; i++) - DPRINTF((" %02x", sc->sc_ibuf[i])); - DPRINTF(("\n")); - } -#endif - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("uhid_intr: status=%d\n", status)); - if (status == USBD_STALLED) - 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; - DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q)); - wakeup(&sc->sc_q); - } - selwakeuppri(&sc->sc_rsel, PZERO); - if (sc->sc_async != NULL) { - DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async)); - PROC_LOCK(sc->sc_async); - psignal(sc->sc_async, SIGIO); - PROC_UNLOCK(sc->sc_async); - } -} - -int -uhidopen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct uhid_softc *sc; - usbd_status err; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - DPRINTF(("uhidopen: sc=%p\n", sc)); - - if (sc->sc_dying) - return (ENXIO); - - if (sc->sc_state & UHID_OPEN) - return (EBUSY); - sc->sc_state |= UHID_OPEN; - - clist_alloc_cblocks(&sc->sc_q, UHID_BSIZE, UHID_BSIZE); - 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_ibuf = sc->sc_obuf = NULL; - - sc->sc_state &= ~UHID_OPEN; - return (EIO); - } - - sc->sc_state &= ~UHID_IMMED; - - sc->sc_async = 0; - - return (0); -} - -int -uhidclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct uhid_softc *sc; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - - DPRINTF(("uhidclose: sc=%p\n", sc)); - - /* Disable interrupts. */ - usbd_abort_pipe(sc->sc_intrpipe); - usbd_close_pipe(sc->sc_intrpipe); - sc->sc_intrpipe = 0; - - ndflush(&sc->sc_q, sc->sc_q.c_cc); - clist_free_cblocks(&sc->sc_q); - - free(sc->sc_ibuf, M_USBDEV); - free(sc->sc_obuf, M_USBDEV); - sc->sc_ibuf = sc->sc_obuf = NULL; - - sc->sc_state &= ~UHID_OPEN; - - sc->sc_async = 0; - - return (0); -} - -int -uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag) -{ - int s; - int error = 0; - size_t length; - u_char buffer[UHID_CHUNK]; - usbd_status err; - - DPRINTFN(1, ("uhidread\n")); - if (sc->sc_state & UHID_IMMED) { - DPRINTFN(1, ("uhidread immed\n")); - - err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, buffer, sc->sc_isize); - if (err) - return (EIO); - return (uiomove(buffer, sc->sc_isize, uio)); - } - - s = splusb(); - while (sc->sc_q.c_cc == 0) { - if (flag & O_NONBLOCK) { - splx(s); - return (EWOULDBLOCK); - } - sc->sc_state |= UHID_ASLP; - DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q)); - error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0); - DPRINTFN(5, ("uhidread: woke, error=%d\n", error)); - if (sc->sc_dying) - error = EIO; - if (error) { - 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); - - /* Transfer as many chunks as possible. */ - while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) { - length = min(sc->sc_q.c_cc, uio->uio_resid); - if (length > sizeof(buffer)) - length = sizeof(buffer); - - /* Remove a small chunk from the input queue. */ - (void) q_to_b(&sc->sc_q, buffer, length); - DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length)); - - /* Copy the data to the user process. */ - if ((error = uiomove(buffer, length, uio)) != 0) - break; - } - - return (error); -} - -int -uhidread(struct cdev *dev, struct uio *uio, int flag) -{ - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - sc->sc_refcnt++; - error = uhid_do_read(sc, uio, flag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag) -{ - int error; - int size; - usbd_status err; - - DPRINTFN(1, ("uhidwrite\n")); - - if (sc->sc_dying) - return (EIO); - - size = sc->sc_osize; - error = 0; - if (uio->uio_resid != size) - return (EINVAL); - error = uiomove(sc->sc_obuf, size, uio); - if (!error) { - 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; - } - - return (error); -} - -int -uhidwrite(struct cdev *dev, struct uio *uio, int flag) -{ - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - sc->sc_refcnt++; - error = uhid_do_write(sc, uio, flag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr, int flag, - struct thread *p) -{ - struct usb_ctl_report_desc *rd; - struct usb_ctl_report *re; - int size, id; - usbd_status err; - - DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd)); - - if (sc->sc_dying) - return (EIO); - - switch (cmd) { - case FIONBIO: - /* All handled in the upper FS layer. */ - break; - - case FIOASYNC: - if (*(int *)addr) { - if (sc->sc_async != NULL) - return (EBUSY); - sc->sc_async = p->td_proc; - DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", sc->sc_async)); - } else - sc->sc_async = NULL; - break; - - /* XXX this is not the most general solution. */ - case TIOCSPGRP: - if (sc->sc_async == NULL) - return (EINVAL); - if (*(int *)addr != sc->sc_async->p_pgid) - return (EPERM); - break; - - case USB_GET_REPORT_DESC: - rd = (struct usb_ctl_report_desc *)addr; - size = min(sc->sc_repdesc_size, sizeof rd->ucrd_data); - rd->ucrd_size = size; - memcpy(rd->ucrd_data, sc->sc_repdesc, size); - break; - - case USB_SET_IMMED: - if (*(int *)addr) { - /* XXX should read into ibuf, but does it matter? */ - err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT, - sc->sc_iid, sc->sc_ibuf, sc->sc_isize); - if (err) - return (EOPNOTSUPP); - - sc->sc_state |= UHID_IMMED; - } else - sc->sc_state &= ~UHID_IMMED; - break; - - case USB_GET_REPORT: - re = (struct usb_ctl_report *)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 = usbd_get_report(sc->sc_iface, re->ucr_report, id, re->ucr_data, - size); - if (err) - return (EIO); - break; - - case USB_SET_REPORT: - re = (struct usb_ctl_report *)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 = 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 = 0; /* XXX: we only support reportid 0? */ - break; - - default: - return (EINVAL); - } - return (0); -} - -int -uhidioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *p) -{ - struct uhid_softc *sc; - int error; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - sc->sc_refcnt++; - error = uhid_do_ioctl(sc, cmd, addr, flag, p); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -uhidpoll(struct cdev *dev, int events, struct thread *p) -{ - struct uhid_softc *sc; - int revents = 0; - int s; - - sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev)); - if (sc->sc_dying) - return (EIO); - - s = splusb(); - if (events & (POLLOUT | POLLWRNORM)) - revents |= events & (POLLOUT | POLLWRNORM); - if (events & (POLLIN | POLLRDNORM)) { - if (sc->sc_q.c_cc > 0) - revents |= events & (POLLIN | POLLRDNORM); - else - selrecord(p, &sc->sc_rsel); - } - - splx(s); - return (revents); -} diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c deleted file mode 100644 index 86fbba2..0000000 --- a/sys/dev/usb/uhub.c +++ /dev/null @@ -1,703 +0,0 @@ -/* $NetBSD: uhub.c,v 1.68 2004/06/29 06:30:05 mycroft Exp $ */ - -/*- - * Copyright (c) 1998 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> -__FBSDID("$FreeBSD$"); - -/* - * USB spec: http://www.usb.org/developers/docs/usbspec.zip - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/sysctl.h> - -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> - -#define UHUB_INTR_INTERVAL 255 /* ms */ - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uhubdebug) printf x -#define DPRINTFN(n,x) if (uhubdebug > (n)) printf x -#define DEVPRINTF(x) if (uhubdebug) device_printf x -#define DEVPRINTFN(n, x)if (uhubdebug > (n)) device_printf x -int uhubdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB uhub"); -SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW, - &uhubdebug, 0, "uhub debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#define DEVPRINTF(x) -#define DEVPRINTFN(n,x) -#endif - -struct uhub_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_hub; /* USB device */ - usbd_pipe_handle sc_ipipe; /* interrupt pipe */ - u_int8_t sc_status[32]; /* max 255 ports */ - u_char sc_running; -}; -#define UHUB_PROTO(sc) ((sc)->sc_hub->ddesc.bDeviceProtocol) -#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB) -#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT) - -static usbd_status uhub_explore(usbd_device_handle hub); -static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status); - -/* - * We need two attachment points: - * hub to usb and hub to hub - * Every other driver only connects to hubs - */ - -static device_probe_t uhub_match; -static device_attach_t uhub_attach; -static device_detach_t uhub_detach; -static bus_child_location_str_t uhub_child_location_str; -static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str; - -static device_method_t uhub_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uhub_match), - DEVMETHOD(device_attach, uhub_attach), - DEVMETHOD(device_detach, uhub_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str), - DEVMETHOD(bus_child_location_str, uhub_child_location_str), - /* XXX driver_added needs special care */ - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - { 0, 0 } -}; - -static driver_t uhub_driver = { - "uhub", - uhub_methods, - sizeof(struct uhub_softc) -}; - -static devclass_t uhub_devclass; - -/* Create the driver instance for the hub connected to usb case. */ -devclass_t uhubroot_devclass; - -static device_method_t uhubroot_methods[] = { - DEVMETHOD(device_probe, uhub_match), - DEVMETHOD(device_attach, uhub_attach), - DEVMETHOD(device_detach, uhub_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD(bus_child_location_str, uhub_child_location_str), - DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str), - /* XXX driver_added needs special care */ - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - - {0,0} -}; - -static driver_t uhubroot_driver = { - "uhub", - uhubroot_methods, - sizeof(struct uhub_softc) -}; - -static int -uhub_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); - - DPRINTFN(5,("uhub_match, dd=%p\n", dd)); - /* - * The subclass for hubs seems to be 0 for some and 1 for others, - * so we just ignore the subclass. - */ - if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB) - return (UMATCH_DEVCLASS_DEVSUBCLASS); - return (UMATCH_NONE); -} - -int -uhub_attach(device_t self) -{ - struct uhub_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_status err; - struct usbd_hub *hub = NULL; - usb_device_request_t req; - usb_hub_descriptor_t hubdesc; - int p, port, nports, nremov, pwrdly; - usbd_interface_handle iface; - usb_endpoint_descriptor_t *ed; - struct usbd_tt *tts = NULL; - - DPRINTFN(1,("uhub_attach\n")); - sc->sc_hub = dev; - sc->sc_dev = self; - - if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) { - device_printf(sc->sc_dev, "%s transaction translator%s\n", - UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple", - UHUB_IS_SINGLE_TT(sc) ? "" : "s"); - } - err = usbd_set_config_index(dev, 0, 1); - if (err) { - DEVPRINTF((sc->sc_dev, "configuration failed, error=%s\n", - usbd_errstr(err))); - return (ENXIO); - } - - if (dev->depth > USB_HUB_MAX_DEPTH) { - device_printf(sc->sc_dev, "hub depth (%d) exceeded, hub ignored\n", - USB_HUB_MAX_DEPTH); - return (ENXIO); - } - - /* Get hub descriptor. */ - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, (dev->address > 1 ? UDESC_HUB : 0), 0); - USETW(req.wIndex, 0); - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); - DPRINTFN(1,("usb_init_hub: getting hub descriptor\n")); - err = usbd_do_request(dev, &req, &hubdesc); - nports = hubdesc.bNbrPorts; - if (!err && nports > 7) { - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8); - err = usbd_do_request(dev, &req, &hubdesc); - } - if (err) { - DEVPRINTF((sc->sc_dev, "getting hub descriptor failed: %s\n", - usbd_errstr(err))); - return (ENXIO); - } - - for (nremov = 0, port = 1; port <= nports; port++) - if (!UHD_NOT_REMOV(&hubdesc, port)) - nremov++; - device_printf(sc->sc_dev, "%d port%s with %d removable, %s powered\n", - nports, nports != 1 ? "s" : "", nremov, - dev->self_powered ? "self" : "bus"); - - if (nports == 0) { - device_printf(sc->sc_dev, "no ports, hub ignored\n"); - goto bad; - } - - hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port), - M_USBDEV, M_NOWAIT); - if (hub == NULL) { - return (ENXIO); - } - dev->hub = hub; - dev->hub->hubsoftc = sc; - hub->explore = uhub_explore; - hub->hubdesc = hubdesc; - - DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, " - "parent->selfpowered=%d\n", - dev->self_powered, dev->powersrc->parent, - dev->powersrc->parent ? - dev->powersrc->parent->self_powered : 0)); - - if (!dev->self_powered && dev->powersrc->parent != NULL && - !dev->powersrc->parent->self_powered) { - device_printf(sc->sc_dev, "bus powered hub connected to bus " - "powered hub, ignored\n"); - goto bad; - } - - /* Set up interrupt pipe. */ - err = usbd_device2interface_handle(dev, 0, &iface); - if (err) { - device_printf(sc->sc_dev, "no interface handle\n"); - goto bad; - } - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (ed == NULL) { - device_printf(sc->sc_dev, "no endpoint descriptor\n"); - goto bad; - } - if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - device_printf(sc->sc_dev, "bad interrupt endpoint\n"); - goto bad; - } - - err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, - USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status, - (nports + 1 + 7) / 8, uhub_intr, UHUB_INTR_INTERVAL); - if (err) { - device_printf(sc->sc_dev, "cannot open interrupt pipe\n"); - goto bad; - } - - /* Wait with power off for a while. */ - usbd_delay_ms(dev, USB_POWER_DOWN_TIME); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); - - /* - * To have the best chance of success we do things in the exact same - * order as Windoze98. This should not be necessary, but some - * devices do not follow the USB specs to the letter. - * - * These are the events on the bus when a hub is attached: - * Get device and config descriptors (see attach code) - * Get hub descriptor (see above) - * For all ports - * turn on power - * wait for power to become stable - * (all below happens in explore code) - * For all ports - * clear C_PORT_CONNECTION - * For all ports - * get port status - * if device connected - * wait 100 ms - * turn on reset - * wait - * clear C_PORT_RESET - * get port status - * proceed with device attachment - */ - - if (UHUB_IS_HIGH_SPEED(sc)) { - tts = malloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) * - sizeof (struct usbd_tt), M_USBDEV, M_NOWAIT); - if (!tts) - goto bad; - } - - /* Set up data structures */ - for (p = 0; p < nports; p++) { - struct usbd_port *up = &hub->ports[p]; - up->device = NULL; - up->parent = dev; - up->portno = p+1; - if (dev->self_powered) - /* Self powered hub, give ports maximum current. */ - up->power = USB_MAX_POWER; - else - up->power = USB_MIN_POWER; - up->restartcnt = 0; - if (UHUB_IS_HIGH_SPEED(sc)) { - up->tt = &tts[UHUB_IS_SINGLE_TT(sc) ? 0 : p]; - up->tt->hub = hub; - } else { - up->tt = NULL; - } - } - - /* XXX should check for none, individual, or ganged power? */ - - pwrdly = dev->hub->hubdesc.bPwrOn2PwrGood * UHD_PWRON_FACTOR - + USB_EXTRA_POWER_UP_TIME; - for (port = 1; port <= nports; port++) { - /* Turn the power on. */ - err = usbd_set_port_feature(dev, port, UHF_PORT_POWER); - if (err) - device_printf(sc->sc_dev, - "port %d power on failed, %s\n", port, - usbd_errstr(err)); - DPRINTF(("usb_init_port: turn on port %d power\n", port)); - /* Wait for stable power. */ - usbd_delay_ms(dev, pwrdly); - } - - /* The usual exploration will finish the setup. */ - - sc->sc_running = 1; - return (0); - bad: - if (hub) - free(hub, M_USBDEV); - dev->hub = NULL; - return (ENXIO); -} - -usbd_status -uhub_explore(usbd_device_handle dev) -{ - usb_hub_descriptor_t *hd = &dev->hub->hubdesc; - struct uhub_softc *sc = dev->hub->hubsoftc; - struct usbd_port *up; - usbd_status err; - int speed; - int port; - int change, status; - - DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev, dev->address)); - - if (!sc->sc_running) - return (USBD_NOT_STARTED); - - /* Ignore hubs that are too deep. */ - if (dev->depth > USB_HUB_MAX_DEPTH) - return (USBD_TOO_DEEP); - - for(port = 1; port <= hd->bNbrPorts; port++) { - up = &dev->hub->ports[port-1]; - 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); - DEVPRINTFN(3,(sc->sc_dev, - "uhub_explore: port %d status 0x%04x 0x%04x\n", port, - status, change)); - if (change & UPS_C_PORT_ENABLED) { - DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change)); - usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE); - if (change & UPS_C_CONNECT_STATUS) { - /* Ignore the port error if the device - vanished. */ - } else if (status & UPS_PORT_ENABLED) { - device_printf(sc->sc_dev, - "illegal enable change, port %d\n", port); - } else { - /* Port error condition. */ - if (up->restartcnt) /* no message first time */ - device_printf(sc->sc_dev, - "port error, restarting port %d\n", - port); - - if (up->restartcnt++ < USBD_RESTART_MAX) - goto disco; - else - device_printf(sc->sc_dev, - "port error, giving up port %d\n", - port); - } - } - if (!(change & UPS_C_CONNECT_STATUS)) { - DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_" - "STATUS\n", port)); - /* No status change, just do recursive explore. */ - if (up->device != NULL && up->device->hub != NULL) - up->device->hub->explore(up->device); -#if 0 && defined(DIAGNOSTIC) - if (up->device == NULL && - (status & UPS_CURRENT_CONNECT_STATUS)) - deivce_printf(sc->sc_dev, - "connected, no device\n"); -#endif - continue; - } - - /* We have a connect status change, handle it. */ - - DPRINTF(("uhub_explore: status change hub=%d port=%d\n", - dev->address, port)); - usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); - /*usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);*/ - /* - * If there is already a device on the port the change status - * must mean that is has disconnected. Looking at the - * current connect status is not enough to figure this out - * since a new unit may have been connected before we handle - * the disconnect. - */ - disco: - if (up->device != NULL) { - /* Disconnected */ - DPRINTF(("uhub_explore: device addr=%d disappeared " - "on port %d\n", up->device->address, port)); - usb_disconnect_port(up, sc->sc_dev); - usbd_clear_port_feature(dev, port, - UHF_C_PORT_CONNECTION); - } - if (!(status & UPS_CURRENT_CONNECT_STATUS)) { - /* Nothing connected, just ignore it. */ - DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT" - "_STATUS\n", port)); - continue; - } - - /* Connected */ - - if (!(status & UPS_PORT_POWER)) - device_printf(sc->sc_dev, - "strange, connected port %d has no power\n", port); - - /* Wait for maximum device power up time. */ - usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY); - - /* Reset port, which implies enabling it. */ - if (usbd_reset_port(dev, port, &up->status)) { - device_printf(sc->sc_dev, "port %d reset failed\n", - 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 - device_printf(sc->sc_dev, - "port %d, device disappeared after reset\n", port); -#endif - continue; - } - -#if 0 - if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) { - device_printf(sc->sc_dev, - "port %d, transaction translation not implemented," - " low/full speed device ignored\n", port); - continue; - } -#endif - - /* 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(sc->sc_dev, dev->bus, - dev->depth + 1, speed, port, up); - /* XXX retry a few times? */ - if (err) { - DPRINTFN(-1,("uhub_explore: usb_new_device failed, " - "error=%s\n", usbd_errstr(err))); - /* Avoid addressing problems by disabling. */ - /* usbd_reset_port(dev, port, &up->status); */ - - /* - * The unit refused to accept a new address, or had - * some other serious problem. Since we cannot leave - * at 0 we have to disable the port instead. - */ - device_printf(sc->sc_dev, - "device problem (%s), disabling port %d\n", - usbd_errstr(err), port); - usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE); - } else { - /* The port set up succeeded, reset error count. */ - up->restartcnt = 0; - - if (up->device->hub) - up->device->hub->explore(up->device); - } - } - return (USBD_NORMAL_COMPLETION); -} - -/* - * Called from process context when the hub is gone. - * Detach all devices on active ports. - */ -static int -uhub_detach(device_t self) -{ - struct uhub_softc *sc = device_get_softc(self); - struct usbd_hub *hub = sc->sc_hub->hub; - struct usbd_port *rup; - int port, nports; - - DPRINTF(("uhub_detach: sc=%port\n", sc)); - if (hub == NULL) /* Must be partially working */ - return (0); - - usbd_abort_pipe(sc->sc_ipipe); - usbd_close_pipe(sc->sc_ipipe); - - nports = hub->hubdesc.bNbrPorts; - for(port = 0; port < nports; port++) { - rup = &hub->ports[port]; - if (rup->device) - usb_disconnect_port(rup, self); - } - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, sc->sc_dev); - - if (hub->ports[0].tt) - free(hub->ports[0].tt, M_USBDEV); - free(hub, M_USBDEV); - sc->sc_hub->hub = NULL; - - return (0); -} - -int -uhub_child_location_str(device_t cbdev, device_t child, char *buf, - size_t buflen) -{ - struct uhub_softc *sc = device_get_softc(cbdev); - usbd_device_handle devhub = sc->sc_hub; - usbd_device_handle dev; - int nports; - int port; - int i; - - mtx_lock(&Giant); - nports = devhub->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - dev = devhub->hub->ports[port].device; - if (dev && dev->subdevs) { - for (i = 0; dev->subdevs[i]; i++) { - if (dev->subdevs[i] == child) { - if (dev->ifacenums == NULL) { - snprintf(buf, buflen, - "port=%i", port); - } else { - snprintf(buf, buflen, - "port=%i interface=%i", - port, dev->ifacenums[i]); - } - goto found_dev; - } - } - } - } - DPRINTFN(0,("uhub_child_location_str: device not on hub\n")); - buf[0] = '\0'; -found_dev: - mtx_unlock(&Giant); - return (0); -} - -int -uhub_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, - size_t buflen) -{ - struct uhub_softc *sc = device_get_softc(cbdev); - usbd_device_handle devhub = sc->sc_hub; - usbd_device_handle dev; - struct usbd_interface *iface; - char serial[128]; - int nports; - int port; - int i; - - mtx_lock(&Giant); - nports = devhub->hub->hubdesc.bNbrPorts; - for (port = 0; port < nports; port++) { - dev = devhub->hub->ports[port].device; - if (dev && dev->subdevs) { - for (i = 0; dev->subdevs[i]; i++) { - if (dev->subdevs[i] == child) { - goto found_dev; - } - } - } - } - DPRINTFN(0,("uhub_child_pnpinfo_str: device not on hub\n")); - buf[0] = '\0'; - mtx_unlock(&Giant); - return (0); - -found_dev: - /* XXX can sleep */ - (void)usbd_get_string(dev, dev->ddesc.iSerialNumber, serial, - sizeof(serial)); - if (dev->ifacenums == NULL) { - snprintf(buf, buflen, "vendor=0x%04x product=0x%04x " - "devclass=0x%02x devsubclass=0x%02x " - "release=0x%04x sernum=\"%s\"", - UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct), - dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass, - UGETW(dev->ddesc.bcdDevice), serial); - } else { - iface = &dev->ifaces[dev->ifacenums[i]]; - snprintf(buf, buflen, "vendor=0x%04x product=0x%04x " - "devclass=0x%02x devsubclass=0x%02x " - "release=0x%04x sernum=\"%s\" " - "intclass=0x%02x intsubclass=0x%02x", - UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct), - dev->ddesc.bDeviceClass, dev->ddesc.bDeviceSubClass, - UGETW(dev->ddesc.bcdDevice), serial, - iface->idesc->bInterfaceClass, - iface->idesc->bInterfaceSubClass); - } - mtx_unlock(&Giant); - return (0); -} - -/* - * Hub interrupt. - * This an indication that some port has changed status. - * Notify the bus event handler thread that we need - * to be explored again. - */ -void -uhub_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct uhub_softc *sc = addr; - - DPRINTFN(5,("uhub_intr: sc=%p\n", sc)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_ipipe); - else if (status == USBD_NORMAL_COMPLETION) - usb_needs_explore(sc->sc_hub); -} - -MODULE_DEPEND(uhub, usb, 1, 1, 1); -DRIVER_MODULE(uhub, usb, uhubroot_driver, uhubroot_devclass, 0, 0); -DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/uipaq.c b/sys/dev/usb/uipaq.c deleted file mode 100644 index a231a67..0000000 --- a/sys/dev/usb/uipaq.c +++ /dev/null @@ -1,822 +0,0 @@ -/* $NetBSD: uipaq.c,v 1.4 2006/11/16 01:33:27 christos Exp $ */ -/* $OpenBSD: uipaq.c,v 1.1 2005/06/17 23:50:33 deraadt Exp $ */ - -/* - * Copyright (c) 2000-2005 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. - */ - -/* - * iPAQ driver - * - * 19 July 2003: Incorporated changes suggested by Sam Lawrance from - * the uppc module - * - * - * Contact isis@cs.umd.edu if you have any questions/comments about this driver - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/module.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbcdc.h> /*UCDC_* stuff */ - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/ucomvar.h> - -#ifdef UIPAQ_DEBUG -#define DPRINTF(x) if (uipaqdebug) printf x -#define DPRINTFN(n,x) if (uipaqdebug>(n)) printf x -int uipaqdebug = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UIPAQ_CONFIG_NO 1 -#define UIPAQ_IFACE_INDEX 0 - -#define UIPAQIBUFSIZE 1024 -#define UIPAQOBUFSIZE 1024 - -struct uipaq_softc { - struct ucom_softc sc_ucom; - u_int16_t sc_lcr; /* state for DTR/RTS */ - u_int16_t sc_flags; - -}; - -/* Callback routines */ -static void uipaq_set(void *, int, int, int); - -/* Support routines. */ -/* based on uppc module by Sam Lawrance */ -static void uipaq_dtr(struct uipaq_softc *sc, int onoff); -static void uipaq_rts(struct uipaq_softc *sc, int onoff); -static void uipaq_break(struct uipaq_softc* sc, int onoff); - -int uipaq_detach(device_t self); - -struct ucom_callback uipaq_callback = { - .ucom_set = uipaq_set -}; - -struct uipaq_type { - struct usb_devno uv_dev; - u_int16_t uv_flags; -}; - -/* - * Much of this list is generated from lists of other drivers that support - * the same hardware. Numeric values are used where no usbdevs entries - * exist. - */ -static const struct uipaq_type uipaq_devs[] = { - {{ 0x0104, 0x00be }, 0}, /* Socket USB Sync */ - {{ 0x04ad, 0x0301 }, 0}, /* USB Sync 0301 */ - {{ 0x04ad, 0x0302 }, 0}, /* USB Sync 0302 */ - {{ 0x04ad, 0x0303 }, 0}, /* USB Sync 0303 */ - {{ 0x04ad, 0x0306 }, 0}, /* GPS Pocket PC USB Sync */ - {{ 0x0536, 0x01a0 }, 0}, /* HHP PDT */ - {{ 0x067e, 0x1001 }, 0}, /* Intermec Mobile Computer */ - {{ 0x094b, 0x0001 }, 0}, /* Linkup Systems USB Sync */ - {{ 0x0960, 0x0065 }, 0}, /* BCOM USB Sync 0065 */ - {{ 0x0960, 0x0066 }, 0}, /* BCOM USB Sync 0066 */ - {{ 0x0960, 0x0067 }, 0}, /* BCOM USB Sync 0067 */ - {{ 0x0961, 0x0010 }, 0}, /* Portatec USB Sync */ - {{ 0x099e, 0x0052 }, 0}, /* Trimble GeoExplorer */ - {{ 0x099e, 0x4000 }, 0}, /* TDS Data Collector */ - {{ 0x0c44, 0x03a2 }, 0}, /* Motorola iDEN Smartphone */ - {{ 0x0c8e, 0x6000 }, 0}, /* Cesscom Luxian Series */ - {{ 0x0cad, 0x9001 }, 0}, /* Motorola PowerPad Pocket PCDevice */ - {{ 0x0f4e, 0x0200 }, 0}, /* Freedom Scientific USB Sync */ - {{ 0x0f98, 0x0201 }, 0}, /* Cyberbank USB Sync */ - {{ 0x0fb8, 0x3001 }, 0}, /* Wistron USB Sync */ - {{ 0x0fb8, 0x3002 }, 0}, /* Wistron USB Sync */ - {{ 0x0fb8, 0x3003 }, 0}, /* Wistron USB Sync */ - {{ 0x0fb8, 0x4001 }, 0}, /* Wistron USB Sync */ - {{ 0x1066, 0x00ce }, 0}, /* E-TEN USB Sync */ - {{ 0x1066, 0x0300 }, 0}, /* E-TEN P3XX Pocket PC */ - {{ 0x1066, 0x0500 }, 0}, /* E-TEN P5XX Pocket PC */ - {{ 0x1066, 0x0600 }, 0}, /* E-TEN P6XX Pocket PC */ - {{ 0x1066, 0x0700 }, 0}, /* E-TEN P7XX Pocket PC */ - {{ 0x1114, 0x0001 }, 0}, /* Psion Teklogix Sync 753x */ - {{ 0x1114, 0x0004 }, 0}, /* Psion Teklogix Sync netBookPro */ - {{ 0x1114, 0x0006 }, 0}, /* Psion Teklogix Sync 7525 */ - {{ 0x1182, 0x1388 }, 0}, /* VES USB Sync */ - {{ 0x11d9, 0x1002 }, 0}, /* Rugged Pocket PC 2003 */ - {{ 0x11d9, 0x1003 }, 0}, /* Rugged Pocket PC 2003 */ - {{ 0x1231, 0xce01 }, 0}, /* USB Sync 03 */ - {{ 0x1231, 0xce02 }, 0}, /* USB Sync 03 */ - {{ 0x3340, 0x011c }, 0}, /* Mio DigiWalker PPC StrongARM */ - {{ 0x3340, 0x0326 }, 0}, /* Mio DigiWalker 338 */ - {{ 0x3340, 0x0426 }, 0}, /* Mio DigiWalker 338 */ - {{ 0x3340, 0x043a }, 0}, /* Mio DigiWalker USB Sync */ - {{ 0x3340, 0x051c }, 0}, /* MiTAC USB Sync 528 */ - {{ 0x3340, 0x053a }, 0}, /* Mio DigiWalker SmartPhone USB Sync */ - {{ 0x3340, 0x071c }, 0}, /* MiTAC USB Sync */ - {{ 0x3340, 0x0b1c }, 0}, /* Generic PPC StrongARM */ - {{ 0x3340, 0x0e3a }, 0}, /* Generic PPC USB Sync */ - {{ 0x3340, 0x0f1c }, 0}, /* Itautec USB Sync */ - {{ 0x3340, 0x0f3a }, 0}, /* Generic SmartPhone USB Sync */ - {{ 0x3340, 0x1326 }, 0}, /* Itautec USB Sync */ - {{ 0x3340, 0x191c }, 0}, /* YAKUMO USB Sync */ - {{ 0x3340, 0x2326 }, 0}, /* Vobis USB Sync */ - {{ 0x3340, 0x3326 }, 0}, /* MEDION Winodws Moble USB Sync */ - {{ 0x3708, 0x20ce }, 0}, /* Legend USB Sync */ - {{ 0x3708, 0x21ce }, 0}, /* Lenovo USB Sync */ - {{ 0x4113, 0x0210 }, 0}, /* Mobile Media Technology USB Sync */ - {{ 0x4113, 0x0211 }, 0}, /* Mobile Media Technology USB Sync */ - {{ 0x4113, 0x0400 }, 0}, /* Mobile Media Technology USB Sync */ - {{ 0x4113, 0x0410 }, 0}, /* Mobile Media Technology USB Sync */ - {{ 0x4505, 0x0010 }, 0}, /* Smartphone */ - {{ 0x5e04, 0xce00 }, 0}, /* SAGEM Wireless Assistant */ - {{ USB_VENDOR_ACER, 0x1631 }, 0}, /* c10 Series */ - {{ USB_VENDOR_ACER, 0x1632 }, 0}, /* c20 Series */ - {{ USB_VENDOR_ACER, 0x16e1 }, 0}, /* Acer n10 Handheld USB Sync */ - {{ USB_VENDOR_ACER, 0x16e2 }, 0}, /* Acer n20 Handheld USB Sync */ - {{ USB_VENDOR_ACER, 0x16e3 }, 0}, /* Acer n30 Handheld USB Sync */ - {{ USB_VENDOR_ASUS, 0x4200 }, 0}, /* ASUS USB Sync */ - {{ USB_VENDOR_ASUS, 0x4201 }, 0}, /* ASUS USB Sync */ - {{ USB_VENDOR_ASUS, 0x4202 }, 0}, /* ASUS USB Sync */ - {{ USB_VENDOR_ASUS, 0x9200 }, 0}, /* ASUS USB Sync */ - {{ USB_VENDOR_ASUS, 0x9202 }, 0}, /* ASUS USB Sync */ - {{ USB_VENDOR_ASUS, USB_PRODUCT_ASUS_P535 }, 0}, - {{ USB_VENDOR_CASIO, 0x2001 }, 0}, /* CASIO USB Sync 2001 */ - {{ USB_VENDOR_CASIO, 0x2003 }, 0}, /* CASIO USB Sync 2003 */ - {{ USB_VENDOR_CASIO, USB_PRODUCT_CASIO_BE300 } , 0}, - {{ USB_VENDOR_COMPAL, 0x0531 }, 0}, /* MyGuide 7000 XL USB Sync */ - {{ USB_VENDOR_COMPAQ, 0x0032 }, 0}, /* Compaq iPAQ USB Sync */ - {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQPOCKETPC } , 0}, - {{ USB_VENDOR_DELL, 0x4001 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4002 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4003 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4004 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4005 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4006 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4007 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4008 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_DELL, 0x4009 }, 0}, /* Dell Axim USB Sync */ - {{ USB_VENDOR_FSC, 0x1001 }, 0}, /* Fujitsu Siemens Computers USB Sync */ - {{ USB_VENDOR_FUJITSU, 0x1058 }, 0}, /* FUJITSU USB Sync */ - {{ USB_VENDOR_FUJITSU, 0x1079 }, 0}, /* FUJITSU USB Sync */ - {{ USB_VENDOR_GIGASET, 0x0601 }, 0}, /* Askey USB Sync */ - {{ USB_VENDOR_HITACHI, 0x0014 }, 0}, /* Hitachi USB Sync */ - {{ USB_VENDOR_HP, 0x1216 }, 0}, /* HP USB Sync 1612 */ - {{ USB_VENDOR_HP, 0x2016 }, 0}, /* HP USB Sync 1620 */ - {{ USB_VENDOR_HP, 0x2116 }, 0}, /* HP USB Sync 1621 */ - {{ USB_VENDOR_HP, 0x2216 }, 0}, /* HP USB Sync 1622 */ - {{ USB_VENDOR_HP, 0x3016 }, 0}, /* HP USB Sync 1630 */ - {{ USB_VENDOR_HP, 0x3116 }, 0}, /* HP USB Sync 1631 */ - {{ USB_VENDOR_HP, 0x3216 }, 0}, /* HP USB Sync 1632 */ - {{ USB_VENDOR_HP, 0x4016 }, 0}, /* HP USB Sync 1640 */ - {{ USB_VENDOR_HP, 0x4116 }, 0}, /* HP USB Sync 1641 */ - {{ USB_VENDOR_HP, 0x4216 }, 0}, /* HP USB Sync 1642 */ - {{ USB_VENDOR_HP, 0x5016 }, 0}, /* HP USB Sync 1650 */ - {{ USB_VENDOR_HP, 0x5116 }, 0}, /* HP USB Sync 1651 */ - {{ USB_VENDOR_HP, 0x5216 }, 0}, /* HP USB Sync 1652 */ - {{ USB_VENDOR_HP, USB_PRODUCT_HP_2215 }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_568J }, 0}, - {{ USB_VENDOR_HTC, 0x00cf }, 0}, /* HTC USB Modem */ - {{ USB_VENDOR_HTC, 0x0a01 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a02 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a03 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a04 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a05 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a06 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a07 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a08 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a09 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0a }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0b }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0c }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0d }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0e }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a0f }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a10 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a11 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a12 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a13 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a14 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a15 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a16 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a17 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a18 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a19 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1a }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1b }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1c }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1d }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1e }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a1f }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a20 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a21 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a22 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a23 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a24 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a25 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a26 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a27 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a28 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a29 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2a }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2b }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2c }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2d }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2e }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a2f }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a30 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a31 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a32 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a33 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a34 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a35 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a36 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a37 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a38 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a39 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3a }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3b }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3c }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3d }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3e }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a3f }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a40 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a41 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a42 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a43 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a44 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a45 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a46 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a47 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a48 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a49 }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4a }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4b }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4c }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4d }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4e }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a4f }, 0}, /* PocketPC USB Sync */ - {{ USB_VENDOR_HTC, 0x0a50 }, 0}, /* HTC SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a52 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a53 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a54 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a55 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a56 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a57 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a58 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a59 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5a }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5b }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5c }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5d }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5e }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a5f }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a60 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a61 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a62 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a63 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a64 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a65 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a66 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a67 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a68 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a69 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6a }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6b }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6c }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6d }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6e }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a6f }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a70 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a71 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a72 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a73 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a74 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a75 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a76 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a77 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a78 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a79 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7a }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7b }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7c }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7d }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7e }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a7f }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a80 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a81 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a82 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a83 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a84 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a85 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a86 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a87 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a88 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a89 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8a }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8b }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8c }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8d }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8e }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a8f }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a90 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a91 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a92 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a93 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a94 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a95 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a96 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a97 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a98 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a99 }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9a }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9b }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9c }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9d }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9e }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0a9f }, 0}, /* SmartPhone USB Sync */ - {{ USB_VENDOR_HTC, 0x0bce }, 0}, /* "High Tech Computer Corp" */ - {{ USB_VENDOR_HTC, USB_PRODUCT_HTC_PPC6700MODEM }, 0}, - {{ USB_VENDOR_HTC, USB_PRODUCT_HTC_SMARTPHONE }, 0}, - {{ USB_VENDOR_HTC, USB_PRODUCT_HTC_WINMOBILE }, 0}, - {{ USB_VENDOR_JVC, 0x3011 }, 0}, /* JVC USB Sync */ - {{ USB_VENDOR_JVC, 0x3012 }, 0}, /* JVC USB Sync */ - {{ USB_VENDOR_LG, 0x9c01 }, 0}, /* LGE USB Sync */ - {{ USB_VENDOR_MICROSOFT, 0x00ce }, 0}, /* Microsoft USB Sync */ - {{ USB_VENDOR_MICROSOFT, 0x0400 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0401 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0402 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0403 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0404 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0405 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0406 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0407 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0408 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0409 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040a }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040b }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040c }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040d }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040e }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x040f }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0410 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0411 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0412 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0413 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0414 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0415 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0416 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0417 }, 0}, /* Windows Pocket PC 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x0432 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0433 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0434 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0435 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0436 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0437 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0438 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0439 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043a }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043b }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043c }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043d }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043e }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x043f }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0440 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0441 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0442 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0443 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0444 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0445 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0446 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0447 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0448 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0449 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044a }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044b }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044c }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044d }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044e }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x044f }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0450 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0451 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0452 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0453 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0454 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0455 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0456 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0457 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0458 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0459 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045a }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045b }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045c }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045d }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045e }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x045f }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0460 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0461 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0462 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0463 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0464 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0465 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0466 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0467 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0468 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0469 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046a }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046b }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046c }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046d }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046e }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x046f }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0470 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0471 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0472 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0473 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0474 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0475 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0476 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0477 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0478 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x0479 }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x047a }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x047b }, 0}, /* Windows Pocket PC 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04c8 }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04c9 }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04ca }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04cb }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04cc }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04cd }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04ce }, 0}, /* Windows Smartphone 2002 */ - {{ USB_VENDOR_MICROSOFT, 0x04d7 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04d8 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04d9 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04da }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04db }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04dc }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04dd }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04de }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04df }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e0 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e1 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e2 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e3 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e4 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e5 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e6 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e7 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e8 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04e9 }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MICROSOFT, 0x04ea }, 0}, /* Windows Smartphone 2003 */ - {{ USB_VENDOR_MOTOROLA2, 0x4204 }, 0}, /* Motorola MPx200 Smartphone */ - {{ USB_VENDOR_MOTOROLA2, 0x4214 }, 0}, /* Motorola MPc GSM */ - {{ USB_VENDOR_MOTOROLA2, 0x4224 }, 0}, /* Motorola MPx220 Smartphone */ - {{ USB_VENDOR_MOTOROLA2, 0x4234 }, 0}, /* Motorola MPc CDMA */ - {{ USB_VENDOR_MOTOROLA2, 0x4244 }, 0}, /* Motorola MPx100 Smartphone */ - {{ USB_VENDOR_NEC, 0x00d5 }, 0}, /* NEC USB Sync */ - {{ USB_VENDOR_NEC, 0x00d6 }, 0}, /* NEC USB Sync */ - {{ USB_VENDOR_NEC, 0x00d7 }, 0}, /* NEC USB Sync */ - {{ USB_VENDOR_NEC, 0x8024 }, 0}, /* NEC USB Sync */ - {{ USB_VENDOR_NEC, 0x8025 }, 0}, /* NEC USB Sync */ - {{ USB_VENDOR_PANASONIC, 0x2500 }, 0}, /* Panasonic USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x5f00 }, 0}, /* Samsung NEXiO USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x5f01 }, 0}, /* Samsung NEXiO USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x5f02 }, 0}, /* Samsung NEXiO USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x5f03 }, 0}, /* Samsung NEXiO USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x5f04 }, 0}, /* Samsung NEXiO USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6611 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6613 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6615 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6617 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6619 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x661b }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x662e }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6630 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SAMSUNG, 0x6632 }, 0}, /* Samsung MITs USB Sync */ - {{ USB_VENDOR_SHARP, 0x9102 }, 0}, /* SHARP WS003SH USB Modem */ - {{ USB_VENDOR_SHARP, 0x9121 }, 0}, /* SHARP WS004SH USB Modem */ - {{ USB_VENDOR_SHARP, 0x9151 }, 0}, /* SHARP S01SH USB Modem */ - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_WZERO3ES }, 0}, - {{ USB_VENDOR_SYMBOL, 0x2000 }, 0}, /* Symbol USB Sync */ - {{ USB_VENDOR_SYMBOL, 0x2001 }, 0}, /* Symbol USB Sync 0x2001 */ - {{ USB_VENDOR_SYMBOL, 0x2002 }, 0}, /* Symbol USB Sync 0x2002 */ - {{ USB_VENDOR_SYMBOL, 0x2003 }, 0}, /* Symbol USB Sync 0x2003 */ - {{ USB_VENDOR_SYMBOL, 0x2004 }, 0}, /* Symbol USB Sync 0x2004 */ - {{ USB_VENDOR_SYMBOL, 0x2005 }, 0}, /* Symbol USB Sync 0x2005 */ - {{ USB_VENDOR_SYMBOL, 0x2006 }, 0}, /* Symbol USB Sync 0x2006 */ - {{ USB_VENDOR_SYMBOL, 0x2007 }, 0}, /* Symbol USB Sync 0x2007 */ - {{ USB_VENDOR_SYMBOL, 0x2008 }, 0}, /* Symbol USB Sync 0x2008 */ - {{ USB_VENDOR_SYMBOL, 0x2009 }, 0}, /* Symbol USB Sync 0x2009 */ - {{ USB_VENDOR_SYMBOL, 0x200a }, 0}, /* Symbol USB Sync 0x200a */ - {{ USB_VENDOR_TOSHIBA, 0x0700 }, 0}, /* TOSHIBA USB Sync 0700 */ - {{ USB_VENDOR_TOSHIBA, 0x0705 }, 0}, /* TOSHIBA Pocket PC e310 */ - {{ USB_VENDOR_TOSHIBA, 0x0707 }, 0}, /* TOSHIBA Pocket PC e330 Series */ - {{ USB_VENDOR_TOSHIBA, 0x0708 }, 0}, /* TOSHIBA Pocket PC e350Series */ - {{ USB_VENDOR_TOSHIBA, 0x0709 }, 0}, /* TOSHIBA Pocket PC e750 Series */ - {{ USB_VENDOR_TOSHIBA, 0x070a }, 0}, /* TOSHIBA Pocket PC e400 Series */ - {{ USB_VENDOR_TOSHIBA, 0x070b }, 0}, /* TOSHIBA Pocket PC e800 Series */ - {{ USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_POCKETPC_E740 }, 0}, /* TOSHIBA Pocket PC e740 */ - {{ USB_VENDOR_VIEWSONIC, 0x0ed9 }, 0}, /* ViewSonic Color Pocket PC V35 */ - {{ USB_VENDOR_VIEWSONIC, 0x1527 }, 0}, /* ViewSonic Color Pocket PC V36 */ - {{ USB_VENDOR_VIEWSONIC, 0x1529 }, 0}, /* ViewSonic Color Pocket PC V37 */ - {{ USB_VENDOR_VIEWSONIC, 0x152b }, 0}, /* ViewSonic Color Pocket PC V38 */ - {{ USB_VENDOR_VIEWSONIC, 0x152e }, 0}, /* ViewSonic Pocket PC */ - {{ USB_VENDOR_VIEWSONIC, 0x1921 }, 0}, /* ViewSonic Communicator Pocket PC */ - {{ USB_VENDOR_VIEWSONIC, 0x1922 }, 0}, /* ViewSonic Smartphone */ - {{ USB_VENDOR_VIEWSONIC, 0x1923 }, 0}, /* ViewSonic Pocket PC V30 */ -}; - -#define uipaq_lookup(v, p) ((const struct uipaq_type *)usb_lookup(uipaq_devs, v, p)) - -static int -uipaq_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - DPRINTFN(20,("uipaq: vendor=0x%x, product=0x%x\n", - uaa->vendor, uaa->product)); - - return (uipaq_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uipaq_attach(device_t self) -{ - usb_device_request_t req; - struct uipaq_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; - - ucom->sc_dev = self; - ucom->sc_udev = dev; - - DPRINTFN(10,("\nuipaq_attach: sc=%p\n", sc)); - - /* Move the device into the configured state. */ - err = usbd_set_config_no(dev, UIPAQ_CONFIG_NO, 1); - if (err) { - device_printf(ucom->sc_dev, - "failed to set configuration: %s\n", usbd_errstr(err)); - goto bad; - } - - err = usbd_device2interface_handle(dev, UIPAQ_IFACE_INDEX, &iface); - if (err) { - device_printf(ucom->sc_dev, "failed to get interface: %s\n", - usbd_errstr(err)); - goto bad; - } - - sc->sc_flags = uipaq_lookup(uaa->vendor, uaa->product)->uv_flags; - id = usbd_get_interface_descriptor(iface); - ucom->sc_iface = iface; - ucom->sc_ibufsize = UIPAQIBUFSIZE; - ucom->sc_obufsize = UIPAQOBUFSIZE; - ucom->sc_ibufsizepad = UIPAQIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uipaq_callback; - ucom->sc_parent = sc; - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i=0; i<id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(ucom->sc_dev, - "no endpoint descriptor for %d\n", i); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(ucom->sc_dev, - "no proper endpoints found (%d,%d)\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no); - return (ENXIO); - } - /* - * Send magic bytes, cribbed from Linux ipaq driver that claims - * to have sniffed them from Win98. - */ - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, UCDC_LINE_DTR); - USETW(req.wIndex, 0x0); - USETW(req.wLength, 0); - for (i = 0; i < 100; i++) { - err = usbd_do_request_flags(ucom->sc_udev, &req, NULL, 0, NULL, 100); - if (!err) - break; - usbd_delay_ms(dev, 1000); - } - ucom_attach(&sc->sc_ucom); - return (0); -bad: - DPRINTF(("uipaq_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return (ENXIO); -} - -void -uipaq_dtr(struct uipaq_softc* sc, int onoff) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - usbd_status err; - int retries = 3; - - DPRINTF(("%s: uipaq_dtr: onoff=%x\n", device_get_nameunit(ucom->sc_dev), onoff)); - - /* Avoid sending unnecessary requests */ - if (onoff && (sc->sc_lcr & UCDC_LINE_DTR)) - return; - if (!onoff && !(sc->sc_lcr & UCDC_LINE_DTR)) - return; - - /* Other parameters depend on reg */ - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - sc->sc_lcr = onoff ? sc->sc_lcr | UCDC_LINE_DTR : sc->sc_lcr & ~UCDC_LINE_DTR; - USETW(req.wValue, sc->sc_lcr); - USETW(req.wIndex, 0x0); - USETW(req.wLength, 0); - - /* Fire off the request a few times if necessary */ - while (retries) { - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (!err) - break; - retries--; - } -} - -void -uipaq_rts(struct uipaq_softc* sc, int onoff) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - usbd_status err; - int retries = 3; - - DPRINTF(("%s: uipaq_rts: onoff=%x\n", device_get_nameunit(ucom->sc_dev), onoff)); - - /* Avoid sending unnecessary requests */ - if (onoff && (sc->sc_lcr & UCDC_LINE_RTS)) return; - if (!onoff && !(sc->sc_lcr & UCDC_LINE_RTS)) return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - sc->sc_lcr = onoff ? sc->sc_lcr | UCDC_LINE_RTS : sc->sc_lcr & ~UCDC_LINE_RTS; - USETW(req.wValue, sc->sc_lcr); - USETW(req.wIndex, 0x0); - USETW(req.wLength, 0); - - while (retries) { - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (!err) - break; - retries--; - } -} - -void -uipaq_break(struct uipaq_softc* sc, int onoff) -{ - usb_device_request_t req; - struct ucom_softc *ucom = &sc->sc_ucom; - usbd_status err; - int retries = 3; - - DPRINTF(("%s: uipaq_break: onoff=%x\n", device_get_nameunit(ucom->sc_dev), onoff)); - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, 0x0); - USETW(req.wLength, 0); - - while (retries) { - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (!err) - break; - retries--; - } -} - -void -uipaq_set(void *addr, int portno, int reg, int onoff) -{ - struct uipaq_softc* sc = addr; - struct ucom_softc *ucom = &sc->sc_ucom; - - switch (reg) { - case UCOM_SET_DTR: - uipaq_dtr(addr, onoff); - break; - case UCOM_SET_RTS: - uipaq_rts(addr, onoff); - break; - case UCOM_SET_BREAK: - uipaq_break(addr, onoff); - break; - default: - printf("%s: unhandled set request: reg=%x onoff=%x\n", - device_get_nameunit(ucom->sc_dev), reg, onoff); - return; - } -} - -int -uipaq_detach(device_t self) -{ - struct uipaq_softc *sc = device_get_softc(self); - struct ucom_softc *ucom = &sc->sc_ucom; - int rv = 0; - - DPRINTF(("uipaq_detach: sc=%p flags=%d\n", sc, flags)); - ucom->sc_dying = 1; - - rv = ucom_detach(ucom); - - return (rv); -} - -static device_method_t uipaq_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uipaq_match), - DEVMETHOD(device_attach, uipaq_attach), - DEVMETHOD(device_detach, uipaq_detach), - - { 0, 0 } -}; -static driver_t uipaq_driver = { - "ucom", - uipaq_methods, - sizeof (struct uipaq_softc) -}; - -DRIVER_MODULE(uipaq, uhub, uipaq_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uipaq, usb, 1, 1, 1); -MODULE_DEPEND(uipaq, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c deleted file mode 100644 index 5a7c9fc..0000000 --- a/sys/dev/usb/ukbd.c +++ /dev/null @@ -1,1538 +0,0 @@ -/*- - * Copyright (c) 1998 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> -__FBSDID("$FreeBSD$"); - -/* - * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf - */ - -#include "opt_compat.h" -#include "opt_kbd.h" -#include "opt_ukbd.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/ioccom.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/file.h> -#include <sys/limits.h> -#include <sys/selinfo.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> -#include <dev/usb/hid.h> - -#include <sys/kbio.h> -#include <dev/kbd/kbdreg.h> - -#define UKBD_EMULATE_ATSCANCODE 1 - -#define DRIVER_NAME "ukbd" - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ukbddebug) printf x -#define DPRINTFN(n,x) if (ukbddebug>(n)) printf x -int ukbddebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd"); -SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RW, - &ukbddebug, 0, "ukbd debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UPROTO_BOOT_KEYBOARD 1 - -#define NKEYCODE 6 - -struct ukbd_data { - 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 MAXKEYS (NMOD+2*NKEYCODE) - -typedef struct ukbd_softc { - device_t sc_dev; /* base device */ -} ukbd_softc_t; - -#define UKBD_CHUNK 128 /* chunk size for read */ -#define UKBD_BSIZE 1020 /* buffer size */ - -typedef void usbd_intr_t(usbd_xfer_handle, usbd_private_handle, usbd_status); -typedef void usbd_disco_t(void *); - -static usbd_intr_t ukbd_intr; -static int ukbd_driver_load(module_t mod, int what, void *arg); - -static device_probe_t ukbd_match; -static device_attach_t ukbd_attach; -static device_detach_t ukbd_detach; -static device_resume_t ukbd_resume; - -static device_method_t ukbd_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ukbd_match), - DEVMETHOD(device_attach, ukbd_attach), - DEVMETHOD(device_detach, ukbd_detach), - DEVMETHOD(device_resume, ukbd_resume), - - { 0, 0 } -}; - -static driver_t ukbd_driver = { - "ukbd", - ukbd_methods, - sizeof(struct ukbd_softc) -}; - -static devclass_t ukbd_devclass; - -MODULE_DEPEND(ukbd, usb, 1, 1, 1); -DRIVER_MODULE(ukbd, uhub, ukbd_driver, ukbd_devclass, ukbd_driver_load, 0); - -static int -ukbd_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - keyboard_switch_t *sw; - void *arg[2]; - int unit = device_get_unit(self); - - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return (UMATCH_NONE); - - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - if ((*sw->probe)(unit, (void *)arg, 0)) - return (UMATCH_NONE); - - if (usbd_get_quirks(uaa->device)->uq_flags & UQ_KBD_IGNORE) - return (UMATCH_NONE); - - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); -} - -static int -ukbd_attach(device_t self) -{ - struct ukbd_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *id; - - keyboard_switch_t *sw; - keyboard_t *kbd; - void *arg[2]; - int unit = device_get_unit(self); - - sc->sc_dev = self; - sw = kbd_get_switch(DRIVER_NAME); - if (sw == NULL) - return ENXIO; - - id = usbd_get_interface_descriptor(iface); - - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - kbd = NULL; - if ((*sw->probe)(unit, (void *)arg, 0)) - return ENXIO; - if ((*sw->init)(unit, &kbd, (void *)arg, 0)) - return ENXIO; - (*sw->enable)(kbd); - -#ifdef KBD_INSTALL_CDEV - if (kbd_attach(kbd)) - return ENXIO; -#endif - if (bootverbose) - (*sw->diag)(kbd, bootverbose); - - return 0; -} - -int -ukbd_detach(device_t self) -{ - keyboard_t *kbd; - int error; - - kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, - device_get_unit(self))); - if (kbd == NULL) { - DPRINTF(("%s: keyboard not attached!?\n", device_get_nameunit(self))); - return ENXIO; - } - kbdd_disable(kbd); - -#ifdef KBD_INSTALL_CDEV - error = kbd_detach(kbd); - if (error) - return error; -#endif - error = kbdd_term(kbd); - if (error) - return error; - - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - - return (0); -} - -static int -ukbd_resume(device_t self) -{ - keyboard_t *kbd; - - kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME, - device_get_unit(self))); - if (kbd) - kbdd_clear_state(kbd); - return (0); -} - -void -ukbd_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - keyboard_t *kbd = (keyboard_t *)addr; - - kbdd_intr(kbd, (void *)status); -} - -#define UKBD_DEFAULT 0 - -#define KEY_ERROR 0x01 - -#define KEY_PRESS 0 -#define KEY_RELEASE 0x400 -#define KEY_INDEX(c) ((c) & ~KEY_RELEASE) - -#define SCAN_PRESS 0 -#define SCAN_RELEASE 0x80 -#define SCAN_PREFIX_E0 0x100 -#define SCAN_PREFIX_E1 0x200 -#define SCAN_PREFIX_CTL 0x400 -#define SCAN_PREFIX_SHIFT 0x800 -#define SCAN_PREFIX (SCAN_PREFIX_E0 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL \ - | SCAN_PREFIX_SHIFT) -#define SCAN_CHAR(c) ((c) & 0x7f) - -#define NMOD 8 -static struct { - int mask, key; -} ukbd_mods[NMOD] = { - { MOD_CONTROL_L, 0xe0 }, - { MOD_CONTROL_R, 0xe4 }, - { MOD_SHIFT_L, 0xe1 }, - { MOD_SHIFT_R, 0xe5 }, - { MOD_ALT_L, 0xe2 }, - { MOD_ALT_R, 0xe6 }, - { MOD_WIN_L, 0xe3 }, - { MOD_WIN_R, 0xe7 }, -}; - -#define NN 0 /* no translation */ -/* - * Translate USB keycodes to AT keyboard scancodes. - */ -/* - * FIXME: Mac USB keyboard generates: - * 0x53: keypad NumLock/Clear - * 0x66: Power - * 0x67: keypad = - * 0x68: F13 - * 0x69: F14 - * 0x6a: F15 - */ -static u_int8_t ukbd_trtab[256] = { - 0, 0, 0, 0, 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, 92, 70, /* 40 - 47 */ - 104, 102, 94, 96, 103, 99, 101, 98, /* 48 - 4F */ - 97, 100, 95, 69, 91, 55, 74, 78, /* 50 - 57 */ - 89, 79, 80, 81, 75, 76, 77, 71, /* 58 - 5F */ - 72, 73, 82, 83, 86, 107, 122, NN, /* 60 - 67 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* 68 - 6F */ - NN, NN, NN, NN, 115, 108, 111, 113, /* 70 - 77 */ - 109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */ - 121, 120, NN, NN, NN, NN, NN, 115, /* 80 - 87 */ - 112, 125, 121, 123, 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, 105, 90, 54, 93, 106, /* 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 */ -}; - -typedef struct ukbd_state { - usbd_interface_handle ks_iface; /* interface */ - usbd_pipe_handle ks_intrpipe; /* interrupt pipe */ - struct usb_attach_arg *ks_uaa; - int ks_ep_addr; - - struct ukbd_data ks_ndata; - struct ukbd_data ks_odata; - u_long ks_ntime[NKEYCODE]; - u_long ks_otime[NKEYCODE]; - -#define INPUTBUFSIZE (NMOD + 2*NKEYCODE) - u_int ks_input[INPUTBUFSIZE]; /* input buffer */ - int ks_inputs; - int ks_inputhead; - int ks_inputtail; - - int ks_ifstate; -#define INTRENABLED (1 << 0) -#define DISCONNECTED (1 << 1) - - struct callout ks_timeout_handle; - - int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ - int ks_flags; /* flags */ -#define COMPOSE (1 << 0) - int ks_polling; - int ks_state; /* shift/lock key state */ - int ks_accents; /* accent key index (> 0) */ - u_int ks_composed_char; /* composed char code (> 0) */ -#ifdef UKBD_EMULATE_ATSCANCODE - u_int ks_buffered_char[2]; - u_int8_t ks_leds; /* store for async led requests */ -#endif -} ukbd_state_t; - -/* keyboard driver declaration */ -static int ukbd_configure(int flags); -static kbd_probe_t ukbd_probe; -static kbd_init_t ukbd_init; -static kbd_term_t ukbd_term; -static kbd_intr_t ukbd_interrupt; -static kbd_test_if_t ukbd_test_if; -static kbd_enable_t ukbd_enable; -static kbd_disable_t ukbd_disable; -static kbd_read_t ukbd_read; -static kbd_check_t ukbd_check; -static kbd_read_char_t ukbd_read_char; -static kbd_check_char_t ukbd_check_char; -static kbd_ioctl_t ukbd_ioctl; -static kbd_lock_t ukbd_lock; -static kbd_clear_state_t ukbd_clear_state; -static kbd_get_state_t ukbd_get_state; -static kbd_set_state_t ukbd_set_state; -static kbd_poll_mode_t ukbd_poll; - -keyboard_switch_t ukbdsw = { - ukbd_probe, - ukbd_init, - ukbd_term, - ukbd_interrupt, - ukbd_test_if, - ukbd_enable, - ukbd_disable, - ukbd_read, - ukbd_check, - ukbd_read_char, - ukbd_check_char, - ukbd_ioctl, - ukbd_lock, - ukbd_clear_state, - ukbd_get_state, - ukbd_set_state, - genkbd_get_fkeystr, - ukbd_poll, - genkbd_diag, -}; - -KEYBOARD_DRIVER(ukbd, ukbdsw, ukbd_configure); - -/* local functions */ -static int ukbd_enable_intr(keyboard_t *kbd, int on, - usbd_intr_t *func); -static void ukbd_timeout(void *arg); - -static int ukbd_getc(ukbd_state_t *state, int wait); -static int probe_keyboard(struct usb_attach_arg *uaa, int flags); -static int init_keyboard(ukbd_state_t *state, int *type, - int flags); -static void set_leds(ukbd_state_t *state, int leds); -static int set_typematic(keyboard_t *kbd, int code); -#ifdef UKBD_EMULATE_ATSCANCODE -static int keycode2scancode(int keycode, int shift, int up); -#endif - -/* local variables */ - -/* the initial key map, accent map and fkey strings */ -#if defined(UKBD_DFLT_KEYMAP) && !defined(KLD_MODULE) -#define KBD_DFLT_KEYMAP -#include "ukbdmap.h" -#endif -#include <dev/kbd/kbdtables.h> - -/* structures for the default keyboard */ -static keyboard_t default_kbd; -static ukbd_state_t default_kbd_state; -static keymap_t default_keymap; -static accentmap_t default_accentmap; -static fkeytab_t default_fkeytab[NUM_FKEYS]; - -/* - * The back door to the keyboard driver! - * This function is called by the console driver, via the kbdio module, - * to tickle keyboard drivers when the low-level console is being initialized. - * Almost nothing in the kernel has been initialied yet. Try to probe - * keyboards if possible. - * NOTE: because of the way the low-level conole is initialized, this routine - * may be called more than once!! - */ -static int -ukbd_configure(int flags) -{ - return 0; - -#if 0 /* not yet */ - keyboard_t *kbd; - device_t device; - struct usb_attach_arg *uaa; - void *arg[2]; - - device = devclass_get_device(ukbd_devclass, UKBD_DEFAULT); - if (device == NULL) - return 0; - uaa = (struct usb_attach_arg *)device_get_ivars(device); - if (uaa == NULL) - return 0; - - /* probe the default keyboard */ - arg[0] = (void *)uaa; - arg[1] = (void *)ukbd_intr; - kbd = NULL; - if (ukbd_probe(UKBD_DEFAULT, arg, flags)) - return 0; - if (ukbd_init(UKBD_DEFAULT, &kbd, arg, flags)) - return 0; - - /* return the number of found keyboards */ - return 1; -#endif -} - -/* low-level functions */ - -/* detect a keyboard */ -static int -ukbd_probe(int unit, void *arg, int flags) -{ - void **data; - struct usb_attach_arg *uaa; - - data = (void **)arg; - uaa = (struct usb_attach_arg *)data[0]; - - /* XXX */ - if (unit == UKBD_DEFAULT) { - if (KBD_IS_PROBED(&default_kbd)) - return 0; - } - if (probe_keyboard(uaa, flags)) - return ENXIO; - return 0; -} - -/* reset and initialize the device */ -static int -ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) -{ - keyboard_t *kbd; - ukbd_state_t *state; - keymap_t *keymap; - accentmap_t *accmap; - fkeytab_t *fkeymap; - int fkeymap_size; - void **data = (void **)arg; - struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0]; - - /* XXX */ - if (unit == UKBD_DEFAULT) { - *kbdp = kbd = &default_kbd; - if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) - return 0; - state = &default_kbd_state; - keymap = &default_keymap; - accmap = &default_accentmap; - fkeymap = default_fkeytab; - fkeymap_size = - sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); - } else if (*kbdp == NULL) { - *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT); - if (kbd == NULL) - return ENOMEM; - bzero(kbd, sizeof(*kbd)); - state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT); - keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); - accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); - fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); - fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); - if ((state == NULL) || (keymap == NULL) || (accmap == NULL) - || (fkeymap == NULL)) { - if (state != NULL) - free(state, M_DEVBUF); - if (keymap != NULL) - free(keymap, M_DEVBUF); - if (accmap != NULL) - free(accmap, M_DEVBUF); - if (fkeymap != NULL) - free(fkeymap, M_DEVBUF); - free(kbd, M_DEVBUF); - return ENOMEM; - } - } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { - return 0; - } else { - kbd = *kbdp; - state = (ukbd_state_t *)kbd->kb_data; - keymap = kbd->kb_keymap; - accmap = kbd->kb_accentmap; - fkeymap = kbd->kb_fkeytab; - fkeymap_size = kbd->kb_fkeytab_size; - } - - if (!KBD_IS_PROBED(kbd)) { - kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, 0, 0); - bzero(state, sizeof(*state)); - bcopy(&key_map, keymap, sizeof(key_map)); - bcopy(&accent_map, accmap, sizeof(accent_map)); - bcopy(fkey_tab, fkeymap, - imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); - kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); - kbd->kb_data = (void *)state; - - if (probe_keyboard(uaa, flags)) - return ENXIO; - else - KBD_FOUND_DEVICE(kbd); - ukbd_clear_state(kbd); - state->ks_mode = K_XLATE; - state->ks_iface = uaa->iface; - state->ks_uaa = uaa; - state->ks_ifstate = 0; - callout_init(&state->ks_timeout_handle, 0); - /* - * FIXME: set the initial value for lock keys in ks_state - * according to the BIOS data? - */ - KBD_PROBE_DONE(kbd); - } - if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { - if (KBD_HAS_DEVICE(kbd) - && init_keyboard((ukbd_state_t *)kbd->kb_data, - &kbd->kb_type, kbd->kb_flags)) { - kbd->kb_flags = 0; - /* XXX: Missing free()'s */ - return ENXIO; - } - ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state)); - KBD_INIT_DONE(kbd); - } - if (!KBD_IS_CONFIGURED(kbd)) { - if (kbd_register(kbd) < 0) { - kbd->kb_flags = 0; - /* XXX: Missing free()'s */ - return ENXIO; - } - if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0) - ukbd_timeout((void *)kbd); - KBD_CONFIG_DONE(kbd); - } - - return 0; -} - -static int -ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func) -{ - ukbd_state_t *state = (ukbd_state_t *)kbd->kb_data; - usbd_status err; - - if (on) { - /* Set up interrupt pipe. */ - if (state->ks_ifstate & INTRENABLED) - return EBUSY; - - state->ks_ifstate |= INTRENABLED; - err = usbd_open_pipe_intr(state->ks_iface, state->ks_ep_addr, - USBD_SHORT_XFER_OK, - &state->ks_intrpipe, kbd, - &state->ks_ndata, - sizeof(state->ks_ndata), func, - USBD_DEFAULT_INTERVAL); - if (err) - return (EIO); - } else { - /* Disable interrupts. */ - usbd_abort_pipe(state->ks_intrpipe); - usbd_close_pipe(state->ks_intrpipe); - - state->ks_ifstate &= ~INTRENABLED; - } - - return (0); -} - -/* finish using this keyboard */ -static int -ukbd_term(keyboard_t *kbd) -{ - ukbd_state_t *state; - int error; - int s; - - s = splusb(); - - state = (ukbd_state_t *)kbd->kb_data; - DPRINTF(("ukbd_term: ks_ifstate=0x%x\n", state->ks_ifstate)); - - callout_stop(&state->ks_timeout_handle); - - if (state->ks_ifstate & INTRENABLED) - ukbd_enable_intr(kbd, FALSE, NULL); - if (state->ks_ifstate & INTRENABLED) { - splx(s); - DPRINTF(("ukbd_term: INTRENABLED!\n")); - return ENXIO; - } - - error = kbd_unregister(kbd); - DPRINTF(("ukbd_term: kbd_unregister() %d\n", error)); - if (error == 0) { - kbd->kb_flags = 0; - if (kbd != &default_kbd) { - free(kbd->kb_keymap, M_DEVBUF); - free(kbd->kb_accentmap, M_DEVBUF); - free(kbd->kb_fkeytab, M_DEVBUF); - free(state, M_DEVBUF); - free(kbd, M_DEVBUF); - } - } - - splx(s); - return error; -} - - -/* keyboard interrupt routine */ - -static void -ukbd_timeout(void *arg) -{ - keyboard_t *kbd; - ukbd_state_t *state; - int s; - - kbd = (keyboard_t *)arg; - state = (ukbd_state_t *)kbd->kb_data; - s = splusb(); - kbdd_intr(kbd, (void *)USBD_NORMAL_COMPLETION); - callout_reset(&state->ks_timeout_handle, hz / 40, ukbd_timeout, arg); - splx(s); -} - -static int -ukbd_interrupt(keyboard_t *kbd, void *arg) -{ - usbd_status status = (usbd_status)arg; - ukbd_state_t *state; - struct ukbd_data *ud; - struct timeval tv; - u_long now; - int mod, omod; - int key, c; - int i, j; - - DPRINTFN(5, ("ukbd_intr: status=%d\n", status)); - if (status == USBD_CANCELLED) - return 0; - - state = (ukbd_state_t *)kbd->kb_data; - ud = &state->ks_ndata; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ukbd_intr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(state->ks_intrpipe); - return 0; - } - - if (ud->keycode[0] == KEY_ERROR) - return 0; /* ignore */ - - getmicrouptime(&tv); - now = (u_long)tv.tv_sec*1000 + (u_long)tv.tv_usec/1000; - -#define ADDKEY1(c) \ - if (state->ks_inputs < INPUTBUFSIZE) { \ - state->ks_input[state->ks_inputtail] = (c); \ - ++state->ks_inputs; \ - state->ks_inputtail = (state->ks_inputtail + 1)%INPUTBUFSIZE; \ - } - - mod = ud->modifiers; - omod = state->ks_odata.modifiers; - if (mod != omod) { - for (i = 0; i < NMOD; i++) - if (( mod & ukbd_mods[i].mask) != - (omod & ukbd_mods[i].mask)) - ADDKEY1(ukbd_mods[i].key | - (mod & ukbd_mods[i].mask - ? KEY_PRESS : KEY_RELEASE)); - } - - /* Check for released keys. */ - for (i = 0; i < NKEYCODE; i++) { - key = state->ks_odata.keycode[i]; - if (key == 0) - continue; - for (j = 0; j < NKEYCODE; j++) { - if (ud->keycode[j] == 0) - continue; - if (key == ud->keycode[j]) - goto rfound; - } - ADDKEY1(key | KEY_RELEASE); - rfound: - ; - } - - /* Check for pressed keys. */ - for (i = 0; i < NKEYCODE; i++) { - key = ud->keycode[i]; - if (key == 0) - continue; - state->ks_ntime[i] = now + kbd->kb_delay1; - for (j = 0; j < NKEYCODE; j++) { - if (state->ks_odata.keycode[j] == 0) - continue; - if (key == state->ks_odata.keycode[j]) { - state->ks_ntime[i] = state->ks_otime[j]; - if (state->ks_otime[j] > now) - goto pfound; - state->ks_ntime[i] = now + kbd->kb_delay2; - break; - } - } - ADDKEY1(key | KEY_PRESS); - /* - * If any other key is presently down, force its repeat to be - * well in the future (100s). This makes the last key to be - * pressed do the autorepeat. - */ - for (j = 0; j < NKEYCODE; j++) { - if (j != i) - state->ks_ntime[j] = now + 100 * 1000; - } - pfound: - ; - } - - state->ks_odata = *ud; - bcopy(state->ks_ntime, state->ks_otime, sizeof(state->ks_ntime)); - if (state->ks_inputs <= 0) - return 0; - -#ifdef USB_DEBUG - for (i = state->ks_inputhead, j = 0; j < state->ks_inputs; ++j, - i = (i + 1)%INPUTBUFSIZE) { - c = state->ks_input[i]; - DPRINTF(("0x%x (%d) %s\n", c, c, - (c & KEY_RELEASE) ? "released":"pressed")); - } - if (ud->modifiers) - DPRINTF(("mod:0x%04x ", ud->modifiers)); - for (i = 0; i < NKEYCODE; i++) { - if (ud->keycode[i]) - DPRINTF(("%d ", ud->keycode[i])); - } - DPRINTF(("\n")); -#endif /* USB_DEBUG */ - - if (state->ks_polling) - return 0; - - if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) { - /* let the callback function to process the input */ - (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT, - kbd->kb_callback.kc_arg); - } else { - /* read and discard the input; no one is waiting for it */ - do { - c = ukbd_read_char(kbd, FALSE); - } while (c != NOKEY); - } - - return 0; -} - -static int -ukbd_getc(ukbd_state_t *state, int wait) -{ - int c; - int s; - - if (state->ks_polling) { - DPRINTFN(1,("ukbd_getc: polling\n")); - s = splusb(); - while (state->ks_inputs <= 0) { - usbd_dopoll(state->ks_iface); - if (wait == FALSE) - break; - } - splx(s); - } - s = splusb(); - if (state->ks_inputs <= 0) { - c = -1; - } else { - c = state->ks_input[state->ks_inputhead]; - --state->ks_inputs; - state->ks_inputhead = (state->ks_inputhead + 1)%INPUTBUFSIZE; - } - splx(s); - return c; -} - -/* test the interface to the device */ -static int -ukbd_test_if(keyboard_t *kbd) -{ - return 0; -} - -/* - * Enable the access to the device; until this function is called, - * the client cannot read from the keyboard. - */ -static int -ukbd_enable(keyboard_t *kbd) -{ - int s; - - s = splusb(); - KBD_ACTIVATE(kbd); - splx(s); - return 0; -} - -/* disallow the access to the device */ -static int -ukbd_disable(keyboard_t *kbd) -{ - int s; - - s = splusb(); - KBD_DEACTIVATE(kbd); - splx(s); - return 0; -} - -/* read one byte from the keyboard if it's allowed */ -static int -ukbd_read(keyboard_t *kbd, int wait) -{ - ukbd_state_t *state; - int usbcode; -#ifdef UKBD_EMULATE_ATSCANCODE - int keycode; - int scancode; -#endif - - state = (ukbd_state_t *)kbd->kb_data; -#ifdef UKBD_EMULATE_ATSCANCODE - if (state->ks_buffered_char[0]) { - scancode = state->ks_buffered_char[0]; - if (scancode & SCAN_PREFIX) { - state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX; - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } else { - state->ks_buffered_char[0] = state->ks_buffered_char[1]; - state->ks_buffered_char[1] = 0; - return scancode; - } - } -#endif /* UKBD_EMULATE_ATSCANCODE */ - - /* XXX */ - usbcode = ukbd_getc(state, wait); - if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) - return -1; - ++kbd->kb_count; -#ifdef UKBD_EMULATE_ATSCANCODE - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) - return -1; - - scancode = keycode2scancode(keycode, state->ks_ndata.modifiers, - usbcode & KEY_RELEASE); - if (scancode & SCAN_PREFIX) { - if (scancode & SCAN_PREFIX_CTL) { - state->ks_buffered_char[0] = - 0x1d | (scancode & SCAN_RELEASE); /* Ctrl */ - state->ks_buffered_char[1] = scancode & ~SCAN_PREFIX; - } else if (scancode & SCAN_PREFIX_SHIFT) { - state->ks_buffered_char[0] = - 0x2a | (scancode & SCAN_RELEASE); /* Shift */ - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX_SHIFT; - } else { - state->ks_buffered_char[0] = scancode & ~SCAN_PREFIX; - state->ks_buffered_char[1] = 0; - } - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } - return scancode; -#else /* !UKBD_EMULATE_ATSCANCODE */ - return usbcode; -#endif /* UKBD_EMULATE_ATSCANCODE */ -} - -/* check if data is waiting */ -static int -ukbd_check(keyboard_t *kbd) -{ - if (!KBD_IS_ACTIVE(kbd)) - return FALSE; -#ifdef UKBD_EMULATE_ATSCANCODE - if (((ukbd_state_t *)kbd->kb_data)->ks_buffered_char[0]) - return TRUE; -#endif - if (((ukbd_state_t *)kbd->kb_data)->ks_inputs > 0) - return TRUE; - return FALSE; -} - -/* read char from the keyboard */ -static u_int -ukbd_read_char(keyboard_t *kbd, int wait) -{ - ukbd_state_t *state; - u_int action; - int usbcode; - int keycode; -#ifdef UKBD_EMULATE_ATSCANCODE - int scancode; -#endif - - state = (ukbd_state_t *)kbd->kb_data; -next_code: - /* do we have a composed char to return? */ - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) { - action = state->ks_composed_char; - state->ks_composed_char = 0; - if (action > UCHAR_MAX) - return ERRKEY; - return action; - } - -#ifdef UKBD_EMULATE_ATSCANCODE - /* do we have a pending raw scan code? */ - if (state->ks_mode == K_RAW) { - if (state->ks_buffered_char[0]) { - scancode = state->ks_buffered_char[0]; - if (scancode & SCAN_PREFIX) { - state->ks_buffered_char[0] = - scancode & ~SCAN_PREFIX; - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } else { - state->ks_buffered_char[0] = - state->ks_buffered_char[1]; - state->ks_buffered_char[1] = 0; - return scancode; - } - } - } -#endif /* UKBD_EMULATE_ATSCANCODE */ - - /* see if there is something in the keyboard port */ - /* XXX */ - usbcode = ukbd_getc(state, wait); - if (usbcode == -1) - return NOKEY; - ++kbd->kb_count; - -#ifdef UKBD_EMULATE_ATSCANCODE - /* USB key index -> key code -> AT scan code */ - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) - return NOKEY; - - /* return an AT scan code for the K_RAW mode */ - if (state->ks_mode == K_RAW) { - scancode = keycode2scancode(keycode, state->ks_ndata.modifiers, - usbcode & KEY_RELEASE); - if (scancode & SCAN_PREFIX) { - if (scancode & SCAN_PREFIX_CTL) { - state->ks_buffered_char[0] = - 0x1d | (scancode & SCAN_RELEASE); - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX; - } else if (scancode & SCAN_PREFIX_SHIFT) { - state->ks_buffered_char[0] = - 0x2a | (scancode & SCAN_RELEASE); - state->ks_buffered_char[1] = - scancode & ~SCAN_PREFIX_SHIFT; - } else { - state->ks_buffered_char[0] = - scancode & ~SCAN_PREFIX; - state->ks_buffered_char[1] = 0; - } - return ((scancode & SCAN_PREFIX_E0) ? 0xe0 : 0xe1); - } - return scancode; - } -#else /* !UKBD_EMULATE_ATSCANCODE */ - /* return the byte as is for the K_RAW mode */ - if (state->ks_mode == K_RAW) - return usbcode; - - /* USB key index -> key code */ - keycode = ukbd_trtab[KEY_INDEX(usbcode)]; - if (keycode == NN) - return NOKEY; -#endif /* UKBD_EMULATE_ATSCANCODE */ - - switch (keycode) { - case 0x38: /* left alt (compose key) */ - if (usbcode & KEY_RELEASE) { - if (state->ks_flags & COMPOSE) { - state->ks_flags &= ~COMPOSE; - if (state->ks_composed_char > UCHAR_MAX) - state->ks_composed_char = 0; - } - } else { - if (!(state->ks_flags & COMPOSE)) { - state->ks_flags |= COMPOSE; - state->ks_composed_char = 0; - } - } - break; - /* XXX: I don't like these... */ - case 0x5c: /* print screen */ - if (state->ks_flags & ALTS) - keycode = 0x54; /* sysrq */ - break; - case 0x68: /* pause/break */ - if (state->ks_flags & CTLS) - keycode = 0x6c; /* break */ - break; - } - - /* return the key code in the K_CODE mode */ - if (usbcode & KEY_RELEASE) - keycode |= SCAN_RELEASE; - if (state->ks_mode == K_CODE) - return keycode; - - /* compose a character code */ - if (state->ks_flags & COMPOSE) { - switch (keycode) { - /* key pressed, process it */ - case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x40; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x47; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ - state->ks_composed_char *= 10; - state->ks_composed_char += keycode - 0x4E; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - case 0x52: /* keypad 0 */ - state->ks_composed_char *= 10; - if (state->ks_composed_char > UCHAR_MAX) - return ERRKEY; - goto next_code; - - /* key released, no interest here */ - case SCAN_RELEASE | 0x47: - case SCAN_RELEASE | 0x48: - case SCAN_RELEASE | 0x49: /* keypad 7,8,9 */ - case SCAN_RELEASE | 0x4B: - case SCAN_RELEASE | 0x4C: - case SCAN_RELEASE | 0x4D: /* keypad 4,5,6 */ - case SCAN_RELEASE | 0x4F: - case SCAN_RELEASE | 0x50: - case SCAN_RELEASE | 0x51: /* keypad 1,2,3 */ - case SCAN_RELEASE | 0x52: /* keypad 0 */ - goto next_code; - - case 0x38: /* left alt key */ - break; - - default: - if (state->ks_composed_char > 0) { - state->ks_flags &= ~COMPOSE; - state->ks_composed_char = 0; - return ERRKEY; - } - break; - } - } - - /* keycode to key action */ - action = genkbd_keyaction(kbd, SCAN_CHAR(keycode), - keycode & SCAN_RELEASE, &state->ks_state, - &state->ks_accents); - if (action == NOKEY) - goto next_code; - else - return action; -} - -/* check if char is waiting */ -static int -ukbd_check_char(keyboard_t *kbd) -{ - ukbd_state_t *state; - - if (!KBD_IS_ACTIVE(kbd)) - return FALSE; - state = (ukbd_state_t *)kbd->kb_data; - if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) - return TRUE; - return ukbd_check(kbd); -} - -/* some useful control functions */ -static int -ukbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) -{ - /* trasnlate LED_XXX bits into the device specific bits */ - static u_char ledmap[8] = { - 0, 2, 1, 3, 4, 6, 5, 7, - }; - ukbd_state_t *state = kbd->kb_data; - int s; - int i; -#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ - defined(COMPAT_FREEBSD4) || defined(COMPAT_43) - int ival; -#endif - - s = splusb(); - switch (cmd) { - - case KDGKBMODE: /* get keyboard mode */ - *(int *)arg = state->ks_mode; - break; -#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ - defined(COMPAT_FREEBSD4) || defined(COMPAT_43) - case _IO('K', 7): - ival = IOCPARM_IVAL(arg); - arg = (caddr_t)&ival; - /* FALLTHROUGH */ -#endif - case KDSKBMODE: /* set keyboard mode */ - switch (*(int *)arg) { - case K_XLATE: - if (state->ks_mode != K_XLATE) { - /* make lock key state and LED state match */ - state->ks_state &= ~LOCK_MASK; - state->ks_state |= KBD_LED_VAL(kbd); - } - /* FALLTHROUGH */ - case K_RAW: - case K_CODE: - if (state->ks_mode != *(int *)arg) { - ukbd_clear_state(kbd); - state->ks_mode = *(int *)arg; - } - break; - default: - splx(s); - return EINVAL; - } - break; - - case KDGETLED: /* get keyboard LED */ - *(int *)arg = KBD_LED_VAL(kbd); - break; -#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ - defined(COMPAT_FREEBSD4) || defined(COMPAT_43) - case _IO('K', 66): - ival = IOCPARM_IVAL(arg); - arg = (caddr_t)&ival; - /* FALLTHROUGH */ -#endif - case KDSETLED: /* set keyboard LED */ - /* NOTE: lock key state in ks_state won't be changed */ - if (*(int *)arg & ~LOCK_MASK) { - splx(s); - return EINVAL; - } - i = *(int *)arg; - /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ - if (state->ks_mode == K_XLATE && - kbd->kb_keymap->n_keys > ALTGR_OFFSET) { - if (i & ALKED) - i |= CLKED; - else - i &= ~CLKED; - } - if (KBD_HAS_DEVICE(kbd)) { - set_leds(state, ledmap[i & LED_MASK]); - /* XXX: error check? */ - } - KBD_LED_VAL(kbd) = *(int *)arg; - break; - - case KDGKBSTATE: /* get lock key state */ - *(int *)arg = state->ks_state & LOCK_MASK; - break; -#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ - defined(COMPAT_FREEBSD4) || defined(COMPAT_43) - case _IO('K', 20): - ival = IOCPARM_IVAL(arg); - arg = (caddr_t)&ival; - /* FALLTHROUGH */ -#endif - case KDSKBSTATE: /* set lock key state */ - if (*(int *)arg & ~LOCK_MASK) { - splx(s); - return EINVAL; - } - state->ks_state &= ~LOCK_MASK; - state->ks_state |= *(int *)arg; - splx(s); - /* set LEDs and quit */ - return ukbd_ioctl(kbd, KDSETLED, arg); - - case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ - splx(s); - if (!KBD_HAS_DEVICE(kbd)) - return 0; - if (((int *)arg)[1] < 0) - return EINVAL; - if (((int *)arg)[0] < 0) - return EINVAL; - else if (((int *)arg)[0] == 0) /* fastest possible value */ - kbd->kb_delay1 = 200; - else - kbd->kb_delay1 = ((int *)arg)[0]; - kbd->kb_delay2 = ((int *)arg)[1]; - return 0; - -#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ - defined(COMPAT_FREEBSD4) || defined(COMPAT_43) - case _IO('K', 67): - ival = IOCPARM_IVAL(arg); - arg = (caddr_t)&ival; - /* FALLTHROUGH */ -#endif - case KDSETRAD: /* set keyboard repeat rate (old interface) */ - splx(s); - return set_typematic(kbd, *(int *)arg); - - case PIO_KEYMAP: /* set keyboard translation table */ - case PIO_KEYMAPENT: /* set keyboard translation table entry */ - case PIO_DEADKEYMAP: /* set accent key translation table */ - state->ks_accents = 0; - /* FALLTHROUGH */ - default: - splx(s); - return genkbd_commonioctl(kbd, cmd, arg); - -#ifdef USB_DEBUG - case USB_SETDEBUG: - ukbddebug = *(int *)arg; - break; -#endif - } - - splx(s); - return 0; -} - -/* lock the access to the keyboard */ -static int -ukbd_lock(keyboard_t *kbd, int lock) -{ - /* XXX ? */ - return TRUE; -} - -/* clear the internal state of the keyboard */ -static void -ukbd_clear_state(keyboard_t *kbd) -{ - ukbd_state_t *state; - - state = (ukbd_state_t *)kbd->kb_data; - state->ks_flags = 0; - state->ks_polling = 0; - state->ks_state &= LOCK_MASK; /* preserve locking key state */ - state->ks_accents = 0; - state->ks_composed_char = 0; -#ifdef UKBD_EMULATE_ATSCANCODE - state->ks_buffered_char[0] = 0; - state->ks_buffered_char[1] = 0; -#endif - bzero(&state->ks_ndata, sizeof(state->ks_ndata)); - bzero(&state->ks_odata, sizeof(state->ks_odata)); - bzero(&state->ks_ntime, sizeof(state->ks_ntime)); - bzero(&state->ks_otime, sizeof(state->ks_otime)); -} - -/* save the internal state */ -static int -ukbd_get_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len == 0) - return sizeof(ukbd_state_t); - if (len < sizeof(ukbd_state_t)) - return -1; - bcopy(kbd->kb_data, buf, sizeof(ukbd_state_t)); - return 0; -} - -/* set the internal state */ -static int -ukbd_set_state(keyboard_t *kbd, void *buf, size_t len) -{ - if (len < sizeof(ukbd_state_t)) - return ENOMEM; - bcopy(buf, kbd->kb_data, sizeof(ukbd_state_t)); - return 0; -} - -static int -ukbd_poll(keyboard_t *kbd, int on) -{ - ukbd_state_t *state; - usbd_device_handle dev; - int s; - - state = (ukbd_state_t *)kbd->kb_data; - usbd_interface2device_handle(state->ks_iface, &dev); - - s = splusb(); - if (on) { - ++state->ks_polling; - if (state->ks_polling == 1) - usbd_set_polling(dev, on); - } else { - --state->ks_polling; - if (state->ks_polling == 0) - usbd_set_polling(dev, on); - } - splx(s); - return 0; -} - -/* local functions */ - -static int -probe_keyboard(struct usb_attach_arg *uaa, int flags) -{ - usb_interface_descriptor_t *id; - - if (!uaa->iface) /* we attach to ifaces only */ - return EINVAL; - - /* Check that this is a keyboard that speaks the boot protocol. */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id - && id->bInterfaceClass == UICLASS_HID - && id->bInterfaceSubClass == UISUBCLASS_BOOT - && id->bInterfaceProtocol == UPROTO_BOOT_KEYBOARD) - return 0; /* found it */ - - return EINVAL; -} - -static int -init_keyboard(ukbd_state_t *state, int *type, int flags) -{ - usb_endpoint_descriptor_t *ed; - - *type = KB_OTHER; - - state->ks_ifstate |= DISCONNECTED; - - ed = usbd_interface2endpoint_descriptor(state->ks_iface, 0); - if (!ed) { - printf("ukbd: could not read endpoint descriptor\n"); - return EIO; - } - - DPRINTFN(10,("ukbd:init_keyboard: \ -bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - UE_GET_ADDR(ed->bEndpointAddress), - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out", - UE_GET_XFERTYPE(ed->bmAttributes), - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || - UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { - printf("ukbd: unexpected endpoint\n"); - return EINVAL; - } - - /* Ignore if SETIDLE fails since it is not crucial. */ - usbd_set_idle(state->ks_iface, 0, 0); - - state->ks_ep_addr = ed->bEndpointAddress; - state->ks_ifstate &= ~DISCONNECTED; - - return 0; -} - -static void -set_leds(ukbd_state_t *state, int leds) -{ - - DPRINTF(("ukbd:set_leds: state=%p leds=%d\n", state, leds)); - state->ks_leds = leds; - usbd_set_report_async(state->ks_iface, UHID_OUTPUT_REPORT, 0, - &state->ks_leds, 1); -} - -static int -set_typematic(keyboard_t *kbd, int code) -{ - static int delays[] = { 250, 500, 750, 1000 }; - static int rates[] = { 34, 38, 42, 46, 50, 55, 59, 63, - 68, 76, 84, 92, 100, 110, 118, 126, - 136, 152, 168, 184, 200, 220, 236, 252, - 272, 304, 336, 368, 400, 440, 472, 504 }; - - if (code & ~0x7f) - return EINVAL; - kbd->kb_delay1 = delays[(code >> 5) & 3]; - kbd->kb_delay2 = rates[code & 0x1f]; - return 0; -} - -#ifdef UKBD_EMULATE_ATSCANCODE -static int -keycode2scancode(int keycode, int shift, int up) -{ - static int scan[] = { - 0x1c, 0x1d, 0x35, - 0x37 | SCAN_PREFIX_SHIFT, /* PrintScreen */ - 0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f, - 0x50, 0x51, 0x52, 0x53, - 0x46, /* XXX Pause/Break */ - 0x5b, 0x5c, 0x5d, - /* SUN TYPE 6 USB KEYBOARD */ - 0x68, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, - 0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e, - 0x20, - }; - int scancode; - - scancode = keycode; - if ((keycode >= 89) && (keycode < 89 + sizeof(scan)/sizeof(scan[0]))) - scancode = scan[keycode - 89] | SCAN_PREFIX_E0; - /* Pause/Break */ - if ((keycode == 104) && !(shift & (MOD_CONTROL_L | MOD_CONTROL_R))) - scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL; - if (shift & (MOD_SHIFT_L | MOD_SHIFT_R)) - scancode &= ~SCAN_PREFIX_SHIFT; - return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS)); -} -#endif /* UKBD_EMULATE_ATSCANCODE */ - -static int -ukbd_driver_load(module_t mod, int what, void *arg) -{ - switch (what) { - case MOD_LOAD: - kbd_add_driver(&ukbd_kbd_driver); - break; - case MOD_UNLOAD: - kbd_delete_driver(&ukbd_kbd_driver); - break; - } - return usbd_driver_load(mod, what, arg); -} diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c deleted file mode 100644 index 99a1433..0000000 --- a/sys/dev/usb/ulpt.c +++ /dev/null @@ -1,815 +0,0 @@ -/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */ - -/*- - * Copyright (c) 1998, 2003 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> -__FBSDID("$FreeBSD$"); - -/* - * Printer Class spec: http://www.usb.org/developers/data/devclass/usbprint109.PDF - */ - -/* XXXimp: need to migrate from devclass_get_softc */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/fcntl.h> -#include <sys/ioccom.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/uio.h> -#include <sys/conf.h> -#include <sys/syslog.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ -#define STEP hz/4 - -#define LPTPRI (PZERO+8) -#define ULPT_BSIZE PAGE_SIZE - -#define ULPT_READS_PER_SEC 5 -#define ULPT_READ_TIMO 10 - -#ifdef USB_DEBUG -#define DPRINTF(x) if (ulptdebug) printf x -#define DPRINTFN(n,x) if (ulptdebug>(n)) printf x -int ulptdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ulpt, CTLFLAG_RW, 0, "USB ulpt"); -SYSCTL_INT(_hw_usb_ulpt, OID_AUTO, debug, CTLFLAG_RW, - &ulptdebug, 0, "ulpt debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UR_GET_DEVICE_ID 0 -#define UR_GET_PORT_STATUS 1 -#define UR_SOFT_RESET 2 - -#define LPS_NERR 0x08 /* printer no error */ -#define LPS_SELECT 0x10 /* printer selected */ -#define LPS_NOPAPER 0x20 /* printer out of paper */ -#define LPS_INVERT (LPS_SELECT|LPS_NERR) -#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) - -struct ulpt_softc { - device_t sc_dev; - usbd_device_handle sc_udev; /* device */ - usbd_interface_handle sc_iface; /* interface */ - int sc_ifaceno; - - int sc_out; - usbd_pipe_handle sc_out_pipe; /* bulk out pipe */ - usbd_xfer_handle sc_out_xfer; - void *sc_out_buf; - - int sc_in; - usbd_pipe_handle sc_in_pipe; /* bulk in pipe */ - usbd_xfer_handle sc_in_xfer; - void *sc_in_buf; - - struct callout sc_read_callout; - int sc_has_callout; - - u_char sc_state; -#define ULPT_OPEN 0x01 /* device is open */ -#define ULPT_OBUSY 0x02 /* printer is busy doing output */ -#define ULPT_INIT 0x04 /* waiting to initialize for open */ - u_char sc_flags; -#define ULPT_NOPRIME 0x40 /* don't prime on open */ - u_char sc_laststatus; - - int sc_refcnt; - u_char sc_dying; - - struct cdev *dev; - struct cdev *dev_noprime; -}; - -static d_open_t ulptopen; -static d_close_t ulptclose; -static d_write_t ulptwrite; -static d_read_t ulptread; -static d_ioctl_t ulptioctl; - - -static struct cdevsw ulpt_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ulptopen, - .d_close = ulptclose, - .d_write = ulptwrite, - .d_read = ulptread, - .d_ioctl = ulptioctl, - .d_name = "ulpt", -}; - -void ulpt_disco(void *); - -int ulpt_do_write(struct ulpt_softc *, struct uio *uio, int); -int ulpt_do_read(struct ulpt_softc *, struct uio *uio, int); -int ulpt_status(struct ulpt_softc *); -void ulpt_reset(struct ulpt_softc *); -int ulpt_statusmsg(u_char, struct ulpt_softc *); -void ulpt_read_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status); -void ulpt_tick(void *xsc); - -#if 0 -void ieee1284_print_id(char *); -#endif - -#define ULPTUNIT(s) (dev2unit(s) & 0x1f) -#define ULPTFLAGS(s) (dev2unit(s) & 0xe0) - -static device_probe_t ulpt_match; -static device_attach_t ulpt_attach; -static device_detach_t ulpt_detach; - -static device_method_t ulpt_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ulpt_match), - DEVMETHOD(device_attach, ulpt_attach), - DEVMETHOD(device_detach, ulpt_detach), - - { 0, 0 } -}; - -static driver_t ulpt_driver = { - "ulpt", - ulpt_methods, - sizeof(struct ulpt_softc) -}; - -static devclass_t ulpt_devclass; - -MODULE_DEPEND(umass, usb, 1, 1, 1); -DRIVER_MODULE(ulpt, uhub, ulpt_driver, ulpt_devclass, usbd_driver_load, 0); - -static int -ulpt_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - DPRINTFN(10,("ulpt_match\n")); - if (uaa->iface == NULL) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (id != NULL && - id->bInterfaceClass == UICLASS_PRINTER && - id->bInterfaceSubClass == UISUBCLASS_PRINTER && - (id->bInterfaceProtocol == UIPROTO_PRINTER_UNI || - id->bInterfaceProtocol == UIPROTO_PRINTER_BI || - id->bInterfaceProtocol == UIPROTO_PRINTER_1284)) - return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); - return (UMATCH_NONE); -} - -static int -ulpt_attach(device_t self) -{ - struct ulpt_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); - usb_interface_descriptor_t *id, *iend; - usb_config_descriptor_t *cdesc; - usbd_status err; - usb_endpoint_descriptor_t *ed; - u_int8_t epcount; - int i, altno; - - DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); - sc->sc_dev = self; - - /* XXX - * Stepping through the alternate settings needs to be abstracted out. - */ - cdesc = usbd_get_config_descriptor(dev); - if (cdesc == NULL) { - printf("%s: failed to get configuration descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - iend = (usb_interface_descriptor_t *) - ((char *)cdesc + UGETW(cdesc->wTotalLength)); -#ifdef DIAGNOSTIC - if (ifcd < (usb_interface_descriptor_t *)cdesc || - ifcd >= iend) - panic("ulpt: iface desc out of range"); -#endif - /* Step through all the descriptors looking for bidir mode */ - for (id = ifcd, altno = 0; - id < iend; - id = (void *)((char *)id + id->bLength)) { - if (id->bDescriptorType == UDESC_INTERFACE && - id->bInterfaceNumber == ifcd->bInterfaceNumber) { - if (id->bInterfaceClass == UICLASS_PRINTER && - id->bInterfaceSubClass == UISUBCLASS_PRINTER && - (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /* || - id->bInterfaceProtocol == UIPROTO_PRINTER_1284 */)) - goto found; - altno++; - } - } - id = ifcd; /* not found, use original */ - found: - if (id != ifcd) { - /* Found a new bidir setting */ - DPRINTF(("ulpt_attach: set altno = %d\n", altno)); - err = usbd_set_interface(iface, altno); - if (err) { - printf("%s: setting alternate interface failed\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - } - - epcount = 0; - (void)usbd_endpoint_count(iface, &epcount); - - sc->sc_in = -1; - sc->sc_out = -1; - for (i = 0; i < epcount; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - printf("%s: couldn't get ep %d\n", - device_get_nameunit(sc->sc_dev), i); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_in = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - sc->sc_out = ed->bEndpointAddress; - } - } - if (sc->sc_out == -1) { - printf("%s: could not find bulk out endpoint\n", - device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } - - if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { - /* This device doesn't handle reading properly. */ - sc->sc_in = -1; - } - - printf("%s: using %s-directional mode\n", device_get_nameunit(sc->sc_dev), - sc->sc_in >= 0 ? "bi" : "uni"); - - DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); - - sc->sc_iface = iface; - sc->sc_ifaceno = id->bInterfaceNumber; - sc->sc_udev = dev; - -#if 0 -/* - * This code is disabled because for some mysterious reason it causes - * printing not to work. But only sometimes, and mostly with - * UHCI and less often with OHCI. *sigh* - */ - { - usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); - usb_device_request_t req; - int len, alen; - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_DEVICE_ID; - USETW(req.wValue, cd->bConfigurationValue); - USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); - USETW(req.wLength, sizeof devinfo - 1); - err = usbd_do_request_flags(dev, &req, devinfo, USBD_SHORT_XFER_OK, - &alen, USBD_DEFAULT_TIMEOUT); - if (err) { - printf("%s: cannot get device id\n", device_get_nameunit(sc->sc_dev)); - } else if (alen <= 2) { - printf("%s: empty device id, no printer connected?\n", - device_get_nameunit(sc->sc_dev)); - } else { - /* devinfo now contains an IEEE-1284 device ID */ - len = ((devinfo[0] & 0xff) << 8) | (devinfo[1] & 0xff); - if (len > sizeof devinfo - 3) - len = sizeof devinfo - 3; - devinfo[len] = 0; - printf("%s: device id <", device_get_nameunit(sc->sc_dev)); - ieee1284_print_id(devinfo+2); - printf(">\n"); - } - } -#endif - - sc->dev = make_dev(&ulpt_cdevsw, device_get_unit(self), - UID_ROOT, GID_OPERATOR, 0644, "ulpt%d", device_get_unit(self)); - sc->dev_noprime = make_dev(&ulpt_cdevsw, - device_get_unit(self)|ULPT_NOPRIME, - UID_ROOT, GID_OPERATOR, 0644, "unlpt%d", device_get_unit(self)); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); - - return 0; -} - - -static int -ulpt_detach(device_t self) -{ - struct ulpt_softc *sc = device_get_softc(self); - int s; - - DPRINTF(("ulpt_detach: sc=%p\n", sc)); - - sc->sc_dying = 1; - if (sc->sc_out_pipe != NULL) - usbd_abort_pipe(sc->sc_out_pipe); - if (sc->sc_in_pipe != NULL) - usbd_abort_pipe(sc->sc_in_pipe); - - s = splusb(); - if (--sc->sc_refcnt >= 0) { - /* There is noone to wake, aborting the pipe is enough */ - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - splx(s); - - destroy_dev(sc->dev); - destroy_dev(sc->dev_noprime); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return (0); -} - -int -ulpt_status(struct ulpt_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - u_char status; - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_PORT_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_udev, &req, &status); - DPRINTFN(1, ("ulpt_status: status=0x%02x err=%d\n", status, err)); - if (!err) - return (status); - else - return (0); -} - -void -ulpt_reset(struct ulpt_softc *sc) -{ - usb_device_request_t req; - - DPRINTFN(1, ("ulpt_reset\n")); - req.bRequest = UR_SOFT_RESET; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ifaceno); - USETW(req.wLength, 0); - - /* - * There was a mistake in the USB printer 1.0 spec that gave the - * request type as UT_WRITE_CLASS_OTHER; it should have been - * UT_WRITE_CLASS_INTERFACE. Many printers use the old one, - * so we try both. - */ - req.bmRequestType = UT_WRITE_CLASS_OTHER; - if (usbd_do_request(sc->sc_udev, &req, 0)) { /* 1.0 */ - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - (void)usbd_do_request(sc->sc_udev, &req, 0); /* 1.1 */ - } -} -#if 0 -static void -ulpt_input(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct ulpt_softc *sc = priv; - u_int32_t count; - - /* Don't loop on errors or 0-length input. */ - usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); - if (status != USBD_NORMAL_COMPLETION || count == 0) - return; - - DPRINTFN(2,("ulpt_input: got some data\n")); - /* Do it again. */ - if (xfer == sc->sc_in_xfer1) - usbd_transfer(sc->sc_in_xfer2); - else - usbd_transfer(sc->sc_in_xfer1); -} -#endif - -int ulptusein = 1; - -/* - * Reset the printer, then wait until it's selected and not busy. - */ -int -ulptopen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - u_char flags = ULPTFLAGS(dev); - struct ulpt_softc *sc; - usbd_status err; - int error; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying) - return (ENXIO); - - if (sc->sc_state) - return (EBUSY); - - sc->sc_state = ULPT_INIT; - sc->sc_flags = flags; - DPRINTF(("ulptopen: flags=0x%x\n", (unsigned)flags)); - -#if defined(USB_DEBUG) - /* Ignoring these flags might not be a good idea */ - if ((flags & ~ULPT_NOPRIME) != 0) - printf("ulptopen: flags ignored: %b\n", flags, - "\20\3POS_INIT\4POS_ACK\6PRIME_OPEN\7AUTOLF\10BYPASS"); -#endif - - - error = 0; - sc->sc_refcnt++; - - if ((flags & ULPT_NOPRIME) == 0) { - ulpt_reset(sc); - if (sc->sc_dying) { - error = ENXIO; - sc->sc_state = 0; - goto done; - } - } - - err = usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe); - if (err) { - error = EIO; - goto err0; - } - sc->sc_out_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_out_xfer == NULL) { - error = ENOMEM; - goto err1; - } - sc->sc_out_buf = usbd_alloc_buffer(sc->sc_out_xfer, ULPT_BSIZE); - if (sc->sc_out_buf == NULL) { - error = ENOMEM; - goto err2; - } - - if (ulptusein && sc->sc_in != -1) { - DPRINTF(("ulpt_open: open input pipe\n")); - err = usbd_open_pipe(sc->sc_iface, sc->sc_in,0,&sc->sc_in_pipe); - if (err) { - error = EIO; - goto err2; - } - sc->sc_in_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_in_xfer == NULL) { - error = ENOMEM; - goto err3; - } - sc->sc_in_buf = usbd_alloc_buffer(sc->sc_in_xfer, ULPT_BSIZE); - if (sc->sc_in_buf == NULL) { - error = ENOMEM; - goto err4; - } - - /* If it's not opened for read the set up a reader. */ - if (!(flag & FREAD)) { - DPRINTF(("ulpt_open: start read callout\n")); - callout_init(&sc->sc_read_callout, 0); - callout_reset(&sc->sc_read_callout, hz/5, ulpt_tick, - sc); - sc->sc_has_callout = 1; - } - } - - sc->sc_state = ULPT_OPEN; - goto done; - - err4: - usbd_free_xfer(sc->sc_in_xfer); - sc->sc_in_xfer = NULL; - err3: - usbd_close_pipe(sc->sc_in_pipe); - sc->sc_in_pipe = NULL; - err2: - usbd_free_xfer(sc->sc_out_xfer); - sc->sc_out_xfer = NULL; - err1: - usbd_close_pipe(sc->sc_out_pipe); - sc->sc_out_pipe = NULL; - err0: - sc->sc_state = 0; - - done: - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - DPRINTF(("ulptopen: done, error=%d\n", error)); - return (error); -} - -int -ulpt_statusmsg(u_char status, struct ulpt_softc *sc) -{ - u_char new; - - status = (status ^ LPS_INVERT) & LPS_MASK; - new = status & ~sc->sc_laststatus; - sc->sc_laststatus = status; - - if (new & LPS_SELECT) - log(LOG_NOTICE, "%s: offline\n", device_get_nameunit(sc->sc_dev)); - else if (new & LPS_NOPAPER) - log(LOG_NOTICE, "%s: out of paper\n", device_get_nameunit(sc->sc_dev)); - else if (new & LPS_NERR) - log(LOG_NOTICE, "%s: output error\n", device_get_nameunit(sc->sc_dev)); - - return (status); -} - -int -ulptclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct ulpt_softc *sc; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - - if (sc->sc_state != ULPT_OPEN) - /* We are being forced to close before the open completed. */ - return (0); - - if (sc->sc_has_callout) { - callout_stop(&sc->sc_read_callout); - sc->sc_has_callout = 0; - } - - if (sc->sc_out_pipe != NULL) { - usbd_abort_pipe(sc->sc_out_pipe); - usbd_close_pipe(sc->sc_out_pipe); - sc->sc_out_pipe = NULL; - } - if (sc->sc_out_xfer != NULL) { - usbd_free_xfer(sc->sc_out_xfer); - sc->sc_out_xfer = NULL; - } - - if (sc->sc_in_pipe != NULL) { - usbd_abort_pipe(sc->sc_in_pipe); - usbd_close_pipe(sc->sc_in_pipe); - sc->sc_in_pipe = NULL; - } - if (sc->sc_in_xfer != NULL) { - usbd_free_xfer(sc->sc_in_xfer); - sc->sc_in_xfer = NULL; - } - - sc->sc_state = 0; - - DPRINTF(("ulptclose: closed\n")); - return (0); -} - -int -ulpt_do_write(struct ulpt_softc *sc, struct uio *uio, int flags) -{ - u_int32_t n; - int error = 0; - void *bufp; - usbd_xfer_handle xfer; - usbd_status err; - - DPRINTF(("ulptwrite\n")); - xfer = sc->sc_out_xfer; - bufp = sc->sc_out_buf; - while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { - ulpt_statusmsg(ulpt_status(sc), sc); - error = uiomove(bufp, n, uio); - if (error) - break; - DPRINTFN(1, ("ulptwrite: transfer %d bytes\n", n)); - err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY, - USBD_NO_TIMEOUT, bufp, &n, "ulptwr"); - if (err) { - DPRINTF(("ulptwrite: error=%d\n", err)); - error = EIO; - break; - } - } - - return (error); -} - -int -ulptwrite(struct cdev *dev, struct uio *uio, int flags) -{ - struct ulpt_softc *sc; - int error; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ulpt_do_write(sc, uio, flags); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -int -ulpt_do_read(struct ulpt_softc *sc, struct uio *uio, int flags) -{ - u_int32_t n, on; - int error = 0; - void *bufp; - usbd_xfer_handle xfer; - usbd_status err; - - DPRINTF(("ulptread\n")); - - if (sc->sc_in_pipe == NULL) - return 0; - - xfer = sc->sc_in_xfer; - bufp = sc->sc_in_buf; - while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { - DPRINTFN(1, ("ulptread: transfer %d bytes\n", n)); - on = n; - err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, - USBD_NO_COPY | USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, bufp, &n, "ulptrd"); - if (err) { - DPRINTF(("ulptread: error=%d\n", err)); - error = EIO; - break; - } - error = uiomove(bufp, n, uio); - if (error) - break; - if (on != n) - break; - } - - return (error); -} - -int -ulptread(struct cdev *dev, struct uio *uio, int flags) -{ - struct ulpt_softc *sc; - int error; - - sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev)); - - if (sc->sc_dying) - return (EIO); - - sc->sc_refcnt++; - error = ulpt_do_read(sc, uio, flags); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -void -ulpt_read_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - usbd_status err; - u_int32_t n; - usbd_private_handle xsc; - struct ulpt_softc *sc; - - usbd_get_xfer_status(xfer, &xsc, NULL, &n, &err); - sc = xsc; - - DPRINTFN(1,("ulpt_read_cb: start sc=%p, err=%d n=%d\n", sc, err, n)); - -#ifdef ULPT_DEBUG - if (!err && n > 0) - DPRINTF(("ulpt_tick: discarding %d bytes\n", n)); -#endif - if (!err || err == USBD_TIMEOUT) - callout_reset(&sc->sc_read_callout, hz / ULPT_READS_PER_SEC, - ulpt_tick, sc); -} - -void -ulpt_tick(void *xsc) -{ - struct ulpt_softc *sc = xsc; - usbd_status err; - - if (sc == NULL || sc->sc_dying) - return; - - DPRINTFN(1,("ulpt_tick: start sc=%p\n", sc)); - - usbd_setup_xfer(sc->sc_in_xfer, sc->sc_in_pipe, sc, sc->sc_in_buf, - ULPT_BSIZE, USBD_NO_COPY | USBD_SHORT_XFER_OK, - ULPT_READ_TIMO, ulpt_read_cb); - err = usbd_transfer(sc->sc_in_xfer); - DPRINTFN(1,("ulpt_tick: err=%d\n", err)); -} - -int -ulptioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *p) -{ - int error = 0; - - switch (cmd) { - default: - error = ENODEV; - } - - return (error); -} - -#if 0 -/* XXX This does not belong here. */ -/* - * Print select parts of an IEEE 1284 device ID. - */ -void -ieee1284_print_id(char *str) -{ - char *p, *q; - - for (p = str-1; p; p = strchr(p, ';')) { - p++; /* skip ';' */ - if (strncmp(p, "MFG:", 4) == 0 || - strncmp(p, "MANUFACTURER:", 14) == 0 || - strncmp(p, "MDL:", 4) == 0 || - strncmp(p, "MODEL:", 6) == 0) { - q = strchr(p, ';'); - if (q) - printf("%.*s", (int)(q - p + 1), p); - } - } -} -#endif diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c deleted file mode 100644 index b0b73cc..0000000 --- a/sys/dev/usb/umass.c +++ /dev/null @@ -1,3611 +0,0 @@ -/*- - * 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$ - * $NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $ - */ - -/* Also already merged from NetBSD: - * $NetBSD: umass.c,v 1.67 2001/11/25 19:05:22 augustss Exp $ - * $NetBSD: umass.c,v 1.90 2002/11/04 19:17:33 pooka Exp $ - * $NetBSD: umass.c,v 1.108 2003/11/07 17:03:25 wiz Exp $ - * $NetBSD: umass.c,v 1.109 2003/12/04 13:57:31 keihan Exp $ - */ - -/* - * Universal Serial Bus Mass Storage Class specs: - * http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf - * http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf - * http://www.usb.org/developers/devclass_docs/usb_msc_cbi_1.1.pdf - * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf - */ - -/* - * Ported to NetBSD by Lennart Augustsson <augustss@NetBSD.org>. - * Parts of the code written by Jason R. Thorpe <thorpej@shagadelic.org>. - */ - -/* - * The driver handles 3 Wire Protocols - * - Command/Bulk/Interrupt (CBI) - * - Command/Bulk/Interrupt with Command Completion Interrupt (CBI with CCI) - * - Mass Storage Bulk-Only (BBB) - * (BBB refers Bulk/Bulk/Bulk for Command/Data/Status phases) - * - * Over these wire protocols it handles the following command protocols - * - SCSI - * - UFI (floppy command set) - * - 8070i (ATAPI) - * - * UFI and 8070i (ATAPI) 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): - * - * - probe/attach/detach - * - generic transfer routines - * - BBB - * - CBI - * - CBI_I (in addition to functions from CBI) - * - CAM (Common Access Method) - * - SCSI - * - UFI - * - 8070i (ATAPI) - * - * The protocols are implemented using a state machine, for the transfers as - * well as for the resets. The state machine is contained in umass_*_state. - * The state machine is started through either umass_*_transfer or - * umass_*_reset. - * - * The reason for doing this is a) CAM performs a lot better this way and b) it - * avoids using tsleep from interrupt context (for example after a failed - * transfer). - */ - -/* - * The SCSI related part of this driver has been derived from the - * dev/ppbus/vpo.c driver, by Nicolas Souchu (nsouch@freebsd.org). - * - * The CAM layer uses so called actions which are messages sent to the host - * adapter for completion. The actions come in through umass_cam_action. The - * appropriate block of routines is called depending on the transport protocol - * in use. When the transfer has finished, these routines call - * umass_cam_cb again to complete the CAM command. - */ - -/* - * XXX Currently CBI with CCI is not supported because it bombs the system - * when the device is detached (low frequency interrupts are detached - * too late. - */ -#undef CBI_I - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/bus.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#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> - -#include <cam/cam_periph.h> - -#ifdef USB_DEBUG -#define DIF(m, x) if (umassdebug & (m)) do { x ; } while (0) -#define DPRINTF(m, x) if (umassdebug & (m)) printf x -#define UDMASS_GEN 0x00010000 /* general */ -#define UDMASS_SCSI 0x00020000 /* scsi */ -#define UDMASS_UFI 0x00040000 /* ufi command set */ -#define UDMASS_ATAPI 0x00080000 /* 8070i command set */ -#define UDMASS_CMD (UDMASS_SCSI|UDMASS_UFI|UDMASS_ATAPI) -#define UDMASS_USB 0x00100000 /* USB general */ -#define UDMASS_BBB 0x00200000 /* Bulk-Only transfers */ -#define UDMASS_CBI 0x00400000 /* CBI transfers */ -#define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI) -#define UDMASS_ALL 0xffff0000 /* all of the above */ -int umassdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass"); -SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW, - &umassdebug, 0, "umass debug level"); -#else -#define DIF(m, x) /* nop */ -#define DPRINTF(m, x) /* nop */ -#endif - - -/* Generic definitions */ - -/* Direction for umass_*_transfer */ -#define DIR_NONE 0 -#define DIR_IN 1 -#define DIR_OUT 2 - -/* device name */ -#define DEVNAME "umass" -#define DEVNAME_SIM "umass-sim" - -#define UMASS_MAX_TRANSFER_SIZE 65536 -/* Approximate maximum transfer speeds (assumes 33% overhead). */ -#define UMASS_FULL_TRANSFER_SPEED 1000 -#define UMASS_HIGH_TRANSFER_SPEED 40000 -#define UMASS_FLOPPY_TRANSFER_SPEED 20 - -#define UMASS_TIMEOUT 5000 /* msecs */ - -/* CAM specific definitions */ - -#define UMASS_SCSIID_MAX 1 /* maximum number of drives expected */ -#define UMASS_SCSIID_HOST UMASS_SCSIID_MAX - -#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 /* Get maximum lun */ - -/* 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]; -} __packed umass_bbb_cbw_t; -#define UMASS_BBB_CBW_SIZE 31 - -/* Command Status Wrapper */ -typedef struct { - uDWord dCSWSignature; -# define CSWSIGNATURE 0x53425355 -# define CSWSIGNATURE_IMAGINATION_DBX1 0x43425355 -# define CSWSIGNATURE_OLYMPUS_C1 0x55425355 - uDWord dCSWTag; - uDWord dCSWDataResidue; - uByte bCSWStatus; -# define CSWSTATUS_GOOD 0x0 -# define CSWSTATUS_FAILED 0x1 -# define CSWSTATUS_PHASE 0x2 -} __packed 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, u_int timeout, transfer_cb_f cb, void *priv); -typedef void (*wire_state_f) (usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status err); - -typedef int (*command_transform_f) (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - - -struct umass_devdescr_t { - u_int32_t vid; -# define VID_WILDCARD 0xffffffff -# define VID_EOT 0xfffffffe - u_int32_t pid; -# define PID_WILDCARD 0xffffffff -# define PID_EOT 0xfffffffe - u_int32_t rid; -# define RID_WILDCARD 0xffffffff -# define RID_EOT 0xfffffffe - - /* wire and command protocol */ - u_int16_t proto; -# define UMASS_PROTO_BBB 0x0001 /* USB wire protocol */ -# define UMASS_PROTO_CBI 0x0002 -# define UMASS_PROTO_CBI_I 0x0004 -# define UMASS_PROTO_WIRE 0x00ff /* USB wire protocol mask */ -# define UMASS_PROTO_SCSI 0x0100 /* command protocol */ -# define UMASS_PROTO_ATAPI 0x0200 -# define UMASS_PROTO_UFI 0x0400 -# define UMASS_PROTO_RBC 0x0800 -# define UMASS_PROTO_COMMAND 0xff00 /* command protocol mask */ - - /* Device specific quirks */ - u_int16_t quirks; -# define NO_QUIRKS 0x0000 - /* The drive does not support Test Unit Ready. Convert to Start Unit - */ -# define NO_TEST_UNIT_READY 0x0001 - /* 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. - */ -# define RS_NO_CLEAR_UA 0x0002 - /* The drive does not support START STOP. */ -# define NO_START_STOP 0x0004 - /* Don't ask for full inquiry data (255b). */ -# define FORCE_SHORT_INQUIRY 0x0008 - /* Needs to be initialised the Shuttle way */ -# define SHUTTLE_INIT 0x0010 - /* Drive needs to be switched to alternate iface 1 */ -# define ALT_IFACE_1 0x0020 - /* Drive does not do 1Mb/s, but just floppy speeds (20kb/s) */ -# define FLOPPY_SPEED 0x0040 - /* The device can't count and gets the residue of transfers wrong */ -# define IGNORE_RESIDUE 0x0080 - /* No GetMaxLun call */ -# define NO_GETMAXLUN 0x0100 - /* The device uses a weird CSWSIGNATURE. */ -# define WRONG_CSWSIG 0x0200 - /* Device cannot handle INQUIRY so fake a generic response */ -# define NO_INQUIRY 0x0400 - /* Device cannot handle INQUIRY EVPD, return CHECK CONDITION */ -# define NO_INQUIRY_EVPD 0x0800 - /* Pad all RBC requests to 12 bytes. */ -# define RBC_PAD_TO_12 0x1000 - /* Device reports number of sectors from READ_CAPACITY, not max - * sector number. - */ -# define READ_CAPACITY_OFFBY1 0x2000 - /* Device cannot handle a SCSI synchronize cache command. Normally - * this quirk would be handled in the cam layer, but for IDE bridges - * we need to associate the quirk with the bridge and not the - * underlying disk device. This is handled by faking a success result. - */ -# define NO_SYNCHRONIZE_CACHE 0x4000 -}; - -static struct umass_devdescr_t umass_devdescrs[] = { - { USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_CABLE_205, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_AIPTEK, USB_PRODUCT_AIPTEK_POCKETCAM3M, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_UMCR_9361, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO330, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_ASAHIOPTICAL, PID_WILDCARD, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - RS_NO_CLEAR_UA - }, - { USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2SCSI, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_CASIO, USB_PRODUCT_CASIO_QV_DIGICAM, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_INQUIRY - }, - { USB_VENDOR_CCYU, USB_PRODUCT_CCYU_ED1064, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35QUAT, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_DESKNOTE, USB_PRODUCT_DESKNOTE_UCR_61S2B, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_DMI, USB_PRODUCT_DMI_CFSM_RW, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_GETMAXLUN - }, - { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_INQUIRY - }, - { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_895, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_DVD, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - RS_NO_CLEAR_UA - }, - { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB_2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - WRONG_CSWSIG - }, - { USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FG, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGSM, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - NO_INQUIRY - }, - { USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_GETMAXLUN - }, - { USB_VENDOR_HP, USB_PRODUCT_HP_CDW4E, RID_WILDCARD, - UMASS_PROTO_ATAPI, - NO_QUIRKS - }, - { USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - NO_TEST_UNIT_READY | NO_START_STOP - }, - { USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - WRONG_CSWSIG - }, - { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_STORAGE_V2, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1 - }, - { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100, RID_WILDCARD, - /* XXX This is not correct as there are Zip drives that use ATAPI. - */ - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_TEST_UNIT_READY - }, - { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S3X, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_INQUIRY - }, - { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S4, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_INQUIRY - }, - { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S5, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_LACIE, USB_PRODUCT_LACIE_HD, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_CF_READER, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_JUMPSHOT, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_TEST_UNIT_READY | NO_START_STOP - }, - { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIHD50, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_E223, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_F300, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_CDRRW, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_FDD, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_INQUIRY_EVPD | NO_GETMAXLUN - }, - { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE | NO_GETMAXLUN | RS_NO_CLEAR_UA - }, - { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY | IGNORE_RESIDUE - }, - { USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY - }, - { USB_VENDOR_NETAC, USB_PRODUCT_NETAC_CF_CARD, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_NETAC, USB_PRODUCT_NETAC_ONLYDISK, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_CLIK_40, RID_WILDCARD, - UMASS_PROTO_ATAPI, - NO_INQUIRY - }, - { USB_VENDOR_NIKON, USB_PRODUCT_NIKON_D300, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - WRONG_CSWSIG - }, - { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_GETMAXLUN - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_COMBO, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER2, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN | NO_SYNCHRONIZE_CACHE - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDSM_B_READER, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_INQUIRY - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_READER, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - NO_INQUIRY | NO_GETMAXLUN - }, - { USB_VENDOR_ONSPEC2, USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_GETMAXLUN - }, - { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXL840AN, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_LS120CAM, RID_WILDCARD, - UMASS_PROTO_UFI, - NO_QUIRKS - }, - { USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_TEST_UNIT_READY - }, - { USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE | NO_START_STOP - }, - { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_YP_U2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - SHUTTLE_INIT | NO_GETMAXLUN - }, - { USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05A, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR09, RID_WILDCARD, - UMASS_PROTO_SCSI, - READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR12, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - READ_CAPACITY_OFFBY1 | NO_GETMAXLUN - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - READ_CAPACITY_OFFBY1 - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_128, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_256, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CDRW, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CF, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBATAPI, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBCFSM, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_HIFD, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_GETMAXLUN - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SDDR09, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_GETMAXLUN - }, - { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_GETMAXLUN - }, - { USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - SHUTTLE_INIT - }, - { USB_VENDOR_SIIG, USB_PRODUCT_SIIG_WINTERREADER, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_MD_7425, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_SX_520Z, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40_MS, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, 0x0500, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - RBC_PAD_TO_12 - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, 0x0600, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - RBC_PAD_TO_12 - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM, 0x0500, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - RBC_PAD_TO_12 - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_MSC_U03, RID_WILDCARD, - UMASS_PROTO_UFI | UMASS_PROTO_CBI, - NO_GETMAXLUN - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_NW_MS7, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_PEG_N760C, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSACUS1, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_GETMAXLUN - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD, - UMASS_PROTO_RBC | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_PORTABLE_HDD_V2, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB, RID_WILDCARD, - UMASS_PROTO_UFI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_BBB, - IGNORE_RESIDUE - }, - { USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_C3310, RID_WILDCARD, - UMASS_PROTO_UFI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_MP3, RID_WILDCARD, - UMASS_PROTO_RBC, - NO_QUIRKS - }, - { USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_T33520, RID_WILDCARD, - UMASS_PROTO_SCSI, - NO_QUIRKS - }, - { USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_QUIRKS - }, - { USB_VENDOR_VIA, USB_PRODUCT_VIA_USB2IDEBRIDGE, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_SYNCHRONIZE_CACHE - }, - { USB_VENDOR_VIVITAR, USB_PRODUCT_VIVITAR_35XX, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_COMBO, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_EXTHDD, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYBOOK, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY_EVPD - }, - { USB_VENDOR_WINMAXGROUP, USB_PRODUCT_WINMAXGROUP_FLASH64MC, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - NO_INQUIRY - }, - { USB_VENDOR_YANO, USB_PRODUCT_YANO_FW800HD, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_BBB, - FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE - }, - { USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I, - FORCE_SHORT_INQUIRY - }, - { USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU, RID_WILDCARD, - UMASS_PROTO_SCSI | UMASS_PROTO_CBI, - NO_GETMAXLUN - }, - { USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC, RID_WILDCARD, - UMASS_PROTO_ATAPI | UMASS_PROTO_CBI, - NO_QUIRKS - }, - { VID_EOT, PID_EOT, RID_EOT, 0, 0 } -}; - - -/* the per device structure */ -struct umass_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; /* USB device */ - - struct cam_sim *umass_sim; /* SCSI Interface Module */ - - unsigned char flags; /* various device flags */ -# define UMASS_FLAGS_GONE 0x01 /* devices is no more */ - - u_int16_t proto; /* wire and cmd protocol */ - u_int16_t quirks; /* they got it almost right */ - - 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; - - /* 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 */ - - /* 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 */ - - 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_ATTACH 0 /* in attach */ -# define TSTATE_IDLE 1 -# define TSTATE_BBB_COMMAND 2 /* CBW transfer */ -# define TSTATE_BBB_DATA 3 /* Data transfer */ -# define TSTATE_BBB_DCLEAR 4 /* clear endpt stall */ -# define TSTATE_BBB_STATUS1 5 /* clear endpt stall */ -# define TSTATE_BBB_SCLEAR 6 /* clear endpt stall */ -# define TSTATE_BBB_STATUS2 7 /* CSW transfer */ -# define TSTATE_BBB_RESET1 8 /* reset command */ -# define TSTATE_BBB_RESET2 9 /* in clear stall */ -# define TSTATE_BBB_RESET3 10 /* out clear stall */ -# define TSTATE_CBI_COMMAND 11 /* command transfer */ -# define TSTATE_CBI_DATA 12 /* data transfer */ -# define TSTATE_CBI_STATUS 13 /* status transfer */ -# define TSTATE_CBI_DCLEAR 14 /* clear ep stall */ -# define TSTATE_CBI_SCLEAR 15 /* clear ep stall */ -# define TSTATE_CBI_RESET1 16 /* reset command */ -# define TSTATE_CBI_RESET2 17 /* in clear stall */ -# define TSTATE_CBI_RESET3 18 /* out clear stall */ -# define TSTATE_STATES 19 /* # of states above */ - - - /* SCSI/CAM specific variables */ - unsigned char cam_scsi_command[CAM_MAX_CDBLEN]; - unsigned char cam_scsi_command2[CAM_MAX_CDBLEN]; - struct scsi_sense cam_scsi_sense; - struct scsi_sense cam_scsi_test_unit_ready; - struct callout cam_scsi_rescan_ch; - - int timeout; /* in msecs */ - - int maxlun; /* maximum LUN number */ -}; - -#ifdef USB_DEBUG -char *states[TSTATE_STATES+1] = { - /* should be kept in sync with the list at transfer_state */ - "Attach", - "Idle", - "BBB CBW", - "BBB Data", - "BBB Data bulk-in/-out clear stall", - "BBB CSW, 1st attempt", - "BBB CSW bulk-in clear stall", - "BBB CSW, 2nd attempt", - "BBB Reset", - "BBB bulk-in clear stall", - "BBB bulk-out clear stall", - "CBI Command", - "CBI Data", - "CBI Status", - "CBI Data bulk-in/-out clear stall", - "CBI Status intr-in clear stall", - "CBI Reset", - "CBI bulk-in clear stall", - "CBI bulk-out clear stall", - NULL -}; -#endif - -/* If device cannot return valid inquiry data, fake it */ -static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = { - 0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2, - /*additional_length*/ 31, 0, 0, 0 -}; - -/* USB device probe/attach/detach functions */ -static device_probe_t umass_match; -static device_attach_t umass_attach; -static device_detach_t umass_detach; - -static device_method_t umass_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, umass_match), - DEVMETHOD(device_attach, umass_attach), - DEVMETHOD(device_detach, umass_detach), - - { 0, 0 } -}; - -static driver_t umass_driver = { - "umass", - umass_methods, - sizeof(struct umass_softc) -}; - -static devclass_t umass_devclass; - -static int umass_match_proto (struct umass_softc *sc, - usbd_interface_handle iface, - usbd_device_handle udev); - -/* quirk functions */ -static void umass_init_shuttle (struct umass_softc *sc); - -/* generic transfer functions */ -static usbd_status umass_setup_transfer (struct umass_softc *sc, - usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer); -static usbd_status umass_setup_ctrl_transfer (struct umass_softc *sc, - usbd_device_handle udev, - 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, - u_int8_t endpt, usbd_pipe_handle pipe, - int state, usbd_xfer_handle xfer); -static void umass_reset (struct umass_softc *sc, - transfer_cb_f cb, void *priv); - -/* Bulk-Only related functions */ -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, u_int timeout, - transfer_cb_f cb, void *priv); -static void umass_bbb_state (usbd_xfer_handle xfer, - usbd_private_handle priv, - usbd_status err); -static int umass_bbb_get_max_lun - (struct umass_softc *sc); - -/* CBI related functions */ -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, u_int timeout, - transfer_cb_f cb, void *priv); -static void umass_cbi_state (usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status err); - -/* 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); -static void umass_cam_quirk_cb (struct umass_softc *sc, void *priv, - int residue, int status); - -static void umass_cam_rescan_callback - (struct cam_periph *periph,union ccb *ccb); -static void umass_cam_rescan (void *addr); - -static int umass_cam_attach_sim (struct umass_softc *sc); -static int umass_cam_attach (struct umass_softc *sc); -static int umass_cam_detach_sim (struct umass_softc *sc); - - -/* 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 */ -#define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ -static int umass_ufi_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -/* ATAPI (8070i) specific functions */ -#define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ -static int umass_atapi_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -/* RBC specific functions */ -static int umass_rbc_transform (struct umass_softc *sc, - unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen); - -#ifdef USB_DEBUG -/* General debugging functions */ -static void umass_bbb_dump_cbw (struct umass_softc *sc, umass_bbb_cbw_t *cbw); -static void umass_bbb_dump_csw (struct umass_softc *sc, umass_bbb_csw_t *csw); -static void umass_cbi_dump_cmd (struct umass_softc *sc, void *cmd, int cmdlen); -static void umass_dump_buffer (struct umass_softc *sc, u_int8_t *buffer, - int buflen, int printlen); -#endif - -MODULE_DEPEND(umass, cam, 1, 1, 1); -MODULE_DEPEND(umass, usb, 1, 1, 1); - -/* - * USB device probe/attach/detach - */ - -/* - * Match the device we are seeing with the devices supported. Fill in the - * description in the softc accordingly. This function is called from both - * probe and attach. - */ - -static int -umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface, - usbd_device_handle udev) -{ - usb_device_descriptor_t *dd; - usb_interface_descriptor_t *id; - int i; - int found = 0; - - sc->sc_udev = udev; - sc->proto = 0; - sc->quirks = 0; - - dd = usbd_get_device_descriptor(udev); - - /* An entry specifically for Y-E Data devices as they don't fit in the - * device description table. - */ - if (UGETW(dd->idVendor) == USB_VENDOR_YEDATA - && UGETW(dd->idProduct) == USB_PRODUCT_YEDATA_FLASHBUSTERU) { - - /* Revisions < 1.28 do not handle the interrupt endpoint - * very well. - */ - if (UGETW(dd->bcdDevice) < 0x128) { - sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_CBI; - } else { - sc->proto = UMASS_PROTO_UFI | UMASS_PROTO_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->quirks |= NO_TEST_UNIT_READY; - - sc->quirks |= RS_NO_CLEAR_UA | FLOPPY_SPEED; - return(UMATCH_VENDOR_PRODUCT); - } - - /* Check the list of supported devices for a match. While looking, - * check for wildcarded and fully matched. First match wins. - */ - for (i = 0; umass_devdescrs[i].vid != VID_EOT && !found; i++) { - if (umass_devdescrs[i].vid == VID_WILDCARD && - umass_devdescrs[i].pid == PID_WILDCARD && - umass_devdescrs[i].rid == RID_WILDCARD) { - printf("umass: ignoring invalid wildcard quirk\n"); - continue; - } - if ((umass_devdescrs[i].vid == UGETW(dd->idVendor) || - umass_devdescrs[i].vid == VID_WILDCARD) - && (umass_devdescrs[i].pid == UGETW(dd->idProduct) || - umass_devdescrs[i].pid == PID_WILDCARD)) { - if (umass_devdescrs[i].rid == RID_WILDCARD) { - sc->proto = umass_devdescrs[i].proto; - sc->quirks = umass_devdescrs[i].quirks; - return (UMATCH_VENDOR_PRODUCT); - } else if (umass_devdescrs[i].rid == - UGETW(dd->bcdDevice)) { - sc->proto = umass_devdescrs[i].proto; - sc->quirks = umass_devdescrs[i].quirks; - return (UMATCH_VENDOR_PRODUCT_REV); - } /* else RID does not match */ - } - } - - /* Check for a standards compliant device */ - id = usbd_get_interface_descriptor(iface); - if (id == NULL || id->bInterfaceClass != UICLASS_MASS) - return(UMATCH_NONE); - - switch (id->bInterfaceSubClass) { - case UISUBCLASS_SCSI: - sc->proto |= UMASS_PROTO_SCSI; - break; - case UISUBCLASS_UFI: - sc->proto |= UMASS_PROTO_UFI; - break; - case UISUBCLASS_RBC: - sc->proto |= UMASS_PROTO_RBC; - break; - case UISUBCLASS_SFF8020I: - case UISUBCLASS_SFF8070I: - sc->proto |= UMASS_PROTO_ATAPI; - break; - default: - DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n", - device_get_nameunit(sc->sc_dev), id->bInterfaceSubClass)); - return(UMATCH_NONE); - } - - switch (id->bInterfaceProtocol) { - case UIPROTO_MASS_CBI: - sc->proto |= UMASS_PROTO_CBI; - break; - case UIPROTO_MASS_CBI_I: - sc->proto |= UMASS_PROTO_CBI_I; - break; - case UIPROTO_MASS_BBB_OLD: - case UIPROTO_MASS_BBB: - sc->proto |= UMASS_PROTO_BBB; - break; - default: - DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n", - device_get_nameunit(sc->sc_dev), id->bInterfaceProtocol)); - return(UMATCH_NONE); - } - - return(UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); -} - -static int -umass_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct umass_softc *sc = device_get_softc(self); - - sc->sc_dev = self; - if (uaa->iface == NULL) - return(UMATCH_NONE); - - return(umass_match_proto(sc, uaa->iface, uaa->device)); -} - -static int -umass_attach(device_t self) -{ - struct umass_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - int err; - - /* - * the softc struct is bzero-ed in device_set_driver. We can safely - * call umass_detach without specifically initialising the struct. - */ - sc->sc_dev = self; - sc->iface = uaa->iface; - sc->ifaceno = uaa->ifaceno; - callout_init(&sc->cam_scsi_rescan_ch, 0); - - /* initialise the proto and drive values in the umass_softc (again) */ - (void) umass_match_proto(sc, sc->iface, uaa->device); - - id = usbd_get_interface_descriptor(sc->iface); -#ifdef USB_DEBUG - printf("%s: ", device_get_nameunit(sc->sc_dev)); - switch (sc->proto&UMASS_PROTO_COMMAND) { - case UMASS_PROTO_SCSI: - printf("SCSI"); - break; - case UMASS_PROTO_ATAPI: - printf("8070i (ATAPI)"); - break; - case UMASS_PROTO_UFI: - printf("UFI"); - break; - case UMASS_PROTO_RBC: - printf("RBC"); - break; - default: - printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_COMMAND); - break; - } - printf(" over "); - switch (sc->proto&UMASS_PROTO_WIRE) { - case UMASS_PROTO_BBB: - printf("Bulk-Only"); - break; - case UMASS_PROTO_CBI: /* uses Comand/Bulk pipes */ - printf("CBI"); - break; - case UMASS_PROTO_CBI_I: /* uses Comand/Bulk/Interrupt pipes */ - printf("CBI with CCI"); -#ifndef CBI_I - printf(" (using CBI)"); -#endif - break; - default: - printf("(unknown 0x%02x)", sc->proto&UMASS_PROTO_WIRE); - } - printf("; quirks = 0x%04x\n", sc->quirks); -#endif - -#ifndef CBI_I - if (sc->proto & UMASS_PROTO_CBI_I) { - /* See beginning of file for comment on the use of CBI with CCI */ - sc->proto = (sc->proto & ~UMASS_PROTO_CBI_I) | UMASS_PROTO_CBI; - } -#endif - - if (sc->quirks & ALT_IFACE_1) { - err = usbd_set_interface(uaa->iface, 1); - if (err) { - DPRINTF(UDMASS_USB, ("%s: could not switch to " - "Alt Interface %d\n", - device_get_nameunit(sc->sc_dev), 1)); - umass_detach(self); - return ENXIO; - } - } - - /* - * In addition to the Control endpoint the following endpoints - * are required: - * a) bulk-in endpoint. - * b) bulk-out endpoint. - * and for Control/Bulk/Interrupt with CCI (CBI_I) - * c) intr-in - * - * The endpoint addresses are not fixed, so we have to read them - * from the device descriptors of the current interface. - */ - for (i = 0 ; i < id->bNumEndpoints ; i++) { - ed = usbd_interface2endpoint_descriptor(sc->iface, i); - if (!ed) { - printf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkin = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - sc->bulkout = ed->bEndpointAddress; - } else if (sc->proto & UMASS_PROTO_CBI_I - && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - sc->intrin = ed->bEndpointAddress; -#ifdef USB_DEBUG - if (UGETW(ed->wMaxPacketSize) > 2) { - DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n", - device_get_nameunit(sc->sc_dev), - UGETW(ed->wMaxPacketSize))); - } -#endif - } - } - - /* check whether we found all the endpoints we need */ - if (!sc->bulkin || !sc->bulkout - || (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) { - DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n", - device_get_nameunit(sc->sc_dev), - sc->bulkin, sc->bulkout, sc->intrin)); - umass_detach(self); - return ENXIO; - } - - /* Open the bulk-in and -out pipe */ - err = usbd_open_pipe(sc->iface, sc->bulkout, - USBD_EXCLUSIVE_USE, &sc->bulkout_pipe); - if (err) { - DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n", - device_get_nameunit(sc->sc_dev), sc->bulkout)); - umass_detach(self); - return ENXIO; - } - err = usbd_open_pipe(sc->iface, sc->bulkin, - USBD_EXCLUSIVE_USE, &sc->bulkin_pipe); - if (err) { - DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n", - device_get_nameunit(sc->sc_dev), sc->bulkin)); - umass_detach(self); - return ENXIO; - } - /* Open the intr-in pipe if the protocol is CBI with CCI. - * Note: early versions of the Zip drive do have an interrupt pipe, but - * this pipe is unused. - * - * We do not open the interrupt pipe as an interrupt pipe, but as a - * normal bulk endpoint. We send an IN transfer down the wire at the - * appropriate time, because we know exactly when to expect data on - * that endpoint. This saves bandwidth, but more important, makes the - * code for handling the data on that endpoint simpler. No data - * arriving concurrently. - */ - if (sc->proto & UMASS_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 %d-in (intr)\n", - device_get_nameunit(sc->sc_dev), sc->intrin)); - umass_detach(self); - return ENXIO; - } - } - - /* initialisation of generic part */ - sc->transfer_state = TSTATE_ATTACH; - - /* request a sufficient number of xfer handles */ - for (i = 0; i < XFER_NR; i++) { - sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device); - if (!sc->transfer_xfer[i]) { - DPRINTF(UDMASS_USB, ("%s: Out of memory\n", - device_get_nameunit(sc->sc_dev))); - umass_detach(self); - return ENXIO; - } - } - - /* Initialise the wire protocol specific methods */ - if (sc->proto & UMASS_PROTO_BBB) { - sc->reset = umass_bbb_reset; - sc->transfer = umass_bbb_transfer; - sc->state = umass_bbb_state; - } else if (sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I)) { - sc->reset = umass_cbi_reset; - sc->transfer = umass_cbi_transfer; - sc->state = umass_cbi_state; -#ifdef USB_DEBUG - } else { - panic("%s:%d: Unknown proto 0x%02x", - __FILE__, __LINE__, sc->proto); -#endif - } - - if (sc->proto & UMASS_PROTO_SCSI) - sc->transform = umass_scsi_transform; - else if (sc->proto & UMASS_PROTO_UFI) - sc->transform = umass_ufi_transform; - else if (sc->proto & UMASS_PROTO_ATAPI) - sc->transform = umass_atapi_transform; - else if (sc->proto & UMASS_PROTO_RBC) - sc->transform = umass_rbc_transform; -#ifdef USB_DEBUG - else - panic("No transformation defined for command proto 0x%02x", - sc->proto & UMASS_PROTO_COMMAND); -#endif - - /* From here onwards the device can be used. */ - - if (sc->quirks & SHUTTLE_INIT) - umass_init_shuttle(sc); - - /* Get the maximum LUN supported by the device. - */ - if (((sc->proto & UMASS_PROTO_WIRE) == UMASS_PROTO_BBB) && - !(sc->quirks & NO_GETMAXLUN)) - sc->maxlun = umass_bbb_get_max_lun(sc); - else - sc->maxlun = 0; - - if ((sc->proto & UMASS_PROTO_SCSI) || - (sc->proto & UMASS_PROTO_ATAPI) || - (sc->proto & UMASS_PROTO_UFI) || - (sc->proto & UMASS_PROTO_RBC)) { - /* Prepare the SCSI command block */ - sc->cam_scsi_sense.opcode = REQUEST_SENSE; - sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY; - - /* register the SIM */ - err = umass_cam_attach_sim(sc); - if (err) { - umass_detach(self); - return ENXIO; - } - /* scan the new sim */ - err = umass_cam_attach(sc); - if (err) { - umass_cam_detach_sim(sc); - umass_detach(self); - return ENXIO; - } - } else { - panic("%s:%d: Unknown proto 0x%02x", - __FILE__, __LINE__, sc->proto); - } - - sc->transfer_state = TSTATE_IDLE; - DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", device_get_nameunit(sc->sc_dev))); - - return 0; -} - -static int -umass_detach(device_t self) -{ - struct umass_softc *sc = device_get_softc(self); - int err = 0; - int i; - - DPRINTF(UDMASS_USB, ("%s: detached\n", device_get_nameunit(sc->sc_dev))); - - sc->flags |= UMASS_FLAGS_GONE; - - /* abort all the pipes in case there are transfers active. */ - usbd_abort_default_pipe(sc->sc_udev); - if (sc->bulkout_pipe) - usbd_abort_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_abort_pipe(sc->bulkin_pipe); - if (sc->intrin_pipe) - usbd_abort_pipe(sc->intrin_pipe); - - callout_drain(&sc->cam_scsi_rescan_ch); - if ((sc->proto & UMASS_PROTO_SCSI) || - (sc->proto & UMASS_PROTO_ATAPI) || - (sc->proto & UMASS_PROTO_UFI) || - (sc->proto & UMASS_PROTO_RBC)) - /* detach the SCSI host controller (SIM) */ - err = umass_cam_detach_sim(sc); - - for (i = 0; i < XFER_NR; i++) - if (sc->transfer_xfer[i]) - usbd_free_xfer(sc->transfer_xfer[i]); - - /* remove all the pipes */ - if (sc->bulkout_pipe) - usbd_close_pipe(sc->bulkout_pipe); - if (sc->bulkin_pipe) - usbd_close_pipe(sc->bulkin_pipe); - if (sc->intrin_pipe) - usbd_close_pipe(sc->intrin_pipe); - - return(err); -} - -static void -umass_init_shuttle(struct umass_softc *sc) -{ - usb_device_request_t req; - u_char status[2]; - - /* The Linux driver does this, but no one can tell us what the - * command does. - */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = 1; /* XXX unknown command */ - USETW(req.wValue, 0); - USETW(req.wIndex, sc->ifaceno); - USETW(req.wLength, sizeof status); - (void) usbd_do_request(sc->sc_udev, &req, &status); - - DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n", - device_get_nameunit(sc->sc_dev), status[0], status[1])); -} - - /* - * Generic functions to handle transfers - */ - -static usbd_status -umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Initialise a USB transfer and then schedule it */ - - (void) usbd_setup_xfer(xfer, pipe, (void *) sc, buffer, buflen, flags, - sc->timeout, sc->state); - - err = usbd_transfer(xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - - -static usbd_status -umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle udev, - usb_device_request_t *req, - void *buffer, int buflen, int flags, - usbd_xfer_handle xfer) -{ - usbd_status err; - - /* Initialise a USB control transfer and then schedule it */ - - (void) usbd_setup_default_xfer(xfer, udev, (void *) sc, - sc->timeout, req, buffer, buflen, flags, sc->state); - - err = usbd_transfer(xfer); - if (err && err != USBD_IN_PROGRESS) { - DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err))); - - /* do not reset, as this would make us loop */ - return(err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -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 udev; - - DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n", - device_get_nameunit(sc->sc_dev), endpt)); - - usbd_interface2device_handle(sc->iface, &udev); - - sc->transfer_state = state; - - 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, udev, &sc->request, NULL, 0, 0, xfer); -} - -static void -umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv) -{ - sc->transfer_cb = cb; - sc->transfer_priv = priv; - - /* The reset is a forced reset, so no error (yet) */ - sc->reset(sc, STATUS_CMD_OK); -} - -/* - * Bulk protocol specific functions - */ - -static void -umass_bbb_reset(struct umass_softc *sc, int status) -{ - usbd_device_handle udev; - - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_reset: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class) - * - * For Reset Recovery the host shall issue in the following order: - * a) a Bulk-Only Mass Storage Reset - * b) a Clear Feature HALT to the Bulk-In endpoint - * c) a Clear Feature HALT to the Bulk-Out endpoint - * - * This is done in 3 steps, states: - * TSTATE_BBB_RESET1 - * TSTATE_BBB_RESET2 - * TSTATE_BBB_RESET3 - * - * If the reset doesn't succeed, the device should be port reset. - */ - - DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n", - device_get_nameunit(sc->sc_dev))); - - sc->transfer_state = TSTATE_BBB_RESET1; - sc->transfer_status = status; - - usbd_interface2device_handle(sc->iface, &udev); - - /* reset is a class specific interface write */ - 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, udev, &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, - transfer_cb_f cb, void *priv) -{ - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_transfer: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* Be a little generous. */ - sc->timeout = timeout + UMASS_TIMEOUT; - - /* - * Do a Bulk-Only transfer with cmdlen bytes from cmd, possibly - * a data phase of datalen bytes from/to the device and finally a - * csw read phase. - * If the data direction was inbound a maximum of datalen bytes - * is stored in the buffer pointed to by data. - * - * umass_bbb_transfer initialises the transfer and lets the state - * machine in umass_bbb_state handle the completion. It uses the - * following states: - * TSTATE_BBB_COMMAND - * -> TSTATE_BBB_DATA - * -> TSTATE_BBB_STATUS - * -> TSTATE_BBB_STATUS2 - * -> TSTATE_BBB_IDLE - * - * An error in any of those states will invoke - * umass_bbb_reset. - */ - - /* check the given arguments */ - KASSERT(datalen == 0 || data != NULL, - ("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev))); - KASSERT(cmdlen <= CBWCDBLENGTH, - ("%s: cmdlen exceeds CDB length in CBW (%d > %d)", - device_get_nameunit(sc->sc_dev), cmdlen, CBWCDBLENGTH)); - KASSERT(dir == DIR_NONE || datalen > 0, - ("%s: datalen == 0 while direction is not NONE\n", - device_get_nameunit(sc->sc_dev))); - KASSERT(datalen == 0 || dir != DIR_NONE, - ("%s: direction is NONE while datalen is not zero\n", - device_get_nameunit(sc->sc_dev))); - KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE, - ("%s: CBW struct does not have the right size (%ld vs. %d)\n", - device_get_nameunit(sc->sc_dev), - (long)sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE)); - KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE, - ("%s: CSW struct does not have the right size (%ld vs. %d)\n", - device_get_nameunit(sc->sc_dev), - (long)sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE)); - - /* - * Determine the direction of the data transfer and the length. - * - * dCBWDataTransferLength (datalen) : - * This field indicates the number of bytes of data that the host - * intends to transfer on the IN or OUT Bulk endpoint(as indicated by - * the Direction bit) during the execution of this command. If this - * field is set to 0, the device will expect that no data will be - * transferred IN or OUT during this command, regardless of the value - * of the Direction bit defined in dCBWFlags. - * - * dCBWFlags (dir) : - * The bits of the Flags field are defined as follows: - * Bits 0-6 reserved - * Bit 7 Direction - this bit shall be ignored if the - * dCBWDataTransferLength field is zero. - * 0 = data Out from host to device - * 1 = data In from device to host - */ - - /* Fill in the Command Block Wrapper - * We fill in all the fields, so there is no need to bzero it first. - */ - USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE); - /* We don't care about the initial value, as long as the values are unique */ - USETDW(sc->cbw.dCBWTag, UGETDW(sc->cbw.dCBWTag) + 1); - USETDW(sc->cbw.dCBWDataTransferLength, datalen); - /* DIR_NONE is treated as DIR_OUT (0x00) */ - sc->cbw.bCBWFlags = (dir == DIR_IN? CBWFLAGS_IN:CBWFLAGS_OUT); - sc->cbw.bCBWLUN = lun; - sc->cbw.bCDBLength = cmdlen; - bcopy(cmd, sc->cbw.CBWCDB, cmdlen); - - DIF(UDMASS_BBB, umass_bbb_dump_cbw(sc, &sc->cbw)); - - /* store the details for the data transfer phase */ - sc->transfer_dir = dir; - sc->transfer_data = data; - sc->transfer_datalen = datalen; - sc->transfer_actlen = 0; - sc->transfer_cb = cb; - sc->transfer_priv = priv; - sc->transfer_status = STATUS_CMD_OK; - - /* move from idle to the command state */ - sc->transfer_state = TSTATE_BBB_COMMAND; - - /* Send the CBW from host to device via bulk-out endpoint. */ - 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); - } -} - - -static void -umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - struct umass_softc *sc = (struct umass_softc *) priv; - usbd_xfer_handle next_xfer; - - KASSERT(sc->proto & UMASS_PROTO_BBB, - ("%s: umass_bbb_state: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * State handling for BBB transfers. - * - * The subroutine is rather long. It steps through the states given in - * Annex A of the Bulk-Only specification. - * Each state first does the error handling of the previous transfer - * and then prepares the next transfer. - * Each transfer is done asynchronously so after the request/transfer - * has been submitted you will find a 'return;'. - */ - - DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state, - states[sc->transfer_state], xfer, usbd_errstr(err))); - - /* Give up if the device has detached. */ - if (sc->flags & UMASS_FLAGS_GONE) { - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, - STATUS_CMD_FAILED); - return; - } - - switch (sc->transfer_state) { - - /***** Bulk Transfer *****/ - case TSTATE_BBB_COMMAND: - /* Command transport phase, error handling */ - if (err) { - DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n", - device_get_nameunit(sc->sc_dev))); - /* If the device detects that the CBW is invalid, then - * the device may STALL both bulk endpoints and require - * a Bulk-Reset - */ - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - - /* Data transport phase, setup transfer */ - sc->transfer_state = TSTATE_BBB_DATA; - if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->bulkin_pipe, - sc->transfer_data, sc->transfer_datalen, - USBD_SHORT_XFER_OK, - sc->transfer_xfer[XFER_BBB_DATA])) - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - - return; - } else if (sc->transfer_dir == DIR_OUT) { - if (umass_setup_transfer(sc, sc->bulkout_pipe, - sc->transfer_data, sc->transfer_datalen, - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_BBB_DATA])) - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - - return; - } else { - DPRINTF(UDMASS_BBB, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - } - - /* FALLTHROUGH if no data phase, err == 0 */ - case TSTATE_BBB_DATA: - /* Command transport phase, error handling (ignored if no data - * phase (fallthrough from previous state)) */ - if (sc->transfer_dir != DIR_NONE) { - /* retrieve the length of the transfer that was done */ - usbd_get_xfer_status(xfer, NULL, NULL, - &sc->transfer_actlen, NULL); - - if (err) { - DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, " - "%s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN?"in":"out"), - sc->transfer_datalen,usbd_errstr(err))); - - if (err == USBD_STALLED) { - umass_clear_endpoint_stall(sc, - (sc->transfer_dir == DIR_IN? - 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 { - /* Unless the error is a pipe stall the - * error is fatal. - */ - umass_bbb_reset(sc,STATUS_WIRE_FAILED); - return; - } - } - } - - DIF(UDMASS_BBB, if (sc->transfer_dir == DIR_IN) - umass_dump_buffer(sc, sc->transfer_data, - sc->transfer_datalen, 48)); - - - - /* FALLTHROUGH, err == 0 (no data phase or successfull) */ - case TSTATE_BBB_DCLEAR: /* stall clear after data phase */ - case TSTATE_BBB_SCLEAR: /* stall clear after status phase */ - /* Reading of CSW after bulk stall condition in data phase - * (TSTATE_BBB_DATA2) or bulk-in stall condition after - * reading CSW (TSTATE_BBB_SCLEAR). - * In the case of no data phase or successfull data phase, - * err == 0 and the following if block is passed. - */ - if (err) { /* should not occur */ - /* try the transfer below, even if clear stall failed */ - DPRINTF(UDMASS_BBB, ("%s: bulk-%s stall clear failed" - ", %s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN? "in":"out"), - usbd_errstr(err))); - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } - - /* Status transport phase, setup transfer */ - if (sc->transfer_state == TSTATE_BBB_COMMAND || - sc->transfer_state == TSTATE_BBB_DATA || - sc->transfer_state == TSTATE_BBB_DCLEAR) { - /* After no data phase, successfull data phase and - * after clearing bulk-in/-out stall condition - */ - sc->transfer_state = TSTATE_BBB_STATUS1; - next_xfer = sc->transfer_xfer[XFER_BBB_CSW1]; - } else { - /* After first attempt of fetching CSW */ - sc->transfer_state = TSTATE_BBB_STATUS2; - next_xfer = sc->transfer_xfer[XFER_BBB_CSW2]; - } - - /* Read the Command Status Wrapper via bulk-in endpoint. */ - 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; - } - - return; - case TSTATE_BBB_STATUS1: /* first attempt */ - case TSTATE_BBB_STATUS2: /* second attempt */ - /* Status transfer, error handling */ - if (err) { - DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err), - (sc->transfer_state == TSTATE_BBB_STATUS1? - ", retrying":""))); - - /* If this was the first attempt at fetching the CSW - * retry it, otherwise fail. - */ - if (sc->transfer_state == TSTATE_BBB_STATUS1) { - 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); - return; - } - } - - DIF(UDMASS_BBB, umass_bbb_dump_csw(sc, &sc->csw)); - - /* Translate weird command-status signatures. */ - if (sc->quirks & WRONG_CSWSIG) { - u_int32_t dCSWSignature = UGETDW(sc->csw.dCSWSignature); - if (dCSWSignature == CSWSIGNATURE_OLYMPUS_C1 || - dCSWSignature == CSWSIGNATURE_IMAGINATION_DBX1) - USETDW(sc->csw.dCSWSignature, CSWSIGNATURE); - } - - int Residue; - Residue = UGETDW(sc->csw.dCSWDataResidue); - if (Residue == 0 && - sc->transfer_datalen - sc->transfer_actlen != 0) - Residue = sc->transfer_datalen - sc->transfer_actlen; - - /* Check CSW and handle any error */ - if (UGETDW(sc->csw.dCSWSignature) != CSWSIGNATURE) { - /* Invalid CSW: Wrong signature or wrong tag might - * indicate that the device is confused -> reset it. - */ - printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n", - device_get_nameunit(sc->sc_dev), - UGETDW(sc->csw.dCSWSignature), - CSWSIGNATURE); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } else if (UGETDW(sc->csw.dCSWTag) - != UGETDW(sc->cbw.dCBWTag)) { - printf("%s: Invalid CSW: tag %d should be %d\n", - device_get_nameunit(sc->sc_dev), - UGETDW(sc->csw.dCSWTag), - UGETDW(sc->cbw.dCBWTag)); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - - /* CSW is valid here */ - } else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) { - printf("%s: Invalid CSW: status %d > %d\n", - device_get_nameunit(sc->sc_dev), - sc->csw.bCSWStatus, - CSWSTATUS_PHASE); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - } else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) { - printf("%s: Phase Error, residue = %d\n", - device_get_nameunit(sc->sc_dev), Residue); - - umass_bbb_reset(sc, STATUS_WIRE_FAILED); - return; - - } else if (sc->transfer_actlen > sc->transfer_datalen) { - /* Buffer overrun! Don't let this go by unnoticed */ - panic("%s: transferred %db instead of %db", - device_get_nameunit(sc->sc_dev), - sc->transfer_actlen, sc->transfer_datalen); - - } else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) { - DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n", - device_get_nameunit(sc->sc_dev), Residue)); - - /* SCSI command failed but transfer was succesful */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, Residue, - STATUS_CMD_FAILED); - return; - - } else { /* success */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, Residue, - STATUS_CMD_OK); - - return; - } - - /***** Bulk Reset *****/ - case TSTATE_BBB_RESET1: - if (err) - printf("%s: BBB reset failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2, - sc->transfer_xfer[XFER_BBB_RESET2]); - - return; - case TSTATE_BBB_RESET2: - if (err) /* should not occur */ - printf("%s: BBB bulk-in clear stall failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - umass_clear_endpoint_stall(sc, - sc->bulkout, sc->bulkout_pipe, TSTATE_BBB_RESET3, - sc->transfer_xfer[XFER_BBB_RESET3]); - - return; - case TSTATE_BBB_RESET3: - if (err) /* should not occur */ - printf("%s: BBB bulk-out clear stall failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - sc->transfer_state = TSTATE_IDLE; - if (sc->transfer_priv) { - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - sc->transfer_status); - } - - return; - - /***** Default *****/ - default: - panic("%s: Unknown state %d", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - } -} - -static int -umass_bbb_get_max_lun(struct umass_softc *sc) -{ - usbd_device_handle udev; - usb_device_request_t req; - usbd_status err; - usb_interface_descriptor_t *id; - int maxlun = 0; - u_int8_t buf = 0; - - usbd_interface2device_handle(sc->iface, &udev); - 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, id->bInterfaceNumber); - USETW(req.wLength, 1); - - err = usbd_do_request(udev, &req, &buf); - switch (err) { - case USBD_NORMAL_COMPLETION: - maxlun = buf; - DPRINTF(UDMASS_BBB, ("%s: Max Lun is %d\n", - device_get_nameunit(sc->sc_dev), maxlun)); - break; - case USBD_STALLED: - case USBD_SHORT_XFER: - default: - /* Device doesn't support Get Max Lun request. */ - printf("%s: Get Max Lun not supported (%s)\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* XXX Should we port_reset the device? */ - break; - } - - return(maxlun); -} - -/* - * Command/Bulk/Interrupt (CBI) specific functions - */ - -static int -umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen, - usbd_xfer_handle xfer) -{ - usbd_device_handle udev; - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_adsc: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - usbd_interface2device_handle(sc->iface, &udev); - - 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, udev, &sc->request, buffer, - buflen, 0, xfer); -} - - -static void -umass_cbi_reset(struct umass_softc *sc, int status) -{ - int i; -# define SEND_DIAGNOSTIC_CMDLEN 12 - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_reset: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * Command Block Reset Protocol - * - * First send a reset request to the device. Then clear - * any possibly stalled bulk endpoints. - * - * This is done in 3 steps, states: - * TSTATE_CBI_RESET1 - * TSTATE_CBI_RESET2 - * TSTATE_CBI_RESET3 - * - * If the reset doesn't succeed, the device should be port reset. - */ - - DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n", - device_get_nameunit(sc->sc_dev))); - - KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN, - ("%s: CBL struct is too small (%ld < %d)\n", - device_get_nameunit(sc->sc_dev), - (long)sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN)); - - sc->transfer_state = TSTATE_CBI_RESET1; - sc->transfer_status = status; - - /* The 0x1d code is the SEND DIAGNOSTIC command. To distinguish between - * the two the last 10 bytes of the cbl is filled with 0xff (section - * 2.2 of the CBI spec). - */ - sc->cbl[0] = 0x1d; /* Command Block Reset */ - sc->cbl[1] = 0x04; - for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++) - sc->cbl[i] = 0xff; - - umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, - sc->transfer_xfer[XFER_CBI_RESET1]); - /* XXX if the command fails we should reset the port on the hub */ -} - -static void -umass_cbi_transfer(struct umass_softc *sc, int lun, - void *cmd, int cmdlen, void *data, int datalen, int dir, - u_int timeout, transfer_cb_f cb, void *priv) -{ - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_transfer: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* Be a little generous. */ - sc->timeout = timeout + UMASS_TIMEOUT; - - /* - * Do a CBI transfer with cmdlen bytes from cmd, possibly - * a data phase of datalen bytes from/to the device and finally a - * csw read phase. - * If the data direction was inbound a maximum of datalen bytes - * is stored in the buffer pointed to by data. - * - * umass_cbi_transfer initialises the transfer and lets the state - * machine in umass_cbi_state handle the completion. It uses the - * following states: - * TSTATE_CBI_COMMAND - * -> XXX fill in - * - * An error in any of those states will invoke - * umass_cbi_reset. - */ - - /* check the given arguments */ - KASSERT(datalen == 0 || data != NULL, - ("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev))); - KASSERT(datalen == 0 || dir != DIR_NONE, - ("%s: direction is NONE while datalen is not zero\n", - device_get_nameunit(sc->sc_dev))); - - /* store the details for the data transfer phase */ - sc->transfer_dir = dir; - sc->transfer_data = data; - sc->transfer_datalen = datalen; - sc->transfer_actlen = 0; - sc->transfer_cb = cb; - sc->transfer_priv = priv; - sc->transfer_status = STATUS_CMD_OK; - - /* move from idle to the command state */ - sc->transfer_state = TSTATE_CBI_COMMAND; - - DIF(UDMASS_CBI, umass_cbi_dump_cmd(sc, cmd, cmdlen)); - - /* Send the Command Block from host to device via control endpoint. */ - if (umass_cbi_adsc(sc, cmd, cmdlen, sc->transfer_xfer[XFER_CBI_CB])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); -} - -static void -umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status err) -{ - struct umass_softc *sc = (struct umass_softc *) priv; - - KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I), - ("%s: umass_cbi_state: wrong sc->proto 0x%02x\n", - device_get_nameunit(sc->sc_dev), sc->proto)); - - /* - * State handling for CBI transfers. - */ - - DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n", - device_get_nameunit(sc->sc_dev), sc->transfer_state, - states[sc->transfer_state], xfer, usbd_errstr(err))); - - /* Give up if the device has detached. */ - if (sc->flags & UMASS_FLAGS_GONE) { - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen, - STATUS_CMD_FAILED); - return; - } - - switch (sc->transfer_state) { - - /***** CBI Transfer *****/ - case TSTATE_CBI_COMMAND: - if (err == USBD_STALLED) { - DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n", - device_get_nameunit(sc->sc_dev))); - /* 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 be stalled at this point. - */ - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - STATUS_CMD_FAILED); - - return; - } else if (err) { - DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n", - device_get_nameunit(sc->sc_dev))); - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - return; - } - - sc->transfer_state = TSTATE_CBI_DATA; - if (sc->transfer_dir == DIR_IN) { - if (umass_setup_transfer(sc, sc->bulkin_pipe, - sc->transfer_data, sc->transfer_datalen, - USBD_SHORT_XFER_OK, - sc->transfer_xfer[XFER_CBI_DATA])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - } else if (sc->transfer_dir == DIR_OUT) { - if (umass_setup_transfer(sc, sc->bulkout_pipe, - sc->transfer_data, sc->transfer_datalen, - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_DATA])) - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - - } else if (sc->proto & UMASS_PROTO_CBI_I) { - DPRINTF(UDMASS_CBI, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - sc->transfer_state = TSTATE_CBI_STATUS; - if (umass_setup_transfer(sc, sc->intrin_pipe, - &sc->sbl, sizeof(sc->sbl), - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_STATUS])){ - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - } else { - DPRINTF(UDMASS_CBI, ("%s: no data phase\n", - device_get_nameunit(sc->sc_dev))); - /* No command completion interrupt. Request - * sense data. - */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - 0, STATUS_CMD_UNKNOWN); - } - - return; - - case TSTATE_CBI_DATA: - /* retrieve the length of the transfer that was done */ - usbd_get_xfer_status(xfer,NULL,NULL,&sc->transfer_actlen,NULL); - - if (err) { - DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, " - "%s\n", device_get_nameunit(sc->sc_dev), - (sc->transfer_dir == DIR_IN?"in":"out"), - sc->transfer_datalen,usbd_errstr(err))); - - if (err == USBD_STALLED) { - 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); - } - return; - } - - DIF(UDMASS_CBI, if (sc->transfer_dir == DIR_IN) - umass_dump_buffer(sc, sc->transfer_data, - sc->transfer_actlen, 48)); - - if (sc->proto & UMASS_PROTO_CBI_I) { - sc->transfer_state = TSTATE_CBI_STATUS; - if (umass_setup_transfer(sc, sc->intrin_pipe, - &sc->sbl, sizeof(sc->sbl), - 0, /* fixed length transfer */ - sc->transfer_xfer[XFER_CBI_STATUS])){ - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - } else { - /* No command completion interrupt. Request - * sense to get status of command. - */ - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen - sc->transfer_actlen, - STATUS_CMD_UNKNOWN); - } - return; - - case TSTATE_CBI_STATUS: - if (err) { - DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n", - device_get_nameunit(sc->sc_dev))); - /* Status transport by interrupt pipe (section 2.3.2.2). - */ - - if (err == USBD_STALLED) { - 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); - } - return; - } - - /* Dissect the information in the buffer */ - - if (sc->proto & UMASS_PROTO_UFI) { - int status; - - /* Section 3.4.3.1.3 specifies that the UFI command - * protocol returns an ASC and ASCQ in the interrupt - * data block. - */ - - DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, " - "ASCQ = 0x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sbl.ufi.asc, sc->sbl.ufi.ascq)); - - if (sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0) - status = STATUS_CMD_OK; - else - status = STATUS_CMD_FAILED; - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen - sc->transfer_actlen, - status); - } else { - /* Command Interrupt Data Block */ - DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sbl.common.type, sc->sbl.common.value)); - - if (sc->sbl.common.type == IDB_TYPE_CCI) { - int err; - - if ((sc->sbl.common.value&IDB_VALUE_STATUS_MASK) - == IDB_VALUE_PASS) { - err = STATUS_CMD_OK; - } else if ((sc->sbl.common.value & IDB_VALUE_STATUS_MASK) - == IDB_VALUE_FAIL || - (sc->sbl.common.value & IDB_VALUE_STATUS_MASK) - == IDB_VALUE_PERSISTENT) { - err = STATUS_CMD_FAILED; - } else { - err = STATUS_WIRE_FAILED; - } - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen-sc->transfer_actlen, - err); - } - } - return; - - case TSTATE_CBI_DCLEAR: - if (err) { /* should not occur */ - printf("%s: CBI bulk-in/out stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - umass_cbi_reset(sc, STATUS_WIRE_FAILED); - } - - sc->transfer_state = TSTATE_IDLE; - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - STATUS_CMD_FAILED); - return; - - case TSTATE_CBI_SCLEAR: - if (err) /* should not occur */ - printf("%s: CBI intr-in stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - /* Something really bad is going on. Reset the device */ - umass_cbi_reset(sc, STATUS_CMD_FAILED); - return; - - /***** CBI Reset *****/ - case TSTATE_CBI_RESET1: - if (err) - printf("%s: CBI reset failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - - umass_clear_endpoint_stall(sc, - sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2, - sc->transfer_xfer[XFER_CBI_RESET2]); - - return; - case TSTATE_CBI_RESET2: - if (err) /* should not occur */ - printf("%s: CBI bulk-in stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - umass_clear_endpoint_stall(sc, - sc->bulkout, sc->bulkout_pipe, TSTATE_CBI_RESET3, - sc->transfer_xfer[XFER_CBI_RESET3]); - - return; - case TSTATE_CBI_RESET3: - if (err) /* should not occur */ - printf("%s: CBI bulk-out stall clear failed, %s\n", - device_get_nameunit(sc->sc_dev), usbd_errstr(err)); - /* no error recovery, otherwise we end up in a loop */ - - sc->transfer_state = TSTATE_IDLE; - if (sc->transfer_priv) { - sc->transfer_cb(sc, sc->transfer_priv, - sc->transfer_datalen, - sc->transfer_status); - } - - return; - - - /***** Default *****/ - default: - panic("%s: Unknown state %d", - device_get_nameunit(sc->sc_dev), sc->transfer_state); - } -} - - - - -/* - * CAM specific functions (used by SCSI, UFI, 8070i (ATAPI)) - */ - -static int -umass_cam_attach_sim(struct umass_softc *sc) -{ - 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 SIMs is limited to one. - */ - - devq = cam_simq_alloc(1 /*maximum openings*/); - if (devq == NULL) - return(ENOMEM); - - sc->umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll, - DEVNAME_SIM, - sc /*priv*/, - device_get_unit(sc->sc_dev) /*unit number*/, - &Giant, - 1 /*maximum device openings*/, - 0 /*maximum tagged device openings*/, - devq); - if (sc->umass_sim == NULL) { - cam_simq_free(devq); - return(ENOMEM); - } - - if(xpt_bus_register(sc->umass_sim, NULL, device_get_unit(sc->sc_dev)) != - CAM_SUCCESS) - return(ENOMEM); - - return(0); -} - -static void -umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) -{ -#ifdef USB_DEBUG - if (ccb->ccb_h.status != CAM_REQ_CMP) { - DPRINTF(UDMASS_SCSI, ("%s:%d Rescan failed, 0x%04x\n", - periph->periph_name, periph->unit_number, - ccb->ccb_h.status)); - } else { - DPRINTF(UDMASS_SCSI, ("%s%d: Rescan succeeded\n", - periph->periph_name, periph->unit_number)); - } -#endif - - xpt_free_path(ccb->ccb_h.path); - free(ccb, M_USBDEV); -} - -static void -umass_cam_rescan(void *addr) -{ - struct umass_softc *sc = (struct umass_softc *) addr; - struct cam_path *path; - union ccb *ccb; - - DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n", - cam_sim_path(sc->umass_sim), - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD)); - - ccb = malloc(sizeof(union ccb), M_USBDEV, M_NOWAIT | M_ZERO); - if (ccb == NULL) - return; - if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->umass_sim), - device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD) - != CAM_REQ_CMP) { - free(ccb, M_USBDEV); - 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. */ -} - -static int -umass_cam_attach(struct umass_softc *sc) -{ -#ifndef USB_DEBUG - if (bootverbose) -#endif - printf("%s:%d:%d:%d: Attached to scbus%d\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD, - cam_sim_path(sc->umass_sim)); - - if (!cold) { - /* Notify CAM of the new device after a short delay. 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. - */ - - callout_reset(&sc->cam_scsi_rescan_ch, MS_TO_TICKS(200), - umass_cam_rescan, sc); - } - - return(0); /* always succesfull */ -} - -/* umass_cam_detach - * detach from the CAM layer - */ - -static int -umass_cam_detach_sim(struct umass_softc *sc) -{ - if (sc->umass_sim) { - if (xpt_bus_deregister(cam_sim_path(sc->umass_sim))) - cam_sim_free(sc->umass_sim, /*free_devq*/TRUE); - else - return(EBUSY); - - sc->umass_sim = NULL; - } - - 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 = (struct umass_softc *)sim->softc; - - /* 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->flags & UMASS_FLAGS_GONE)) { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: " - "Invalid target (gone)\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - 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 (target needed)\n", - DEVNAME_SIM, cam_sim_path(sc->umass_sim), - 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 (no wildcard)\n", - DEVNAME_SIM, cam_sim_path(sc->umass_sim), - 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 */ - break; - } - - /* 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; - unsigned char *rcmd; - int rcmdlen; - - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: " - "cmd: 0x%02x, flags: 0x%02x, " - "%db cmd/%db data/%db sense\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - 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 in progress, deferring (state %d, %s)\n", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - 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 (csio->ccb_h.flags & CAM_CDB_POINTER) { - cmd = (unsigned char *) csio->cdb_io.cdb_ptr; - } else { - cmd = (unsigned char *) &csio->cdb_io.cdb_bytes; - } - cmdlen = csio->cdb_len; - rcmd = (unsigned char *) &sc->cam_scsi_command; - rcmdlen = sizeof(sc->cam_scsi_command); - - /* sc->transform will convert the command to the command - * (format) needed by the specific command set and return - * the converted command in a buffer pointed to be rcmd. - * We pass in a buffer, but if the command does not - * have to be transformed it returns a ptr to the original - * buffer (see umass_scsi_transform). - */ - - switch (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) { - case 1: - /* - * Handle EVPD inquiry for broken devices first - * NO_INQUIRY also implies NO_INQUIRY_EVPD - */ - if ((sc->quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) && - rcmd[0] == INQUIRY && (rcmd[1] & SI_EVPD)) { - struct scsi_sense_data *sense; - - sense = &ccb->csio.sense_data; - bzero(sense, sizeof(*sense)); - sense->error_code = SSD_CURRENT_ERROR; - sense->flags = SSD_KEY_ILLEGAL_REQUEST; - sense->add_sense_code = 0x24; - sense->extra_len = 10; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | - CAM_AUTOSNS_VALID; - xpt_done(ccb); - return; - } - /* Return fake inquiry data for broken devices */ - if ((sc->quirks & NO_INQUIRY) && rcmd[0] == INQUIRY) { - struct ccb_scsiio *csio = &ccb->csio; - - memcpy(csio->data_ptr, &fake_inq_data, - sizeof(fake_inq_data)); - csio->scsi_status = SCSI_STATUS_OK; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - if ((sc->quirks & NO_SYNCHRONIZE_CACHE) && - rcmd[0] == SYNCHRONIZE_CACHE) { - struct ccb_scsiio *csio = &ccb->csio; - - csio->scsi_status = SCSI_STATUS_OK; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - if ((sc->quirks & FORCE_SHORT_INQUIRY) && - rcmd[0] == INQUIRY) { - csio->dxfer_len = SHORT_INQUIRY_LENGTH; - } - sc->transfer(sc, ccb->ccb_h.target_lun, rcmd, rcmdlen, - csio->data_ptr, - csio->dxfer_len, dir, ccb->ccb_h.timeout, - umass_cam_cb, (void *) ccb); - break; - case 0: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case 2: - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - - 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:device_get_nameunit(sc->sc_dev)), - cam_sim_path(sc->umass_sim), - 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 = PIM_NO_6_BYTE; - cpi->hba_eng_cnt = 0; - cpi->max_target = UMASS_SCSIID_MAX; /* one target */ - 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 = device_get_unit(sc->sc_dev); - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - cpi->transport = XPORT_USB; - cpi->transport_version = 0; - - if (sc == NULL) { - cpi->base_transfer_speed = 0; - cpi->max_lun = 0; - } else { - if (sc->quirks & FLOPPY_SPEED) { - cpi->base_transfer_speed = - UMASS_FLOPPY_TRANSFER_SPEED; - } else if (usbd_get_speed(sc->sc_udev) == - USB_SPEED_HIGH) { - cpi->base_transfer_speed = - UMASS_HIGH_TRANSFER_SPEED; - } else { - cpi->base_transfer_speed = - UMASS_FULL_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", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - 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; - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_USB; - cts->transport_version = 0; - cts->xport_specific.valid = 0; - - - 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", - device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim), - 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: - { - cam_calc_geometry(&ccb->ccg, /*extended*/1); - xpt_done(ccb); - break; - } - case XPT_NOOP: - { - DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n", - (sc == NULL? DEVNAME_SIM:device_get_nameunit(sc->sc_dev)), - cam_sim_path(sc->umass_sim), - 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:device_get_nameunit(sc->sc_dev)), - cam_sim_path(sc->umass_sim), - 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; - } -} - -static void -umass_cam_poll(struct cam_sim *sim) -{ - struct umass_softc *sc = (struct umass_softc *) sim->softc; - - DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n", - device_get_nameunit(sc->sc_dev))); - - usbd_set_polling(sc->sc_udev, 1); - usbd_dopoll(sc->iface); - usbd_set_polling(sc->sc_udev, 0); -} - - -/* 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 */ - - /* If the device is gone, just fail the request. */ - if (sc->flags & UMASS_FLAGS_GONE) { - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } - - csio->resid = residue; - - switch (status) { - case STATUS_CMD_OK: - ccb->ccb_h.status = CAM_REQ_CMP; - if ((sc->quirks & READ_CAPACITY_OFFBY1) && - (ccb->ccb_h.func_code == XPT_SCSI_IO) && - (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY)) { - struct scsi_read_capacity_data *rcap; - uint32_t maxsector; - - rcap = (struct scsi_read_capacity_data *)csio->data_ptr; - maxsector = scsi_4btoul(rcap->addr) - 1; - scsi_ulto4b(maxsector, rcap->addr); - } - xpt_done(ccb); - break; - - case STATUS_CMD_UNKNOWN: - case STATUS_CMD_FAILED: - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: - { - unsigned char *rcmd; - int rcmdlen; - - /* fetch sense data */ - /* the rest of the command was filled in at attach */ - sc->cam_scsi_sense.length = csio->sense_len; - - DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n", - device_get_nameunit(sc->sc_dev), csio->sense_len)); - - rcmd = (unsigned char *) &sc->cam_scsi_command; - rcmdlen = sizeof(sc->cam_scsi_command); - - if (sc->transform(sc, - (unsigned char *) &sc->cam_scsi_sense, - sizeof(sc->cam_scsi_sense), - &rcmd, &rcmdlen) == 1) { - if ((sc->quirks & FORCE_SHORT_INQUIRY) && (rcmd[0] == INQUIRY)) { - csio->sense_len = SHORT_INQUIRY_LENGTH; - } - sc->transfer(sc, ccb->ccb_h.target_lun, - rcmd, rcmdlen, - &csio->sense_data, - csio->sense_len, DIR_IN, ccb->ccb_h.timeout, - umass_cam_sense_cb, (void *) ccb); - } else { - panic("transform(REQUEST_SENSE) failed"); - } - 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", - 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", - device_get_nameunit(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 */ - unsigned char *rcmd; - int rcmdlen; - - if (sc->flags & UMASS_FLAGS_GONE) { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - xpt_done(ccb); - return; - } - - switch (status) { - case STATUS_CMD_OK: - case STATUS_CMD_UNKNOWN: - case STATUS_CMD_FAILED: - /* Getting sense data always succeeds (apart from wire - * failures). - */ - 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 if ((sc->quirks & RS_NO_CLEAR_UA) && - (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY) && - ((csio->sense_data.flags & SSD_KEY) - == SSD_KEY_UNIT_ATTENTION)) { - /* - * Some devices do not clear the unit attention error - * on request sense. We insert a test unit ready - * command to make sure we clear the unit attention - * condition, then allow the retry to proceed as - * usual. - */ - - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - csio->scsi_status = SCSI_STATUS_CHECK_COND; - -#if 0 - DELAY(300000); -#endif - - DPRINTF(UDMASS_SCSI,("%s: Doing a sneaky" - "TEST_UNIT_READY\n", - device_get_nameunit(sc->sc_dev))); - - /* the rest of the command was filled in at attach */ - - rcmd = (unsigned char *) &sc->cam_scsi_command2; - rcmdlen = sizeof(sc->cam_scsi_command2); - - if (sc->transform(sc, - (unsigned char *) - &sc->cam_scsi_test_unit_ready, - sizeof(sc->cam_scsi_test_unit_ready), - &rcmd, &rcmdlen) == 1) { - sc->transfer(sc, ccb->ccb_h.target_lun, - rcmd, rcmdlen, - NULL, 0, DIR_NONE, ccb->ccb_h.timeout, - umass_cam_quirk_cb, (void *) ccb); - } else { - panic("transform(TEST_UNIT_READY) failed"); - } - break; - } 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", - device_get_nameunit(sc->sc_dev), status)); - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - xpt_done(ccb); - } -} - -/* - * This completion code just handles the fact that we sent a test-unit-ready - * after having previously failed a READ CAPACITY with CHECK_COND. Even - * though this command succeeded, we have to tell CAM to retry. - */ -static void -umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status) -{ - union ccb *ccb = (union ccb *) priv; - - DPRINTF(UDMASS_SCSI, ("%s: Test unit ready returned status %d\n", - device_get_nameunit(sc->sc_dev), status)); - - if (sc->flags & UMASS_FLAGS_GONE) { - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } -#if 0 - ccb->ccb_h.status = CAM_REQ_CMP; -#endif - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR - | CAM_AUTOSNS_VALID; - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - xpt_done(ccb); -} - -/* - * SCSI specific functions - */ - -static int -umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - switch (cmd[0]) { - case TEST_UNIT_READY: - if (sc->quirks & NO_TEST_UNIT_READY) { - KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), - ("rcmdlen = %d < %ld, buffer too small", - *rcmdlen, - (long)sizeof(struct scsi_start_stop_unit))); - DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " - "to START_UNIT\n", device_get_nameunit(sc->sc_dev))); - memset(*rcmd, 0, *rcmdlen); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - return 1; - } - /* fallthrough */ - case INQUIRY: - /* some drives wedge when asked for full inquiry information. */ - if (sc->quirks & FORCE_SHORT_INQUIRY) { - memcpy(*rcmd, cmd, cmdlen); - *rcmdlen = cmdlen; - (*rcmd)[4] = SHORT_INQUIRY_LENGTH; - return 1; - } - /* fallthrough */ - default: - *rcmd = cmd; /* We don't need to copy it */ - *rcmdlen = cmdlen; - } - - return 1; -} -/* RBC specific functions */ -static int -umass_rbc_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - switch (cmd[0]) { - /* these commands are defined in RBC: */ - case READ_10: - case READ_CAPACITY: - case START_STOP_UNIT: - case SYNCHRONIZE_CACHE: - case WRITE_10: - case 0x2f: /* VERIFY_10 is absent from scsi_all.h??? */ - case INQUIRY: - case MODE_SELECT_10: - case MODE_SENSE_10: - case TEST_UNIT_READY: - case WRITE_BUFFER: - /* The following commands are not listed in my copy of the RBC specs. - * CAM however seems to want those, and at least the Sony DSC device - * appears to support those as well */ - case REQUEST_SENSE: - case PREVENT_ALLOW: - if ((sc->quirks & RBC_PAD_TO_12) && cmdlen < 12) { - *rcmdlen = 12; - bcopy(cmd, *rcmd, cmdlen); - bzero(*rcmd + cmdlen, 12 - cmdlen); - } else { - *rcmd = cmd; /* We don't need to copy it */ - *rcmdlen = cmdlen; - } - return 1; - /* All other commands are not legal in RBC */ - default: - printf("%s: Unsupported RBC command 0x%02x", - device_get_nameunit(sc->sc_dev), cmd[0]); - printf("\n"); - return 0; /* failure */ - } -} - -/* - * UFI specific functions - */ -static int -umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - /* A UFI command is always 12 bytes in length */ - KASSERT(*rcmdlen >= UFI_COMMAND_LENGTH, - ("rcmdlen = %d < %d, buffer too small", - *rcmdlen, UFI_COMMAND_LENGTH)); - - *rcmdlen = UFI_COMMAND_LENGTH; - memset(*rcmd, 0, UFI_COMMAND_LENGTH); - - switch (cmd[0]) { - /* Commands of which the format has been verified. They should work. - * Copy the command into the (zeroed out) destination buffer. - */ - case TEST_UNIT_READY: - if (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", device_get_nameunit(sc->sc_dev))); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - } else { - memcpy(*rcmd, cmd, cmdlen); - } - return 1; - - case REZERO_UNIT: - case REQUEST_SENSE: - case FORMAT_UNIT: - case INQUIRY: - case START_STOP_UNIT: - case SEND_DIAGNOSTIC: - case PREVENT_ALLOW: - case READ_CAPACITY: - case READ_10: - case WRITE_10: - case POSITION_TO_ELEMENT: /* SEEK_10 */ - case WRITE_AND_VERIFY: - case VERIFY: - case MODE_SELECT_10: - case MODE_SENSE_10: - case READ_12: - case WRITE_12: - case READ_FORMAT_CAPACITIES: - memcpy(*rcmd, cmd, cmdlen); - return 1; - - /* - * SYNCHRONIZE_CACHE isn't supported by UFI, nor should it be - * required for UFI devices, so it is appropriate to fake - * success. - */ - case SYNCHRONIZE_CACHE: - return 2; - - default: - printf("%s: Unsupported UFI command 0x%02x\n", - device_get_nameunit(sc->sc_dev), cmd[0]); - return 0; /* failure */ - } -} - -/* - * 8070i (ATAPI) specific functions - */ -static int -umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen, - unsigned char **rcmd, int *rcmdlen) -{ - /* An ATAPI command is always 12 bytes in length. */ - KASSERT(*rcmdlen >= ATAPI_COMMAND_LENGTH, - ("rcmdlen = %d < %d, buffer too small", - *rcmdlen, ATAPI_COMMAND_LENGTH)); - - *rcmdlen = ATAPI_COMMAND_LENGTH; - memset(*rcmd, 0, ATAPI_COMMAND_LENGTH); - - switch (cmd[0]) { - /* Commands of which the format has been verified. They should work. - * Copy the command into the (zeroed out) destination buffer. - */ - case INQUIRY: - memcpy(*rcmd, cmd, cmdlen); - /* some drives wedge when asked for full inquiry information. */ - if (sc->quirks & FORCE_SHORT_INQUIRY) - (*rcmd)[4] = SHORT_INQUIRY_LENGTH; - return 1; - - case TEST_UNIT_READY: - if (sc->quirks & NO_TEST_UNIT_READY) { - KASSERT(*rcmdlen >= sizeof(struct scsi_start_stop_unit), - ("rcmdlen = %d < %ld, buffer too small", - *rcmdlen, - (long)sizeof(struct scsi_start_stop_unit))); - DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY " - "to START_UNIT\n", device_get_nameunit(sc->sc_dev))); - memset(*rcmd, 0, *rcmdlen); - (*rcmd)[0] = START_STOP_UNIT; - (*rcmd)[4] = SSS_START; - return 1; - } - /* fallthrough */ - case REZERO_UNIT: - case REQUEST_SENSE: - case START_STOP_UNIT: - case SEND_DIAGNOSTIC: - case PREVENT_ALLOW: - case READ_CAPACITY: - case READ_10: - case WRITE_10: - case POSITION_TO_ELEMENT: /* SEEK_10 */ - case SYNCHRONIZE_CACHE: - case MODE_SELECT_10: - case MODE_SENSE_10: - case READ_BUFFER: - case 0x42: /* READ_SUBCHANNEL */ - case 0x43: /* READ_TOC */ - case 0x44: /* READ_HEADER */ - case 0x47: /* PLAY_MSF (Play Minute/Second/Frame) */ - case 0x48: /* PLAY_TRACK */ - case 0x49: /* PLAY_TRACK_REL */ - case 0x4b: /* PAUSE */ - case 0x51: /* READ_DISK_INFO */ - case 0x52: /* READ_TRACK_INFO */ - case 0x54: /* SEND_OPC */ - case 0x59: /* READ_MASTER_CUE */ - case 0x5b: /* CLOSE_TR_SESSION */ - case 0x5c: /* READ_BUFFER_CAP */ - case 0x5d: /* SEND_CUE_SHEET */ - case 0xa1: /* BLANK */ - case 0xa5: /* PLAY_12 */ - case 0xa6: /* EXCHANGE_MEDIUM */ - case 0xad: /* READ_DVD_STRUCTURE */ - case 0xbb: /* SET_CD_SPEED */ - case 0xe5: /* READ_TRACK_INFO_PHILIPS */ - memcpy(*rcmd, cmd, cmdlen); - return 1; - - case READ_12: - case WRITE_12: - default: - printf("%s: Unsupported ATAPI command 0x%02x" - " - trying anyway\n", - device_get_nameunit(sc->sc_dev), cmd[0]); - memcpy(*rcmd, cmd, cmdlen); - return 1; - } -} - - -/* (even the comment is missing) */ - -DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, usbd_driver_load, 0); - - - -#ifdef USB_DEBUG -static void -umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw) -{ - int clen = cbw->bCDBLength; - int dlen = UGETDW(cbw->dCBWDataTransferLength); - u_int8_t *c = cbw->CBWCDB; - int tag = UGETDW(cbw->dCBWTag); - int flags = cbw->bCBWFlags; - - DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db " - "(0x%02x%02x%02x%02x%02x%02x%s), " - "data = %db, dir = %s\n", - device_get_nameunit(sc->sc_dev), tag, clen, - c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""), - dlen, (flags == CBWFLAGS_IN? "in": - (flags == CBWFLAGS_OUT? "out":"<invalid>")))); -} - -static void -umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw) -{ - int sig = UGETDW(csw->dCSWSignature); - int tag = UGETW(csw->dCSWTag); - int res = UGETDW(csw->dCSWDataResidue); - int status = csw->bCSWStatus; - - DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, " - "res = %d, status = 0x%02x (%s)\n", device_get_nameunit(sc->sc_dev), - tag, sig, (sig == CSWSIGNATURE? "valid":"invalid"), - tag, res, - status, (status == CSWSTATUS_GOOD? "good": - (status == CSWSTATUS_FAILED? "failed": - (status == CSWSTATUS_PHASE? "phase":"<invalid>"))))); -} - -static void -umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, int cmdlen) -{ - u_int8_t *c = cmd; - int dir = sc->transfer_dir; - - DPRINTF(UDMASS_BBB, ("%s: cmd = %db " - "(0x%02x%02x%02x%02x%02x%02x%s), " - "data = %db, dir = %s\n", - device_get_nameunit(sc->sc_dev), cmdlen, - c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6? "...":""), - sc->transfer_datalen, - (dir == DIR_IN? "in": - (dir == DIR_OUT? "out": - (dir == DIR_NONE? "no data phase": "<invalid>"))))); -} - -static void -umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen, - int printlen) -{ - int i, j; - char s1[40]; - char s2[40]; - char s3[5]; - - s1[0] = '\0'; - s3[0] = '\0'; - - sprintf(s2, " buffer=%p, buflen=%d", buffer, buflen); - for (i = 0; i < buflen && i < printlen; i++) { - j = i % 16; - if (j == 0 && i != 0) { - DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n", - device_get_nameunit(sc->sc_dev), s1, s2)); - s2[0] = '\0'; - } - sprintf(&s1[j*2], "%02x", buffer[i] & 0xff); - } - if (buflen > printlen) - sprintf(s3, " ..."); - DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n", - device_get_nameunit(sc->sc_dev), s1, s2, s3)); -} -#endif diff --git a/sys/dev/usb/umct.c b/sys/dev/usb/umct.c deleted file mode 100644 index 63de146..0000000 --- a/sys/dev/usb/umct.c +++ /dev/null @@ -1,511 +0,0 @@ -/*- - * Copyright (c) 2003 Scott Long - * 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. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Driver for the MCT (Magic Control Technology) USB-RS232 Converter. - * Based on the superb documentation from the linux mct_u232 driver by - * Wolfgang Grandeggar <wolfgang@cec.ch>. - * This device smells a lot like the Belkin F5U103, except that it has - * suffered some mild brain-damage. This driver is based off of the ubsa.c - * driver from Alexander Kabaev <kan@freebsd.org>. Merging the two together - * might be useful, though the subtle differences might lead to lots of - * #ifdef's. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/tty.h> -#include <sys/taskqueue.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/ucomvar.h> - -/* The UMCT advertises the standard 8250 UART registers */ -#define UMCT_GET_MSR 2 /* Get Modem Status Register */ -#define UMCT_GET_MSR_SIZE 1 -#define UMCT_GET_LCR 6 /* Get Line Control Register */ -#define UMCT_GET_LCR_SIZE 1 -#define UMCT_SET_BAUD 5 /* Set the Baud Rate Divisor */ -#define UMCT_SET_BAUD_SIZE 4 -#define UMCT_SET_LCR 7 /* Set Line Control Register */ -#define UMCT_SET_LCR_SIZE 1 -#define UMCT_SET_MCR 10 /* Set Modem Control Register */ -#define UMCT_SET_MCR_SIZE 1 - -#define UMCT_INTR_INTERVAL 100 -#define UMCT_IFACE_INDEX 0 -#define UMCT_CONFIG_INDEX 1 - -struct umct_softc { - struct ucom_softc sc_ucom; - int sc_iface_number; - usbd_interface_handle sc_intr_iface; - int sc_intr_number; - usbd_pipe_handle sc_intr_pipe; - u_char *sc_intr_buf; - int sc_isize; - uint8_t sc_lsr; - uint8_t sc_msr; - uint8_t sc_lcr; - uint8_t sc_mcr; - struct task sc_task; -}; - -static void umct_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static void umct_get_status(void *, int, u_char *, u_char *); -static void umct_set(void *, int, int, int); -static int umct_param(void *, int, struct termios *); -static int umct_open(void *, int); -static void umct_close(void *, int); -static void umct_notify(void *, int count); - -static struct ucom_callback umct_callback = { - umct_get_status, /* ucom_get_status */ - umct_set, /* ucom_set */ - umct_param, /* ucom_param */ - NULL, /* ucom_ioctl */ - umct_open, /* ucom_open */ - umct_close, /* ucom_close */ - NULL, /* ucom_read */ - NULL /* ucom_write */ -}; - -static const struct umct_product { - uint16_t vendor; - uint16_t product; -} umct_products[] = { - { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232 }, - { USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232 }, - { USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109 }, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409 }, - { 0, 0 } -}; - -static device_probe_t umct_match; -static device_attach_t umct_attach; -static device_detach_t umct_detach; - -static device_method_t umct_methods[] = { - DEVMETHOD(device_probe, umct_match), - DEVMETHOD(device_attach, umct_attach), - DEVMETHOD(device_detach, umct_detach), - { 0, 0 } -}; - -static driver_t umct_driver = { - "ucom", - umct_methods, - sizeof(struct umct_softc) -}; - -DRIVER_MODULE(umct, uhub, umct_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(umct, usb, 1, 1, 1); -MODULE_DEPEND(umct, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(umct, 1); - -static int -umct_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - int i; - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - for (i = 0; umct_products[i].vendor != 0; i++) { - if (umct_products[i].vendor == uaa->vendor && - umct_products[i].product == uaa->product) { - return (UMATCH_VENDOR_PRODUCT); - } - } - - return (UMATCH_NONE); -} - -static int -umct_attach(device_t self) -{ - struct umct_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const char *devname; - usbd_status err; - int i; - - dev = uaa->device; - bzero(sc, sizeof(struct umct_softc)); - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - ucom->sc_bulkout_no = -1; - ucom->sc_bulkin_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - devname = device_get_nameunit(ucom->sc_dev); - - err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1); - if (err) { - printf("%s: failed to set configuration: %s\n", - devname, usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - if (cdesc == NULL) { - printf("%s: failed to get configuration descriptor\n", devname); - ucom->sc_dying = 1; - goto error; - } - - err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - printf("%s: failed to get interface: %s\n", devname, - usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - printf("%s: no endpoint descriptor for %d\n", - devname, i); - ucom->sc_dying = 1; - goto error; - } - - /* - * The real bulk-in endpoint is also marked as an interrupt. - * The only way to differentiate it from the real interrupt - * endpoint is to look at the wMaxPacketSize field. - */ - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) { - if (UGETW(ed->wMaxPacketSize) == 0x2) { - sc->sc_intr_number = ed->bEndpointAddress; - sc->sc_isize = UGETW(ed->wMaxPacketSize); - } else { - ucom->sc_bulkin_no = ed->bEndpointAddress; - ucom->sc_ibufsize = UGETW(ed->wMaxPacketSize); - } - continue; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - if (uaa->product == USB_PRODUCT_MCT_SITECOM_USB232) - ucom->sc_obufsize = 16; /* device is broken */ - else - ucom->sc_obufsize = UGETW(ed->wMaxPacketSize); - continue; - } - - printf("%s: warning - unsupported endpoint 0x%x\n", devname, - ed->bEndpointAddress); - } - - if (sc->sc_intr_number == -1) { - printf("%s: Could not find interrupt in\n", devname); - ucom->sc_dying = 1; - goto error; - } - - sc->sc_intr_iface = ucom->sc_iface; - - if (ucom->sc_bulkout_no == -1) { - printf("%s: Could not find data bulk out\n", devname); - ucom->sc_dying = 1; - goto error; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &umct_callback; - ucom_attach(ucom); - TASK_INIT(&sc->sc_task, 0, umct_notify, sc); - return 0; - -error: - return ENXIO; -} - -static int -umct_detach(device_t self) -{ - struct umct_softc *sc = device_get_softc(self); - - int rv; - - 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_ucom.sc_dying = 1; -#if 0 - taskqueue_drain(taskqueue_swi_giant); -#endif - rv = ucom_detach(&sc->sc_ucom); - return (rv); -} - -static int -umct_request(struct umct_softc *sc, uint8_t request, int len, uint32_t value) -{ - usb_device_request_t req; - usbd_status err; - uint8_t oval[4]; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = request; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, len); - USETDW(oval, value); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, oval); - if (err) - printf("%s: umct_request: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); -} - -static void -umct_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umct_softc *sc; - u_char *buf; - - sc = (struct umct_softc *)priv; - buf = sc->sc_intr_buf; - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - sc->sc_msr = buf[0]; - sc->sc_lsr = buf[1]; - - /* - * Defer notifying the ucom layer as it doesn't like to be bothered - * from an interrupt context. - */ - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); -} - -static void -umct_notify(void *arg, int count) -{ - struct umct_softc *sc; - - sc = (struct umct_softc *)arg; - if (sc->sc_ucom.sc_dying == 0) - ucom_status_change(&sc->sc_ucom); -} - -static void -umct_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct umct_softc *sc; - - sc = addr; - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; - - return; -} - -static void -umct_set(void *addr, int portno, int reg, int onoff) -{ - struct umct_softc *sc; - - sc = addr; - switch (reg) { - case UCOM_SET_BREAK: - sc->sc_lcr &= ~0x40; - sc->sc_lcr |= (onoff) ? 0x40 : 0; - umct_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, sc->sc_lcr); - break; - case UCOM_SET_DTR: - sc->sc_mcr &= ~0x01; - sc->sc_mcr |= (onoff) ? 0x01 : 0; - umct_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr); - break; - case UCOM_SET_RTS: - sc->sc_mcr &= ~0x2; - sc->sc_mcr |= (onoff) ? 0x02 : 0; - umct_request(sc, UMCT_SET_MCR, UMCT_SET_MCR_SIZE, sc->sc_mcr); - break; - default: - break; - } -} - -static int -umct_calc_baud(u_int baud) -{ - switch(baud) { - case B300: return (0x1); - case B600: return (0x2); - case B1200: return (0x3); - case B2400: return (0x4); - case B4800: return (0x6); - case B9600: return (0x8); - case B19200: return (0x9); - case B38400: return (0xa); - case B57600: return (0xb); - case 115200: return (0xc); - case B0: - default: - break; - } - - return (0x0); -} - -static int -umct_param(void *addr, int portno, struct termios *ti) -{ - struct umct_softc *sc; - uint32_t value; - - sc = addr; - value = umct_calc_baud(ti->c_ospeed); - umct_request(sc, UMCT_SET_BAUD, UMCT_SET_BAUD_SIZE, value); - - value = sc->sc_lcr & 0x40; - - switch (ti->c_cflag & CSIZE) { - case CS5: value |= 0x0; break; - case CS6: value |= 0x1; break; - case CS7: value |= 0x2; break; - case CS8: value |= 0x3; break; - default: value |= 0x0; break; - } - - value |= (ti->c_cflag & CSTOPB) ? 0x4 : 0; - if (ti->c_cflag & PARENB) { - value |= 0x8; - value |= (ti->c_cflag & PARODD) ? 0x0 : 0x10; - } - - /* - * XXX There doesn't seem to be a way to tell the device to use flow - * control. - */ - - sc->sc_lcr = value; - umct_request(sc, UMCT_SET_LCR, UMCT_SET_LCR_SIZE, value); - - return (0); -} - -static int -umct_open(void *addr, int portno) -{ - struct umct_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) { - return (ENXIO); - } - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number, - USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buf, - sc->sc_isize, umct_intr, UMCT_INTR_INTERVAL); - if (err) { - printf("%s: cannot open interrupt pipe (addr %d)\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - sc->sc_intr_number); - free(sc->sc_intr_buf, M_USBDEV); - return (EIO); - } - } - - return (0); -} - -static void -umct_close(void *addr, int portno) -{ - struct umct_softc *sc; - int err; - - sc = addr; - if (sc->sc_ucom.sc_dying) - return; - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - printf("%s: abort interrupt pipe failed: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - printf("%s: close interrupt pipe failed: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c deleted file mode 100644 index f0cb17c..0000000 --- a/sys/dev/usb/umodem.c +++ /dev/null @@ -1,821 +0,0 @@ -/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */ - - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -/*- - * Copyright (c) 2003, M. Warner Losh <imp@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. - */ - -/*- - * Copyright (c) 1998 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. - */ - -/* - * Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf - * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf - */ - -/* - * TODO: - * - Add error recovery in various places; the big problem is what - * to do in a callback if there is an error. - * - Implement a Call Device for modems without multiplexed commands. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/ioccom.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/select.h> -#include <sys/sysctl.h> -#include <sys/proc.h> -#include <sys/bus.h> -#include <sys/poll.h> -#include <sys/uio.h> -#include <sys/taskqueue.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/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -#include "usbdevs.h" - -#ifdef USB_DEBUG -int umodemdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, umodem, CTLFLAG_RW, 0, "USB umodem"); -SYSCTL_INT(_hw_usb_umodem, OID_AUTO, debug, CTLFLAG_RW, - &umodemdebug, 0, "umodem debug level"); -#define DPRINTFN(n, x) if (umodemdebug > (n)) printf x -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -static const struct umodem_product { - u_int16_t vendor; - u_int16_t product; - u_int8_t interface; -} umodem_products[] = { - /* Kyocera AH-K3001V*/ - { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_AHK3001V, 0 }, - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, 0 }, - { USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_PC5740, 0 }, - { 0, 0, 0 }, -}; - -/* - * These are the maximum number of bytes transferred per frame. - * As speeds for umodem deivces increase, these numbers will need to - * be increased. They should be good for G3 speeds and below. - */ -#define UMODEMIBUFSIZE 1024 -#define UMODEMOBUFSIZE 1024 - -#define UMODEM_MODVER 1 /* module version */ - -struct umodem_softc { - struct ucom_softc sc_ucom; - - device_t sc_dev; /* base device */ - - usbd_device_handle sc_udev; /* USB device */ - - int sc_ctl_iface_no; - usbd_interface_handle sc_ctl_iface; /* control interface */ - int sc_data_iface_no; - usbd_interface_handle sc_data_iface; /* data interface */ - - int sc_cm_cap; /* CM capabilities */ - int sc_acm_cap; /* ACM capabilities */ - - int sc_cm_over_data; - - 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_opening; /* lock during open */ - - int sc_ctl_notify; /* Notification endpoint */ - usbd_pipe_handle sc_notify_pipe; /* Notification pipe */ - usb_cdc_notification_t sc_notify_buf; /* Notification structure */ - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* Modem status register */ - - struct task sc_task; -}; - -static void *umodem_get_desc(usbd_device_handle dev, int type, int subtype); -static usbd_status umodem_set_comm_feature(struct umodem_softc *sc, - int feature, int state); -static usbd_status umodem_set_line_coding(struct umodem_softc *sc, - usb_cdc_line_state_t *state); - -static void umodem_get_caps(usbd_device_handle, int *, int *); - -static void umodem_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void umodem_set(void *, int, int, int); -static void umodem_dtr(struct umodem_softc *, int); -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, struct thread *); -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); -static void umodem_notify(void *, int); - -static struct ucom_callback umodem_callback = { - .ucom_get_status = umodem_get_status, - .ucom_set = umodem_set, - .ucom_param = umodem_param, - .ucom_ioctl = umodem_ioctl, - .ucom_open = umodem_open, - .ucom_close = umodem_close -}; - -static device_probe_t umodem_match; -static device_attach_t umodem_attach; -static device_detach_t umodem_detach; - -static device_method_t umodem_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, umodem_match), - DEVMETHOD(device_attach, umodem_attach), - DEVMETHOD(device_detach, umodem_detach), - { 0, 0 } -}; - -static driver_t umodem_driver = { - "ucom", - umodem_methods, - sizeof (struct umodem_softc) -}; - -DRIVER_MODULE(umodem, uhub, umodem_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(umodem, usb, 1, 1, 1); -MODULE_DEPEND(umodem, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(umodem, UMODEM_MODVER); - -static int -umodem_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - usb_device_descriptor_t *dd; - int cm, acm, i, ret; - - if (uaa->iface == NULL) - return (UMATCH_NONE); - - id = usbd_get_interface_descriptor(uaa->iface); - dd = usbd_get_device_descriptor(uaa->device); - if (id == NULL || dd == NULL) - return (UMATCH_NONE); - - ret = UMATCH_NONE; - for (i = 0; umodem_products[i].vendor != 0; i++) { - if (umodem_products[i].vendor == UGETW(dd->idVendor) && - umodem_products[i].product == UGETW(dd->idProduct) && - umodem_products[i].interface == id->bInterfaceNumber) { - ret = UMATCH_VENDOR_PRODUCT; - break; - } - } - - if (ret == UMATCH_NONE && - id->bInterfaceClass == UICLASS_CDC && - id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL && - id->bInterfaceProtocol == UIPROTO_CDC_AT) - ret = UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; - - if (ret == UMATCH_NONE) - return (ret); - - umodem_get_caps(uaa->device, &cm, &acm); - if (!(cm & USB_CDC_CM_DOES_CM) || - !(cm & USB_CDC_CM_OVER_DATA) || - !(acm & USB_CDC_ACM_HAS_LINE)) - return (UMATCH_NONE); - - return ret; -} - -static int -umodem_attach(device_t self) -{ - struct umodem_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usb_cdc_cm_descriptor_t *cmd; - int data_ifcno; - int i; - struct ucom_softc *ucom; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - sc->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - sc->sc_udev = dev; - sc->sc_ctl_iface = uaa->iface; - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); - sc->sc_ctl_iface_no = id->bInterfaceNumber; - device_printf(self, "iclass %d/%d\n", id->bInterfaceClass, - id->bInterfaceSubClass); - - umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap); - - /* Get the data interface no. */ - cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); - if (cmd == NULL) { - device_printf(sc->sc_dev, "no CM descriptor\n"); - goto bad; - } - sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface; - - device_printf(sc->sc_dev, - "data interface %d, has %sCM over data, has %sbreak\n", - data_ifcno, sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ", - sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no "); - - /* Get the data interface too. */ - for (i = 0; i < uaa->nifaces; i++) { - if (uaa->ifaces[i] != NULL) { - id = usbd_get_interface_descriptor(uaa->ifaces[i]); - if (id != NULL && id->bInterfaceNumber == data_ifcno) { - sc->sc_data_iface = uaa->ifaces[i]; - uaa->ifaces[i] = NULL; - } - } - } - if (sc->sc_data_iface == NULL) { - device_printf(sc->sc_dev, "no data interface\n"); - goto bad; - } - ucom->sc_iface = sc->sc_data_iface; - - /* - * Find the bulk endpoints. - * Iterate over all endpoints in the data interface and take note. - */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - - id = usbd_get_interface_descriptor(sc->sc_data_iface); - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i); - if (ed == NULL) { - device_printf(sc->sc_dev, - "no endpoint descriptor for %d\n", i); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - device_printf(sc->sc_dev, "Could not find data bulk in\n"); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - device_printf(sc->sc_dev, "Could not find data bulk out\n"); - goto bad; - } - - if (sc->sc_cm_cap & USB_CDC_CM_OVER_DATA) { - if (sc->sc_acm_cap & USB_CDC_ACM_HAS_FEATURE) - umodem_set_comm_feature(sc, UCDC_ABSTRACT_STATE, - UCDC_DATA_MULTIPLEXED); - sc->sc_cm_over_data = 1; - } - - /* - * The standard allows for notification messages (to indicate things - * like a modem hangup) to come in via an interrupt endpoint - * off of the control interface. Iterate over the endpoints on - * the control interface and see if there are any interrupt - * endpoints; if there are, then register it. - */ - - sc->sc_ctl_notify = -1; - sc->sc_notify_pipe = NULL; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); - if (ed == NULL) - continue; - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { - device_printf(sc->sc_dev, - "status change notification available\n"); - sc->sc_ctl_notify = ed->bEndpointAddress; - } - } - - sc->sc_dtr = -1; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UMODEMIBUFSIZE; - ucom->sc_obufsize = UMODEMOBUFSIZE; - ucom->sc_ibufsizepad = UMODEMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &umodem_callback; - - TASK_INIT(&sc->sc_task, 0, umodem_notify, sc); - ucom_attach(&sc->sc_ucom); - return 0; - - bad: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -umodem_open(void *addr, int portno) -{ - struct umodem_softc *sc = addr; - int err; - - DPRINTF(("umodem_open: sc=%p\n", sc)); - - if (sc->sc_ctl_notify != -1 && sc->sc_notify_pipe == NULL) { - err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_ctl_notify, - USBD_SHORT_XFER_OK, &sc->sc_notify_pipe, sc, - &sc->sc_notify_buf, sizeof(sc->sc_notify_buf), - umodem_intr, USBD_DEFAULT_INTERVAL); - - if (err) { - DPRINTF(("Failed to establish notify pipe: %s\n", - usbd_errstr(err))); - return EIO; - } - } - - return 0; -} - -static void -umodem_close(void *addr, int portno) -{ - struct umodem_softc *sc = addr; - int err; - - DPRINTF(("umodem_close: sc=%p\n", sc)); - - if (sc->sc_notify_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_notify_pipe); - if (err) - device_printf(sc->sc_dev, - "abort notify pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_notify_pipe); - if (err) - device_printf(sc->sc_dev, - "close notify pipe failed: %s\n", - usbd_errstr(err)); - sc->sc_notify_pipe = NULL; - } -} - -static void -umodem_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct umodem_softc *sc = priv; - u_char mstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - device_printf(sc->sc_dev, "abnormal status: %s\n", - usbd_errstr(status)); - return; - } - - if (sc->sc_notify_buf.bmRequestType != UCDC_NOTIFICATION) { - DPRINTF(("%s: unknown message type (%02x) on notify pipe\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.bmRequestType)); - return; - } - - switch (sc->sc_notify_buf.bNotification) { - case UCDC_N_SERIAL_STATE: - /* - * Set the serial state in ucom driver based on - * the bits from the notify message - */ - if (UGETW(sc->sc_notify_buf.wLength) != 2) { - device_printf(sc->sc_dev, - "Invalid notification length! (%d)\n", - UGETW(sc->sc_notify_buf.wLength)); - break; - } - DPRINTF(("%s: notify bytes = %02x%02x\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.data[0], - sc->sc_notify_buf.data[1])); - /* Currently, lsr is always zero. */ - sc->sc_lsr = sc->sc_msr = 0; - mstatus = sc->sc_notify_buf.data[0]; - - if (ISSET(mstatus, UCDC_N_SERIAL_RI)) - sc->sc_msr |= SER_RI; - if (ISSET(mstatus, UCDC_N_SERIAL_DSR)) - sc->sc_msr |= SER_DSR; - if (ISSET(mstatus, UCDC_N_SERIAL_DCD)) - sc->sc_msr |= SER_DCD; - /* Deferred notifying to the ucom layer */ - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); - break; - default: - DPRINTF(("%s: unknown notify message: %02x\n", - device_get_nameunit(sc->sc_dev), - sc->sc_notify_buf.bNotification)); - break; - } -} - -static void -umodem_notify(void *arg, int count) -{ - struct umodem_softc *sc; - - sc = (struct umodem_softc *)arg; - if (sc->sc_ucom.sc_dying) - return; - ucom_status_change(&sc->sc_ucom); -} - -void -umodem_get_caps(usbd_device_handle dev, int *cm, int *acm) -{ - usb_cdc_cm_descriptor_t *cmd; - usb_cdc_acm_descriptor_t *cad; - - *cm = *acm = 0; - - cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); - if (cmd == NULL) { - DPRINTF(("umodem_get_desc: no CM desc\n")); - return; - } - *cm = cmd->bmCapabilities; - - cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM); - if (cad == NULL) { - DPRINTF(("umodem_get_desc: no ACM desc\n")); - return; - } - *acm = cad->bmCapabilities; -} - -void -umodem_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct umodem_softc *sc = addr; - - DPRINTF(("umodem_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} - -int -umodem_param(void *addr, int portno, struct termios *t) -{ - struct umodem_softc *sc = addr; - usbd_status err; - usb_cdc_line_state_t ls; - - DPRINTF(("umodem_param: sc=%p\n", sc)); - - USETDW(ls.dwDTERate, t->c_ospeed); - if (ISSET(t->c_cflag, CSTOPB)) - ls.bCharFormat = UCDC_STOP_BIT_2; - else - ls.bCharFormat = UCDC_STOP_BIT_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - ls.bParityType = UCDC_PARITY_ODD; - else - ls.bParityType = UCDC_PARITY_EVEN; - } else - ls.bParityType = UCDC_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - ls.bDataBits = 5; - break; - case CS6: - ls.bDataBits = 6; - break; - case CS7: - ls.bDataBits = 7; - break; - case CS8: - ls.bDataBits = 8; - break; - } - - err = umodem_set_line_coding(sc, &ls); - if (err) { - DPRINTF(("umodem_param: err=%s\n", usbd_errstr(err))); - return (EIO); - } - return (0); -} - -int -umodem_ioctl(void *addr, int portno, u_long cmd, caddr_t data, - struct thread *p) -{ - struct umodem_softc *sc = addr; - int error = 0; - - if (sc->sc_ucom.sc_dying) - return (EIO); - - DPRINTF(("umodemioctl: cmd=0x%08lx\n", cmd)); - - switch (cmd) { - case USB_GET_CM_OVER_DATA: - *(int *)data = sc->sc_cm_over_data; - break; - - case USB_SET_CM_OVER_DATA: - if (*(int *)data != sc->sc_cm_over_data) { - /* XXX change it */ - } - break; - - default: - DPRINTF(("umodemioctl: unknown\n")); - error = ENOIOCTL; - break; - } - - return (error); -} - -void -umodem_dtr(struct umodem_softc *sc, int onoff) -{ - DPRINTF(("umodem_modem: onoff=%d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - umodem_set_line_state(sc); -} - -void -umodem_rts(struct umodem_softc *sc, int onoff) -{ - DPRINTF(("umodem_modem: onoff=%d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - umodem_set_line_state(sc); -} - -void -umodem_set_line_state(struct umodem_softc *sc) -{ - usb_device_request_t req; - int ls; - - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(sc->sc_udev, &req, 0); - -} - -void -umodem_break(struct umodem_softc *sc, int onoff) -{ - usb_device_request_t req; - - DPRINTF(("umodem_break: onoff=%d\n", onoff)); - - if (!(sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK)) - return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, 0); - - (void)usbd_do_request(sc->sc_udev, &req, 0); -} - -void -umodem_set(void *addr, int portno, int reg, int onoff) -{ - struct umodem_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - umodem_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - umodem_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - umodem_break(sc, onoff); - break; - default: - break; - } -} - -usbd_status -umodem_set_line_coding(struct umodem_softc *sc, usb_cdc_line_state_t *state) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("umodem_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n", - UGETDW(state->dwDTERate), state->bCharFormat, - state->bParityType, state->bDataBits)); - - if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { - DPRINTF(("umodem_set_line_coding: already set\n")); - return (USBD_NORMAL_COMPLETION); - } - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_LINE_CODING; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, UCDC_LINE_STATE_LENGTH); - - err = usbd_do_request(sc->sc_udev, &req, state); - if (err) { - DPRINTF(("umodem_set_line_coding: failed, err=%s\n", - usbd_errstr(err))); - return (err); - } - - sc->sc_line_state = *state; - - return (USBD_NORMAL_COMPLETION); -} - -void * -umodem_get_desc(usbd_device_handle dev, int type, int subtype) -{ - 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 && - desc->bDescriptorSubtype == subtype) - return (desc); - p += desc->bLength; - } - - return (0); -} - -usbd_status -umodem_set_comm_feature(struct umodem_softc *sc, int feature, int state) -{ - usb_device_request_t req; - usbd_status err; - usb_cdc_abstract_state_t ast; - - DPRINTF(("umodem_set_comm_feature: feature=%d state=%d\n", feature, - state)); - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_COMM_FEATURE; - USETW(req.wValue, feature); - USETW(req.wIndex, sc->sc_ctl_iface_no); - USETW(req.wLength, UCDC_ABSTRACT_STATE_LENGTH); - USETW(ast.wState, state); - - err = usbd_do_request(sc->sc_udev, &req, &ast); - if (err) { - DPRINTF(("umodem_set_comm_feature: feature=%d, err=%s\n", - feature, usbd_errstr(err))); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static int -umodem_detach(device_t self) -{ - struct umodem_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("umodem_detach: sc=%p\n", sc)); - - if (sc->sc_notify_pipe != NULL) { - usbd_abort_pipe(sc->sc_notify_pipe); - usbd_close_pipe(sc->sc_notify_pipe); - sc->sc_notify_pipe = NULL; - } - - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c deleted file mode 100644 index 6484303..0000000 --- a/sys/dev/usb/ums.c +++ /dev/null @@ -1,972 +0,0 @@ -/*- - * Copyright (c) 1998 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> -__FBSDID("$FreeBSD$"); - -/* - * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> -#include <dev/usb/hid.h> - -#include <sys/mouse.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (umsdebug) printf x -#define DPRINTFN(n,x) if (umsdebug>(n)) printf x -int umsdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, ums, CTLFLAG_RW, 0, "USB ums"); -SYSCTL_INT(_hw_usb_ums, OID_AUTO, debug, CTLFLAG_RW, - &umsdebug, 0, "ums debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UMSUNIT(s) (dev2unit(s)&0x1f) - -#define MS_TO_TICKS(ms) ((ms) * hz / 1000) - -#define QUEUE_BUFSIZE 400 /* MUST be divisible by 5 _and_ 8 */ - -struct ums_softc { - device_t sc_dev; /* base device */ - 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, sc_loc_t, sc_loc_w; - struct hid_location *sc_loc_btn; - - struct callout callout_handle; /* for spurious button ups */ - - int sc_enabled; - int sc_disconnected; /* device is gone */ - - int flags; /* device configuration */ -#define UMS_Z 0x01 /* z direction available */ -#define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */ -#define UMS_T 0x04 /* aa direction available (tilt) */ -#define UMS_REVZ 0x08 /* Z-axis is reversed */ - int nbuttons; -#define MAX_BUTTONS 31 /* chosen because sc_buttons is int */ - - u_char qbuf[QUEUE_BUFSIZE]; /* must be divisable by 3&4 */ - u_char dummy[100]; /* XXX just for safety and for now */ - int qcount, qhead, qtail; - mousehw_t hw; - mousemode_t mode; - mousestatus_t status; - - int state; -# define UMS_ASLEEP 0x01 /* readFromDevice is waiting */ -# define UMS_SELECT 0x02 /* select is waiting */ - struct selinfo rsel; /* process waiting in select */ - - struct cdev *dev; /* specfs */ -}; - -#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) -#define MOUSE_FLAGS (HIO_RELATIVE) - -static void ums_intr(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); - -static void ums_add_to_queue(struct ums_softc *sc, - int dx, int dy, int dz, int dt, int buttons); -static void ums_add_to_queue_timeout(void *priv); - -static int ums_enable(void *); -static void ums_disable(void *); - -static d_open_t ums_open; -static d_close_t ums_close; -static d_read_t ums_read; -static d_ioctl_t ums_ioctl; -static d_poll_t ums_poll; - - -static struct cdevsw ums_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = ums_open, - .d_close = ums_close, - .d_read = ums_read, - .d_ioctl = ums_ioctl, - .d_poll = ums_poll, - .d_name = "ums", -}; - -static device_probe_t ums_match; -static device_attach_t ums_attach; -static device_detach_t ums_detach; - -static device_method_t ums_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ums_match), - DEVMETHOD(device_attach, ums_attach), - DEVMETHOD(device_detach, ums_detach), - - { 0, 0 } -}; - -static driver_t ums_driver = { - "ums", - ums_methods, - sizeof(struct ums_softc) -}; - -static devclass_t ums_devclass; - -static int -ums_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - int size, ret; - void *desc; - usbd_status err; - - if (!uaa->iface) - return (UMATCH_NONE); - id = usbd_get_interface_descriptor(uaa->iface); - if (!id || id->bInterfaceClass != UICLASS_HID) - return (UMATCH_NONE); - - 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 if (id->bInterfaceClass == UICLASS_HID && - id->bInterfaceSubClass == UISUBCLASS_BOOT && - id->bInterfaceProtocol == UIPROTO_MOUSE) - ret = UMATCH_IFACECLASS; - else - ret = UMATCH_NONE; - - free(desc, M_TEMP); - return (ret); -} - -static int -ums_attach(device_t self) -{ - struct ums_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_interface_handle iface = uaa->iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int size; - void *desc; - usbd_status err; - u_int32_t flags; - int i, wheel; - struct hid_location loc_btn; - - sc->sc_disconnected = 1; - sc->sc_iface = iface; - id = usbd_get_interface_descriptor(iface); - sc->sc_dev = self; - ed = usbd_interface2endpoint_descriptor(iface, 0); - if (!ed) { - printf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d " - "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" - " bInterval=%d\n", - ed->bLength, ed->bDescriptorType, - UE_GET_ADDR(ed->bEndpointAddress), - UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out", - UE_GET_XFERTYPE(ed->bmAttributes), - UGETW(ed->wMaxPacketSize), ed->bInterval)); - - if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN || - UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) { - printf("%s: unexpected endpoint\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP); - if (err) - return ENXIO; - - if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), - hid_input, &sc->sc_loc_x, &flags)) { - printf("%s: mouse has no X report\n", device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("%s: X report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - return ENXIO; - } - - if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), - hid_input, &sc->sc_loc_y, &flags)) { - printf("%s: mouse has no Y report\n", device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("%s: Y report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - return ENXIO; - } - - /* Try the wheel first as the Z activator since it's tradition. */ - wheel = hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, - HUG_WHEEL), - hid_input, &sc->sc_loc_z, &flags) || - hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, - HUG_TWHEEL), - hid_input, &sc->sc_loc_z, &flags); - - if (wheel) { - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("\n%s: Wheel report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ - } else { - sc->flags |= UMS_Z; - if (usbd_get_quirks(uaa->device)->uq_flags & - UQ_MS_REVZ) { - /* Some wheels need the Z axis reversed. */ - sc->flags |= UMS_REVZ; - } - - } - /* - * We might have both a wheel and Z direction, if so put - * put the Z on the W coordinate. - */ - if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, - HUG_Z), - hid_input, &sc->sc_loc_w, &flags)) { - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("\n%s: Z report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - sc->sc_loc_w.size = 0; /* Bad Z, ignore */ - } - } - } else if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, - HUG_Z), - hid_input, &sc->sc_loc_z, &flags)) { - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { - printf("\n%s: Z report 0x%04x not supported\n", - device_get_nameunit(sc->sc_dev), flags); - sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ - } else { - sc->flags |= UMS_Z; - } - } - - /* - * The Microsoft Wireless Intellimouse 2.0 reports it's wheel - * using 0x0048 (i've called it HUG_TWHEEL) and seems to expect - * you to know that the byte after the wheel is the tilt axis. - * There are no other HID axis descriptors other than X,Y and - * TWHEEL - */ - if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), - hid_input, &sc->sc_loc_t, &flags)) { - sc->sc_loc_t.pos = sc->sc_loc_t.pos + 8; - sc->flags |= UMS_T; - } - - /* figure out the number of buttons */ - for (i = 1; i <= MAX_BUTTONS; i++) - if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - 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", device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - printf("%s: %d buttons%s%s.\n", device_get_nameunit(sc->sc_dev), - sc->nbuttons, sc->flags & UMS_Z? " and Z dir" : "", - sc->flags & UMS_T?" and a TILT dir": ""); - - for (i = 1; i <= sc->nbuttons; i++) - hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), - hid_input, &sc->sc_loc_btn[i-1], 0); - - sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); - - /* - * The Microsoft Wireless Notebook Optical Mouse seems to be in worse - * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and - * all of its other button positions are all off. It also reports that - * it has two addional buttons and a tilt wheel. - */ - if (usbd_get_quirks(uaa->device)->uq_flags & UQ_MS_BAD_CLASS) { - sc->flags = UMS_Z; - sc->flags |= UMS_SPUR_BUT_UP; - sc->nbuttons = 3; - sc->sc_isize = 5; - sc->sc_iid = 0; - /* 1st byte of descriptor report contains garbage */ - sc->sc_loc_x.pos = 16; - sc->sc_loc_y.pos = 24; - sc->sc_loc_z.pos = 32; - sc->sc_loc_btn[0].pos = 8; - sc->sc_loc_btn[1].pos = 9; - sc->sc_loc_btn[2].pos = 10; - } - - /* - * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has - * five Report IDs: 19 23 24 17 18 (in the order they appear in report - * descriptor), it seems that report id 17 contains the necessary - * mouse information(3-buttons,X,Y,wheel) so we specify it manually. - */ - if (uaa->vendor == USB_VENDOR_MICROSOFT && - uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) { - sc->flags = UMS_Z; - sc->nbuttons = 3; - sc->sc_isize = 5; - sc->sc_iid = 17; - sc->sc_loc_x.pos = 8; - sc->sc_loc_y.pos = 16; - sc->sc_loc_z.pos = 24; - sc->sc_loc_btn[0].pos = 0; - sc->sc_loc_btn[1].pos = 1; - sc->sc_loc_btn[2].pos = 2; - } - - sc->sc_ibuf = malloc(sc->sc_isize, M_USB, M_NOWAIT); - if (!sc->sc_ibuf) { - printf("%s: no memory\n", device_get_nameunit(sc->sc_dev)); - free(sc->sc_loc_btn, M_USB); - return ENXIO; - } - - sc->sc_ep_addr = ed->bEndpointAddress; - sc->sc_disconnected = 0; - free(desc, M_TEMP); - -#ifdef USB_DEBUG - DPRINTF(("ums_attach: sc=%p\n", sc)); - DPRINTF(("ums_attach: X\t%d/%d\n", - sc->sc_loc_x.pos, sc->sc_loc_x.size)); - DPRINTF(("ums_attach: Y\t%d/%d\n", - sc->sc_loc_y.pos, sc->sc_loc_y.size)); - if (sc->flags & UMS_Z) - DPRINTF(("ums_attach: Z\t%d/%d\n", - sc->sc_loc_z.pos, sc->sc_loc_z.size)); - for (i = 1; i <= sc->nbuttons; i++) { - 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 - - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->hw.iftype = MOUSE_IF_USB; - sc->hw.type = MOUSE_MOUSE; - sc->hw.model = MOUSE_MODEL_GENERIC; - sc->hw.hwid = 0; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.rate = -1; - sc->mode.resolution = MOUSE_RES_UNKNOWN; - sc->mode.accelfactor = 0; - sc->mode.level = 0; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - - sc->status.flags = 0; - sc->status.button = sc->status.obutton = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; - - sc->dev = make_dev(&ums_cdevsw, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "ums%d", device_get_unit(self)); - - callout_init(&sc->callout_handle, 0); - if (usbd_get_quirks(uaa->device)->uq_flags & UQ_SPUR_BUT_UP) { - DPRINTF(("%s: Spurious button up events\n", - device_get_nameunit(sc->sc_dev))); - sc->flags |= UMS_SPUR_BUT_UP; - } - - return 0; -} - - -static int -ums_detach(device_t self) -{ - struct ums_softc *sc = device_get_softc(self); - - if (sc->sc_enabled) - ums_disable(sc); - - DPRINTF(("%s: disconnected\n", device_get_nameunit(self))); - - free(sc->sc_loc_btn, M_USB); - free(sc->sc_ibuf, M_USB); - - /* someone waiting for data */ - /* - * XXX If we wakeup the process here, the device will be gone by - * the time the process gets a chance to notice. *_close and friends - * should be fixed to handle this case. - * Or we should do a delayed detach for this. - * Does this delay now force tsleep to exit with an error? - */ - if (sc->state & UMS_ASLEEP) { - sc->state &= ~UMS_ASLEEP; - wakeup(sc); - } - if (sc->state & UMS_SELECT) { - sc->state &= ~UMS_SELECT; - selwakeuppri(&sc->rsel, PZERO); - } - - destroy_dev(sc->dev); - - return 0; -} - -void -ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) -{ - struct ums_softc *sc = addr; - u_char *ibuf; - int dx, dy, dz, dw, dt; - int buttons = 0; - int i; - -#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) - - DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status)); - DPRINTFN(5, ("ums_intr: data =")); - for (i = 0; i < sc->sc_isize; i++) - DPRINTFN(5, (" %02x", sc->sc_ibuf[i])); - DPRINTFN(5, ("\n")); - - if (status == USBD_CANCELLED) - return; - - if (status != USBD_NORMAL_COMPLETION) { - DPRINTF(("ums_intr: status=%d\n", status)); - if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->sc_intrpipe); - if(status != USBD_IOERROR) - return; - } - - ibuf = sc->sc_ibuf; - /* - * The M$ Wireless Intellimouse 2.0 sends 1 extra leading byte of - * data compared to most USB mice. This byte frequently switches - * from 0x01 (usual state) to 0x02. I assume it is to allow - * extra, non-standard, reporting (say battery-life). However - * at the same time it generates a left-click message on the button - * byte which causes spurious left-click's where there shouldn't be. - * This should sort that. - * Currently it's the only user of UMS_T so use it as an identifier. - * We probably should switch to some more official quirk. - * - * UPDATE: This problem affects the M$ Wireless Notebook Optical Mouse, - * too. However, the leading byte for this mouse is normally 0x11, - * and the phantom mouse click occurs when its 0x14. - */ - if (sc->flags & UMS_T) { - if (sc->sc_iid) { - if (*ibuf++ == 0x02) - return; - } - } else if (sc->flags & UMS_SPUR_BUT_UP) { - DPRINTFN(5, ("ums_intr: #### ibuf[0] =3D %d ####\n", *ibuf)); - if (*ibuf == 0x14 || *ibuf == 0x15) - return; - } else { - if (sc->sc_iid) { - 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); - dw = hid_get_data(ibuf, &sc->sc_loc_w); - if (sc->flags & UMS_REVZ) - dz = -dz; - if (sc->flags & UMS_T) - dt = -hid_get_data(ibuf, &sc->sc_loc_t); - else - dt = 0; - for (i = 0; i < sc->nbuttons; i++) - if (hid_get_data(ibuf, &sc->sc_loc_btn[i])) - buttons |= (1 << UMS_BUT(i)); - - if (dx || dy || dz || dt || dw || (sc->flags & UMS_Z) - || buttons != sc->status.button) { - DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d w:%d t:%d buttons:0x%x\n", - dx, dy, dz, dw, dt, buttons)); - - sc->status.button = buttons; - sc->status.dx += dx; - sc->status.dy += dy; - sc->status.dz += dz; - /* sc->status.dt += dt; */ /* no way to export this yet */ - /* sc->status.dw += dw; */ /* idem */ - - /* Discard data in case of full buffer */ - if (sc->qcount == sizeof(sc->qbuf)) { - DPRINTF(("Buffer full, discarded packet")); - return; - } - - /* - * The Qtronix keyboard has a built in PS/2 port for a mouse. - * The firmware once in a while posts a spurious button up - * event. This event we ignore by doing a timeout for 50 msecs. - * If we receive dx=dy=dz=buttons=0 before we add the event to - * the queue. - * In any other case we delete the timeout event. - */ - if (sc->flags & UMS_SPUR_BUT_UP && - dx == 0 && dy == 0 && dz == 0 && dt == 0 && buttons == 0) { - callout_reset(&sc->callout_handle, MS_TO_TICKS(50), - ums_add_to_queue_timeout, (void *) sc); - } else { - callout_stop(&sc->callout_handle); - ums_add_to_queue(sc, dx, dy, dz, dt, buttons); - } - } -} - -static void -ums_add_to_queue_timeout(void *priv) -{ - struct ums_softc *sc = priv; - int s; - - s = splusb(); - ums_add_to_queue(sc, 0, 0, 0, 0, 0); - splx(s); -} - -static void -ums_add_to_queue(struct ums_softc *sc, int dx, int dy, int dz, int dt, int buttons) -{ - /* Discard data in case of full buffer */ - if (sc->qhead+sc->mode.packetsize > sizeof(sc->qbuf)) { - DPRINTF(("Buffer full, discarded packet")); - return; - } - - if (dx > 254) dx = 254; - if (dx < -256) dx = -256; - if (dy > 254) dy = 254; - if (dy < -256) dy = -256; - if (dz > 126) dz = 126; - if (dz < -128) dz = -128; - if (dt > 126) dt = 126; - if (dt < -128) dt = -128; - - sc->qbuf[sc->qhead] = sc->mode.syncmask[1]; - sc->qbuf[sc->qhead] |= ~buttons & MOUSE_MSC_BUTTONS; - sc->qbuf[sc->qhead+1] = dx >> 1; - sc->qbuf[sc->qhead+2] = dy >> 1; - sc->qbuf[sc->qhead+3] = dx - (dx >> 1); - sc->qbuf[sc->qhead+4] = dy - (dy >> 1); - - if (sc->mode.level == 1) { - sc->qbuf[sc->qhead+5] = dz >> 1; - sc->qbuf[sc->qhead+6] = dz - (dz >> 1); - sc->qbuf[sc->qhead+7] = ((~buttons >> 3) - & MOUSE_SYS_EXTBUTTONS); - } - - sc->qhead += sc->mode.packetsize; - sc->qcount += sc->mode.packetsize; - /* wrap round at end of buffer */ - if (sc->qhead >= sizeof(sc->qbuf)) - sc->qhead = 0; - - /* someone waiting for data */ - if (sc->state & UMS_ASLEEP) { - sc->state &= ~UMS_ASLEEP; - wakeup(sc); - } - if (sc->state & UMS_SELECT) { - sc->state &= ~UMS_SELECT; - selwakeuppri(&sc->rsel, PZERO); - } -} -static int -ums_enable(v) - void *v; -{ - struct ums_softc *sc = v; - - usbd_status err; - - if (sc->sc_enabled) - return EBUSY; - - sc->sc_enabled = 1; - sc->qcount = 0; - sc->qhead = sc->qtail = 0; - sc->status.flags = 0; - sc->status.button = sc->status.obutton = 0; - sc->status.dx = sc->status.dy = sc->status.dz /* = sc->status.dt */ = 0; - - callout_handle_init((struct callout_handle *)&sc->callout_handle); - - /* - * Force the report (non-boot) protocol. - * - * Mice without boot protocol support may choose not to implement - * Set_Protocol at all; do not check for error. - */ - usbd_set_protocol(sc->sc_iface, 1); - - /* 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 -ums_disable(priv) - void *priv; -{ - struct ums_softc *sc = priv; - - callout_stop(&sc->callout_handle); - - /* Disable interrupts. */ - usbd_abort_pipe(sc->sc_intrpipe); - usbd_close_pipe(sc->sc_intrpipe); - - sc->sc_enabled = 0; - - if (sc->qcount != 0) - DPRINTF(("Discarded %d bytes in queue\n", sc->qcount)); -} - -static int -ums_open(struct cdev *dev, int flag, int fmt, struct thread *p) -{ - struct ums_softc *sc; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (sc == NULL) - return (ENXIO); - - return ums_enable(sc); -} - -static int -ums_close(struct cdev *dev, int flag, int fmt, struct thread *p) -{ - struct ums_softc *sc; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (!sc) - return 0; - - if (sc->sc_enabled) - ums_disable(sc); - - return 0; -} - -static int -ums_read(struct cdev *dev, struct uio *uio, int flag) -{ - struct ums_softc *sc; - int s; - char buf[sizeof(sc->qbuf)]; - int l = 0; - int error; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - s = splusb(); - if (!sc) { - splx(s); - return EIO; - } - - while (sc->qcount == 0 ) { - if (flag & O_NONBLOCK) { /* non-blocking I/O */ - splx(s); - return EWOULDBLOCK; - } - - sc->state |= UMS_ASLEEP; /* blocking I/O */ - error = tsleep(sc, PZERO | PCATCH, "umsrea", 0); - if (error) { - splx(s); - return error; - } else if (!sc->sc_enabled) { - splx(s); - return EINTR; - } - /* check whether the device is still there */ - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (!sc) { - splx(s); - return EIO; - } - } - - /* - * XXX we could optimise the use of splx/splusb somewhat. The writer - * process only extends qcount and qtail. We could copy them and use the copies - * to do the copying out of the queue. - */ - - while ((sc->qcount > 0) && (uio->uio_resid > 0)) { - l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid); - if (l > sizeof(buf)) - l = sizeof(buf); - if (l > sizeof(sc->qbuf) - sc->qtail) /* transfer till end of buf */ - l = sizeof(sc->qbuf) - sc->qtail; - - splx(s); - uiomove(&sc->qbuf[sc->qtail], l, uio); - s = splusb(); - - if ( sc->qcount - l < 0 ) { - DPRINTF(("qcount below 0, count=%d l=%d\n", sc->qcount, l)); - sc->qcount = l; - } - sc->qcount -= l; /* remove the bytes from the buffer */ - sc->qtail = (sc->qtail + l) % sizeof(sc->qbuf); - } - splx(s); - - return 0; -} - -static int -ums_poll(struct cdev *dev, int events, struct thread *p) -{ - struct ums_softc *sc; - int revents = 0; - int s; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (!sc) - return 0; - - s = splusb(); - if (events & (POLLIN | POLLRDNORM)) { - if (sc->qcount) { - revents = events & (POLLIN | POLLRDNORM); - } else { - sc->state |= UMS_SELECT; - selrecord(p, &sc->rsel); - } - } - splx(s); - - return revents; -} - -int -ums_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *p) -{ - struct ums_softc *sc; - int error = 0; - int s; - mousemode_t mode; - - sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); - if (!sc) - return EIO; - - switch(cmd) { - case MOUSE_GETHWINFO: - *(mousehw_t *)addr = sc->hw; - break; - case MOUSE_GETMODE: - *(mousemode_t *)addr = sc->mode; - break; - case MOUSE_SETMODE: - mode = *(mousemode_t *)addr; - - if (mode.level == -1) - /* don't change the current setting */ - ; - else if ((mode.level < 0) || (mode.level > 1)) - return (EINVAL); - - s = splusb(); - sc->mode.level = mode.level; - - if (sc->mode.level == 0) { - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->mode.level == 1) { - if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) - sc->hw.buttons = MOUSE_SYS_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_SYS_SYNC; - } - - bzero(sc->qbuf, sizeof(sc->qbuf)); - sc->qhead = sc->qtail = sc->qcount = 0; - splx(s); - - break; - case MOUSE_GETLEVEL: - *(int *)addr = sc->mode.level; - break; - case MOUSE_SETLEVEL: - if (*(int *)addr < 0 || *(int *)addr > 1) - return (EINVAL); - - s = splusb(); - sc->mode.level = *(int *)addr; - - if (sc->mode.level == 0) { - if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) - sc->hw.buttons = MOUSE_MSC_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_MSC; - sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->mode.level == 1) { - if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) - sc->hw.buttons = MOUSE_SYS_MAXBUTTON; - else - sc->hw.buttons = sc->nbuttons; - sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->mode.syncmask[1] = MOUSE_SYS_SYNC; - } - - bzero(sc->qbuf, sizeof(sc->qbuf)); - sc->qhead = sc->qtail = sc->qcount = 0; - splx(s); - - break; - case MOUSE_GETSTATUS: { - mousestatus_t *status = (mousestatus_t *) addr; - - s = splusb(); - *status = sc->status; - sc->status.obutton = sc->status.button; - sc->status.button = 0; - sc->status.dx = sc->status.dy - = sc->status.dz = /* sc->status.dt = */ 0; - splx(s); - - if (status->dx || status->dy || status->dz /* || status->dt */) - status->flags |= MOUSE_POSCHANGED; - if (status->button != status->obutton) - status->flags |= MOUSE_BUTTONSCHANGED; - break; - } - default: - error = ENOTTY; - } - - return error; -} - -MODULE_DEPEND(ums, usb, 1, 1, 1); -DRIVER_MODULE(ums, uhub, ums_driver, ums_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/uplcom.c b/sys/dev/usb/uplcom.c deleted file mode 100644 index ab5ab93..0000000 --- a/sys/dev/usb/uplcom.c +++ /dev/null @@ -1,990 +0,0 @@ -/* $NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $ */ - -/*- - * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama@jp.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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * 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. - */ - -/* - * This driver supports several USB-to-RS232 serial adapters driven by - * Prolific PL-2303, PL-2303X and probably PL-2303HX USB-to-RS232 - * bridge chip. The adapters are sold under many different brand - * names. - * - * Datasheets are available at Prolific www site at - * http://www.prolific.com.tw. The datasheets don't contain full - * programming information for the chip. - * - * PL-2303HX is probably programmed the same as PL-2303X. - * - * There are several differences between PL-2303 and PL-2303(H)X. - * PL-2303(H)X can do higher bitrate in bulk mode, has _probably_ - * different command for controlling CRTSCTS and needs special - * sequence of commands for initialization which aren't also - * documented in the datasheet. - */ - -#include "opt_uplcom.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/uio.h> -#include <sys/taskqueue.h> - -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -SYSCTL_NODE(_hw_usb, OID_AUTO, uplcom, CTLFLAG_RW, 0, "USB uplcom"); -#ifdef USB_DEBUG -static int uplcomdebug = 0; -SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RW, - &uplcomdebug, 0, "uplcom debug level"); - -#define DPRINTFN(n, x) do { \ - if (uplcomdebug > (n)) \ - printf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UPLCOM_MODVER 1 /* module version */ - -#define UPLCOM_CONFIG_INDEX 0 -#define UPLCOM_IFACE_INDEX 0 -#define UPLCOM_SECOND_IFACE_INDEX 1 - -#ifndef UPLCOM_INTR_INTERVAL -#define UPLCOM_INTR_INTERVAL 100 /* ms */ -#endif - -#define UPLCOM_SET_REQUEST 0x01 -#define UPLCOM_SET_CRTSCTS 0x41 -#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 -#define RSAQ_STATUS_CTS 0x80 -#define RSAQ_STATUS_DSR 0x02 -#define RSAQ_STATUS_DCD 0x01 - -#define TYPE_PL2303 0 -#define TYPE_PL2303X 1 - -struct uplcom_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number; /* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - 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_status; - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* uplcom status register */ - - int sc_chiptype; /* Type of chip */ - - struct task sc_task; -}; - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UPLCOMIBUFSIZE 256 -#define UPLCOMOBUFSIZE 256 - -static usbd_status uplcom_reset(struct uplcom_softc *); -static usbd_status uplcom_set_line_coding(struct uplcom_softc *, - usb_cdc_line_state_t *); -static usbd_status uplcom_set_crtscts(struct uplcom_softc *); -static void uplcom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); - -static void uplcom_set(void *, int, int, int); -static void uplcom_dtr(struct uplcom_softc *, int); -static void uplcom_rts(struct uplcom_softc *, int); -static void uplcom_break(struct uplcom_softc *, int); -static void uplcom_set_line_state(struct uplcom_softc *); -static void uplcom_get_status(void *, int, u_char *, u_char *); -static int uplcom_param(void *, int, struct termios *); -static int uplcom_open(void *, int); -static void uplcom_close(void *, int); -static void uplcom_notify(void *, int); - -struct ucom_callback uplcom_callback = { - uplcom_get_status, - uplcom_set, - uplcom_param, - NULL, - uplcom_open, - uplcom_close, - NULL, - NULL -}; - -static const struct uplcom_product { - uint16_t vendor; - uint16_t product; - int32_t release; /* release is a 16bit entity, - * if -1 is specified we "don't care" - * This is a floor value. The table - * must have newer revs before older - * revs (and -1 last). - */ - char chiptype; -} uplcom_products [] = { - { USB_VENDOR_RADIOSHACK, USB_PRODUCT_RADIOSHACK_USBCABLE, -1, TYPE_PL2303 }, - - /* I/O DATA USB-RSAQ */ - { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ, -1, TYPE_PL2303 }, - /* Prolific Pharos */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PHAROS, -1, TYPE_PL2303 }, - /* I/O DATA USB-RSAQ2 */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2, -1, TYPE_PL2303 }, - /* I/O DATA USB-RSAQ3 */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ3, -1, TYPE_PL2303X }, - /* Willcom W-SIM*/ - { USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_WSIM, -1, TYPE_PL2303X}, - /* PLANEX USB-RS232 URS-03 */ - { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A, -1, TYPE_PL2303 }, - /* TrendNet TU-S9 */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, - 0x400, TYPE_PL2303X }, - /* ST Lab USB-SERIAL-4 */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, - 0x300, TYPE_PL2303X }, - /* IOGEAR/ATEN UC-232A (also ST Lab USB-SERIAL-1) */ - { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, -1, TYPE_PL2303 }, - /* TDK USB-PHS Adapter UHA6400 */ - { USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400, -1, TYPE_PL2303 }, - /* RATOC REX-USB60 */ - { USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60, -1, TYPE_PL2303 }, - /* ELECOM UC-SGT */ - { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT, -1, TYPE_PL2303 }, - { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0, -1, TYPE_PL2303 }, - /* Sagem USB-Serial Controller */ - { USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_USBSERIAL, -1, TYPE_PL2303X }, - /* Sony Ericsson USB Cable */ - { USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DCU10, - -1,TYPE_PL2303 }, - /* SOURCENEXT KeikaiDenwa 8 */ - { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8, - -1, TYPE_PL2303 }, - /* SOURCENEXT KeikaiDenwa 8 with charger */ - { USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG, - -1, TYPE_PL2303 }, - /* HAL Corporation Crossam2+USB */ - { USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001, -1, TYPE_PL2303 }, - /* Sitecom USB to Serial */ - { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_SERIAL, -1, TYPE_PL2303 }, - /* Tripp-Lite U209-000-R */ - { USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209, -1, TYPE_PL2303X }, - /* Belkin F5U257 */ - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U257, -1, TYPE_PL2303X }, - { 0, 0 } -}; - -static device_probe_t uplcom_match; -static device_attach_t uplcom_attach; -static device_detach_t uplcom_detach; - -static device_method_t uplcom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uplcom_match), - DEVMETHOD(device_attach, uplcom_attach), - DEVMETHOD(device_detach, uplcom_detach), - { 0, 0 } -}; - -static driver_t uplcom_driver = { - "ucom", - uplcom_methods, - sizeof (struct uplcom_softc) -}; - -DRIVER_MODULE(uplcom, uhub, uplcom_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uplcom, usb, 1, 1, 1); -MODULE_DEPEND(uplcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uplcom, UPLCOM_MODVER); - -static int uplcominterval = UPLCOM_INTR_INTERVAL; - -static int -sysctl_hw_usb_uplcom_interval(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = uplcominterval; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - if (0 < val && val <= 1000) - uplcominterval = val; - else - err = EINVAL; - - return (err); -} - -SYSCTL_PROC(_hw_usb_uplcom, OID_AUTO, interval, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_usb_uplcom_interval, - "I", "uplcom interrupt pipe interval"); - -static int -uplcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - int i; - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - for (i = 0; uplcom_products[i].vendor != 0; i++) { - if (uplcom_products[i].vendor == uaa->vendor && - uplcom_products[i].product == uaa->product && - (uplcom_products[i].release <= uaa->release || - uplcom_products[i].release == -1)) { - return (UMATCH_VENDOR_PRODUCT); - } - } - return (UMATCH_NONE); -} - -static int -uplcom_attach(device_t self) -{ - struct uplcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - const char *devname; - usbd_status err; - int i; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - devname = device_get_nameunit(ucom->sc_dev); - - DPRINTF(("uplcom attach: sc = %p\n", sc)); - - /* determine chip type */ - for (i = 0; uplcom_products[i].vendor != 0; i++) { - if (uplcom_products[i].vendor == uaa->vendor && - uplcom_products[i].product == uaa->product && - (uplcom_products[i].release == uaa->release || - uplcom_products[i].release == -1)) { - sc->sc_chiptype = uplcom_products[i].chiptype; - break; - } - } - - /* - * check we found the device - attach should have ensured we - * don't get here without matching device - */ - if (uplcom_products[i].vendor == 0) { - printf("%s: didn't match\n", devname); - ucom->sc_dying = 1; - goto error; - } - -#ifdef USB_DEBUG - /* print the chip type */ - if (sc->sc_chiptype == TYPE_PL2303X) { - DPRINTF(("uplcom_attach: chiptype 2303X\n")); - } else { - DPRINTF(("uplcom_attach: chiptype 2303\n")); - } -#endif - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UPLCOM_CONFIG_INDEX, 1); - if (err) { - printf("%s: failed to set configuration: %s\n", - devname, usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - printf("%s: failed to get configuration descriptor\n", - device_get_nameunit(ucom->sc_dev)); - ucom->sc_dying = 1; - goto error; - } - - /* get the (first/common) interface */ - err = usbd_device2interface_handle(dev, UPLCOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - printf("%s: failed to get interface: %s\n", - devname, usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - /* Find the interrupt endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - printf("%s: no endpoint descriptor for %d\n", - device_get_nameunit(ucom->sc_dev), i); - ucom->sc_dying = 1; - goto error; - } - - 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 (sc->sc_intr_number == -1) { - printf("%s: Could not find interrupt in\n", - device_get_nameunit(ucom->sc_dev)); - ucom->sc_dying = 1; - goto error; - } - - /* keep interface for interrupt */ - sc->sc_intr_iface = ucom->sc_iface; - - /* - * USB-RSAQ1 has two interface - * - * USB-RSAQ1 | USB-RSAQ2 - * -----------------+----------------- - * Interface 0 |Interface 0 - * Interrupt(0x81) | Interrupt(0x81) - * -----------------+ BulkIN(0x02) - * Interface 1 | BulkOUT(0x83) - * BulkIN(0x02) | - * BulkOUT(0x83) | - */ - if (cdesc->bNumInterface == 2) { - err = usbd_device2interface_handle(dev, - UPLCOM_SECOND_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - printf("%s: failed to get second interface: %s\n", - devname, usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - } - - /* Find the bulk{in,out} endpoints */ - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - printf("%s: no endpoint descriptor for %d\n", - device_get_nameunit(ucom->sc_dev), i); - ucom->sc_dying = 1; - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - } - - if (ucom->sc_bulkin_no == -1) { - printf("%s: Could not find data bulk in\n", - device_get_nameunit(ucom->sc_dev)); - ucom->sc_dying = 1; - goto error; - } - - if (ucom->sc_bulkout_no == -1) { - printf("%s: Could not find data bulk out\n", - device_get_nameunit(ucom->sc_dev)); - ucom->sc_dying = 1; - goto error; - } - - sc->sc_dtr = sc->sc_rts = -1; - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UPLCOMIBUFSIZE; - ucom->sc_obufsize = UPLCOMOBUFSIZE; - ucom->sc_ibufsizepad = UPLCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uplcom_callback; - - err = uplcom_reset(sc); - - if (err) { - printf("%s: reset failed: %s\n", - device_get_nameunit(ucom->sc_dev), usbd_errstr(err)); - ucom->sc_dying = 1; - goto error; - } - - DPRINTF(("uplcom: in = 0x%x, out = 0x%x, intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - TASK_INIT(&sc->sc_task, 0, uplcom_notify, sc); - ucom_attach(&sc->sc_ucom); - return 0; - -error: - return ENXIO; -} - -static int -uplcom_detach(device_t self) -{ - struct uplcom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uplcom_detach: sc = %p\n", sc)); - - 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_ucom.sc_dying = 1; - - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static usbd_status -uplcom_reset(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UPLCOM_SET_REQUEST; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - printf("%s: uplcom_reset: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (EIO); - } - - return (0); -} - -struct pl2303x_init { - uint8_t req_type; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -}; - -static const struct pl2303x_init pl2303x[] = { - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 0 }, - { UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0 }, - { UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0 } -}; -#define N_PL2302X_INIT (sizeof(pl2303x)/sizeof(pl2303x[0])) - -static usbd_status -uplcom_pl2303x_init(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - int i; - - for (i = 0; i < N_PL2302X_INIT; i++) { - req.bmRequestType = pl2303x[i].req_type; - req.bRequest = pl2303x[i].request; - USETW(req.wValue, pl2303x[i].value); - USETW(req.wIndex, pl2303x[i].index); - USETW(req.wLength, pl2303x[i].length); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - printf("%s: uplcom_pl2303x_init: %d: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), i, - usbd_errstr(err)); - return (EIO); - } - } - - return (0); -} - -static void -uplcom_set_line_state(struct uplcom_softc *sc) -{ - usb_device_request_t req; - int ls; - usbd_status err; - - ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) | - (sc->sc_rts ? UCDC_LINE_RTS : 0); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - printf("%s: uplcom_set_line_status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); -} - -static void -uplcom_set(void *addr, int portno, int reg, int onoff) -{ - struct uplcom_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - uplcom_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - uplcom_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - uplcom_break(sc, onoff); - break; - default: - break; - } -} - -static void -uplcom_dtr(struct uplcom_softc *sc, int onoff) -{ - DPRINTF(("uplcom_dtr: onoff = %d\n", onoff)); - - if (sc->sc_dtr == onoff) - return; - sc->sc_dtr = onoff; - - uplcom_set_line_state(sc); -} - -static void -uplcom_rts(struct uplcom_softc *sc, int onoff) -{ - DPRINTF(("uplcom_rts: onoff = %d\n", onoff)); - - if (sc->sc_rts == onoff) - return; - sc->sc_rts = onoff; - - uplcom_set_line_state(sc); -} - -static void -uplcom_break(struct uplcom_softc *sc, int onoff) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("uplcom_break: onoff = %d\n", onoff)); - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_BREAK; - USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) - printf("%s: uplcom_break: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); -} - -static usbd_status -uplcom_set_crtscts(struct uplcom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("uplcom_set_crtscts: on\n")); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UPLCOM_SET_REQUEST; - USETW(req.wValue, 0); - if (sc->sc_chiptype == TYPE_PL2303X) - USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); - else - USETW(req.wIndex, UPLCOM_SET_CRTSCTS); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, 0); - if (err) { - printf("%s: uplcom_set_crtscts: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uplcom_set_line_coding(struct uplcom_softc *sc, usb_cdc_line_state_t *state) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(( -"uplcom_set_line_coding: rate = %d, fmt = %d, parity = %d bits = %d\n", - UGETDW(state->dwDTERate), state->bCharFormat, - state->bParityType, state->bDataBits)); - - if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) { - DPRINTF(("uplcom_set_line_coding: already set\n")); - return (USBD_NORMAL_COMPLETION); - } - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_LINE_CODING; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_iface_number); - USETW(req.wLength, UCDC_LINE_STATE_LENGTH); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, state); - if (err) { - printf("%s: uplcom_set_line_coding: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), usbd_errstr(err)); - return (err); - } - - sc->sc_line_state = *state; - - return (USBD_NORMAL_COMPLETION); -} - -static const int uplcom_rates[] = { - 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, - 19200, 28800, 38400, 57600, 115200, - /* - * Higher speeds are probably possible. PL2303X supports up to - * 6Mb and can set any rate - */ - 230400, 460800, 614400, 921600, 1228800 -}; -#define N_UPLCOM_RATES (sizeof(uplcom_rates)/sizeof(uplcom_rates[0])) - -static int -uplcom_param(void *addr, int portno, struct termios *t) -{ - struct uplcom_softc *sc = addr; - usbd_status err; - usb_cdc_line_state_t ls; - int i; - - DPRINTF(("uplcom_param: sc = %p\n", sc)); - - /* Check requested baud rate */ - for (i = 0; i < N_UPLCOM_RATES; i++) - if (uplcom_rates[i] == t->c_ospeed) - break; - if (i == N_UPLCOM_RATES) { - DPRINTF(("uplcom_param: bad baud rate (%d)\n", t->c_ospeed)); - return (EIO); - } - - USETDW(ls.dwDTERate, t->c_ospeed); - if (ISSET(t->c_cflag, CSTOPB)) - ls.bCharFormat = UCDC_STOP_BIT_2; - else - ls.bCharFormat = UCDC_STOP_BIT_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - ls.bParityType = UCDC_PARITY_ODD; - else - ls.bParityType = UCDC_PARITY_EVEN; - } else - ls.bParityType = UCDC_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - ls.bDataBits = 5; - break; - case CS6: - ls.bDataBits = 6; - break; - case CS7: - ls.bDataBits = 7; - break; - case CS8: - ls.bDataBits = 8; - break; - } - - err = uplcom_set_line_coding(sc, &ls); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - err = uplcom_set_crtscts(sc); - if (err) - return (EIO); - } - - return (0); -} - -static int -uplcom_open(void *addr, int portno) -{ - struct uplcom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("uplcom_open: sc = %p\n", sc)); - - 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_intr_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - uplcom_intr, - uplcominterval); - if (err) { - printf("%s: cannot open interrupt pipe (addr %d)\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - sc->sc_intr_number); - return (EIO); - } - } - - if (sc->sc_chiptype == TYPE_PL2303X) - return (uplcom_pl2303x_init(sc)); - - return (0); -} - -static void -uplcom_close(void *addr, int portno) -{ - struct uplcom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("uplcom_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", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - printf("%s: close interrupt pipe failed: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -uplcom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct uplcom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - u_char pstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - DPRINTF(("%s: uplcom_intr: abnormal status: %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), - usbd_errstr(status))); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - DPRINTF(("%s: uplcom status = %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), buf[8])); - - sc->sc_lsr = sc->sc_msr = 0; - pstatus = buf[8]; - if (ISSET(pstatus, RSAQ_STATUS_CTS)) - sc->sc_msr |= SER_CTS; - else - sc->sc_msr &= ~SER_CTS; - if (ISSET(pstatus, RSAQ_STATUS_DSR)) - sc->sc_msr |= SER_DSR; - else - sc->sc_msr &= ~SER_DSR; - if (ISSET(pstatus, RSAQ_STATUS_DCD)) - sc->sc_msr |= SER_DCD; - else - sc->sc_msr &= ~SER_DCD; - - /* Deferred notifying to the ucom layer */ - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); -} - -static void -uplcom_notify(void *arg, int count) -{ - struct uplcom_softc *sc; - - sc = (struct uplcom_softc *)arg; - if (sc->sc_ucom.sc_dying) - return; - ucom_status_change(&sc->sc_ucom); -} - -static void -uplcom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct uplcom_softc *sc = addr; - - DPRINTF(("uplcom_get_status:\n")); - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} diff --git a/sys/dev/usb/urio.c b/sys/dev/usb/urio.c deleted file mode 100644 index 5f69918..0000000 --- a/sys/dev/usb/urio.c +++ /dev/null @@ -1,518 +0,0 @@ -/*- - * Copyright (c) 2000 Iwasa Kazmi - * 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. - * - * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. - * This code includes software developed by the NetBSD Foundation, Inc. and - * its contributors. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - - -/* - * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky) - * 2000/3/07 use two bulk-pipe handles for read and write (Dirk) - * 2000/3/06 change major number(143), and copyright header - * some fix for 4.0 (Dirk) - * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik) - * 2000/3/01 remove retry code from urioioctl() - * change method of bulk transfer (no interrupt) - * 2000/2/28 small fixes for new rio_usb.h - * 2000/2/24 first version. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/conf.h> -#include <sys/uio.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include "usbdevs.h" -#include <dev/usb/rio500_usb.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uriodebug) printf x -#define DPRINTFN(n,x) if (uriodebug>(n)) printf x -int uriodebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); -SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW, - &uriodebug, 0, "urio debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -/* difference of usbd interface */ -#define USBDI 1 - -#define RIO_OUT 0 -#define RIO_IN 1 -#define RIO_NODIR 2 - -d_open_t urioopen; -d_close_t urioclose; -d_read_t urioread; -d_write_t uriowrite; -d_ioctl_t urioioctl; - - -static struct cdevsw urio_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = urioopen, - .d_close = urioclose, - .d_read = urioread, - .d_write = uriowrite, - .d_ioctl = urioioctl, - .d_name = "urio", -}; -#define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\ - ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\ - RIO_NODIR)) - -#define URIO_BBSIZE 1024 - -struct urio_softc { - device_t sc_dev; - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - - int sc_opened; - usbd_pipe_handle sc_pipeh_in; - usbd_pipe_handle sc_pipeh_out; - int sc_epaddr[2]; - - int sc_refcnt; - struct cdev *sc_dev_t; - u_char sc_dying; -}; - -#define URIOUNIT(n) (dev2unit(n)) - -#define RIO_RW_TIMEOUT 4000 /* ms */ - -static device_probe_t urio_match; -static device_attach_t urio_attach; -static device_detach_t urio_detach; - -static device_method_t urio_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, urio_match), - DEVMETHOD(device_attach, urio_attach), - DEVMETHOD(device_detach, urio_detach), - - { 0, 0 } -}; - -static driver_t urio_driver = { - "urio", - urio_methods, - sizeof(struct urio_softc) -}; - -static devclass_t urio_devclass; - -static int -urio_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_device_descriptor_t *dd; - - DPRINTFN(10,("urio_match\n")); - if (!uaa->iface) - return UMATCH_NONE; - - dd = usbd_get_device_descriptor(uaa->device); - - if (dd && - ((UGETW(dd->idVendor) == USB_VENDOR_DIAMOND && - UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND_RIO500USB) || - (UGETW(dd->idVendor) == USB_VENDOR_DIAMOND2 && - (UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO600USB || - UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO800USB)))) - return UMATCH_VENDOR_PRODUCT; - else - return UMATCH_NONE; -} - -static int -urio_attach(device_t self) -{ - struct urio_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle udev; - usbd_interface_handle iface; - u_int8_t epcount; - usbd_status r; - char * ermsg = "<none>"; - int i; - - DPRINTFN(10,("urio_attach: sc=%p\n", sc)); - sc->sc_dev = self; - sc->sc_udev = udev = uaa->device; - - if ((!uaa->device) || (!uaa->iface)) { - ermsg = "device or iface"; - goto nobulk; - } - sc->sc_iface = iface = uaa->iface; - sc->sc_opened = 0; - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - sc->sc_refcnt = 0; - - r = usbd_endpoint_count(iface, &epcount); - if (r != USBD_NORMAL_COMPLETION) { - ermsg = "endpoints"; - goto nobulk; - } - - sc->sc_epaddr[RIO_OUT] = 0xff; - sc->sc_epaddr[RIO_IN] = 0x00; - - for (i = 0; i < epcount; i++) { - usb_endpoint_descriptor_t *edesc = - usbd_interface2endpoint_descriptor(iface, i); - int d; - - if (!edesc) { - ermsg = "interface endpoint"; - goto nobulk; - } - - d = RIO_UE_GET_DIR(edesc->bEndpointAddress); - if (d != RIO_NODIR) - sc->sc_epaddr[d] = edesc->bEndpointAddress; - } - if ( sc->sc_epaddr[RIO_OUT] == 0xff || - sc->sc_epaddr[RIO_IN] == 0x00) { - ermsg = "Rio I&O"; - goto nobulk; - } - - sc->sc_dev_t = make_dev(&urio_cdevsw, device_get_unit(self), - UID_ROOT, GID_OPERATOR, - 0644, "urio%d", device_get_unit(self)); - DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev)); - - return 0; - - nobulk: - printf("%s: could not find %s\n", device_get_nameunit(sc->sc_dev),ermsg); - return ENXIO; -} - - -int -urioopen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct urio_softc * sc; - int unit = URIOUNIT(dev); - sc = devclass_get_softc(urio_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n", - flag, mode, unit)); - - if (sc->sc_opened) - return EBUSY; - - if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD)) - return EACCES; - - sc->sc_opened = 1; - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - if (usbd_open_pipe(sc->sc_iface, - sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in) - != USBD_NORMAL_COMPLETION) - { - sc->sc_pipeh_in = 0; - return EIO; - }; - if (usbd_open_pipe(sc->sc_iface, - sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out) - != USBD_NORMAL_COMPLETION) - { - usbd_close_pipe(sc->sc_pipeh_in); - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - return EIO; - }; - return 0; -} - -int -urioclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct urio_softc * sc; - int unit = URIOUNIT(dev); - sc = devclass_get_softc(urio_devclass, unit); - - DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit)); - if (sc->sc_pipeh_in) - usbd_close_pipe(sc->sc_pipeh_in); - - if (sc->sc_pipeh_out) - usbd_close_pipe(sc->sc_pipeh_out); - - sc->sc_pipeh_in = 0; - sc->sc_pipeh_out = 0; - sc->sc_opened = 0; - sc->sc_refcnt = 0; - return 0; -} - -int -urioread(struct cdev *dev, struct uio *uio, int flag) -{ - struct urio_softc * sc; - usbd_xfer_handle reqh; - int unit = URIOUNIT(dev); - usbd_status r; - char buf[URIO_BBSIZE]; - u_int32_t n, tn; - int error = 0; - - sc = devclass_get_softc(urio_devclass, unit); - - DPRINTFN(5, ("urioread: %d\n", unit)); - if (!sc->sc_opened) - return EIO; - - sc->sc_refcnt++; - reqh = usbd_alloc_xfer(sc->sc_udev); - if (reqh == 0) - return ENOMEM; - while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) { - DPRINTFN(1, ("urioread: start transfer %d bytes\n", n)); - tn = n; - usbd_setup_xfer(reqh, sc->sc_pipeh_in, 0, buf, tn, - 0, RIO_RW_TIMEOUT, 0); - r = usbd_sync_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(1, ("urioread: error=%d\n", r)); - usbd_clear_endpoint_stall(sc->sc_pipeh_in); - tn = 0; - error = EIO; - break; - } - usbd_get_xfer_status(reqh, 0, 0, &tn, 0); - - DPRINTFN(1, ("urioread: got %d bytes\n", tn)); - error = uiomove(buf, tn, uio); - if (error || tn < n) - break; - } - usbd_free_xfer(reqh); - return error; -} - -int -uriowrite(struct cdev *dev, struct uio *uio, int flag) -{ - struct urio_softc * sc; - usbd_xfer_handle reqh; - int unit = URIOUNIT(dev); - usbd_status r; - char buf[URIO_BBSIZE]; - u_int32_t n; - int error = 0; - - sc = devclass_get_softc(urio_devclass, unit); - DPRINTFN(5, ("uriowrite: %d\n", unit)); - if (!sc->sc_opened) - return EIO; - - sc->sc_refcnt++; - reqh = usbd_alloc_xfer(sc->sc_udev); - if (reqh == 0) - return EIO; - while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) { - error = uiomove(buf, n, uio); - if (error) - break; - DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n)); - usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n, - 0, RIO_RW_TIMEOUT, 0); - r = usbd_sync_transfer(reqh); - if (r != USBD_NORMAL_COMPLETION) { - DPRINTFN(1, ("uriowrite: error=%d\n", r)); - usbd_clear_endpoint_stall(sc->sc_pipeh_out); - error = EIO; - break; - } - usbd_get_xfer_status(reqh, 0, 0, 0, 0); - } - - usbd_free_xfer(reqh); - return error; -} - - -int -urioioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *p) -{ - struct urio_softc * sc; - int unit = URIOUNIT(dev); - struct RioCommand *rio_cmd; - int requesttype, len; - struct iovec iov; - struct uio uio; - usb_device_request_t req; - int req_flags = 0, req_actlen = 0; - void *ptr = 0; - int error = 0; - usbd_status r; - - sc = devclass_get_softc(urio_devclass, unit); - switch (cmd) { - case RIO_RECV_COMMAND: - if (!(flag & FWRITE)) - return EPERM; - rio_cmd = (struct RioCommand *)addr; - if (rio_cmd == NULL) - return EINVAL; - len = rio_cmd->length; - - requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; - DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); - break; - - case RIO_SEND_COMMAND: - if (!(flag & FWRITE)) - return EPERM; - rio_cmd = (struct RioCommand *)addr; - if (rio_cmd == NULL) - return EINVAL; - len = rio_cmd->length; - - requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; - DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", - requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len)); - break; - - default: - return EINVAL; - break; - } - - /* Send rio control message */ - req.bmRequestType = requesttype; - req.bRequest = rio_cmd->request; - USETW(req.wValue, rio_cmd->value); - USETW(req.wIndex, rio_cmd->index); - USETW(req.wLength, len); - - if (len < 0 || len > 32767) - return EINVAL; - if (len != 0) { - iov.iov_base = (caddr_t)rio_cmd->buffer; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - req.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = p; - ptr = malloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - - r = usbd_do_request_flags(sc->sc_udev, &req, - ptr, req_flags, &req_actlen, - USBD_DEFAULT_TIMEOUT); - if (r == USBD_NORMAL_COMPLETION) { - error = 0; - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - } - } - } else { - error = EIO; - } - -ret: - if (ptr) - free(ptr, M_TEMP); - return error; -} - -static int -urio_detach(device_t self) -{ - struct urio_softc *sc = device_get_softc(self); - int s; - - DPRINTF(("urio_detach: sc=%p\n", sc)); - sc->sc_dying = 1; - if (sc->sc_pipeh_in) - usbd_abort_pipe(sc->sc_pipeh_in); - - if (sc->sc_pipeh_out) - usbd_abort_pipe(sc->sc_pipeh_out); - - s = splusb(); - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - splx(s); - - destroy_dev(sc->sc_dev_t); - /* XXX not implemented yet */ - device_set_desc(self, NULL); - return 0; -} - -MODULE_DEPEND(uscanner, usb, 1, 1, 1); -DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c deleted file mode 100644 index b1b7d44..0000000 --- a/sys/dev/usb/usb.c +++ /dev/null @@ -1,939 +0,0 @@ -/* $NetBSD: usb.c,v 1.68 2002/02/20 20:30:12 christos Exp $ */ - -/* Also already merged from NetBSD: - * $NetBSD: usb.c,v 1.70 2002/05/09 21:54:32 augustss Exp $ - * $NetBSD: usb.c,v 1.71 2002/06/01 23:51:04 lukem Exp $ - * $NetBSD: usb.c,v 1.73 2002/09/23 05:51:19 simonb Exp $ - * $NetBSD: usb.c,v 1.80 2003/11/07 17:03:25 wiz Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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. - */ - -/* - * USB specifications and other documentation can be found at - * http://www.usb.org/developers/docs/ and - * http://www.usb.org/developers/devclass_docs/ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/unistd.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/uio.h> -#include <sys/kthread.h> -#include <sys/proc.h> -#include <sys/conf.h> -#include <sys/poll.h> -#include <sys/selinfo.h> -#include <sys/signalvar.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#define USBUNIT(d) (dev2unit(d)) /* usb_discover device nodes, kthread */ -#define USB_DEV_MINOR 255 /* event queue device */ - -MALLOC_DEFINE(M_USB, "USB", "USB"); -MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); -MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); - -#include "usb_if.h" - -#include <machine/bus.h> - -#include <dev/usb/usbdivar.h> -#include <dev/usb/usb_quirks.h> - -/* Define this unconditionally in case a kernel module is loaded that - * has been compiled with debugging options. - */ -SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging"); - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -int usbdebug = 0; -SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW, - &usbdebug, 0, "usb debug level"); -/* - * 0 - do usual exploration - * 1 - do not use timeout exploration - * >1 - do no exploration - */ -int usb_noexplore = 0; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -struct usb_softc { - device_t sc_dev; /* base device */ - struct cdev *sc_usbdev; /* /dev/usbN device */ - TAILQ_ENTRY(usb_softc) sc_coldexplist; /* cold needs-explore list */ - usbd_bus_handle sc_bus; /* USB controller */ - struct usbd_port sc_port; /* dummy port for root hub */ - - struct proc *sc_event_thread; - - char sc_dying; -}; - -struct usb_taskq { - TAILQ_HEAD(, usb_task) tasks; - struct proc *task_thread_proc; - const char *name; - int taskcreated; /* task thread exists. */ -}; - -static struct usb_taskq usb_taskq[USB_NUM_TASKQS]; - -d_open_t usbopen; -d_close_t usbclose; -d_read_t usbread; -d_ioctl_t usbioctl; -d_poll_t usbpoll; - -struct cdevsw usb_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = usbopen, - .d_close = usbclose, - .d_read = usbread, - .d_ioctl = usbioctl, - .d_poll = usbpoll, - .d_name = "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 struct cdev *usb_dev; /* The /dev/usb device. */ -static int usb_ndevs; /* Number of /dev/usbN devices. */ -/* Busses to explore at the end of boot-time device configuration. */ -static TAILQ_HEAD(, usb_softc) usb_coldexplist = - TAILQ_HEAD_INITIALIZER(usb_coldexplist); - -#define USB_MAX_EVENTS 100 -struct usb_event_q { - struct usb_event ue; - TAILQ_ENTRY(usb_event_q) next; -}; -static TAILQ_HEAD(, usb_event_q) usb_events = - TAILQ_HEAD_INITIALIZER(usb_events); -static int usb_nevents = 0; -static struct selinfo usb_selevent; -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 *); - -static int usb_get_next_event(struct usb_event *); - -static const char *usbrev_str[] = USBREV_STR; - -static device_probe_t usb_match; -static device_attach_t usb_attach; -static device_detach_t usb_detach; -static bus_child_detached_t usb_child_detached; - -static device_method_t usb_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, usb_match), - DEVMETHOD(device_attach, usb_attach), - DEVMETHOD(device_detach, usb_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_child_detached, usb_child_detached), - - { 0, 0 } -}; - -static driver_t usb_driver = { - "usb", - usb_methods, - sizeof(struct usb_softc) -}; - -static devclass_t usb_devclass; - -DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0); -DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0); -DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0); -DRIVER_MODULE(usb, slhci, usb_driver, usb_devclass, 0, 0); -MODULE_VERSION(usb, 1); - -static int -usb_match(device_t self) -{ - DPRINTF(("usbd_match\n")); - return (UMATCH_GENERIC); -} - -static int -usb_attach(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - void *aux = device_get_ivars(self); - usbd_device_handle dev; - usbd_status err; - int usbrev; - int speed; - struct usb_event ue; - - sc->sc_dev = self; - - DPRINTF(("usbd_attach\n")); - - usbd_init(); - sc->sc_bus = aux; - sc->sc_bus->usbctl = sc; - sc->sc_port.power = USB_MAX_POWER; - - printf("%s", device_get_nameunit(sc->sc_dev)); - 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: - printf(", not supported\n"); - sc->sc_dying = 1; - return ENXIO; - } - printf("\n"); - - /* Make sure not to use tsleep() if we are cold booting. */ - if (cold) - sc->sc_bus->use_polling++; - - ue.u.ue_ctrlr.ue_bus = device_get_unit(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", device_get_nameunit(sc->sc_dev)); - sc->sc_dying = 1; - return ENXIO; - } -#else - usb_callout_init(sc->sc_bus->softi); -#endif -#endif - - err = usbd_new_device(sc->sc_dev, sc->sc_bus, 0, speed, 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", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - 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. - */ - if (cold) { - /* Explore high-speed busses before others. */ - if (speed == USB_SPEED_HIGH) - dev->hub->explore(sc->sc_bus->root_hub); - else - TAILQ_INSERT_TAIL(&usb_coldexplist, sc, - sc_coldexplist); - } -#endif - } else { - printf("%s: root hub problem, error=%d\n", - device_get_nameunit(sc->sc_dev), err); - sc->sc_dying = 1; - } - if (cold) - sc->sc_bus->use_polling--; - - /* XXX really do right config_pending_incr(); */ - usb_create_event_thread(sc); - /* The per controller devices (used for usb_discover) */ - /* XXX This is redundant now, but old usbd's will want it */ - sc->sc_usbdev = make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, - GID_OPERATOR, 0660, "usb%d", device_get_unit(self)); - if (usb_ndevs++ == 0) { - /* The device spitting out events */ - usb_dev = make_dev(&usb_cdevsw, USB_DEV_MINOR, UID_ROOT, - GID_OPERATOR, 0660, "usb"); - } - return 0; -} - -static const char *taskq_names[] = USB_TASKQ_NAMES; - -void -usb_create_event_thread(void *arg) -{ - struct usb_softc *sc = arg; - struct usb_taskq *taskq; - int i; - - if (kproc_create(usb_event_thread, sc, &sc->sc_event_thread, - RFHIGHPID, 0, device_get_nameunit(sc->sc_dev))) { - printf("%s: unable to create event thread for\n", - device_get_nameunit(sc->sc_dev)); - panic("usb_create_event_thread"); - } - for (i = 0; i < USB_NUM_TASKQS; i++) { - taskq = &usb_taskq[i]; - - if (taskq->taskcreated == 0) { - taskq->taskcreated = 1; - taskq->name = taskq_names[i]; - TAILQ_INIT(&taskq->tasks); - if (kproc_create(usb_task_thread, taskq, - &taskq->task_thread_proc, RFHIGHPID, 0, - taskq->name)) { - 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 - * 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, int queue) -{ - struct usb_taskq *taskq; - int s; - - s = splusb(); - taskq = &usb_taskq[queue]; - if (task->queue == -1) { - DPRINTFN(2,("usb_add_task: task=%p\n", task)); - TAILQ_INSERT_TAIL(&taskq->tasks, task, next); - task->queue = queue; - } else { - DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); - } - wakeup(&taskq->tasks); - splx(s); -} - -void -usb_rem_task(usbd_device_handle dev, struct usb_task *task) -{ - struct usb_taskq *taskq; - int s; - - s = splusb(); - if (task->queue != -1) { - taskq = &usb_taskq[task->queue]; - TAILQ_REMOVE(&taskq->tasks, task, next); - task->queue = -1; - } - splx(s); -} - -void -usb_event_thread(void *arg) -{ - static int newthread_wchan; - struct usb_softc *sc = arg; - - mtx_lock(&Giant); - - 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. What we do here is wait until no new - * USB threads have been created in a while. XXX we actually - * just want to wait for the PCI slot to be fully scanned. - * - * Note that when you `kldload usb' it actually attaches the - * devices in order that the drivers appear in the kld, not the - * normal PCI order, since the addition of each driver within - * usb.ko (ohci, ehci etc.) causes a separate PCI bus re-scan. - */ - wakeup(&newthread_wchan); - for (;;) { - if (tsleep(&newthread_wchan , PWAIT, "usbets", hz * 4) != 0) - break; - } - - /* Make sure first discover does something. */ - sc->sc_bus->needs_explore = 1; - usb_discover(sc); - /* XXX really do right 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")); - } - sc->sc_event_thread = NULL; - - /* In case parent is waiting for us to exit. */ - wakeup(sc); - - DPRINTF(("usb_event_thread: exit\n")); - while (mtx_owned(&Giant)) - mtx_unlock(&Giant); - kproc_exit(0); -} - -void -usb_task_thread(void *arg) -{ - struct usb_task *task; - struct usb_taskq *taskq; - int s; - - mtx_lock(&Giant); - - taskq = arg; - DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name)); - - s = splusb(); - while (usb_ndevs > 0) { - task = TAILQ_FIRST(&taskq->tasks); - if (task == NULL) { - tsleep(&taskq->tasks, PWAIT, "usbtsk", 0); - task = TAILQ_FIRST(&taskq->tasks); - } - DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task)); - if (task != NULL) { - TAILQ_REMOVE(&taskq->tasks, task, next); - task->queue = -1; - splx(s); - task->fun(task->arg); - s = splusb(); - } - } - splx(s); - - taskq->taskcreated = 0; - wakeup(&taskq->taskcreated); - - DPRINTF(("usb_event_thread: exit\n")); - while (mtx_owned(&Giant)) - mtx_unlock(&Giant); - kproc_exit(0); -} - -int -usbopen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - int unit = USBUNIT(dev); - struct usb_softc *sc; - - if (unit == USB_DEV_MINOR) { - if (usb_dev_open) - return (EBUSY); - usb_dev_open = 1; - usb_async_proc = 0; - return (0); - } - sc = devclass_get_softc(usb_devclass, unit); - if (sc == NULL) - return (ENXIO); - if (sc->sc_dying) - return (EIO); - - return (0); -} - -int -usbread(struct cdev *dev, struct uio *uio, int flag) -{ - struct usb_event ue; - int unit = USBUNIT(dev); - int s, error, n; - - if (unit != USB_DEV_MINOR) - return (ENODEV); - - if (uio->uio_resid != sizeof(struct usb_event)) - return (EINVAL); - - error = 0; - s = splusb(); - for (;;) { - n = usb_get_next_event(&ue); - if (n != 0) - break; - if (flag & O_NONBLOCK) { - error = EWOULDBLOCK; - break; - } - error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0); - if (error) - break; - } - splx(s); - if (!error) - error = uiomove((void *)&ue, uio->uio_resid, uio); - - return (error); -} - -int -usbclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - int unit = USBUNIT(dev); - - if (unit == USB_DEV_MINOR) { - usb_async_proc = 0; - usb_dev_open = 0; - } - - return (0); -} - -int -usbioctl(struct cdev *devt, u_long cmd, caddr_t data, int flag, struct thread *p) -{ - struct usb_softc *sc; - int unit = USBUNIT(devt); - - if (unit == USB_DEV_MINOR) { - switch (cmd) { - case FIONBIO: - /* All handled in the upper FS layer. */ - return (0); - - case FIOASYNC: - if (*(int *)data) - usb_async_proc = p->td_proc; - else - usb_async_proc = 0; - return (0); - - default: - return (EINVAL); - } - } - sc = devclass_get_softc(usb_devclass, unit); - if (sc->sc_dying) - return (EIO); - - switch (cmd) { - /* This part should be deleted */ - case USB_DISCOVER: - break; - case USB_REQUEST: - { - struct usb_ctl_request *ur = (void *)data; - int len = UGETW(ur->ucr_request.wLength); - struct iovec iov; - struct uio uio; - void *ptr = 0; - int addr = ur->ucr_addr; - usbd_status err; - int error = 0; - - 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 || - sc->sc_bus->devices[addr] == 0) - return (EINVAL); - if (len != 0) { - iov.iov_base = (caddr_t)ur->ucr_data; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_resid = len; - uio.uio_offset = 0; - uio.uio_segflg = UIO_USERSPACE; - uio.uio_rw = - ur->ucr_request.bmRequestType & UT_READ ? - UIO_READ : UIO_WRITE; - uio.uio_td = p; - ptr = malloc(len, M_TEMP, M_WAITOK); - if (uio.uio_rw == UIO_WRITE) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - err = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, - USBD_DEFAULT_TIMEOUT); - if (err) { - error = EIO; - goto ret; - } - if (len != 0) { - if (uio.uio_rw == UIO_READ) { - error = uiomove(ptr, len, &uio); - if (error) - goto ret; - } - } - ret: - if (ptr) - free(ptr, M_TEMP); - return (error); - } - - case USB_DEVICEINFO: - { - struct usb_device_info *di = (void *)data; - int addr = di->udi_addr; - usbd_device_handle dev; - - if (addr < 1 || addr >= USB_MAX_DEVICES) - return (EINVAL); - dev = sc->sc_bus->devices[addr]; - if (dev == NULL) - return (ENXIO); - usbd_fill_deviceinfo(dev, di, 1); - break; - } - - case USB_DEVICESTATS: - *(struct usb_device_stats *)data = sc->sc_bus->stats; - break; - - default: - return (EINVAL); - } - return (0); -} - -int -usbpoll(struct cdev *dev, int events, struct thread *p) -{ - int revents, mask, s; - int unit = USBUNIT(dev); - - if (unit == 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 (0); /* select/poll never wakes up - back compat */ - } -} - -/* Explore device tree from the root. */ -static void -usb_discover(void *v) -{ - struct usb_softc *sc = v; - - /* splxxx should be changed to mutexes for preemption safety some day */ - int s; - - DPRINTFN(2,("usb_discover\n")); -#ifdef USB_DEBUG - 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. - */ - s = splusb(); - while (sc->sc_bus->needs_explore && !sc->sc_dying) { - sc->sc_bus->needs_explore = 0; - splx(s); - sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); - s = splusb(); - } - splx(s); -} - -void -usb_needs_explore(usbd_device_handle dev) -{ - DPRINTFN(2,("usb_needs_explore\n")); - dev->bus->needs_explore = 1; - wakeup(&dev->bus->needs_explore); -} - -/* Called at splusb() */ -int -usb_get_next_event(struct usb_event *ue) -{ - struct usb_event_q *ueq; - - if (usb_nevents <= 0) - return (0); - ueq = TAILQ_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; - TAILQ_REMOVE(&usb_events, ueq, next); - free(ueq, M_USBDEV); - usb_nevents--; - return (1); -} - -void -usbd_add_dev_event(int type, usbd_device_handle udev) -{ - struct usb_event ue; - - usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type)); - usb_add_event(type, &ue); -} - -void -usbd_add_drv_event(int type, usbd_device_handle udev, device_t dev) -{ - struct usb_event ue; - - ue.u.ue_driver.ue_cookie = udev->cookie; - strncpy(ue.u.ue_driver.ue_devname, device_get_nameunit(dev), - sizeof ue.u.ue_driver.ue_devname); - usb_add_event(type, &ue); -} - -void -usb_add_event(int type, struct usb_event *uep) -{ - struct usb_event_q *ueq; - struct usb_event ue; - struct timeval thetime; - int s; - - ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK); - ueq->ue = *uep; - ueq->ue.ue_type = type; - microtime(&thetime); - TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); - - s = splusb(); - if (USB_EVENT_IS_DETACH(type)) { - struct usb_event_q *ueqi, *ueqi_next; - - for (ueqi = TAILQ_FIRST(&usb_events); ueqi; ueqi = ueqi_next) { - ueqi_next = TAILQ_NEXT(ueqi, next); - if (ueqi->ue.u.ue_driver.ue_cookie.cookie == - uep->u.ue_device.udi_cookie.cookie) { - TAILQ_REMOVE(&usb_events, ueqi, next); - free(ueqi, M_USBDEV); - usb_nevents--; - ueqi_next = TAILQ_FIRST(&usb_events); - } - } - } - if (usb_nevents >= USB_MAX_EVENTS) { - /* Too many queued events, drop an old one. */ - DPRINTF(("usb: event dropped\n")); - (void)usb_get_next_event(&ue); - } - TAILQ_INSERT_TAIL(&usb_events, ueq, next); - usb_nevents++; - wakeup(&usb_events); - selwakeuppri(&usb_selevent, PZERO); - if (usb_async_proc != NULL) { - PROC_LOCK(usb_async_proc); - psignal(usb_async_proc, SIGIO); - PROC_UNLOCK(usb_async_proc); - } - splx(s); -} - -void -usb_schedsoftintr(usbd_bus_handle 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 (!callout_pending(&bus->softi)) - callout_reset(&bus->softi, 0, bus->methods->soft_intr, - bus); -#endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */ - } -#else - bus->methods->soft_intr(bus); -#endif /* USB_USE_SOFTINTR */ -} - -static int -usb_detach(device_t self) -{ - struct usb_softc *sc = device_get_softc(self); - struct usb_event ue; - struct usb_taskq *taskq; - int i; - - DPRINTF(("usb_detach: start\n")); - - sc->sc_dying = 1; - - /* Make all devices disconnect. */ - if (sc->sc_port.device != NULL) - usb_disconnect_port(&sc->sc_port, self); - - /* Kill off event thread. */ - if (sc->sc_event_thread != NULL) { - wakeup(&sc->sc_bus->needs_explore); - if (tsleep(sc, PWAIT, "usbdet", hz * 60)) - printf("%s: event thread didn't die\n", - device_get_nameunit(sc->sc_dev)); - DPRINTF(("usb_detach: event thread dead\n")); - } - - destroy_dev(sc->sc_usbdev); - if (--usb_ndevs == 0) { - destroy_dev(usb_dev); - usb_dev = NULL; - for (i = 0; i < USB_NUM_TASKQS; i++) { - taskq = &usb_taskq[i]; - wakeup(&taskq->tasks); - if (tsleep(&taskq->taskcreated, PWAIT, "usbtdt", - hz * 60)) { - printf("usb task thread %s didn't die\n", - taskq->name); - } - } - } - - 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 - callout_stop(&sc->sc_bus->softi); -#endif -#endif - - ue.u.ue_ctrlr.ue_bus = device_get_unit(sc->sc_dev); - usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); - - return (0); -} - -static void -usb_child_detached(device_t self, device_t child) -{ - struct usb_softc *sc = device_get_softc(self); - - /* XXX, should check it is the right device. */ - sc->sc_port.device = NULL; -} - -/* Explore USB busses at the end of device configuration. */ -static void -usb_cold_explore(void *arg) -{ - struct usb_softc *sc; - - KASSERT(cold || TAILQ_EMPTY(&usb_coldexplist), - ("usb_cold_explore: busses to explore when !cold")); - while (!TAILQ_EMPTY(&usb_coldexplist)) { - sc = TAILQ_FIRST(&usb_coldexplist); - TAILQ_REMOVE(&usb_coldexplist, sc, sc_coldexplist); - - sc->sc_bus->use_polling++; - sc->sc_port.device->hub->explore(sc->sc_bus->root_hub); - sc->sc_bus->use_polling--; - } -} - -SYSINIT(usb_cold_explore, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, - usb_cold_explore, NULL); diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h deleted file mode 100644 index 7e64cac..0000000 --- a/sys/dev/usb/usb.h +++ /dev/null @@ -1,708 +0,0 @@ -/* $NetBSD: usb.h,v 1.69 2002/09/22 23:20:50 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - - -#ifndef _USB_H_ -#define _USB_H_ - -#include <sys/types.h> -#include <sys/time.h> - -#if defined(_KERNEL) -#include "opt_usb.h" - -#ifdef SYSCTL_DECL -SYSCTL_DECL(_hw_usb); -#endif - -#include <sys/malloc.h> - -MALLOC_DECLARE(M_USB); -MALLOC_DECLARE(M_USBDEV); -MALLOC_DECLARE(M_USBHC); -#endif /* _KERNEL */ - -#define PWR_RESUME 0 -#define PWR_SUSPEND 1 -#define PWR_STANDBY 2 -#define PWR_SOFTSUSPEND 3 -#define PWR_SOFTSTANDBY 4 -#define PWR_SOFTRESUME 5 - -/* 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 */ - -#define USB_STACK_VERSION 2 - -#define USB_MAX_DEVICES 128 -#define USB_START_ADDR 0 - -#define USB_CONTROL_ENDPOINT 0 -#define USB_MAX_ENDPOINTS 16 - -#define USB_FRAMES_PER_SECOND 1000 - -/* - * The USB records contain some unaligned little-endian word - * components. The U[SG]ETW macros take care of both the alignment - * and endian problem and should always be used to access non-byte - * values. - */ -typedef u_int8_t uByte; -typedef u_int8_t uWord[2]; -typedef u_int8_t uDWord[4]; - -#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) - -#if 1 -#define UGETW(w) ((w)[0] | ((w)[1] << 8)) -#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) -#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) -#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ - (w)[1] = (u_int8_t)((v) >> 8), \ - (w)[2] = (u_int8_t)((v) >> 16), \ - (w)[3] = (u_int8_t)((v) >> 24)) -#else -/* - * On little-endian machines that can handle unanliged accesses - * (e.g. i386) these macros can be replaced by the following. - */ -#define UGETW(w) (*(u_int16_t *)(w)) -#define USETW(w,v) (*(u_int16_t *)(w) = (v)) -#define UGETDW(w) (*(u_int32_t *)(w)) -#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) -#endif - -#define UPACKED __packed - -typedef struct { - uByte bmRequestType; - uByte bRequest; - uWord wValue; - uWord wIndex; - uWord wLength; -} UPACKED usb_device_request_t; - -#define UT_WRITE 0x00 -#define UT_READ 0x80 -#define UT_STANDARD 0x00 -#define UT_CLASS 0x20 -#define UT_VENDOR 0x40 -#define UT_DEVICE 0x00 -#define UT_INTERFACE 0x01 -#define UT_ENDPOINT 0x02 -#define UT_OTHER 0x03 - -#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) -#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) -#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) -#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) -#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) -#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) -#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) -#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) -#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) -#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) -#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) -#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) -#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) -#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) -#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) -#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) -#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) -#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) -#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) -#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) -#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) -#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) - -/* Requests */ -#define UR_GET_STATUS 0x00 -#define UR_CLEAR_FEATURE 0x01 -#define UR_SET_FEATURE 0x03 -#define UR_SET_ADDRESS 0x05 -#define UR_GET_DESCRIPTOR 0x06 -#define UDESC_DEVICE 0x01 -#define UDESC_CONFIG 0x02 -#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 -#define UDESC_CS_INTERFACE 0x24 -#define UDESC_CS_ENDPOINT 0x25 -#define UDESC_HUB 0x29 -#define UR_SET_DESCRIPTOR 0x07 -#define UR_GET_CONFIG 0x08 -#define UR_SET_CONFIG 0x09 -#define UR_GET_INTERFACE 0x0a -#define UR_SET_INTERFACE 0x0b -#define UR_SYNCH_FRAME 0x0c - -/* 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; - uByte bDescriptorSubtype; -} UPACKED usb_descriptor_t; - -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; - uByte bMaxPacketSize; - /* The fields below are not part of the initial descriptor. */ - uWord idVendor; - uWord idProduct; - uWord bcdDevice; - uByte iManufacturer; - uByte iProduct; - uByte iSerialNumber; - uByte bNumConfigurations; -} UPACKED usb_device_descriptor_t; -#define USB_DEVICE_DESCRIPTOR_SIZE 18 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord wTotalLength; - uByte bNumInterface; - uByte bConfigurationValue; - uByte iConfiguration; - uByte bmAttributes; -#define UC_BUS_POWERED 0x80 -#define UC_SELF_POWERED 0x40 -#define UC_REMOTE_WAKEUP 0x20 - uByte bMaxPower; /* max current in 2 mA units */ -#define UC_POWER_FACTOR 2 -} UPACKED usb_config_descriptor_t; -#define USB_CONFIG_DESCRIPTOR_SIZE 9 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bInterfaceNumber; - uByte bAlternateSetting; - uByte bNumEndpoints; - uByte bInterfaceClass; - uByte bInterfaceSubClass; - uByte bInterfaceProtocol; - uByte iInterface; -} UPACKED usb_interface_descriptor_t; -#define USB_INTERFACE_DESCRIPTOR_SIZE 9 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bEndpointAddress; -#define UE_GET_DIR(a) ((a) & 0x80) -#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) -#define UE_DIR_IN 0x80 -#define UE_DIR_OUT 0x00 -#define UE_ADDR 0x0f -#define UE_GET_ADDR(a) ((a) & UE_ADDR) - uByte bmAttributes; -#define UE_XFERTYPE 0x03 -#define UE_CONTROL 0x00 -#define UE_ISOCHRONOUS 0x01 -#define UE_BULK 0x02 -#define UE_INTERRUPT 0x03 -#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) -#define UE_ISO_TYPE 0x0c -#define UE_ISO_ASYNC 0x04 -#define UE_ISO_ADAPT 0x08 -#define UE_ISO_SYNC 0x0c -#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) - uWord wMaxPacketSize; -#define UE_GET_TRANS(a) (((a) >> 11) & 0x3) -#define UE_GET_SIZE(a) ((a) & 0x7ff) - uByte bInterval; -} UPACKED usb_endpoint_descriptor_t; -#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uWord bString[127]; -} UPACKED usb_string_descriptor_t; -#define USB_MAX_STRING_LEN 128 -#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ - -/* 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 -#define UHF_C_HUB_OVER_CURRENT 1 -#define UHF_PORT_CONNECTION 0 -#define UHF_PORT_ENABLE 1 -#define UHF_PORT_SUSPEND 2 -#define UHF_PORT_OVER_CURRENT 3 -#define UHF_PORT_RESET 4 -#define UHF_PORT_POWER 8 -#define UHF_PORT_LOW_SPEED 9 -#define UHF_C_PORT_CONNECTION 16 -#define UHF_C_PORT_ENABLE 17 -#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 - uByte bPwrOn2PwrGood; /* delay in 2 ms units */ -#define UHD_PWRON_FACTOR 2 - uByte bHubContrCurrent; - uByte DeviceRemovable[32]; /* max 255 ports */ -#define UHD_NOT_REMOV(desc, i) \ - (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) - /* deprecated */ uByte PortPowerCtrlMask[1]; -} UPACKED usb_hub_descriptor_t; -#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 -#define UDS_REMOTE_WAKEUP 0x0002 -/* Endpoint status flags */ -#define UES_HALT 0x0001 -} UPACKED usb_status_t; - -typedef struct { - uWord wHubStatus; -#define UHS_LOCAL_POWER 0x0001 -#define UHS_OVER_CURRENT 0x0002 - uWord wHubChange; -} UPACKED usb_hub_status_t; - -typedef struct { - uWord wPortStatus; -#define UPS_CURRENT_CONNECT_STATUS 0x0001 -#define UPS_PORT_ENABLED 0x0002 -#define UPS_SUSPEND 0x0004 -#define UPS_OVERCURRENT_INDICATOR 0x0008 -#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 -#define UPS_C_SUSPEND 0x0004 -#define UPS_C_OVERCURRENT_INDICATOR 0x0008 -#define UPS_C_PORT_RESET 0x0010 -} UPACKED usb_port_status_t; - -/* Device class codes */ -#define UDCLASS_IN_INTERFACE 0x00 -#define UDCLASS_COMM 0x02 -#define UDCLASS_HUB 0x09 -#define UDSUBCLASS_HUB 0x00 -#define UDPROTO_FSHUB 0x00 -#define UDPROTO_HSHUBSTT 0x01 -#define UDPROTO_HSHUBMTT 0x02 -#define UDCLASS_DIAGNOSTIC 0xdc -#define UDCLASS_WIRELESS 0xe0 -#define UDSUBCLASS_RF 0x01 -#define UDPROTO_BLUETOOTH 0x01 -#define UDCLASS_VENDOR 0xff - -/* Interface class codes */ -#define UICLASS_UNSPEC 0x00 - -#define UICLASS_AUDIO 0x01 -#define UISUBCLASS_AUDIOCONTROL 1 -#define UISUBCLASS_AUDIOSTREAM 2 -#define UISUBCLASS_MIDISTREAM 3 - -#define UICLASS_CDC 0x02 /* communication */ -#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 -#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 -#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 -#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -#define UISUBCLASS_CAPI_CONTROLMODEL 5 -#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 -#define UIPROTO_CDC_AT 1 - -#define UICLASS_HID 0x03 -#define UISUBCLASS_BOOT 1 -#define UIPROTO_BOOT_KEYBOARD 1 -#define UIPROTO_MOUSE 2 - -#define UICLASS_PHYSICAL 0x05 - -#define UICLASS_IMAGE 0x06 - -#define UICLASS_PRINTER 0x07 -#define UISUBCLASS_PRINTER 1 -#define UIPROTO_PRINTER_UNI 1 -#define UIPROTO_PRINTER_BI 2 -#define UIPROTO_PRINTER_1284 3 - -#define UICLASS_MASS 0x08 -#define UISUBCLASS_RBC 1 -#define UISUBCLASS_SFF8020I 2 -#define UISUBCLASS_QIC157 3 -#define UISUBCLASS_UFI 4 -#define UISUBCLASS_SFF8070I 5 -#define UISUBCLASS_SCSI 6 -#define UIPROTO_MASS_CBI_I 0 -#define UIPROTO_MASS_CBI 1 -#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ -#define UIPROTO_MASS_BBB 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 -#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ -#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ -#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ -#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ -#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ -#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ -#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ -#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ -#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ -#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ -#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ -#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ -#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ - -#define UICLASS_SMARTCARD 0x0b - -/*#define UICLASS_FIRM_UPD 0x0c*/ - -#define UICLASS_SECURITY 0x0d - -#define UICLASS_DIAGNOSTIC 0xdc - -#define UICLASS_WIRELESS 0xe0 -#define UISUBCLASS_RF 0x01 -#define UIPROTO_BLUETOOTH 0x01 - -#define UICLASS_APPL_SPEC 0xfe -#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 -#define UISUBCLASS_IRDA 2 -#define UIPROTO_IRDA 0 - -#define UICLASS_VENDOR 0xff -#define UISUBCLASS_XBOX360_CONTROLLER 0x5d -#define UIPROTO_XBOX360_GAMEPAD 0x01 - - -#define USB_HUB_MAX_DEPTH 5 - -/* - * Minimum time a device needs to be powered down to go through - * a power cycle. XXX Are these time in the spec? - */ -#define USB_POWER_DOWN_TIME 200 /* ms */ -#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ - -#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_RECOVERY 10 /* ms */ -#define USB_PORT_POWERUP_DELAY 100 /* ms */ -#define USB_SET_ADDRESS_SETTLE 2 /* ms */ -#define USB_RESUME_DELAY (20*5) /* ms */ -#define USB_RESUME_WAIT 10 /* ms */ -#define USB_RESUME_RECOVERY 10 /* ms */ -#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ -#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 250 /* ms */ -#define USB_PORT_POWERUP_DELAY 300 /* ms */ -#define USB_SET_ADDRESS_SETTLE 10 /* ms */ -#define USB_RESUME_DELAY (50*5) /* ms */ -#define USB_RESUME_WAIT 50 /* ms */ -#define USB_RESUME_RECOVERY 50 /* ms */ -#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ -#endif - -#define USB_MIN_POWER 100 /* mA */ -#define USB_MAX_POWER 500 /* mA */ - -#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ - - -#define USB_UNCONFIG_NO 0 -#define USB_UNCONFIG_INDEX (-1) - -/*** ioctl() related stuff ***/ - -struct usb_ctl_request { - int ucr_addr; - usb_device_request_t ucr_request; - void *ucr_data; - int ucr_flags; -#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ - int ucr_actlen; /* actual length transferred */ -}; - -struct usb_alt_interface { - int uai_config_index; - int uai_interface_index; - int uai_alt_no; -}; - -#define USB_CURRENT_CONFIG_INDEX (-1) -#define USB_CURRENT_ALT_INDEX (-1) - -struct usb_config_desc { - int ucd_config_index; - usb_config_descriptor_t ucd_desc; -}; - -struct usb_interface_desc { - int uid_config_index; - int uid_interface_index; - int uid_alt_index; - usb_interface_descriptor_t uid_desc; -}; - -struct usb_endpoint_desc { - int ued_config_index; - int ued_interface_index; - int ued_alt_index; - int ued_endpoint_index; - usb_endpoint_descriptor_t ued_desc; -}; - -struct usb_full_desc { - int ufd_config_index; - u_int ufd_size; - u_char *ufd_data; -}; - -struct usb_string_desc { - int usd_string_index; - int usd_language_id; - usb_string_descriptor_t usd_desc; -}; - -struct usb_ctl_report_desc { - int ucrd_size; - u_char ucrd_data[1024]; /* filled data size will vary */ -}; - -typedef struct { u_int32_t cookie; } usb_event_cookie_t; - -#define USB_MAX_DEVNAMES 4 -#define USB_MAX_DEVNAMELEN 16 -struct usb_device_info { - u_int8_t udi_bus; - u_int8_t udi_addr; /* device address */ - usb_event_cookie_t udi_cookie; - char udi_product[USB_MAX_STRING_LEN]; - char udi_vendor[USB_MAX_STRING_LEN]; - char udi_release[8]; - u_int16_t udi_productNo; - u_int16_t udi_vendorNo; - u_int16_t udi_releaseNo; - u_int8_t udi_class; - 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 - int udi_power; /* power consumption in mA, 0 if selfpowered */ - int udi_nports; - char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; - u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ -#define USB_PORT_ENABLED 0xff -#define USB_PORT_SUSPENDED 0xfe -#define USB_PORT_POWERED 0xfd -#define USB_PORT_DISABLED 0xfc -}; - -struct usb_ctl_report { - int ucr_report; - u_char ucr_data[1024]; /* filled data size will vary */ -}; - -struct usb_device_stats { - u_long uds_requests[4]; /* indexed by transfer type UE_* */ -}; - -/* Events that can be read from /dev/usb */ -struct usb_event { - int ue_type; -#define USB_EVENT_CTRLR_ATTACH 1 -#define USB_EVENT_CTRLR_DETACH 2 -#define USB_EVENT_DEVICE_ATTACH 3 -#define USB_EVENT_DEVICE_DETACH 4 -#define USB_EVENT_DRIVER_ATTACH 5 -#define USB_EVENT_DRIVER_DETACH 6 -#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 { - int ue_bus; - } ue_ctrlr; - struct usb_device_info ue_device; - struct { - usb_event_cookie_t ue_cookie; - char ue_devname[16]; - } ue_driver; - } u; -}; - -/* USB controller */ -#define USB_REQUEST _IOWR('U', 1, struct usb_ctl_request) -#define USB_SETDEBUG _IOW ('U', 2, int) -#define USB_DISCOVER _IO ('U', 3) -#define USB_DEVICEINFO _IOWR('U', 4, struct usb_device_info) -#define USB_DEVICESTATS _IOR ('U', 5, struct usb_device_stats) - -/* Generic HID device */ -#define USB_GET_REPORT_DESC _IOR ('U', 21, struct usb_ctl_report_desc) -#define USB_SET_IMMED _IOW ('U', 22, int) -#define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report) -#define USB_SET_REPORT _IOW ('U', 24, struct usb_ctl_report) -#define USB_GET_REPORT_ID _IOR ('U', 25, int) - -/* Generic USB device */ -#define USB_GET_CONFIG _IOR ('U', 100, int) -#define USB_SET_CONFIG _IOW ('U', 101, int) -#define USB_GET_ALTINTERFACE _IOWR('U', 102, struct usb_alt_interface) -#define USB_SET_ALTINTERFACE _IOWR('U', 103, struct usb_alt_interface) -#define USB_GET_NO_ALT _IOWR('U', 104, struct usb_alt_interface) -#define USB_GET_DEVICE_DESC _IOR ('U', 105, usb_device_descriptor_t) -#define USB_GET_CONFIG_DESC _IOWR('U', 106, struct usb_config_desc) -#define USB_GET_INTERFACE_DESC _IOWR('U', 107, struct usb_interface_desc) -#define USB_GET_ENDPOINT_DESC _IOWR('U', 108, struct usb_endpoint_desc) -#define USB_GET_FULL_DESC _IOWR('U', 109, struct usb_full_desc) -#define USB_GET_STRING_DESC _IOWR('U', 110, struct usb_string_desc) -#define USB_DO_REQUEST _IOWR('U', 111, struct usb_ctl_request) -#define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info) -#define USB_SET_SHORT_XFER _IOW ('U', 113, int) -#define USB_SET_TIMEOUT _IOW ('U', 114, int) -#define USB_RESET_DEVICE _IO ('U', 115) - -/* Modem device */ -#define USB_GET_CM_OVER_DATA _IOR ('U', 130, int) -#define USB_SET_CM_OVER_DATA _IOW ('U', 131, int) - -#endif /* _USB_H_ */ diff --git a/sys/dev/usb/usb_ethersubr.c b/sys/dev/usb/usb_ethersubr.c deleted file mode 100644 index d0a3b83..0000000 --- a/sys/dev/usb/usb_ethersubr.c +++ /dev/null @@ -1,283 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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> -__FBSDID("$FreeBSD$"); - -/* - * Callbacks in the USB code operate at splusb() (actually splbio() - * in FreeBSD). However adding packets to the input queues has to be - * done at splimp(). It is conceivable that this arrangement could - * trigger a condition where the splimp() is ignored and the input - * queues could get trampled in spite of our best effors to prevent - * it. To work around this, we implement a special input queue for - * USB ethernet adapter drivers. Rather than passing the frames directly - * to ether_input(), we pass them here, then schedule a soft interrupt - * to hand them to ether_input() later, outside of the USB interrupt - * context. - * - * It's questional as to whether this code should be expanded to - * handle other kinds of devices, or handle USB transfer callbacks - * in general. Right now, I need USB network interfaces to work - * properly. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/socket.h> -#include <sys/taskqueue.h> - -#include <net/if.h> -#include <net/if_types.h> -#include <net/if_arp.h> -#include <net/ethernet.h> -#include <net/netisr.h> -#include <net/bpf.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usb_ethersubr.h> - -static struct ifqueue usbq_rx; -static struct ifqueue usbq_tx; -static int mtx_inited = 0; - -static void usbintr (void); - -static void -usbintr(void) -{ - struct mbuf *m; - struct usb_qdat *q; - struct ifnet *ifp; - - mtx_lock(&Giant); - - /* Check the RX queue */ - while(1) { - IF_DEQUEUE(&usbq_rx, m); - if (m == NULL) - break; - q = (struct usb_qdat *)m->m_pkthdr.rcvif; - ifp = q->ifp; - m->m_pkthdr.rcvif = ifp; - (*ifp->if_input)(ifp, m); - - /* Re-arm the receiver */ - (*q->if_rxstart)(ifp); - if (ifp->if_snd.ifq_head != NULL) - (*ifp->if_start)(ifp); - } - - /* Check the TX queue */ - while(1) { - IF_DEQUEUE(&usbq_tx, m); - if (m == NULL) - break; - ifp = m->m_pkthdr.rcvif; - m_freem(m); - if (ifp->if_snd.ifq_head != NULL) - (*ifp->if_start)(ifp); - } - - mtx_unlock(&Giant); - - return; -} - -void -usb_register_netisr(void) -{ - if (mtx_inited) - return; - netisr_register(NETISR_USB, (netisr_t *)usbintr, NULL, - NETISR_FORCEQUEUE); - mtx_init(&usbq_tx.ifq_mtx, "usbq_tx_mtx", NULL, MTX_DEF); - mtx_init(&usbq_rx.ifq_mtx, "usbq_rx_mtx", NULL, MTX_DEF); - mtx_inited++; - return; -} - -/* - * Must be called at splusb() (actually splbio()). This should be - * the case when called from a transfer callback routine. - */ -void -usb_ether_input(m) - struct mbuf *m; -{ - IF_ENQUEUE(&usbq_rx, m); - schednetisr(NETISR_USB); - - return; -} - -void -usb_tx_done(m) - struct mbuf *m; -{ - IF_ENQUEUE(&usbq_tx, m); - schednetisr(NETISR_USB); - - return; -} - -struct mbuf * -usb_ether_newbuf(void) -{ - struct mbuf *m_new; - - m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m_new == NULL) - return (NULL); - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - - m_adj(m_new, ETHER_ALIGN); - return (m_new); -} - -int -usb_ether_rx_list_init(void *sc, struct ue_cdata *cd, - usbd_device_handle ue_udev) -{ - struct ue_chain *c; - int i; - - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &cd->ue_rx_chain[i]; - c->ue_sc = sc; - c->ue_idx = i; - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) - return (ENOBUFS); - if (c->ue_xfer == NULL) { - c->ue_xfer = usbd_alloc_xfer(ue_udev); - if (c->ue_xfer == NULL) - return (ENOBUFS); - c->ue_buf = usbd_alloc_buffer(c->ue_xfer, UE_BUFSZ); - if (c->ue_buf == NULL) - return (ENOBUFS); - } - } - - return (0); -} - -int -usb_ether_tx_list_init(void *sc, struct ue_cdata *cd, - usbd_device_handle ue_udev) -{ - struct ue_chain *c; - int i; - - for (i = 0; i < UE_TX_LIST_CNT; i++) { - c = &cd->ue_tx_chain[i]; - c->ue_sc = sc; - c->ue_idx = i; - c->ue_mbuf = NULL; - if (c->ue_xfer == NULL) { - c->ue_xfer = usbd_alloc_xfer(ue_udev); - if (c->ue_xfer == NULL) - return (ENOBUFS); - c->ue_buf = usbd_alloc_buffer(c->ue_xfer, UE_BUFSZ); - if (c->ue_buf == NULL) - return (ENOBUFS); - } - } - - return (0); -} - -void -usb_ether_rx_list_free(struct ue_cdata *cd) -{ - int i; - - for (i = 0; i < UE_RX_LIST_CNT; i++) { - if (cd->ue_rx_chain[i].ue_mbuf != NULL) { - m_freem(cd->ue_rx_chain[i].ue_mbuf); - cd->ue_rx_chain[i].ue_mbuf = NULL; - } - if (cd->ue_rx_chain[i].ue_xfer != NULL) { - usbd_free_xfer(cd->ue_rx_chain[i].ue_xfer); - cd->ue_rx_chain[i].ue_xfer = NULL; - } - } -} - -void -usb_ether_tx_list_free(struct ue_cdata *cd) -{ - int i; - - for (i = 0; i < UE_RX_LIST_CNT; i++) { - if (cd->ue_tx_chain[i].ue_mbuf != NULL) { - m_freem(cd->ue_tx_chain[i].ue_mbuf); - cd->ue_tx_chain[i].ue_mbuf = NULL; - } - if (cd->ue_tx_chain[i].ue_xfer != NULL) { - usbd_free_xfer(cd->ue_tx_chain[i].ue_xfer); - cd->ue_tx_chain[i].ue_xfer = NULL; - } - } -} - -void -usb_ether_task_init(device_t dev, int flags, struct usb_taskqueue *tq) -{ - - /* nothing for now. */ -} - -void -usb_ether_task_enqueue(struct usb_taskqueue *tq, struct task *task) -{ - - taskqueue_enqueue(taskqueue_thread, task); -} - -void -usb_ether_task_drain(struct usb_taskqueue *tq, struct task *task) -{ - - taskqueue_drain(taskqueue_thread, task); -} - -void -usb_ether_task_destroy(struct usb_taskqueue *tq) -{ - - /* nothing for now */ - -} diff --git a/sys/dev/usb/usb_ethersubr.h b/sys/dev/usb/usb_ethersubr.h deleted file mode 100644 index f3d2e34..0000000 --- a/sys/dev/usb/usb_ethersubr.h +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul <wpaul@ee.columbia.edu>. 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 Bill Paul. - * 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 Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD - * 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$ - */ - -#ifndef _USB_ETHERSUBR_H_ -#define _USB_ETHERSUBR_H_ - -#include <sys/bus.h> -#include <sys/module.h> - -#include <dev/usb/usbdi.h> - -#define UE_TX_LIST_CNT 1 -#define UE_RX_LIST_CNT 1 -#define UE_BUFSZ 1536 - -struct usb_qdat { - struct ifnet *ifp; - void (*if_rxstart) (struct ifnet *); -}; - -struct ue_chain { - void *ue_sc; - usbd_xfer_handle ue_xfer; - char *ue_buf; - struct mbuf *ue_mbuf; - int ue_idx; - usbd_status ue_status; -}; - -struct ue_cdata { - struct ue_chain ue_tx_chain[UE_TX_LIST_CNT]; - struct ue_chain ue_rx_chain[UE_RX_LIST_CNT]; - void *ue_ibuf; - int ue_tx_prod; - int ue_tx_cons; - int ue_tx_cnt; - int ue_rx_prod; -}; - -void usb_register_netisr (void); -void usb_ether_input (struct mbuf *); -void usb_tx_done (struct mbuf *); -struct mbuf *usb_ether_newbuf (void); -int usb_ether_rx_list_init (void *, struct ue_cdata *, - usbd_device_handle); -int usb_ether_tx_list_init (void *, struct ue_cdata *, - usbd_device_handle); -void usb_ether_rx_list_free (struct ue_cdata *); -void usb_ether_tx_list_free (struct ue_cdata *); - -struct usb_taskqueue { - int dummy; -}; - -void usb_ether_task_init(device_t, int, struct usb_taskqueue *); -void usb_ether_task_enqueue(struct usb_taskqueue *, struct task *); -void usb_ether_task_drain(struct usb_taskqueue *, struct task *); -void usb_ether_task_destroy(struct usb_taskqueue *); - -#endif /* _USB_ETHERSUBR_H_ */ diff --git a/sys/dev/usb/usb_if.m b/sys/dev/usb/usb_if.m deleted file mode 100644 index b04c8a4..0000000 --- a/sys/dev/usb/usb_if.m +++ /dev/null @@ -1,42 +0,0 @@ -#- -# Copyright (c) 1992-1998 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, -# without modification, immediately at the beginning of the file. -# 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. 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. -# -# $FreeBSD$ -# - -# USB interface description -# - -#include <sys/bus.h> - -INTERFACE usb; - -# The device should start probing for new drivers again -# -METHOD int reconfigure { - device_t dev; -}; diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c deleted file mode 100644 index bbb0bf6..0000000 --- a/sys/dev/usb/usb_mem.c +++ /dev/null @@ -1,297 +0,0 @@ -/* $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -/* - * USB DMA memory allocation. - * We need to allocate a lot of small (many 8 byte, some larger) - * memory blocks that can be used for DMA. Using the bus_dma - * routines directly would incur large overheads in space and time. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/endian.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/queue.h> - -#include <machine/bus.h> -#include <machine/endian.h> - -#ifdef DIAGNOSTIC -#include <sys/proc.h> -#endif - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdivar.h> /* just for usb_dma_t */ -#include <dev/usb/usb_mem.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define USB_MEM_SMALL 64 -#define USB_MEM_CHUNKS (PAGE_SIZE / USB_MEM_SMALL) -#define USB_MEM_BLOCK (USB_MEM_SMALL * USB_MEM_CHUNKS) - -/* This struct is overlayed on free fragments. */ -struct usb_frag_dma { - usb_dma_block_t *block; - u_int offs; - LIST_ENTRY(usb_frag_dma) next; -}; - -static bus_dmamap_callback_t usbmem_callback; -static usbd_status usb_block_allocmem(bus_dma_tag_t, size_t, size_t, - usb_dma_block_t **); -static void usb_block_freemem(usb_dma_block_t *); - -static LIST_HEAD(, usb_dma_block) usb_blk_freelist = - LIST_HEAD_INITIALIZER(usb_blk_freelist); -static int usb_blk_nfree = 0; -/* XXX should have different free list for different tags (for speed) */ -static LIST_HEAD(, usb_frag_dma) usb_frag_freelist = - LIST_HEAD_INITIALIZER(usb_frag_freelist); - -static void -usbmem_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - int i; - usb_dma_block_t *p = arg; - - if (error == EFBIG) { - printf("usb: mapping to large\n"); - return; - } - - p->nsegs = nseg; - for (i = 0; i < nseg && i < sizeof p->segs / sizeof *p->segs; i++) - p->segs[i] = segs[i]; -} - -static usbd_status -usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align, - usb_dma_block_t **dmap) -{ - usb_dma_block_t *p; - int s; - - DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n", - (u_long)size, (u_long)align)); - -#ifdef DIAGNOSTIC - if (!curproc) { - printf("usb_block_allocmem: in interrupt context, size=%lu\n", - (unsigned long) size); - } -#endif - - s = splusb(); - /* First check the free list. */ - for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) { - if (p->tag == tag && p->size >= size && p->size < size * 2 && - p->align >= align) { - LIST_REMOVE(p, next); - usb_blk_nfree--; - splx(s); - *dmap = p; - DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n", - (u_long)p->size)); - return (USBD_NORMAL_COMPLETION); - } - } - splx(s); - -#ifdef DIAGNOSTIC - if (!curproc) { - printf("usb_block_allocmem: in interrupt context, failed\n"); - return (USBD_NOMEM); - } -#endif - - DPRINTFN(6, ("usb_block_allocmem: no free\n")); - p = malloc(sizeof *p, M_USB, M_NOWAIT); - if (p == NULL) - return (USBD_NOMEM); - - if (bus_dma_tag_create(tag, align, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - size, sizeof(p->segs) / sizeof(p->segs[0]), size, - 0, NULL, NULL, &p->tag) == ENOMEM) - { - goto free; - } - - p->size = size; - p->align = align; - if (bus_dmamem_alloc(p->tag, &p->kaddr, - BUS_DMA_NOWAIT|BUS_DMA_COHERENT, &p->map)) - goto tagfree; - - if (bus_dmamap_load(p->tag, p->map, p->kaddr, p->size, - usbmem_callback, p, 0)) - goto memfree; - - /* XXX - override the tag, ok since we never free it */ - p->tag = tag; - *dmap = p; - return (USBD_NORMAL_COMPLETION); - - /* - * XXX - do we need to _unload? is the order of _free and _destroy - * correct? - */ -memfree: - bus_dmamem_free(p->tag, p->kaddr, p->map); -tagfree: - bus_dma_tag_destroy(p->tag); -free: - free(p, M_USB); - return (USBD_NOMEM); -} - -/* - * Do not free the memory unconditionally since we might be called - * from an interrupt context and that is BAD. - * XXX when should we really free? - */ -static void -usb_block_freemem(usb_dma_block_t *p) -{ - int s; - - DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size)); - s = splusb(); - LIST_INSERT_HEAD(&usb_blk_freelist, p, next); - usb_blk_nfree++; - splx(s); -} - -usbd_status -usb_allocmem(usbd_bus_handle bus, size_t size, size_t align, usb_dma_t *p) -{ - bus_dma_tag_t tag = bus->parent_dmatag; - usbd_status err; - struct usb_frag_dma *f; - usb_dma_block_t *b; - int i; - int s; - - /* compat w/ Net/OpenBSD */ - if (align == 0) - align = 1; - - /* If the request is large then just use a full block. */ - if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) { - DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size)); - size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1); - err = usb_block_allocmem(tag, size, align, &p->block); - if (!err) { - p->block->fullblock = 1; - p->offs = 0; - p->len = size; - } - return (err); - } - - s = splusb(); - /* Check for free fragments. */ - for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next)) - if (f->block->tag == tag) - break; - if (f == NULL) { - DPRINTFN(1, ("usb_allocmem: adding fragments\n")); - err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL,&b); - if (err) { - splx(s); - return (err); - } - b->fullblock = 0; - /* XXX - override the tag, ok since we never free it */ - b->tag = tag; - KASSERT(sizeof *f <= USB_MEM_SMALL, ("USB_MEM_SMALL(%d) is too small for struct usb_frag_dma(%zd)\n", - USB_MEM_SMALL, sizeof *f)); - for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) { - f = (struct usb_frag_dma *)((char *)b->kaddr + i); - f->block = b; - f->offs = i; - LIST_INSERT_HEAD(&usb_frag_freelist, f, next); - } - f = LIST_FIRST(&usb_frag_freelist); - } - p->block = f->block; - p->offs = f->offs; - p->len = USB_MEM_SMALL; - LIST_REMOVE(f, next); - splx(s); - DPRINTFN(5, ("usb_allocmem: use frag=%p size=%d\n", f, (int)size)); - return (USBD_NORMAL_COMPLETION); -} - -void -usb_freemem(usbd_bus_handle bus, usb_dma_t *p) -{ - struct usb_frag_dma *f; - int s; - - if (p->block->fullblock) { - DPRINTFN(1, ("usb_freemem: large free\n")); - usb_block_freemem(p->block); - return; - } - f = KERNADDR(p, 0); - f->block = p->block; - f->offs = p->offs; - s = splusb(); - LIST_INSERT_HEAD(&usb_frag_freelist, f, next); - splx(s); - DPRINTFN(5, ("usb_freemem: frag=%p\n", f)); -} diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h deleted file mode 100644 index b8f0a14..0000000 --- a/sys/dev/usb/usb_mem.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: usb_mem.h,v 1.18 2002/05/28 17:45:17 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -typedef struct usb_dma_block { - bus_dma_tag_t tag; - bus_dmamap_t map; - void *kaddr; - bus_dma_segment_t segs[1]; - int nsegs; - size_t size; - size_t align; - int fullblock; - LIST_ENTRY(usb_dma_block) next; -} usb_dma_block_t; - -#define DMAADDR(dma, o) ((dma)->block->segs[0].ds_addr + (dma)->offs + (o)) -#define KERNADDR(dma, o) \ - ((void *)((char *)((dma)->block->kaddr) + (dma)->offs + (o))) - -usbd_status usb_allocmem(usbd_bus_handle,size_t,size_t, usb_dma_t *); -void usb_freemem(usbd_bus_handle, usb_dma_t *); diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h deleted file mode 100644 index fd92d7b..0000000 --- a/sys/dev/usb/usb_port.h +++ /dev/null @@ -1,200 +0,0 @@ -/* $OpenBSD: usb_port.h,v 1.18 2000/09/06 22:42:10 rahnds Exp $ */ -/* $NetBSD: usb_port.h,v 1.54 2002/03/28 21:49:19 ichiro Exp $ */ -/* $FreeBSD$ */ - -/* Also already merged from NetBSD: - * $NetBSD: usb_port.h,v 1.57 2002/09/27 20:42:01 thorpej Exp $ - * $NetBSD: usb_port.h,v 1.58 2002/10/01 01:25:26 thorpej Exp $ - */ - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _USB_PORT_H -#define _USB_PORT_H - -/* - * Macro's to cope with the differences between operating systems. - */ - -/* - * FreeBSD - */ - -/* We don't use the soft interrupt code in FreeBSD. */ -#if 0 -#define USB_USE_SOFTINTR -#endif - -#define Static static - -#define device_ptr_t device_t -#define USBBASEDEVICE device_t -#define USBDEV(bdev) (bdev) -#define USBDEVNAME(bdev) device_get_nameunit(bdev) -#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev) -#define USBDEVUNIT(bdev) device_get_unit(bdev) -#define USBGETSOFTC(bdev) (device_get_softc(bdev)) - -#define DECLARE_USB_DMA_T \ - struct usb_dma_block; \ - typedef struct { \ - struct usb_dma_block *block; \ - u_int offs; \ - u_int len; \ - } usb_dma_t - -typedef struct thread *usb_proc_ptr; - -#define uio_procp uio_td - -#define usb_kthread_create1(f, s, p, a0, a1) \ - kproc_create((f), (s), (p), RFHIGHPID, 0, (a0), (a1)) -#define usb_kthread_create2(f, s, p, a0) \ - kproc_create((f), (s), (p), RFHIGHPID, 0, (a0)) -#define usb_kthread_create kproc_create - -#define config_pending_incr() -#define config_pending_decr() - -typedef struct callout usb_callout_t; -#define usb_callout_init(h) callout_init(&(h), 0) -#define usb_callout(h, t, f, d) callout_reset(&(h), (t), (f), (d)) -#define usb_uncallout(h, f, d) callout_stop(&(h)) -#define usb_uncallout_drain(h, f, d) callout_drain(&(h)) - -#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0) -#define clfree(p) clist_free_cblocks((p)) - -#define config_detach(dev, flag) \ - do { \ - device_detach(dev); \ - free(device_get_ivars(dev), M_USB); \ - device_delete_child(device_get_parent(dev), dev); \ - } while (0); - -typedef struct malloc_type *usb_malloc_type; - -#define USB_DECLARE_DRIVER_INIT(dname, init...) \ -static device_probe_t __CONCAT(dname,_match); \ -static device_attach_t __CONCAT(dname,_attach); \ -static device_detach_t __CONCAT(dname,_detach); \ -\ -static devclass_t __CONCAT(dname,_devclass); \ -\ -static device_method_t __CONCAT(dname,_methods)[] = { \ - DEVMETHOD(device_probe, __CONCAT(dname,_match)), \ - DEVMETHOD(device_attach, __CONCAT(dname,_attach)), \ - DEVMETHOD(device_detach, __CONCAT(dname,_detach)), \ - init, \ - {0,0} \ -}; \ -\ -static driver_t __CONCAT(dname,_driver) = { \ - #dname, \ - __CONCAT(dname,_methods), \ - sizeof(struct __CONCAT(dname,_softc)) \ -}; \ -MODULE_DEPEND(dname, usb, 1, 1, 1) - - -#define METHODS_NONE {0,0} -#define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE) - -#define USB_MATCH(dname) \ -static int \ -__CONCAT(dname,_match)(device_t self) - -#define USB_MATCH_START(dname, uaa) \ - struct usb_attach_arg *uaa = device_get_ivars(self) - -#define USB_MATCH_SETUP \ - sc->sc_dev = self - -#define USB_ATTACH(dname) \ -static int \ -__CONCAT(dname,_attach)(device_t self) - -#define USB_ATTACH_START(dname, sc, uaa) \ - struct __CONCAT(dname,_softc) *sc = device_get_softc(self); \ - struct usb_attach_arg *uaa = device_get_ivars(self) - -/* Returns from attach */ -#define USB_ATTACH_ERROR_RETURN return ENXIO -#define USB_ATTACH_SUCCESS_RETURN return 0 - -#define USB_ATTACH_SETUP \ - sc->sc_dev = self; \ - -#define USB_DETACH(dname) \ -static int \ -__CONCAT(dname,_detach)(device_t self) - -#define USB_DETACH_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = device_get_softc(self) - -#define USB_GET_SC_OPEN(dname, unit, sc) \ - sc = devclass_get_softc(__CONCAT(dname,_devclass), unit); \ - if (sc == NULL) \ - return (ENXIO) - -#define USB_GET_SC(dname, unit, sc) \ - sc = devclass_get_softc(__CONCAT(dname,_devclass), unit) - -#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \ - (device_probe_and_attach((bdev)) == 0 ? (bdev) : 0) - -/* conversion from one type of queue to the other */ -#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD -#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD -#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL -#define SIMPLEQ_NEXT STAILQ_NEXT -#define SIMPLEQ_FIRST STAILQ_FIRST -#define SIMPLEQ_HEAD STAILQ_HEAD -#define SIMPLEQ_EMPTY STAILQ_EMPTY -#define SIMPLEQ_FOREACH STAILQ_FOREACH -#define SIMPLEQ_INIT STAILQ_INIT -#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER -#define SIMPLEQ_ENTRY STAILQ_ENTRY - -#include <sys/syslog.h> -/* -#define logprintf(args...) log(LOG_DEBUG, args) -*/ -#define logprintf printf - -#endif /* _USB_PORT_H */ diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c deleted file mode 100644 index 2771bb7..0000000 --- a/sys/dev/usb/usb_quirks.c +++ /dev/null @@ -1,153 +0,0 @@ -/* $NetBSD: usb_quirks.c,v 1.50 2004/06/23 02:30:52 mycroft Exp $ */ - -/*- - * Copyright (c) 1998 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> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> - -#include <dev/usb/usb.h> - -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#ifdef USB_DEBUG -extern int usbdebug; -#endif - -#define ANY 0xffff - -static const struct usbd_quirk_entry { - u_int16_t idVendor; - u_int16_t idProduct; - u_int16_t bcdDevice; - struct usbd_quirks quirks; -} usb_quirks[] = { - { USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, - 0x094, { UQ_SWAP_UNICODE}}, - { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }}, - { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_AU_NO_XU }}, - { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }}, - { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }}, - { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, { UQ_SPUR_BUT_UP }}, - { 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_TI, USB_PRODUCT_TI_UTUSB41, 0x110, { UQ_POWER_CLAIM }}, - { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, { UQ_AU_NO_FRAC }}, - { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, - 0x100, { UQ_AU_INP_ASYNC }}, - { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B, ANY, { UQ_NO_STRINGS }}, - /* XXX These should have a revision number, but I don't know what they are. */ - { USB_VENDOR_HP, USB_PRODUCT_HP_895C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_HP, USB_PRODUCT_HP_880C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_HP, USB_PRODUCT_HP_815C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_HP, USB_PRODUCT_HP_810C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_HP, USB_PRODUCT_HP_830C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_HP, USB_PRODUCT_HP_1220C, ANY, { UQ_BROKEN_BIDIR }}, - { USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15, ANY, { UQ_BROKEN_BIDIR }}, - /* MS keyboards do weird things */ - { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK, - ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }}, - { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2, - ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }}, - { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE, - ANY, { UQ_MS_LEADING_BYTE }}, - { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_COMFORT3000, - ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }}, - { USB_VENDOR_SONY, USB_PRODUCT_SONY_RF_RECEIVER, - ANY,{ UQ_MS_BAD_CLASS }}, - - /* Devices which should be ignored by uhid */ - { USB_VENDOR_APC, USB_PRODUCT_APC_UPS, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_1500CAVRLCD, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, - ANY, { UQ_HID_IGNORE }}, - { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, - ANY, { UQ_HID_IGNORE }}, - - /* Devices which should be ignored by both ukbd and uhid */ - { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A, - ANY, { UQ_KBD_IGNORE }}, - { USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B, - ANY, { UQ_KBD_IGNORE }}, - { USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X, - ANY, { UQ_KBD_IGNORE }}, - { 0, 0, 0, { 0 } } -}; - -const struct usbd_quirks usbd_no_quirk = { 0 }; - -const struct usbd_quirks * -usbd_find_quirk(usb_device_descriptor_t *d) -{ - const struct usbd_quirk_entry *t; - u_int16_t vendor = UGETW(d->idVendor); - u_int16_t product = UGETW(d->idProduct); - u_int16_t revision = UGETW(d->bcdDevice); - - for (t = usb_quirks; t->idVendor != 0; t++) { - if (t->idVendor == vendor && - t->idProduct == product && - (t->bcdDevice == ANY || t->bcdDevice == revision)) - break; - } -#ifdef USB_DEBUG - if (usbdebug && t->quirks.uq_flags) - printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n", - UGETW(d->idVendor), UGETW(d->idProduct), - UGETW(d->bcdDevice), t->quirks.uq_flags); -#endif - return (&t->quirks); -} diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h deleted file mode 100644 index 16e2f3f..0000000 --- a/sys/dev/usb/usb_quirks.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $NetBSD: usb_quirks.h,v 1.20 2001/04/15 09:38:01 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -struct usbd_quirks { - u_int32_t uq_flags; /* Device problems: */ -#define UQ_SWAP_UNICODE 0x00000002 /* has some Unicode strings swapped. */ -#define UQ_MS_REVZ 0x00000004 /* mouse has Z-axis reversed */ -#define UQ_NO_STRINGS 0x00000008 /* string descriptors are broken. */ -#define UQ_BAD_ADC 0x00000010 /* bad audio spec version number. */ -#define UQ_BUS_POWERED 0x00000020 /* device is bus powered, despite claim */ -#define UQ_BAD_AUDIO 0x00000040 /* device claims audio class, but isn't */ -#define UQ_SPUR_BUT_UP 0x00000080 /* spurious mouse button up events */ -#define UQ_AU_NO_XU 0x00000100 /* audio device has broken extension unit */ -#define UQ_POWER_CLAIM 0x00000200 /* hub lies about power status */ -#define UQ_AU_NO_FRAC 0x00000400 /* don't adjust for fractional samples */ -#define UQ_AU_INP_ASYNC 0x00000800 /* input is async despite claim of adaptive */ -#define UQ_BROKEN_BIDIR 0x00002000 /* printer has broken bidir mode */ -#define UQ_OPEN_CLEARSTALL 0x04000 /* device needs clear endpoint stall */ -#define UQ_HID_IGNORE 0x00008000 /* device should be ignored by hid class */ -#define UQ_KBD_IGNORE 0x00018000 /* device should be ignored by both kbd and hid class */ -#define UQ_MS_BAD_CLASS 0x00020000 /* doesn't identify properly */ -#define UQ_MS_LEADING_BYTE 0x40000 /* mouse sends an unknown leading byte. */ -}; - -extern const struct usbd_quirks usbd_no_quirk; - -const struct usbd_quirks *usbd_find_quirk(usb_device_descriptor_t *); diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c deleted file mode 100644 index 29d044c..0000000 --- a/sys/dev/usb/usb_subr.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* $NetBSD: usb_subr.c,v 1.99 2002/07/11 21:14:34 augustss Exp $ */ - -/* Also already have from NetBSD: - * $NetBSD: usb_subr.c,v 1.102 2003/01/01 16:21:50 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.111 2004/03/15 10:35:04 augustss Exp $ - * $NetBSD: usb_subr.c,v 1.114 2004/06/23 02:30:52 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.115 2004/06/23 05:23:19 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.116 2004/06/23 06:27:54 mycroft Exp $ - * $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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 "opt_usb.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/proc.h> -#include <sys/sysctl.h> - -#include <machine/bus.h> - -#include <dev/usb/usb.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static usbd_status usbd_set_config(usbd_device_handle, int); -static void usbd_devinfo_vp(usbd_device_handle, char *, char *, int); -static int usbd_getnewaddr(usbd_bus_handle bus); -static void usbd_free_iface_data(usbd_device_handle dev, int ifcno); -static void usbd_kill_pipe(usbd_pipe_handle); -static usbd_status usbd_probe_and_attach(device_t parent, - usbd_device_handle dev, int port, int addr); - -static u_int32_t usb_cookie_no = 0; - -#ifdef USBVERBOSE -typedef u_int16_t usb_vendor_id_t; -typedef u_int16_t usb_product_id_t; - -/* - * Descriptions of of known vendors and devices ("products"). - */ -struct usb_knowndev { - usb_vendor_id_t vendor; - usb_product_id_t product; - int flags; - char *vendorname, *productname; -}; -#define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ - -#include "usbdevs_data.h" -#endif /* USBVERBOSE */ - -static const char * const usbd_error_strs[] = { - "NORMAL_COMPLETION", - "IN_PROGRESS", - "PENDING_REQUESTS", - "NOT_STARTED", - "INVAL", - "NOMEM", - "CANCELLED", - "BAD_ADDRESS", - "IN_USE", - "NO_ADDR", - "SET_ADDR_FAILED", - "NO_POWER", - "TOO_DEEP", - "IOERROR", - "NOT_CONFIGURED", - "TIMEOUT", - "SHORT_XFER", - "STALLED", - "INTERRUPTED", - "XXX", -}; - -const char * -usbd_errstr(usbd_status err) -{ - static char buffer[5]; - - if (err < USBD_ERROR_MAX) { - return usbd_error_strs[err]; - } else { - snprintf(buffer, sizeof buffer, "%d", err); - return buffer; - } -} - -usbd_status -usbd_get_string_desc(usbd_device_handle dev, int sindex, int langid, - usb_string_descriptor_t *sdesc, int *sizep) -{ - usb_device_request_t req; - usbd_status err; - int actlen; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, UDESC_STRING, sindex); - USETW(req.wIndex, langid); - USETW(req.wLength, 2); /* only size byte first */ - err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK, - &actlen, USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - - if (actlen < 2) - return (USBD_SHORT_XFER); - - USETW(req.wLength, sdesc->bLength); /* the whole string */ - err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK, - &actlen, USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - - if (actlen != sdesc->bLength) { - DPRINTFN(-1, ("usbd_get_string_desc: expected %d, got %d\n", - sdesc->bLength, actlen)); - } - - *sizep = actlen; - return (USBD_NORMAL_COMPLETION); -} - -static void -usbd_trim_spaces(char *p) -{ - char *q, *e; - - if (p == NULL) - return; - q = e = p; - while (*q == ' ') /* skip leading spaces */ - q++; - while ((*p = *q++)) /* copy string */ - if (*p++ != ' ') /* remember last non-space */ - e = p; - *e = 0; /* kill trailing spaces */ -} - -static void -usbd_devinfo_vp(usbd_device_handle dev, char *v, char *p, int usedev) -{ - usb_device_descriptor_t *udd = &dev->ddesc; - char *vendor = 0, *product = 0; -#ifdef USBVERBOSE - const struct usb_knowndev *kdp; -#endif - - if (dev == NULL) { - v[0] = p[0] = '\0'; - return; - } - - if (usedev) { - if (usbd_get_string(dev, udd->iManufacturer, v, - USB_MAX_STRING_LEN)) - vendor = NULL; - else - vendor = v; - usbd_trim_spaces(vendor); - if (usbd_get_string(dev, udd->iProduct, p, - USB_MAX_STRING_LEN)) - product = NULL; - else - product = p; - usbd_trim_spaces(product); - if (vendor && !*vendor) - vendor = NULL; - if (product && !*product) - product = NULL; - } else { - vendor = NULL; - product = NULL; - } -#ifdef USBVERBOSE - if (vendor == NULL || product == NULL) { - for(kdp = usb_knowndevs; - kdp->vendorname != NULL; - kdp++) { - if (kdp->vendor == UGETW(udd->idVendor) && - (kdp->product == UGETW(udd->idProduct) || - (kdp->flags & USB_KNOWNDEV_NOPROD) != 0)) - break; - } - if (kdp->vendorname != NULL) { - if (vendor == NULL) - vendor = kdp->vendorname; - if (product == NULL) - product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ? - kdp->productname : NULL; - } - } -#endif - if (vendor != NULL && *vendor) - strcpy(v, vendor); - else - sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor)); - if (product != NULL && *product) - strcpy(p, product); - else - sprintf(p, "product 0x%04x", UGETW(udd->idProduct)); -} - -int -usbd_printBCD(char *cp, int bcd) -{ - return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff)); -} - -void -usbd_devinfo(usbd_device_handle dev, int showclass, char *cp) -{ - usb_device_descriptor_t *udd = &dev->ddesc; - usbd_interface_handle iface; - char vendor[USB_MAX_STRING_LEN]; - char product[USB_MAX_STRING_LEN]; - int bcdDevice, bcdUSB; - usb_interface_descriptor_t *id; - - usbd_devinfo_vp(dev, vendor, product, 1); - cp += sprintf(cp, "%s %s", vendor, product); - if (showclass & USBD_SHOW_DEVICE_CLASS) - cp += sprintf(cp, ", class %d/%d", - udd->bDeviceClass, udd->bDeviceSubClass); - bcdUSB = UGETW(udd->bcdUSB); - bcdDevice = UGETW(udd->bcdDevice); - cp += sprintf(cp, ", rev "); - cp += usbd_printBCD(cp, bcdUSB); - *cp++ = '/'; - cp += usbd_printBCD(cp, bcdDevice); - cp += sprintf(cp, ", addr %d", dev->address); - if (showclass & USBD_SHOW_INTERFACE_CLASS) - { - /* fetch the interface handle for the first interface */ - (void)usbd_device2interface_handle(dev, 0, &iface); - id = usbd_get_interface_descriptor(iface); - cp += sprintf(cp, ", iclass %d/%d", - id->bInterfaceClass, id->bInterfaceSubClass); - } - *cp = 0; -} - -/* Delay for a certain number of ms */ -void -usb_delay_ms(usbd_bus_handle bus, u_int ms) -{ - /* Wait at least two clock ticks so we know the time has passed. */ - if (bus->use_polling || cold) - delay((ms+1) * 1000); - else - pause("usbdly", (ms*hz+999)/1000 + 1); -} - -/* Delay given a device handle. */ -void -usbd_delay_ms(usbd_device_handle dev, u_int ms) -{ - usb_delay_ms(dev->bus, ms); -} - -usbd_status -usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps) -{ - usbd_status err; - int n; - - err = usbd_set_port_feature(dev, port, UHF_PORT_RESET); - DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n", - port, usbd_errstr(err))); - if (err) - return (err); - n = 10; - do { - /* Wait for device to recover from reset. */ - usbd_delay_ms(dev, USB_PORT_RESET_DELAY); - err = usbd_get_port_status(dev, port, ps); - if (err) { - DPRINTF(("usbd_reset_port: get status failed %d\n", - 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); - err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); -#ifdef USB_DEBUG - if (err) - DPRINTF(("usbd_reset_port: clear port feature failed %d\n", - err)); -#endif - - /* Wait for the device to recover from reset. */ - usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); - return (err); -} - -usb_interface_descriptor_t * -usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx) -{ - char *p = (char *)cd; - char *end = p + UGETW(cd->wTotalLength); - usb_interface_descriptor_t *d; - int curidx, lastidx, curaidx = 0; - - for (curidx = lastidx = -1; p < end; ) { - d = (usb_interface_descriptor_t *)p; - DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d " - "type=%d\n", - ifaceidx, curidx, altidx, curaidx, - d->bLength, d->bDescriptorType)); - if (d->bLength == 0) /* bad descriptor */ - break; - p += d->bLength; - if (p <= end && d->bDescriptorType == UDESC_INTERFACE) { - if (d->bInterfaceNumber != lastidx) { - lastidx = d->bInterfaceNumber; - curidx++; - curaidx = 0; - } else - curaidx++; - if (ifaceidx == curidx && altidx == curaidx) - return (d); - } - } - return (NULL); -} - -usb_endpoint_descriptor_t * -usbd_find_edesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx, - int endptidx) -{ - char *p = (char *)cd; - char *end = p + UGETW(cd->wTotalLength); - usb_interface_descriptor_t *d; - usb_endpoint_descriptor_t *e; - int curidx; - - d = usbd_find_idesc(cd, ifaceidx, altidx); - if (d == NULL) - return (NULL); - if (endptidx >= d->bNumEndpoints) /* quick exit */ - return (NULL); - - curidx = -1; - for (p = (char *)d + d->bLength; p < end; ) { - e = (usb_endpoint_descriptor_t *)p; - if (e->bLength == 0) /* bad descriptor */ - break; - p += e->bLength; - if (p <= end && e->bDescriptorType == UDESC_INTERFACE) - return (NULL); - if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) { - curidx++; - if (curidx == endptidx) - return (e); - } - } - return (NULL); -} - -usbd_status -usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx) -{ - usbd_interface_handle ifc = &dev->ifaces[ifaceidx]; - usb_interface_descriptor_t *idesc; - char *p, *end; - int endpt, nendpt; - - DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n", - ifaceidx, altidx)); - idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx); - if (idesc == NULL) - return (USBD_INVAL); - ifc->device = dev; - ifc->idesc = idesc; - ifc->index = ifaceidx; - ifc->altindex = altidx; - nendpt = ifc->idesc->bNumEndpoints; - DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt)); - if (nendpt != 0) { - ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint), - M_USB, M_NOWAIT); - if (ifc->endpoints == NULL) - return (USBD_NOMEM); - } else - ifc->endpoints = NULL; - ifc->priv = NULL; - p = (char *)ifc->idesc + ifc->idesc->bLength; - end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength); -#define ed ((usb_endpoint_descriptor_t *)p) - for (endpt = 0; endpt < nendpt; endpt++) { - DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt)); - for (; p < end; p += ed->bLength) { - DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p " - "len=%d type=%d\n", - p, end, ed->bLength, ed->bDescriptorType)); - if (p + ed->bLength <= end && ed->bLength != 0 && - ed->bDescriptorType == UDESC_ENDPOINT) - goto found; - if (ed->bLength == 0 || - ed->bDescriptorType == UDESC_INTERFACE) - 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"); - 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; - ifc->endpoints[endpt].savedtoggle = 0; - p += ed->bLength; - } -#undef ed - LIST_INIT(&ifc->pipes); - return (USBD_NORMAL_COMPLETION); - - bad: - if (ifc->endpoints != NULL) { - free(ifc->endpoints, M_USB); - ifc->endpoints = NULL; - } - return (USBD_INVAL); -} - -void -usbd_free_iface_data(usbd_device_handle dev, int ifcno) -{ - usbd_interface_handle ifc = &dev->ifaces[ifcno]; - if (ifc->endpoints) - free(ifc->endpoints, M_USB); -} - -static usbd_status -usbd_set_config(usbd_device_handle dev, int conf) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_CONFIG; - USETW(req.wValue, conf); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_config_no(usbd_device_handle dev, int no, int msg) -{ - int index; - usb_config_descriptor_t cd; - usbd_status err; - - if (no == USB_UNCONFIG_NO) - return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg)); - - DPRINTFN(5,("usbd_set_config_no: %d\n", no)); - /* Figure out what config index to use. */ - for (index = 0; index < dev->ddesc.bNumConfigurations; index++) { - err = usbd_get_config_desc(dev, index, &cd); - if (err) - return (err); - if (cd.bConfigurationValue == no) - return (usbd_set_config_index(dev, index, msg)); - } - return (USBD_INVAL); -} - -usbd_status -usbd_set_config_index(usbd_device_handle dev, int index, int msg) -{ - usb_status_t ds; - usb_config_descriptor_t cd, *cdp; - usbd_status err; - int i, ifcidx, nifc, len, selfpowered, power; - - DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); - - if (dev->config != USB_UNCONFIG_NO) { - nifc = dev->cdesc->bNumInterface; - - /* Check that all interfaces are idle */ - for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - if (LIST_EMPTY(&dev->ifaces[ifcidx].pipes)) - continue; - DPRINTF(("usbd_set_config_index: open pipes exist\n")); - return (USBD_IN_USE); - } - - DPRINTF(("usbd_set_config_index: free old config\n")); - /* Free all configuration data structures. */ - for (ifcidx = 0; ifcidx < nifc; ifcidx++) - usbd_free_iface_data(dev, ifcidx); - free(dev->ifaces, M_USB); - free(dev->cdesc, M_USB); - dev->ifaces = NULL; - dev->cdesc = NULL; - dev->config = USB_UNCONFIG_NO; - } - - if (index == USB_UNCONFIG_INDEX) { - /* We are unconfiguring the device, so leave unallocated. */ - DPRINTF(("usbd_set_config_index: set config 0\n")); - err = usbd_set_config(dev, USB_UNCONFIG_NO); - if (err) - DPRINTF(("usbd_set_config_index: setting config=0 " - "failed, error=%s\n", usbd_errstr(err))); - return (err); - } - - /* Get the short descriptor. */ - err = usbd_get_config_desc(dev, index, &cd); - if (err) - return (err); - len = UGETW(cd.wTotalLength); - cdp = malloc(len, M_USB, M_NOWAIT); - if (cdp == NULL) - return (USBD_NOMEM); - - /* Get the full descriptor. Try a few times for slow devices. */ - for (i = 0; i < 3; i++) { - err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); - if (!err) - break; - usbd_delay_ms(dev, 200); - } - if (err) - goto bad; - if (cdp->bDescriptorType != UDESC_CONFIG) { - DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", - cdp->bDescriptorType)); - err = USBD_INVAL; - goto bad; - } - - /* Figure out if the device is self or bus powered. */ - selfpowered = 0; - if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) && - (cdp->bmAttributes & UC_SELF_POWERED)) { - /* May be self powered. */ - if (cdp->bmAttributes & UC_BUS_POWERED) { - /* Must ask device. */ - if (dev->quirks->uq_flags & UQ_POWER_CLAIM) { - /* - * Hub claims to be self powered, but isn't. - * It seems that the power status can be - * determined by the hub characteristics. - */ - usb_hub_descriptor_t hd; - usb_device_request_t req; - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE); - err = usbd_do_request(dev, &req, &hd); - if (!err && - (UGETW(hd.wHubCharacteristics) & - UHD_PWR_INDIVIDUAL)) - selfpowered = 1; - DPRINTF(("usbd_set_config_index: charac=0x%04x" - ", error=%s\n", - UGETW(hd.wHubCharacteristics), - usbd_errstr(err))); - } else { - err = usbd_get_device_status(dev, &ds); - if (!err && - (UGETW(ds.wStatus) & UDS_SELF_POWERED)) - selfpowered = 1; - DPRINTF(("usbd_set_config_index: status=0x%04x" - ", error=%s\n", - UGETW(ds.wStatus), usbd_errstr(err))); - } - } else - selfpowered = 1; - } - DPRINTF(("usbd_set_config_index: (addr %d) cno=%d attr=0x%02x, " - "selfpowered=%d, power=%d\n", - cdp->bConfigurationValue, dev->address, cdp->bmAttributes, - selfpowered, cdp->bMaxPower * 2)); - - /* Check if we have enough power. */ -#ifdef USB_DEBUG - if (dev->powersrc == NULL) { - DPRINTF(("usbd_set_config_index: No power source?\n")); - return (USBD_IOERROR); - } -#endif - power = cdp->bMaxPower * 2; - if (power > dev->powersrc->power) { - DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power)); - /* XXX print nicer message. */ - if (msg) - device_printf(dev->bus->bdev, - "device addr %d (config %d) exceeds " - "power budget, %d mA > %d mA\n", - dev->address, cdp->bConfigurationValue, - power, dev->powersrc->power); - err = USBD_NO_POWER; - goto bad; - } - dev->power = power; - dev->self_powered = selfpowered; - - /* Set the actual configuration value. */ - DPRINTF(("usbd_set_config_index: set config %d\n", - cdp->bConfigurationValue)); - err = usbd_set_config(dev, cdp->bConfigurationValue); - if (err) { - DPRINTF(("usbd_set_config_index: setting config=%d failed, " - "error=%s\n", - cdp->bConfigurationValue, usbd_errstr(err))); - goto bad; - } - - /* Allocate and fill interface data. */ - nifc = cdp->bNumInterface; - dev->ifaces = malloc(nifc * sizeof(struct usbd_interface), - M_USB, M_NOWAIT); - if (dev->ifaces == NULL) { - err = USBD_NOMEM; - goto bad; - } - DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); - dev->cdesc = cdp; - dev->config = cdp->bConfigurationValue; - for (ifcidx = 0; ifcidx < nifc; ifcidx++) { - err = usbd_fill_iface_data(dev, ifcidx, 0); - if (err) { - while (--ifcidx >= 0) - usbd_free_iface_data(dev, ifcidx); - goto bad; - } - } - - return (USBD_NORMAL_COMPLETION); - - bad: - free(cdp, M_USB); - return (err); -} - -/* XXX add function for alternate settings */ - -usbd_status -usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface, - struct usbd_endpoint *ep, int ival, usbd_pipe_handle *pipe) -{ - usbd_pipe_handle p; - usbd_status err; - - DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", - dev, iface, ep, pipe)); - p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT); - if (p == NULL) - return (USBD_NOMEM); - p->device = dev; - p->iface = iface; - p->endpoint = ep; - ep->refcnt++; - p->refcnt = 1; - p->intrxfer = 0; - p->running = 0; - p->aborting = 0; - p->repeat = 0; - p->interval = ival; - STAILQ_INIT(&p->queue); - err = dev->bus->methods->open_pipe(p); - if (err) { - DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=" - "%s\n", - ep->edesc->bEndpointAddress, usbd_errstr(err))); - free(p, M_USB); - return (err); - } - - if (dev->quirks->uq_flags & UQ_OPEN_CLEARSTALL) { - /* Clear any stall and make sure DATA0 toggle will be used next. */ - if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT) { - err = usbd_clear_endpoint_stall(p); - if (err && err != USBD_STALLED && err != USBD_TIMEOUT) { - printf("usbd_setup_pipe: failed to start " - "endpoint, %s\n", usbd_errstr(err)); - return (err); - } - } - } - - *pipe = p; - return (USBD_NORMAL_COMPLETION); -} - -/* Abort the device control pipe. */ -void -usbd_kill_pipe(usbd_pipe_handle pipe) -{ - usbd_abort_pipe(pipe); - pipe->methods->close(pipe); - pipe->endpoint->refcnt--; - free(pipe, M_USB); -} - -int -usbd_getnewaddr(usbd_bus_handle bus) -{ - int addr; - - for (addr = 1; addr < USB_MAX_DEVICES; addr++) - if (bus->devices[addr] == 0) - return (addr); - return (-1); -} - - -usbd_status -usbd_probe_and_attach(device_t parent, usbd_device_handle dev, - int port, int addr) -{ - struct usb_attach_arg uaa; - usb_device_descriptor_t *dd = &dev->ddesc; - int found, i, confi, nifaces; - usbd_status err; - device_t *tmpdv; - usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ - char *devinfo; - - /* XXX FreeBSD may leak resources on failure cases -- fixme */ - device_t bdev; - struct usb_attach_arg *uaap; - - devinfo = malloc(1024, M_USB, M_NOWAIT); - if (devinfo == NULL) { - device_printf(parent, "Can't allocate memory for probe string\n"); - return (USBD_NOMEM); - } - bdev = device_add_child(parent, NULL, -1); - if (!bdev) { - free(devinfo, M_USB); - device_printf(parent, "Device creation failed\n"); - return (USBD_INVAL); - } - uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT); - if (uaap == NULL) { - free(devinfo, M_USB); - return (USBD_INVAL); - } - device_set_ivars(bdev, uaap); - uaa.device = dev; - uaa.iface = NULL; - uaa.ifaces = NULL; - uaa.nifaces = 0; - uaa.usegeneric = 0; - uaa.port = port; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - uaa.vendor = UGETW(dd->idVendor); - uaa.product = UGETW(dd->idProduct); - uaa.release = UGETW(dd->bcdDevice); - uaa.matchlvl = 0; - - /* First try with device specific drivers. */ - DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n")); - - dev->ifacenums = NULL; - dev->subdevs = malloc(2 * sizeof(device_t), M_USB, M_NOWAIT); - if (dev->subdevs == NULL) { - free(devinfo, M_USB); - return (USBD_NOMEM); - } - dev->subdevs[0] = bdev; - dev->subdevs[1] = 0; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - if (device_probe_and_attach(bdev) == 0) { - free(devinfo, M_USB); - return (USBD_NORMAL_COMPLETION); - } - - /* - * Free subdevs so we can reallocate it larger for the number of - * interfaces - */ - tmpdv = dev->subdevs; - dev->subdevs = NULL; - free(tmpdv, M_USB); - DPRINTF(("usbd_probe_and_attach: no device specific driver found\n")); - - DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n", - dd->bNumConfigurations)); - /* Next try with interface drivers. */ - for (confi = 0; confi < dd->bNumConfigurations; confi++) { - DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n", - confi)); - err = usbd_set_config_index(dev, confi, 1); - if (err) { -#ifdef USB_DEBUG - DPRINTF(("%s: port %d, set config at addr %d failed, " - "error=%s\n", device_get_nameunit(parent), port, - addr, usbd_errstr(err))); -#else - printf("%s: port %d, set config at addr %d failed\n", - device_get_nameunit(parent), port, addr); -#endif - free(devinfo, M_USB); - return (err); - } - nifaces = dev->cdesc->bNumInterface; - uaa.configno = dev->cdesc->bConfigurationValue; - for (i = 0; i < nifaces; i++) - ifaces[i] = &dev->ifaces[i]; - uaa.ifaces = ifaces; - uaa.nifaces = nifaces; - dev->subdevs = malloc((nifaces+1) * sizeof(device_t), M_USB,M_NOWAIT); - if (dev->subdevs == NULL) { - free(devinfo, M_USB); - return (USBD_NOMEM); - } - dev->ifacenums = malloc((nifaces) * sizeof(*dev->ifacenums), - M_USB,M_NOWAIT); - if (dev->ifacenums == NULL) { - free(devinfo, M_USB); - return (USBD_NOMEM); - } - - found = 0; - for (i = 0; i < nifaces; i++) { - if (ifaces[i] == NULL) - continue; /* interface already claimed */ - uaa.iface = ifaces[i]; - uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber; - dev->subdevs[found] = bdev; - dev->subdevs[found + 1] = 0; - dev->ifacenums[found] = i; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - if (device_probe_and_attach(bdev) == 0) { - ifaces[i] = NULL; /* consumed */ - found++; - /* create another child for the next iface */ - bdev = device_add_child(parent, NULL, -1); - if (!bdev) { - device_printf(parent, - "Device add failed\n"); - free(devinfo, M_USB); - return (USBD_NORMAL_COMPLETION); - } - uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT); - if (uaap == NULL) { - free(devinfo, M_USB); - return (USBD_NOMEM); - } - device_set_ivars(bdev, uaap); - } else { - dev->subdevs[found] = 0; - } - } - if (found != 0) { - /* remove the last created child. It is unused */ - free(uaap, M_USB); - free(devinfo, M_USB); - device_delete_child(parent, bdev); - /* free(uaap, M_USB); */ /* May be needed? xxx */ - return (USBD_NORMAL_COMPLETION); - } - tmpdv = dev->subdevs; - dev->subdevs = NULL; - free(tmpdv, M_USB); - free(dev->ifacenums, M_USB); - dev->ifacenums = NULL; - } - /* No interfaces were attached in any of the configurations. */ - - if (dd->bNumConfigurations > 1) /* don't change if only 1 config */ - usbd_set_config_index(dev, 0, 0); - - DPRINTF(("usbd_probe_and_attach: no interface drivers found\n")); - - /* Finally try the generic driver. */ - uaa.iface = NULL; - uaa.usegeneric = 1; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - dev->subdevs = malloc(2 * sizeof(device_t), M_USB, M_NOWAIT); - if (dev->subdevs == 0) { - free(devinfo, M_USB); - return (USBD_NOMEM); - } - dev->subdevs[0] = bdev; - dev->subdevs[1] = 0; - *uaap = uaa; - usbd_devinfo(dev, 1, devinfo); - device_set_desc_copy(bdev, devinfo); - free(devinfo, M_USB); - if (device_probe_and_attach(bdev) == 0) - return (USBD_NORMAL_COMPLETION); - - /* - * The generic attach failed, but leave the device as it is. - * We just did not find any drivers, that's all. The device is - * fully operational and not harming anyone. - */ - DPRINTF(("usbd_probe_and_attach: generic attach failed\n")); - return (USBD_NORMAL_COMPLETION); -} - - -/* - * Called when a new device has been put in the powered state, - * but not yet in the addressed state. - * Get initial descriptor, set the address, get full descriptor, - * and attach a driver. - */ -usbd_status -usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, - int speed, int port, struct usbd_port *up) -{ - usbd_device_handle dev, adev; - struct usbd_device *hub; - usb_device_descriptor_t *dd; - usb_port_status_t ps; - usbd_status err; - int addr; - int i; - int p; - - DPRINTF(("usbd_new_device bus=%p port=%d depth=%d speed=%d\n", - bus, port, depth, speed)); - addr = usbd_getnewaddr(bus); - if (addr < 0) { - device_printf(bus->bdev, "No free USB addresses\n"); - return (USBD_NO_ADDR); - } - - dev = malloc(sizeof *dev, M_USB, M_NOWAIT|M_ZERO); - if (dev == NULL) - return (USBD_NOMEM); - - dev->bus = bus; - - /* Set up default endpoint handle. */ - dev->def_ep.edesc = &dev->def_ep_desc; - - /* Set up default endpoint descriptor. */ - dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE; - dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT; - dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT; - dev->def_ep_desc.bmAttributes = UE_CONTROL; - USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET); - dev->def_ep_desc.bInterval = 0; - - dev->quirks = &usbd_no_quirk; - dev->address = USB_START_ADDR; - dev->ddesc.bMaxPacketSize = 0; - dev->depth = depth; - dev->powersrc = up; - dev->myhub = up->parent; - - up->device = dev; - - if (up->parent && speed > up->parent->speed) { -#ifdef USB_DEBUG - printf("%s: maxium speed of attached " - "device, %d, is higher than speed " - "of parent HUB, %d.\n", - __FUNCTION__, speed, up->parent->speed); -#endif - /* - * Reduce the speed, otherwise we won't setup the - * proper transfer methods. - */ - speed = up->parent->speed; - } - - /* Locate port on upstream high speed hub */ - for (adev = dev, hub = up->parent; - hub != NULL && hub->speed != USB_SPEED_HIGH; - adev = hub, hub = hub->myhub) - ; - if (hub) { - for (p = 0; p < hub->hub->hubdesc.bNbrPorts; p++) { - if (hub->hub->ports[p].device == adev) { - dev->myhsport = &hub->hub->ports[p]; - goto found; - } - } - panic("usbd_new_device: cannot find HS port\n"); - found: - DPRINTFN(1,("usbd_new_device: high speed port %d\n", p)); - } else { - dev->myhsport = NULL; - } - dev->speed = speed; - dev->langid = USBD_NOLANG; - dev->cookie.cookie = ++usb_cookie_no; - - /* Establish the default pipe. */ - err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, - &dev->default_pipe); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - dd = &dev->ddesc; - /* Try a few times in case the device is slow (i.e. outside specs.) */ - DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr)); - for (i = 0; i < 15; i++) { - /* Get the first 8 bytes of the device descriptor. */ - err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); - if (!err) - break; - usbd_delay_ms(dev, 200); - if ((i & 3) == 3) { - DPRINTFN(-1,("usb_new_device: set address %d " - "failed - trying a port reset\n", addr)); - usbd_reset_port(up->parent, port, &ps); - } - - } - if (err) { - DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " - "failed\n", addr)); - usbd_remove_device(dev, up); - 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", - addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, - dd->bDeviceProtocol, dd->bMaxPacketSize, dd->bLength, - dev->speed)); - - if (dd->bDescriptorType != UDESC_DEVICE) { - /* Illegal device descriptor */ - DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n", - dd->bDescriptorType)); - usbd_remove_device(dev, up); - return (USBD_INVAL); - } - - if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) { - DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength)); - usbd_remove_device(dev, up); - return (USBD_INVAL); - } - - USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); - - /* Re-establish the default pipe with the new max packet size. */ - usbd_kill_pipe(dev->default_pipe); - err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, - &dev->default_pipe); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - err = usbd_reload_device_desc(dev); - if (err) { - DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " - "failed\n", addr)); - usbd_remove_device(dev, up); - return (err); - } - - /* Set the address */ - DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr)); - err = usbd_set_address(dev, addr); - if (err) { - DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr)); - err = USBD_SET_ADDR_FAILED; - usbd_remove_device(dev, up); - return (err); - } - - /* Allow device time to set new address */ - usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); - dev->address = addr; /* New device address now */ - bus->devices[addr] = dev; - - /* Re-establish the default pipe with the new address. */ - usbd_kill_pipe(dev->default_pipe); - err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, - &dev->default_pipe); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - /* Assume 100mA bus powered for now. Changed when configured. */ - dev->power = USB_MIN_POWER; - dev->self_powered = 0; - - DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", - addr, dev, parent)); - - err = usbd_probe_and_attach(parent, dev, port, addr); - if (err) { - usbd_remove_device(dev, up); - return (err); - } - - usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev); - - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_reload_device_desc(usbd_device_handle dev) -{ - usbd_status err; - int i; - - /* Get the full device descriptor. */ - for (i = 0; i < 3; ++i) { - err = usbd_get_device_desc(dev, &dev->ddesc); - if (!err) - break; - usbd_delay_ms(dev, 200); - } - if (err) - return (err); - - /* Figure out what's wrong with this device. */ - dev->quirks = usbd_find_quirk(&dev->ddesc); - - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_remove_device(usbd_device_handle dev, struct usbd_port *up) -{ - DPRINTF(("usbd_remove_device: %p\n", dev)); - - if (dev->default_pipe != NULL) - usbd_kill_pipe(dev->default_pipe); - up->device = NULL; - dev->bus->devices[dev->address] = NULL; - - free(dev, M_USB); -} - -void -usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di, - int usedev) -{ - struct usbd_port *p; - int i, err, s; - - di->udi_bus = device_get_unit(dev->bus->bdev); - di->udi_addr = dev->address; - di->udi_cookie = dev->cookie; - usbd_devinfo_vp(dev, di->udi_vendor, di->udi_product, usedev); - usbd_printBCD(di->udi_release, UGETW(dev->ddesc.bcdDevice)); - di->udi_vendorNo = UGETW(dev->ddesc.idVendor); - di->udi_productNo = UGETW(dev->ddesc.idProduct); - di->udi_releaseNo = UGETW(dev->ddesc.bcdDevice); - di->udi_class = dev->ddesc.bDeviceClass; - di->udi_subclass = dev->ddesc.bDeviceSubClass; - 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; - - if (dev->subdevs != NULL) { - for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) { - if (device_is_attached(dev->subdevs[i])) - strlcpy(di->udi_devnames[i], - device_get_nameunit(dev->subdevs[i]), - USB_MAX_DEVNAMELEN); - else - di->udi_devnames[i][0] = 0; - } - } else { - i = 0; - } - for (/*i is set */; i < USB_MAX_DEVNAMES; i++) - di->udi_devnames[i][0] = 0; /* empty */ - - if (dev->hub) { - for (i = 0; - i < sizeof(di->udi_ports) / sizeof(di->udi_ports[0]) && - i < dev->hub->hubdesc.bNbrPorts; - i++) { - p = &dev->hub->ports[i]; - if (p->device) - err = p->device->address; - else { - s = UGETW(p->status.wPortStatus); - if (s & UPS_PORT_ENABLED) - err = USB_PORT_ENABLED; - else if (s & UPS_SUSPEND) - err = USB_PORT_SUSPENDED; - else if (s & UPS_PORT_POWER) - err = USB_PORT_POWERED; - else - err = USB_PORT_DISABLED; - } - di->udi_ports[i] = err; - } - di->udi_nports = dev->hub->hubdesc.bNbrPorts; - } else - di->udi_nports = 0; -} - -void -usb_free_device(usbd_device_handle dev) -{ - int ifcidx, nifc; - - if (dev->default_pipe != NULL) - usbd_kill_pipe(dev->default_pipe); - if (dev->ifaces != NULL) { - nifc = dev->cdesc->bNumInterface; - for (ifcidx = 0; ifcidx < nifc; ifcidx++) - usbd_free_iface_data(dev, ifcidx); - free(dev->ifaces, M_USB); - } - if (dev->cdesc != NULL) - free(dev->cdesc, M_USB); - if (dev->subdevs != NULL) - free(dev->subdevs, M_USB); - if (dev->ifacenums != NULL) - free(dev->ifacenums, M_USB); - free(dev, M_USB); -} - -/* - * The general mechanism for detaching drivers works as follows: Each - * driver is responsible for maintaining a reference count on the - * number of outstanding references to its softc (e.g. from - * processing hanging in a read or write). The detach method of the - * driver decrements this counter and flags in the softc that the - * driver is dying and then wakes any sleepers. It then sleeps on the - * softc. Each place that can sleep must maintain the reference - * count. When the reference count drops to -1 (0 is the normal value - * of the reference count) the a wakeup on the softc is performed - * signaling to the detach waiter that all references are gone. - */ - -/* - * Called from process context when we discover that a port has - * been disconnected. - */ -void -usb_disconnect_port(struct usbd_port *up, device_t parent) -{ - usbd_device_handle dev = up->device; - const char *hubname = device_get_nameunit(parent); - int i; - - DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n", - up, dev, up->portno)); - -#ifdef DIAGNOSTIC - if (dev == NULL) { - printf("usb_disconnect_port: no device\n"); - return; - } -#endif - - if (dev->subdevs != NULL) { - DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n")); - for (i = 0; dev->subdevs[i]; i++) { - if (!device_is_quiet(dev->subdevs[i])) { - device_printf(dev->subdevs[i], - "at %s", hubname); - if (up->portno != 0) - printf(" port %d", up->portno); - printf(" (addr %d) disconnected\n", dev->address); - } - - struct usb_attach_arg *uaap = - device_get_ivars(dev->subdevs[i]); - device_detach(dev->subdevs[i]); - free(uaap, M_USB); - device_delete_child(device_get_parent(dev->subdevs[i]), - dev->subdevs[i]); - dev->subdevs[i] = NULL; - } - } - - usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev); - dev->bus->devices[dev->address] = NULL; - up->device = NULL; - usb_free_device(dev); -} diff --git a/sys/dev/usb/usbcdc.h b/sys/dev/usb/usbcdc.h deleted file mode 100644 index d684108..0000000 --- a/sys/dev/usb/usbcdc.h +++ /dev/null @@ -1,188 +0,0 @@ -/* $NetBSD: usbcdc.h,v 1.9 2004/10/23 13:24:24 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _USBCDC_H_ -#define _USBCDC_H_ - -#define UDESCSUB_CDC_HEADER 0 -#define UDESCSUB_CDC_CM 1 /* Call Management */ -#define UDESCSUB_CDC_ACM 2 /* Abstract Control Model */ -#define UDESCSUB_CDC_DLM 3 /* Direct Line Management */ -#define UDESCSUB_CDC_TRF 4 /* Telephone Ringer */ -#define UDESCSUB_CDC_TCLSR 5 /* Telephone Call ... */ -#define UDESCSUB_CDC_UNION 6 -#define UDESCSUB_CDC_CS 7 /* Country Selection */ -#define UDESCSUB_CDC_TOM 8 /* Telephone Operational Modes */ -#define UDESCSUB_CDC_USBT 9 /* USB Terminal */ -#define UDESCSUB_CDC_NCT 10 -#define UDESCSUB_CDC_PUF 11 -#define UDESCSUB_CDC_EUF 12 -#define UDESCSUB_CDC_MCMF 13 -#define UDESCSUB_CDC_CCMF 14 -#define UDESCSUB_CDC_ENF 15 -#define UDESCSUB_CDC_ANF 16 - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uWord bcdCDC; -} UPACKED usb_cdc_header_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bmCapabilities; -#define USB_CDC_CM_DOES_CM 0x01 -#define USB_CDC_CM_OVER_DATA 0x02 - uByte bDataInterface; -} UPACKED usb_cdc_cm_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bmCapabilities; -#define USB_CDC_ACM_HAS_FEATURE 0x01 -#define USB_CDC_ACM_HAS_LINE 0x02 -#define USB_CDC_ACM_HAS_BREAK 0x04 -#define USB_CDC_ACM_HAS_NETWORK_CONN 0x08 -} UPACKED usb_cdc_acm_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte bMasterInterface; - uByte bSlaveInterface[1]; -} UPACKED usb_cdc_union_descriptor_t; - -typedef struct { - uByte bLength; - uByte bDescriptorType; - uByte bDescriptorSubtype; - uByte iMacAddress; - uDWord bmEthernetStatistics; - uWord wMaxSegmentSize; - uWord wNumberMCFikters; - uByte bNumberPowerFilters; -} UPACKED usb_cdc_ethernet_descriptor_t; - -#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00 -#define UCDC_GET_ENCAPSULATED_RESPONSE 0x01 -#define UCDC_SET_COMM_FEATURE 0x02 -#define UCDC_GET_COMM_FEATURE 0x03 -#define UCDC_ABSTRACT_STATE 0x01 -#define UCDC_COUNTRY_SETTING 0x02 -#define UCDC_CLEAR_COMM_FEATURE 0x04 -#define UCDC_SET_LINE_CODING 0x20 -#define UCDC_GET_LINE_CODING 0x21 -#define UCDC_SET_CONTROL_LINE_STATE 0x22 -#define UCDC_LINE_DTR 0x0001 -#define UCDC_LINE_RTS 0x0002 -#define UCDC_SEND_BREAK 0x23 -#define UCDC_BREAK_ON 0xffff -#define UCDC_BREAK_OFF 0x0000 - -typedef struct { - uWord wState; -#define UCDC_IDLE_SETTING 0x0001 -#define UCDC_DATA_MULTIPLEXED 0x0002 -} UPACKED usb_cdc_abstract_state_t; -#define UCDC_ABSTRACT_STATE_LENGTH 2 - -typedef struct { - uDWord dwDTERate; - uByte bCharFormat; -#define UCDC_STOP_BIT_1 0 -#define UCDC_STOP_BIT_1_5 1 -#define UCDC_STOP_BIT_2 2 - uByte bParityType; -#define UCDC_PARITY_NONE 0 -#define UCDC_PARITY_ODD 1 -#define UCDC_PARITY_EVEN 2 -#define UCDC_PARITY_MARK 3 -#define UCDC_PARITY_SPACE 4 - uByte bDataBits; -} UPACKED usb_cdc_line_state_t; -#define UCDC_LINE_STATE_LENGTH 7 - -typedef struct { - uByte bmRequestType; -#define UCDC_NOTIFICATION 0xa1 - uByte bNotification; -#define UCDC_N_NETWORK_CONNECTION 0x00 -#define UCDC_N_RESPONSE_AVAILABLE 0x01 -#define UCDC_N_AUX_JACK_HOOK_STATE 0x08 -#define UCDC_N_RING_DETECT 0x09 -#define UCDC_N_SERIAL_STATE 0x20 -#define UCDC_N_CALL_STATE_CHANGED 0x28 -#define UCDC_N_LINE_STATE_CHANGED 0x29 -#define UCDC_N_CONNECTION_SPEED_CHANGE 0x2a - uWord wValue; - uWord wIndex; - uWord wLength; - uByte data[16]; -} UPACKED usb_cdc_notification_t; -#define UCDC_NOTIFICATION_LENGTH 8 - -/* - * Bits set in the SERIAL STATE notifcation (first byte of data) - */ - -#define UCDC_N_SERIAL_OVERRUN 0x40 -#define UCDC_N_SERIAL_PARITY 0x20 -#define UCDC_N_SERIAL_FRAMING 0x10 -#define UCDC_N_SERIAL_RI 0x08 -#define UCDC_N_SERIAL_BREAK 0x04 -#define UCDC_N_SERIAL_DSR 0x02 -#define UCDC_N_SERIAL_DCD 0x01 - -/* Serial state bit masks */ -#define UCDC_MDM_RXCARRIER 0x01 -#define UCDC_MDM_TXCARRIER 0x02 -#define UCDC_MDM_BREAK 0x04 -#define UCDC_MDM_RING 0x08 -#define UCDC_MDM_FRAMING_ERR 0x10 -#define UCDC_MDM_PARITY_ERR 0x20 -#define UCDC_MDM_OVERRUN_ERR 0x40 - -#endif /* _USBCDC_H_ */ diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs deleted file mode 100644 index 0a3d85e..0000000 --- a/sys/dev/usb/usbdevs +++ /dev/null @@ -1,2527 +0,0 @@ -$FreeBSD$ -/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */ - -/*- - * Copyright (c) 1998-2004 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. - */ - -/* - * List of known USB vendors - * - * USB.org publishes a VID list of USB-IF member companies at - * http://www.usb.org/developers/tools - * Note that it does not show companies that have obtained a Vendor ID - * without becoming full members. - * - * Please note that these IDs do not do anything. Adding an ID here and - * regenerating the usbdevs.h and usbdevs_data.h only makes a symbolic name - * available to the source code and does not change any functionality, nor - * does it make your device available to a specific driver. - * It will however make the descriptive string available if a device does not - * provide the string itself. - * - * After adding a vendor ID VNDR and a product ID PRDCT you will have the - * following extra defines: - * #define USB_VENDOR_VNDR 0x???? - * #define USB_PRODUCT_VNDR_PRDCT 0x???? - * - * You may have to add these defines to the respective probe routines to - * make the device recognised by the appropriate device driver. - */ - -vendor UNKNOWN1 0x0053 Unknown vendor -vendor UNKNOWN2 0x0105 Unknown vendor -vendor EGALAX2 0x0123 eGalax, Inc. -vendor HUMAX 0x02ad HUMAX -vendor LTS 0x0386 LTS -vendor BWCT 0x03da Bernd Walter Computer Technology -vendor AOX 0x03e8 AOX -vendor THESYS 0x03e9 Thesys -vendor DATABROADCAST 0x03ea Data Broadcasting -vendor ATMEL 0x03eb Atmel -vendor IWATSU 0x03ec Iwatsu America -vendor MITSUMI 0x03ee Mitsumi -vendor HP 0x03f0 Hewlett Packard -vendor GENOA 0x03f1 Genoa -vendor OAK 0x03f2 Oak -vendor ADAPTEC 0x03f3 Adaptec -vendor DIEBOLD 0x03f4 Diebold -vendor SIEMENSELECTRO 0x03f5 Siemens Electromechanical -vendor EPSONIMAGING 0x03f8 Epson Imaging -vendor KEYTRONIC 0x03f9 KeyTronic -vendor OPTI 0x03fb OPTi -vendor ELITEGROUP 0x03fc Elitegroup -vendor XILINX 0x03fd Xilinx -vendor FARALLON 0x03fe Farallon Communications -vendor NATIONAL 0x0400 National Semiconductor -vendor NATIONALREG 0x0401 National Registry -vendor ACERLABS 0x0402 Acer Labs -vendor FTDI 0x0403 Future Technology Devices -vendor NCR 0x0404 NCR -vendor SYNOPSYS2 0x0405 Synopsys -vendor FUJITSUICL 0x0406 Fujitsu-ICL -vendor FUJITSU2 0x0407 Fujitsu Personal Systems -vendor QUANTA 0x0408 Quanta -vendor NEC 0x0409 NEC -vendor KODAK 0x040a Eastman Kodak -vendor WELTREND 0x040b Weltrend -vendor VIA 0x040d VIA -vendor MCCI 0x040e MCCI -vendor MELCO 0x0411 Melco -vendor LEADTEK 0x0413 Leadtek -vendor WINBOND 0x0416 Winbond -vendor PHOENIX 0x041a Phoenix -vendor CREATIVE 0x041e Creative Labs -vendor NOKIA 0x0421 Nokia -vendor ADI 0x0422 ADI Systems -vendor CATC 0x0423 Computer Access Technology -vendor SMC2 0x0424 Standard Microsystems -vendor MOTOROLA_HK 0x0425 Motorola HK -vendor GRAVIS 0x0428 Advanced Gravis Computer -vendor CIRRUSLOGIC 0x0429 Cirrus Logic -vendor INNOVATIVE 0x042c Innovative Semiconductors -vendor MOLEX 0x042f Molex -vendor SUN 0x0430 Sun Microsystems -vendor UNISYS 0x0432 Unisys -vendor TAUGA 0x0436 Taugagreining HF -vendor AMD 0x0438 Advanced Micro Devices -vendor LEXMARK 0x043d Lexmark International -vendor LG 0x043e LG Electronics -vendor NANAO 0x0440 NANAO -vendor GATEWAY 0x0443 Gateway 2000 -vendor NMB 0x0446 NMB -vendor ALPS 0x044e Alps Electric -vendor THRUST 0x044f Thrustmaster -vendor TI 0x0451 Texas Instruments -vendor ANALOGDEVICES 0x0456 Analog Devices -vendor SIS 0x0457 Silicon Integrated Systems Corp. -vendor KYE 0x0458 KYE Systems -vendor DIAMOND2 0x045a Diamond (Supra) -vendor RENESAS 0x045b Renesas -vendor MICROSOFT 0x045e Microsoft -vendor PRIMAX 0x0461 Primax Electronics -vendor MGE 0x0463 MGE UPS Systems -vendor AMP 0x0464 AMP -vendor CHERRY 0x046a Cherry Mikroschalter -vendor MEGATRENDS 0x046b American Megatrends -vendor LOGITECH 0x046d Logitech -vendor BTC 0x046e Behavior Tech. Computer -vendor PHILIPS 0x0471 Philips -vendor SUN2 0x0472 Sun Microsystems (offical) -vendor SANYO 0x0474 Sanyo Electric -vendor SEAGATE 0x0477 Seagate -vendor CONNECTIX 0x0478 Connectix -vendor SEMTECH 0x047a Semtech -vendor KENSINGTON 0x047d Kensington -vendor LUCENT 0x047e Lucent -vendor PLANTRONICS 0x047f Plantronics -vendor KYOCERA 0x0482 Kyocera Wireless Corp. -vendor STMICRO 0x0483 STMicroelectronics -vendor FOXCONN 0x0489 Foxconn -vendor MEIZU 0x0492 Meizu Electronics -vendor YAMAHA 0x0499 YAMAHA -vendor COMPAQ 0x049f Compaq -vendor HITACHI 0x04a4 Hitachi -vendor ACERP 0x04a5 Acer Peripherals -vendor DAVICOM 0x04a6 Davicom -vendor VISIONEER 0x04a7 Visioneer -vendor CANON 0x04a9 Canon -vendor NIKON 0x04b0 Nikon -vendor PAN 0x04b1 Pan International -vendor IBM 0x04b3 IBM -vendor CYPRESS 0x04b4 Cypress Semiconductor -vendor ROHM 0x04b5 ROHM -vendor COMPAL 0x04b7 Compal -vendor EPSON 0x04b8 Seiko Epson -vendor RAINBOW 0x04b9 Rainbow Technologies -vendor IODATA 0x04bb I-O Data -vendor TDK 0x04bf TDK -vendor 3COMUSR 0x04c1 U.S. Robotics -vendor METHODE 0x04c2 Methode Electronics Far East -vendor MAXISWITCH 0x04c3 Maxi Switch -vendor LOCKHEEDMER 0x04c4 Lockheed Martin Energy Research -vendor FUJITSU 0x04c5 Fujitsu -vendor TOSHIBAAM 0x04c6 Toshiba America -vendor MICROMACRO 0x04c7 Micro Macro Technologies -vendor KONICA 0x04c8 Konica -vendor LITEON 0x04ca Lite-On Technology -vendor FUJIPHOTO 0x04cb Fuji Photo Film -vendor PHILIPSSEMI 0x04cc Philips Semiconductors -vendor TATUNG 0x04cd Tatung Co. Of America -vendor SCANLOGIC 0x04ce ScanLogic -vendor MYSON 0x04cf Myson Technology -vendor DIGI2 0x04d0 Digi -vendor ITTCANON 0x04d1 ITT Canon -vendor ALTEC 0x04d2 Altec Lansing -vendor LSI 0x04d4 LSI -vendor MENTORGRAPHICS 0x04d6 Mentor Graphics -vendor ITUNERNET 0x04d8 I-Tuner Networks -vendor HOLTEK 0x04d9 Holtek Semiconductor, Inc. -vendor PANASONIC 0x04da Panasonic (Matsushita) -vendor HUANHSIN 0x04dc Huan Hsin -vendor SHARP 0x04dd Sharp -vendor IIYAMA 0x04e1 Iiyama -vendor SHUTTLE 0x04e6 Shuttle Technology -vendor ELO 0x04e7 Elo TouchSystems -vendor SAMSUNG 0x04e8 Samsung Electronics -vendor NORTHSTAR 0x04eb Northstar -vendor TOKYOELECTRON 0x04ec Tokyo Electron -vendor ANNABOOKS 0x04ed Annabooks -vendor JVC 0x04f1 JVC -vendor CHICONY 0x04f2 Chicony Electronics -vendor ELAN 0x04f3 Elan -vendor NEWNEX 0x04f7 Newnex -vendor BROTHER 0x04f9 Brother Industries -vendor DALLAS 0x04fa Dallas Semiconductor -vendor AIPTEK2 0x04fc AIPTEK International -vendor PFU 0x04fe PFU -vendor FUJIKURA 0x0501 Fujikura/DDK -vendor ACER 0x0502 Acer -vendor 3COM 0x0506 3Com -vendor HOSIDEN 0x0507 Hosiden Corporation -vendor AZTECH 0x0509 Aztech Systems -vendor BELKIN 0x050d Belkin Components -vendor KAWATSU 0x050f Kawatsu Semiconductor -vendor FCI 0x0514 FCI -vendor LONGWELL 0x0516 Longwell -vendor COMPOSITE 0x0518 Composite -vendor STAR 0x0519 Star Micronics -vendor APC 0x051d American Power Conversion -vendor SCIATLANTA 0x051e Scientific Atlanta -vendor TSM 0x0520 TSM -vendor CONNECTEK 0x0522 Advanced Connectek USA -vendor NETCHIP 0x0525 NetChip Technology -vendor ALTRA 0x0527 ALTRA -vendor ATI 0x0528 ATI Technologies -vendor AKS 0x0529 Aladdin Knowledge Systems -vendor TEKOM 0x052b Tekom -vendor CANONDEV 0x052c Canon -vendor WACOMTECH 0x0531 Wacom -vendor INVENTEC 0x0537 Inventec -vendor SHYHSHIUN 0x0539 Shyh Shiun Terminals -vendor PREHWERKE 0x053a Preh Werke Gmbh & Co. KG -vendor SYNOPSYS 0x053f Synopsys -vendor UNIACCESS 0x0540 Universal Access -vendor VIEWSONIC 0x0543 ViewSonic -vendor XIRLINK 0x0545 Xirlink -vendor ANCHOR 0x0547 Anchor Chips -vendor SONY 0x054c Sony -vendor FUJIXEROX 0x0550 Fuji Xerox -vendor VISION 0x0553 VLSI Vision -vendor ASAHIKASEI 0x0556 Asahi Kasei Microsystems -vendor ATEN 0x0557 ATEN International -vendor SAMSUNG2 0x055d Samsung Electronics -vendor MUSTEK 0x055f Mustek Systems -vendor TELEX 0x0562 Telex Communications -vendor CHINON 0x0564 Chinon -vendor PERACOM 0x0565 Peracom Networks -vendor ALCOR2 0x0566 Alcor Micro -vendor XYRATEX 0x0567 Xyratex -vendor WACOM 0x056a WACOM -vendor ETEK 0x056c e-TEK Labs -vendor EIZO 0x056d EIZO -vendor ELECOM 0x056e Elecom -vendor CONEXANT 0x0572 Conexant -vendor HAUPPAUGE 0x0573 Hauppauge Computer Works -vendor BAFO 0x0576 BAFO/Quality Computer Accessories -vendor YEDATA 0x057b Y-E Data -vendor AVM 0x057c AVM -vendor QUICKSHOT 0x057f Quickshot -vendor ROLAND 0x0582 Roland -vendor ROCKFIRE 0x0583 Rockfire -vendor RATOC 0x0584 RATOC Systems -vendor ZYXEL 0x0586 ZyXEL Communication -vendor INFINEON 0x058b Infineon -vendor MICREL 0x058d Micrel -vendor ALCOR 0x058f Alcor Micro -vendor OMRON 0x0590 OMRON -vendor ZORAN 0x0595 Zoran Microelectronics -vendor NIIGATA 0x0598 Niigata -vendor IOMEGA 0x059b Iomega -vendor ATREND 0x059c A-Trend Technology -vendor AID 0x059d Advanced Input Devices -vendor LACIE 0x059f LaCie -vendor FUJIFILM 0x05a2 Fuji Film -vendor ARC 0x05a3 ARC -vendor ORTEK 0x05a4 Ortek -vendor BOSE 0x05a7 Bose -vendor OMNIVISION 0x05a9 OmniVision -vendor INSYSTEM 0x05ab In-System Design -vendor APPLE 0x05ac Apple Computer -vendor YCCABLE 0x05ad Y.C. Cable -vendor DIGITALPERSONA 0x05ba DigitalPersona -vendor 3G 0x05bc 3G Green Green Globe -vendor RAFI 0x05bd RAFI -vendor TYCO 0x05be Tyco -vendor KAWASAKI 0x05c1 Kawasaki -vendor DIGI 0x05c5 Digi International -vendor QUALCOMM2 0x05c6 Qualcomm -vendor QTRONIX 0x05c7 Qtronix -vendor FOXLINK 0x05c8 Foxlink -vendor RICOH 0x05ca Ricoh -vendor ELSA 0x05cc ELSA -vendor SCIWORX 0x05ce sci-worx -vendor BRAINBOXES 0x05d1 Brainboxes Limited -vendor ULTIMA 0x05d8 Ultima -vendor AXIOHM 0x05d9 Axiohm Transaction Solutions -vendor MICROTEK 0x05da Microtek -vendor SUNTAC 0x05db SUN Corporation -vendor LEXAR 0x05dc Lexar Media -vendor ADDTRON 0x05dd Addtron -vendor SYMBOL 0x05e0 Symbol Technologies -vendor SYNTEK 0x05e1 Syntek -vendor GENESYS 0x05e3 Genesys Logic -vendor FUJI 0x05e5 Fuji Electric -vendor KEITHLEY 0x05e6 Keithley Instruments -vendor EIZONANAO 0x05e7 EIZO Nanao -vendor KLSI 0x05e9 Kawasaki LSI -vendor FFC 0x05eb FFC -vendor ANKO 0x05ef Anko Electronic -vendor PIENGINEERING 0x05f3 P.I. Engineering -vendor AOC 0x05f6 AOC International -vendor CHIC 0x05fe Chic Technology -vendor BARCO 0x0600 Barco Display Systems -vendor BRIDGE 0x0607 Bridge Information -vendor SOLIDYEAR 0x060b Solid Year -vendor BIORAD 0x0614 Bio-Rad Laboratories -vendor MACALLY 0x0618 Macally -vendor ACTLABS 0x061c Act Labs -vendor ALARIS 0x0620 Alaris -vendor APEX 0x0624 Apex -vendor CREATIVE3 0x062a Creative Labs -vendor VIVITAR 0x0636 Vivitar -vendor GUNZE 0x0637 Gunze Electronics USA -vendor AVISION 0x0638 Avision -vendor TEAC 0x0644 TEAC -vendor SGI 0x065e Silicon Graphics -vendor SANWASUPPLY 0x0663 Sanwa Supply -vendor LINKSYS 0x066b Linksys -vendor ACERSA 0x066e Acer Semiconductor America -vendor SIGMATEL 0x066f Sigmatel -vendor DRAYTEK 0x0675 DrayTek -vendor AIWA 0x0677 Aiwa -vendor ACARD 0x0678 ACARD Technology -vendor PROLIFIC 0x067b Prolific Technology -vendor SIEMENS 0x067c Siemens -vendor AVANCELOGIC 0x0680 Avance Logic -vendor SIEMENS2 0x0681 Siemens -vendor MINOLTA 0x0686 Minolta -vendor CHPRODUCTS 0x068e CH Products -vendor HAGIWARA 0x0693 Hagiwara Sys-Com -vendor CTX 0x0698 Chuntex -vendor ASKEY 0x069a Askey Computer -vendor SAITEK 0x06a3 Saitek -vendor ALCATELT 0x06b9 Alcatel Telecom -vendor AGFA 0x06bd AGFA-Gevaert -vendor ASIAMD 0x06be Asia Microelectronic Development -vendor BIZLINK 0x06c4 Bizlink International -vendor KEYSPAN 0x06cd Keyspan / InnoSys Inc. -vendor AASHIMA 0x06d6 Aashima Technology -vendor MULTITECH 0x06e0 MultiTech -vendor ADS 0x06e1 ADS Technologies -vendor ALCATELM 0x06e4 Alcatel Microelectronics -vendor SIRIUS 0x06ea Sirius Technologies -vendor GUILLEMOT 0x06f8 Guillemot -vendor BOSTON 0x06fd Boston Acoustics -vendor SMC 0x0707 Standard Microsystems -vendor PUTERCOM 0x0708 Putercom -vendor MCT 0x0711 MCT -vendor IMATION 0x0718 Imation -vendor SONYERICSSON 0x0731 Sony Ericsson -vendor EICON 0x0734 Eicon Networks -vendor SYNTECH 0x0745 Syntech Information -vendor DIGITALSTREAM 0x074e Digital Stream -vendor AUREAL 0x0755 Aureal Semiconductor -vendor MIDIMAN 0x0763 Midiman -vendor CYBERPOWER 0x0764 Cyber Power Systems, Inc. -vendor SURECOM 0x0769 Surecom Technology -vendor LINKSYS2 0x077b Linksys -vendor GRIFFIN 0x077d Griffin Technology -vendor SANDISK 0x0781 SanDisk -vendor JENOPTIK 0x0784 Jenoptik -vendor LOGITEC 0x0789 Logitec -vendor BRIMAX 0x078e Brimax -vendor AXIS 0x0792 Axis Communications -vendor ABL 0x0794 ABL Electronics -vendor SAGEM 0x079b Sagem -vendor SUNCOMM 0x079c Sun Communications, Inc. -vendor ALFADATA 0x079d Alfadata Computer -vendor NATIONALTECH 0x07a2 National Technical Systems -vendor ONNTO 0x07a3 Onnto -vendor BE 0x07a4 Be -vendor ADMTEK 0x07a6 ADMtek -vendor COREGA 0x07aa Corega -vendor FREECOM 0x07ab Freecom -vendor MICROTECH 0x07af Microtech -vendor GENERALINSTMNTS 0x07b2 General Instruments (Motorola) -vendor OLYMPUS 0x07b4 Olympus -vendor ABOCOM 0x07b8 AboCom Systems -vendor KEISOKUGIKEN 0x07c1 Keisokugiken -vendor ONSPEC 0x07c4 OnSpec -vendor APG 0x07c5 APG Cash Drawer -vendor BUG 0x07c8 B.U.G. -vendor ALLIEDTELESYN 0x07c9 Allied Telesyn International -vendor AVERMEDIA 0x07ca AVerMedia Technologies -vendor SIIG 0x07cc SIIG -vendor CASIO 0x07cf CASIO -vendor DLINK2 0x07d1 D-Link -vendor APTIO 0x07d2 Aptio Products -vendor ARASAN 0x07da Arasan Chip Systems -vendor ALLIEDCABLE 0x07e6 Allied Cable -vendor STSN 0x07ef STSN -vendor CENTURY 0x07f7 Century Corp -vendor ZOOM 0x0803 Zoom Telephonics -vendor PCS 0x0810 Personal Communication Systems -vendor BROADLOGIC 0x0827 BroadLogic -vendor HANDSPRING 0x082d Handspring -vendor PALM 0x0830 Palm Computing -vendor SOURCENEXT 0x0833 SOURCENEXT -vendor ACTIONSTAR 0x0835 Action Star Enterprise -vendor SAMSUNG_TECHWIN 0x0839 Samsung Techwin -vendor ACCTON 0x083a Accton Technology -vendor DIAMOND 0x0841 Diamond -vendor NETGEAR 0x0846 BayNETGEAR -vendor TOPRE 0x0853 Topre Corporation -vendor ACTIVEWIRE 0x0854 ActiveWire -vendor BBELECTRONICS 0x0856 B&B Electronics -vendor PORTGEAR 0x085a PortGear -vendor NETGEAR2 0x0864 Netgear -vendor SYSTEMTALKS 0x086e System Talks -vendor METRICOM 0x0870 Metricom -vendor ADESSOKBTEK 0x087c ADESSO/Kbtek America -vendor JATON 0x087d Jaton -vendor APT 0x0880 APT Technologies -vendor BOCARESEARCH 0x0885 Boca Research -vendor ANDREA 0x08a8 Andrea Electronics -vendor BURRBROWN 0x08bb Burr-Brown Japan -vendor 2WIRE 0x08c8 2Wire -vendor AIPTEK 0x08ca AIPTEK International -vendor SMARTBRIDGES 0x08d1 SmartBridges -vendor BILLIONTON 0x08dd Billionton Systems -vendor EXTENDED 0x08e9 Extended Systems -vendor MSYSTEMS 0x08ec M-Systems -vendor AUTHENTEC 0x08ff AuthenTec -vendor AUDIOTECHNICA 0x0909 Audio-Technica -vendor TRUMPION 0x090a Trumpion Microelectronics -vendor FEIYA 0x090c Feiya -vendor ALATION 0x0910 Alation Systems -vendor GLOBESPAN 0x0915 Globespan -vendor CONCORDCAMERA 0x0919 Concord Camera -vendor GARMIN 0x091e Garmin International -vendor GOHUBS 0x0921 GoHubs -vendor XEROX 0x0924 Xerox -vendor BIOMETRIC 0x0929 American Biometric Company -vendor TOSHIBA 0x0930 Toshiba -vendor PLEXTOR 0x093b Plextor -vendor INTREPIDCS 0x093c Intrepid -vendor YANO 0x094f Yano -vendor KINGSTON 0x0951 Kingston Technology -vendor BLUEWATER 0x0956 BlueWater Systems -vendor AGILENT 0x0957 Agilent Technologies -vendor GUDE 0x0959 Gude ADS -vendor PORTSMITH 0x095a Portsmith -vendor ACERW 0x0967 Acer -vendor ADIRONDACK 0x0976 Adirondack Wire & Cable -vendor BECKHOFF 0x0978 Beckhoff -vendor MINDSATWORK 0x097a Minds At Work -vendor POINTCHIPS 0x09a6 PointChips -vendor INTERSIL 0x09aa Intersil -vendor ALTIUS 0x09b3 Altius Solutions -vendor ARRIS 0x09c1 Arris Interactive -vendor ACTIVCARD 0x09c3 ACTIVCARD -vendor ACTISYS 0x09c4 ACTiSYS -vendor NOVATEL2 0x09d7 Novatel Wireless -vendor AFOURTECH 0x09da A-FOUR TECH -vendor AIMEX 0x09dc AIMEX -vendor ADDONICS 0x09df Addonics Technologies -vendor AKAI 0x09e8 AKAI professional M.I. -vendor ARESCOM 0x09f5 ARESCOM -vendor BAY 0x09f9 Bay Associates -vendor ALTERA 0x09fb Altera -vendor CSR 0x0a12 Cambridge Silicon Radio -vendor TREK 0x0a16 Trek Technology -vendor ASAHIOPTICAL 0x0a17 Asahi Optical -vendor BOCASYSTEMS 0x0a43 Boca Systems -vendor SHANTOU 0x0a46 ShanTou -vendor MEDIAGEAR 0x0a48 MediaGear -vendor BROADCOM 0x0a5c Broadcom -vendor GREENHOUSE 0x0a6b GREENHOUSE -vendor GEOCAST 0x0a79 Geocast Network Systems -vendor IDQUANTIQUE 0x0aba id Quantique -vendor ZYDAS 0x0ace Zydas Technology Corporation -vendor NEODIO 0x0aec Neodio -vendor OPTION 0x0af0 Option N.V: -vendor ASUS 0x0b05 ASUSTeK Computer -vendor TODOS 0x0b0c Todos Data System -vendor SIIG2 0x0b39 SIIG -vendor TEKRAM 0x0b3b Tekram Technology -vendor HAL 0x0b41 HAL Corporation -vendor EMS 0x0b43 EMS Production -vendor NEC2 0x0b62 NEC -vendor ATI2 0x0b6f ATI -vendor ZEEVO 0x0b7a Zeevo, Inc. -vendor KURUSUGAWA 0x0b7e Kurusugawa Electronics, Inc. -vendor ASIX 0x0b95 ASIX Electronics -vendor O2MICRO 0x0b97 O2 Micro, Inc. -vendor USR 0x0baf U.S. Robotics -vendor AMBIT 0x0bb2 Ambit Microsystems -vendor HTC 0x0bb4 HTC -vendor REALTEK 0x0bda Realtek -vendor ADDONICS2 0x0bf6 Addonics Technology -vendor FSC 0x0bf8 Fujitsu Siemens Computers -vendor AGATE 0x0c08 Agate Technologies -vendor DMI 0x0c0b DMI -vendor CHICONY2 0x0c45 Chicony -vendor SEALEVEL 0x0c52 Sealevel System -vendor LUWEN 0x0c76 Luwen -vendor KYOCERA2 0x0c88 Kyocera Wireless Corp. -vendor ZCOM 0x0cde Z-Com -vendor ATHEROS2 0x0cf3 Atheros Communications -vendor TANGTOP 0x0d3d Tangtop -vendor SMC3 0x0d5c Standard Microsystems -vendor ADDON 0x0d7d Add-on Technology -vendor ACDC 0x0d7e American Computer & Digital Components -vendor ABC 0x0d8c ABC -vendor CONCEPTRONIC 0x0d8e Conceptronic -vendor SKANHEX 0x0d96 Skanhex Technology, Inc. -vendor MSI 0x0db0 Micro Star International -vendor ELCON 0x0db7 ELCON Systemtechnik -vendor NETAC 0x0dd8 Netac -vendor SITECOMEU 0x0df6 Sitecom Europe -vendor MOBILEACTION 0x0df7 Mobile Action -vendor SPEEDDRAGON 0x0e55 Speed Dragon Multimedia -vendor HAWKING 0x0e66 Hawking -vendor FOSSIL 0x0e67 Fossil, Inc -vendor GMATE 0x0e7e G.Mate, Inc -vendor OTI 0x0ea0 Ours Technology -vendor YISO 0x0eab Yiso Wireless Co. -vendor PILOTECH 0x0eaf Pilotech -vendor NOVATECH 0x0eb0 NovaTech -vendor ITEGNO 0x0eba iTegno -vendor WINMAXGROUP 0x0ed1 WinMaxGroup -vendor TOD 0x0ede TOD -vendor EGALAX 0x0eef eGalax, Inc. -vendor AIRPRIME 0x0f3d AirPrime, Inc. -vendor MICROTUNE 0x0f4d Microtune -vendor VTECH 0x0f88 VTech -vendor FALCOM 0x0f94 Falcom Wireless Communications GmbH -vendor RIM 0x0fca Research In Motion -vendor DYNASTREAM 0x0fcf Dynastream Innovations -vendor QUALCOMM 0x1004 Qualcomm -vendor DESKNOTE 0x1019 Desknote -vendor GIGABYTE 0x1044 GIGABYTE -vendor WESTERN 0x1058 Western Digital -vendor MOTOROLA 0x1063 Motorola -vendor CCYU 0x1065 CCYU Technology -vendor CURITEL 0x106c Curitel Communications Inc -vendor SILABS2 0x10a6 SILABS2 -vendor USI 0x10ab USI -vendor PLX 0x10b5 PLX -vendor ASANTE 0x10bd Asante -vendor SILABS 0x10c4 Silicon Labs -vendor ANALOG 0x1110 Analog Devices -vendor TENX 0x1130 Ten X Technology, Inc. -vendor ISSC 0x1131 Integrated System Solution Corp. -vendor JRC 0x1145 Japan Radio Company -vendor SPHAIRON 0x114b Sphairon Access Systems GmbH -vendor DELORME 0x1163 DeLorme -vendor SERVERWORKS 0x1166 ServerWorks -vendor ACERCM 0x1189 Acer Communications & Multimedia -vendor SIERRA 0x1199 Sierra Wireless -vendor TOPFIELD 0x11db Topfield Co., Ltd -vendor SIEMENS3 0x11f5 Siemens -vendor PROLIFIC2 0x11f6 Prolific -vendor ALCATEL 0x11f7 Alcatel -vendor UNKNOWN3 0x1233 Unknown vendor -vendor TSUNAMI 0x1241 Tsunami -vendor PHEENET 0x124a Pheenet -vendor TARGUS 0x1267 Targus -vendor TWINMOS 0x126f TwinMOS -vendor TENDA 0x1286 Tenda -vendor CREATIVE2 0x1292 Creative Labs -vendor BELKIN2 0x1293 Belkin Components -vendor CYBERTAN 0x129b CyberTAN Technology -vendor HUAWEI 0x12d1 Huawei Technologies -vendor ARANEUS 0x12d8 Araneus Information Systems -vendor TAPWAVE 0x12ef Tapwave -vendor AINCOMM 0x12fd Aincomm -vendor MOBILITY 0x1342 Mobility -vendor DICKSMITH 0x1371 Dick Smith Electronics -vendor NETGEAR3 0x1385 Netgear -vendor BALTECH 0x13ad Baltech -vendor CISCOLINKSYS 0x13b1 Cisco-Linksys -vendor SHARK 0x13d2 Shark -vendor NOVATEL 0x1410 Novatel Wireless -vendor MERLIN 0x1416 Merlin -vendor WISTRONNEWEB 0x1435 Wistron NeWeb -vendor RADIOSHACK 0x1453 Radio Shack -vendor HUAWEI3COM 0x1472 Huawei-3Com -vendor SILICOM 0x1485 Silicom -vendor RALINK 0x148f Ralink Technology -vendor IMAGINATION 0x149a Imagination Technologies -vendor CONCEPTRONIC2 0x14b2 Conceptronic -vendor PLANEX3 0x14ea Planex Communications -vendor SILICONPORTALS 0x1527 Silicon Portals -vendor UBIQUAM 0x1529 UBIQUAM Co., Ltd. -vendor UBLOX 0x1546 U-blox -vendor PNY 0x154b PNY -vendor OQO 0x1557 OQO -vendor UMEDIA 0x157e U-MEDIA Communications -vendor FIBERLINE 0x1582 Fiberline -vendor SPARKLAN 0x15a9 SparkLAN -vendor SOHOWARE 0x15e8 SOHOware -vendor UMAX 0x1606 UMAX Data Systems -vendor INSIDEOUT 0x1608 Inside Out Networks -vendor GOODWAY 0x1631 Good Way Technology -vendor ENTREGA 0x1645 Entrega -vendor ACTIONTEC 0x1668 Actiontec Electronics -vendor ATHEROS 0x168c Atheros Communications -vendor GIGASET 0x1690 Gigaset -vendor GLOBALSUN 0x16ab Global Sun Technology -vendor ANYDATA 0x16d5 AnyDATA Corporation -vendor JABLOTRON 0x16d6 Jablotron -vendor CMOTECH 0x16d8 C-motech -vendor AXESSTEL 0x1726 Axesstel Co., Ltd. -vendor LINKSYS4 0x1737 Linksys -vendor SENAO 0x1740 Senao -vendor METAGEEK 0x1781 MetaGeek -vendor AMIT 0x18c5 AMIT -vendor QCOM 0x18e8 Qcom -vendor LINKSYS3 0x1915 Linksys -vendor QUALCOMMINC 0x19d2 Qualcomm, Incorporated -vendor STELERA 0x1a8d Stelera Wireless -vendor DRESDENELEKTRONIK 0x1cf1 dresden elektronik -vendor DLINK 0x2001 D-Link -vendor PLANEX2 0x2019 Planex Communications -vendor ERICSSON 0x2282 Ericsson -vendor MOTOROLA2 0x22b8 Motorola -vendor TRIPPLITE 0x2478 Tripp-Lite -vendor HIROSE 0x2631 Hirose Electric -vendor NHJ 0x2770 NHJ -vendor PLANEX 0x2c02 Planex Communications -vendor VIDZMEDIA 0x3275 VidzMedia Pte Ltd -vendor AEI 0x3334 AEI -vendor HANK 0x3353 Hank Connection -vendor PQI 0x3538 PQI -vendor DAISY 0x3579 Daisy Technology -vendor NI 0x3923 National Instruments -vendor MICRONET 0x3980 Micronet Communications -vendor IODATA2 0x40bb I-O Data -vendor IRIVER 0x4102 iRiver -vendor DELL 0x413c Dell -vendor WCH 0x4348 QinHeng Electronics -vendor ACEECA 0x4766 Aceeca -vendor AVERATEC 0x50c2 Averatec -vendor SWEEX 0x5173 Sweex -vendor ONSPEC2 0x55aa OnSpec Electronic Inc. -vendor ZINWELL 0x5a57 Zinwell -vendor SITECOM 0x6189 Sitecom -vendor ARKMICRO 0x6547 Arkmicro Technologies Inc. -vendor 3COM2 0x6891 3Com -vendor INTEL 0x8086 Intel -vendor SITECOM2 0x9016 Sitecom -vendor MOSCHIP 0x9710 MosChip Semiconductor -vendor 3COM3 0xa727 3Com -vendor HP2 0xf003 Hewlett Packard -vendor USRP 0xfffe GNU Radio USRP - -/* - * List of known products. Grouped by vendor. - */ - -/* 3Com products */ -product 3COM HOMECONN 0x009d HomeConnect Camera -product 3COM 3CREB96 0x00a0 Bluetooth USB Adapter -product 3COM 3C19250 0x03e8 3C19250 Ethernet Adapter -product 3COM 3CRSHEW696 0x0a01 3CRSHEW696 Wireless Adapter -product 3COM 3C460 0x11f8 HomeConnect 3C460 -product 3COM USR56K 0x3021 U.S.Robotics 56000 Voice FaxModem Pro -product 3COM 3C460B 0x4601 HomeConnect 3C460B -product 3COM2 3CRUSB10075 0xa727 3CRUSB10075 -product 3COM3 AR5523_1 0x6893 AR5523 -product 3COM3 AR5523_2 0x6895 AR5523 -product 3COM3 AR5523_3 0x6897 AR5523 - -product 3COMUSR OFFICECONN 0x0082 3Com OfficeConnect Analog Modem -product 3COMUSR USRISDN 0x008f 3Com U.S. Robotics Pro ISDN TA -product 3COMUSR HOMECONN 0x009d 3Com HomeConnect Camera -product 3COMUSR USR56K 0x3021 U.S. Robotics 56000 Voice FaxModem Pro - -/* AboCom products */ -product ABOCOM XX1 0x110c XX1 -product ABOCOM XX2 0x200c XX2 -product ABOCOM URE450 0x4000 URE450 Ethernet Adapter -product ABOCOM UFE1000 0x4002 UFE1000 Fast Ethernet Adapter -product ABOCOM DSB650TX_PNA 0x4003 1/10/100 Ethernet Adapter -product ABOCOM XX4 0x4004 XX4 -product ABOCOM XX5 0x4007 XX5 -product ABOCOM XX6 0x400b XX6 -product ABOCOM XX7 0x400c XX7 -product ABOCOM RTL8151 0x401a RTL8151 -product ABOCOM XX8 0x4102 XX8 -product ABOCOM XX9 0x4104 XX9 -product ABOCOM UF200 0x420a UF200 Ethernet -product ABOCOM WL54 0x6001 WL54 -product ABOCOM XX10 0xabc1 XX10 -product ABOCOM BWU613 0xb000 BWU613 -product ABOCOM HWU54DM 0xb21b HWU54DM -product ABOCOM RT2573_2 0xb21c RT2573 -product ABOCOM RT2573_3 0xb21d RT2573 -product ABOCOM RT2573_4 0xb21e RT2573 -product ABOCOM WUG2700 0xb21f WUG2700 - -/* Accton products */ -product ACCTON USB320_EC 0x1046 USB320-EC Ethernet Adapter -product ACCTON 2664W 0x3501 2664W -product ACCTON 111 0x3503 T-Sinus 111 Wireless Adapter -product ACCTON SMCWUSBG 0x4505 SMCWUSB-G -product ACCTON PRISM_GT 0x4521 PrismGT USB 2.0 WLAN -product ACCTON SS1001 0x5046 SpeedStream Ethernet Adapter -product ACCTON ZD1211B 0xe501 ZD1211B - -/* Aceeca products */ -product ACEECA MEZ1000 0x0001 MEZ1000 RDA - -/* Acer Communications & Multimedia (oemd by Surecom) */ -product ACERCM EP1427X2 0x0893 EP-1427X-2 Ethernet Adapter - -/* Acer Labs products */ -product ACERLABS M5632 0x5632 USB 2.0 Data Link - -/* Acer Peripherals, Inc. products */ -product ACERP ACERSCAN_C310U 0x12a6 Acerscan C310U -product ACERP ACERSCAN_320U 0x2022 Acerscan 320U -product ACERP ACERSCAN_640U 0x2040 Acerscan 640U -product ACERP ACERSCAN_620U 0x2060 Acerscan 620U -product ACERP ACERSCAN_4300U 0x20b0 Benq 3300U/4300U -product ACERP ACERSCAN_640BT 0x20be Acerscan 640BT -product ACERP ACERSCAN_1240U 0x20c0 Acerscan 1240U -product ACERP ATAPI 0x6003 ATA/ATAPI Adapter -product ACERP AWL300 0x9000 AWL300 Wireless Adapter -product ACERP AWL400 0x9001 AWL400 Wireless Adapter - -/* Acer Warp products */ -product ACERW WARPLINK 0x0204 Warplink - -/* Actiontec, Inc. products */ -product ACTIONTEC PRISM_25 0x0408 Prism2.5 Wireless Adapter -product ACTIONTEC PRISM_25A 0x0421 Prism2.5 Wireless Adapter A -product ACTIONTEC FREELAN 0x6106 ROPEX FreeLan 802.11b -product ACTIONTEC UAT1 0x7605 UAT1 Wireless Ethernet Adapter - -/* ACTiSYS products */ -product ACTISYS IR2000U 0x0011 ACT-IR2000U FIR - -/* ActiveWire, Inc. products */ -product ACTIVEWIRE IOBOARD 0x0100 I/O Board -product ACTIVEWIRE IOBOARD_FW1 0x0101 I/O Board, rev. 1 firmware - -/* Adaptec products */ -product ADAPTEC AWN8020 0x0020 AWN-8020 WLAN - -/* Addtron products */ -product ADDTRON AWU120 0xff31 AWU-120 - -/* ADMtek products */ -product ADMTEK PEGASUSII_4 0x07c2 AN986A Ethernet -product ADMTEK PEGASUS 0x0986 AN986 Ethernet -product ADMTEK PEGASUSII 0x8511 AN8511 Ethernet -product ADMTEK PEGASUSII_2 0x8513 AN8513 Ethernet -product ADMTEK PEGASUSII_3 0x8515 AN8515 Ethernet - -/* ADDON products */ -/* PNY OEMs these */ -product ADDON ATTACHE 0x1300 USB 2.0 Flash Drive -product ADDON ATTACHE 0x1300 USB 2.0 Flash Drive -product ADDON A256MB 0x1400 Attache 256MB USB 2.0 Flash Drive -product ADDON DISKPRO512 0x1420 USB 2.0 Flash Drive (DANE-ELEC zMate 512MB USB flash drive) - -/* Addonics products */ -product ADDONICS2 CABLE_205 0xa001 Cable 205 - -/* ADS products */ -product ADS UBS10BT 0x0008 UBS-10BT Ethernet -product ADS UBS10BTX 0x0009 UBS-10BT Ethernet - -/* AEI products */ -product AEI FASTETHERNET 0x1701 Fast Ethernet - -/* Agate Technologies products */ -product AGATE QDRIVE 0x0378 Q-Drive - -/* AGFA products */ -product AGFA SNAPSCAN1212U 0x0001 SnapScan 1212U -product AGFA SNAPSCAN1236U 0x0002 SnapScan 1236U -product AGFA SNAPSCANTOUCH 0x0100 SnapScan Touch -product AGFA SNAPSCAN1212U2 0x2061 SnapScan 1212U -product AGFA SNAPSCANE40 0x208d SnapScan e40 -product AGFA SNAPSCANE50 0x208f SnapScan e50 -product AGFA SNAPSCANE20 0x2091 SnapScan e20 -product AGFA SNAPSCANE25 0x2095 SnapScan e25 -product AGFA SNAPSCANE26 0x2097 SnapScan e26 -product AGFA SNAPSCANE52 0x20fd SnapScan e52 - -/* Ain Communication Technology products */ -product AINCOMM AWU2000B 0x1001 AWU2000B Wireless Adapter - -/* AIPTEK products */ -product AIPTEK POCKETCAM3M 0x2011 PocketCAM 3Mega -product AIPTEK2 PENCAM_MEGA_1_3 0x504a PenCam Mega 1.3 - -/* AirPrime products */ -product AIRPRIME PC5220 0x0112 CDMA Wireless PC Card - -/* AKS products */ -product AKS USBHASP 0x0001 USB-HASP 0.06 - -/* Alcor Micro, Inc. products */ -product ALCOR2 KBD_HUB 0x2802 Kbd Hub - -product ALCOR TRANSCEND 0x6387 Transcend JetFlash Drive -product ALCOR MA_KBD_HUB 0x9213 MacAlly Kbd Hub -product ALCOR AU9814 0x9215 AU9814 Hub -product ALCOR UMCR_9361 0x9361 USB Multimedia Card Reader -product ALCOR SM_KBD 0x9410 MicroConnectors/StrongMan Keyboard -product ALCOR NEC_KBD_HUB 0x9472 NEC Kbd Hub - -/* Altec Lansing products */ -product ALTEC ADA70 0x0070 ADA70 Speakers -product ALTEC ASC495 0xff05 ASC495 Speakers - -/* Allied Telesyn International products */ -product ALLIEDTELESYN ATUSB100 0xb100 AT-USB100 - -/* American Power Conversion products */ -product APC UPS 0x0002 Uninterruptible Power Supply - -/* Ambit Microsystems products */ -product AMBIT WLAN 0x0302 WLAN -product AMBIT NTL_250 0x6098 NTL 250 cable modem - -/* AMIT products */ -product AMIT CGWLUSB2GO 0x0002 CG-WLUSB2GO - -/* Anchor products */ -product ANCHOR EZUSB 0x2131 EZUSB -product ANCHOR EZLINK 0x2720 EZLINK - -/* AnyData products */ -product ANYDATA ADU_E100X 0x6501 CDMA 2000 1xRTT/EV-DO USB Modem -product ANYDATA ADU_500A 0x6502 CDMA 2000 EV-DO USB Modem - -/* AOX, Inc. products */ -product AOX USB101 0x0008 Ethernet - -/* American Power Conversion products */ -product APC UPS 0x0002 Uninterruptible Power Supply - -/* Apple Computer products */ -product APPLE EXT_KBD 0x020c Apple Extended USB Keyboard -product APPLE OPTMOUSE 0x0302 Optical mouse -product APPLE MIGHTYMOUSE 0x0304 Mighty Mouse -product APPLE EXT_KBD_HUB 0x1003 Hub in Apple Extended USB Keyboard -product APPLE SPEAKERS 0x1101 Speakers -product APPLE IPOD 0x1201 iPod -product APPLE IPOD2G 0x1202 iPod 2G -product APPLE IPOD3G 0x1203 iPod 3G -product APPLE IPOD_04 0x1204 iPod '04' -product APPLE IPODMINI 0x1205 iPod Mini -product APPLE IPOD_06 0x1206 iPod '06' -product APPLE IPOD_07 0x1207 iPod '07' -product APPLE IPOD_08 0x1208 iPod '08' -product APPLE IPODVIDEO 0x1209 iPod Video -product APPLE IPODNANO 0x120a iPod Nano -product APPLE IPHONE 0x1290 iPhone -product APPLE IPHONE_3G 0x1292 iPhone 3G -product APPLE ETHERNET 0x1402 Ethernet A1277 - -/* Arkmicro Technologies */ -product ARKMICRO ARK3116 0x0232 ARK3116 Serial - -/* Asahi Optical products */ -product ASAHIOPTICAL OPTIO230 0x0004 Digital camera -product ASAHIOPTICAL OPTIO330 0x0006 Digital camera - -/* Asante products */ -product ASANTE EA 0x1427 Ethernet - -/* ASIX Electronics products */ -product ASIX AX88172 0x1720 10/100 Ethernet -product ASIX AX88178 0x1780 AX88178 -product ASIX AX88772 0x7720 AX88772 - -/* ASUS products */ -product ASUS WL167G 0x1707 WL-167g Wireless Adapter -product ASUS WL159G 0x170c WL-159g -product ASUS A9T_WIFI 0x171b A9T wireless -product ASUS RT2573_1 0x1723 RT2573 -product ASUS RT2573_2 0x1724 RT2573 -product ASUS LCM 0x1726 LCM display -product ASUS P535 0x420f ASUS P535 PDA - -/* ATen products */ -product ATEN UC1284 0x2001 Parallel printer -product ATEN UC10T 0x2002 10Mbps Ethernet -product ATEN UC110T 0x2007 UC-110T Ethernet -product ATEN UC232A 0x2008 Serial -product ATEN UC210T 0x2009 UC-210T Ethernet -product ATEN DSB650C 0x4000 DSB-650C - -/* Atheros Communications products */ -product ATHEROS AR5523 0x0001 AR5523 -product ATHEROS AR5523_NF 0x0002 AR5523 (no firmware) -product ATHEROS2 AR5523_1 0x0001 AR5523 -product ATHEROS2 AR5523_1_NF 0x0002 AR5523 (no firmware) -product ATHEROS2 AR5523_2 0x0003 AR5523 -product ATHEROS2 AR5523_2_NF 0x0004 AR5523 (no firmware) -product ATHEROS2 AR5523_3 0x0005 AR5523 -product ATHEROS2 AR5523_3_NF 0x0006 AR5523 (no firmware) - -/* Atmel Comp. products */ -product ATMEL UHB124 0x3301 UHB124 hub -product ATMEL DWL120 0x7603 DWL-120 Wireless Adapter -product ATMEL BW002 0x7605 BW002 Wireless Adapter -product ATMEL WL1130USB 0x7613 WL-1130 USB -product ATMEL AT76C505A 0x7614 AT76c505a Wireless Adapter - -/* Avision products */ -product AVISION 1200U 0x0268 1200U scanner - -/* Axesstel products */ -product AXESSTEL DATAMODEM 0x1000 Data Modem - -/* Baltech products */ -product BALTECH CARDREADER 0x9999 Card reader - -/* B&B Electronics products */ -product BBELECTRONICS USOTL4 0xAC01 RS-422/485 - -/* Belkin products */ -/*product BELKIN F5U111 0x???? F5U111 Ethernet*/ -product BELKIN F5D6050 0x0050 F5D6050 802.11b Wireless Adapter -product BELKIN FBT001V 0x0081 FBT001v2 Bluetooth -product BELKIN FBT003V 0x0084 FBT003v2 Bluetooth -product BELKIN F5U103 0x0103 F5U103 Serial -product BELKIN F5U109 0x0109 F5U109 Serial -product BELKIN USB2SCSI 0x0115 USB to SCSI -product BELKIN F8T012 0x0121 F8T012xx1 Bluetooth USB Adapter -product BELKIN USB2LAN 0x0121 USB to LAN -product BELKIN F5U208 0x0208 F5U208 VideoBus II -product BELKIN F5U237 0x0237 F5U237 USB 2.0 7-Port Hub -product BELKIN F5U257 0x0257 F5U257 Serial -product BELKIN F5U409 0x0409 F5U409 Serial -product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS -product BELKIN F5U120 0x1203 F5U120-PC Hub -product BELKIN ZD1211B 0x4050 ZD1211B -product BELKIN F5D5055 0x5055 F5D5055 -product BELKIN F5D7050 0x7050 F5D7050 Wireless Adapter -product BELKIN F5D7051 0x7051 F5D7051 54g USB Network Adapter -product BELKIN F5D7050A 0x705a F5D7050A Wireless Adapter -/* Also sold as 'Ativa 802.11g wireless card' */ -product BELKIN F5D7050_V4000 0x705c F5D7050 v4000 Wireless Adapter -product BELKIN F5D9050V3 0x905b F5D9050 ver 3 Wireless Adapter -product BELKIN2 F5U002 0x0002 F5U002 Parallel printer - -/* Billionton products */ -product BILLIONTON USB100 0x0986 USB100N 10/100 FastEthernet -product BILLIONTON USBLP100 0x0987 USB100LP -product BILLIONTON USBEL100 0x0988 USB100EL -product BILLIONTON USBE100 0x8511 USBE100 -product BILLIONTON USB2AR 0x90ff USB2AR Ethernet - -/* Broadcom products */ -product BROADCOM BCM2033 0x2033 BCM2033 Bluetooth USB dongle - -/* Brother Industries products */ -product BROTHER HL1050 0x0002 HL-1050 laser printer - -/* Behavior Technology Computer products */ -product BTC BTC7932 0x6782 Keyboard with mouse port - -/* Canon, Inc. products */ -product CANON N656U 0x2206 CanoScan N656U -product CANON N1220U 0x2207 CanoScan N1220U -product CANON D660U 0x2208 CanoScan D660U -product CANON N676U 0x220d CanoScan N676U -product CANON N1240U 0x220e CanoScan N1240U -product CANON LIDE25 0x2220 CanoScan LIDE 25 -product CANON S10 0x3041 PowerShot S10 -product CANON S100 0x3045 PowerShot S100 -product CANON S200 0x3065 PowerShot S200 -product CANON REBELXT 0x30ef Digital Rebel XT - -/* CATC products */ -product CATC NETMATE 0x000a Netmate Ethernet -product CATC NETMATE2 0x000c Netmate2 Ethernet -product CATC CHIEF 0x000d USB Chief Bus & Protocol Analyzer -product CATC ANDROMEDA 0x1237 Andromeda hub - -/* CASIO products */ -product CASIO QV_DIGICAM 0x1001 QV DigiCam -product CASIO EXS880 0x1105 Exilim EX-S880 -product CASIO BE300 0x2002 BE-300 PDA -product CASIO NAMELAND 0x4001 CASIO Nameland EZ-USB - -/* CCYU products */ -product CCYU ED1064 0x2136 EasyDisk ED1064 - -/* Century products */ -product CENTURY EX35QUAT 0x011e Century USB Disk Enclosure - -/* Cherry products */ -product CHERRY MY3000KBD 0x0001 My3000 keyboard -product CHERRY MY3000HUB 0x0003 My3000 hub -product CHERRY CYBOARD 0x0004 CyBoard Keyboard - -/* Chic Technology products */ -product CHIC MOUSE1 0x0001 mouse -product CHIC CYPRESS 0x0003 Cypress USB Mouse - -/* Chicony products */ -product CHICONY KB8933 0x0001 KB-8933 keyboard -product CHICONY2 TWINKLECAM 0x600d TwinkleCam USB camera - -/* CH Products */ -product CHPRODUCTS PROTHROTTLE 0x00f1 Pro Throttle -product CHPRODUCTS PROPEDALS 0x00f2 Pro Pedals -product CHPRODUCTS FIGHTERSTICK 0x00f3 Fighterstick -product CHPRODUCTS FLIGHTYOKE 0x00ff Flight Sim Yoke - -/* Cisco-Linksys products */ -product CISCOLINKSYS WUSB54G 0x000d WUSB54G Wireless Adapter -product CISCOLINKSYS WUSB54GP 0x0011 WUSB54GP Wireless Adapter -product CISCOLINKSYS USB200MV2 0x0018 USB200M v2 -product CISCOLINKSYS HU200TS 0x001a HU200TS Wireless Adapter -product CISCOLINKSYS WUSB54GC 0x0020 WUSB54GC -product CISCOLINKSYS WUSB54GR 0x0023 WUSB54GR -product CISCOLINKSYS WUSBF54G 0x0024 WUSBF54G - -/* CMOTECH products */ -product CMOTECH CNU510 0x5141 CDMA Technologies USB modem -product CMOTECH CNU550 0x5543 CDMA 2000 1xRTT/1xEVDO USB modem -product CMOTECH CGU628 0x6006 CGU-628 -product CMOTECH CDMA_MODEM1 0x6280 CDMA Technologies USB modem -product CMOTECH DISK 0xf000 disk mode - -/* Compaq products */ -product COMPAQ IPAQPOCKETPC 0x0003 iPAQ PocketPC -product COMPAQ PJB100 0x504a Personal Jukebox PJB100 -product COMPAQ IPAQLINUX 0x505a iPAQ Linux - -/* Composite Corp products looks the same as "TANGTOP" */ -product COMPOSITE USBPS2 0x0001 USB to PS2 Adaptor - -/* Conceptronic products */ -product CONCEPTRONIC PRISM_GT 0x3762 PrismGT USB 2.0 WLAN -product CONCEPTRONIC C11U 0x7100 C11U -product CONCEPTRONIC WL210 0x7110 WL-210 -product CONCEPTRONIC AR5523_1 0x7801 AR5523 -product CONCEPTRONIC AR5523_1_NF 0x7802 AR5523 (no firmware) -product CONCEPTRONIC AR5523_2 0x7811 AR5523 -product CONCEPTRONIC AR5523_2_NF 0x7812 AR5523 (no firmware) -product CONCEPTRONIC2 C54RU 0x3c02 C54RU WLAN -product CONCEPTRONIC2 C54RU2 0x3c22 C54RU - -/* Connectix products */ -product CONNECTIX QUICKCAM 0x0001 QuickCam - -/* Corega products */ -product COREGA ETHER_USB_T 0x0001 Ether USB-T -product COREGA FETHER_USB_TX 0x0004 FEther USB-TX -product COREGA WLAN_USB_USB_11 0x000c WirelessLAN USB-11 -product COREGA FETHER_USB_TXS 0x000d FEther USB-TXS -product COREGA WLANUSB 0x0012 Wireless LAN Stick-11 -product COREGA FETHER_USB2_TX 0x0017 FEther USB2-TX -product COREGA WLUSB_11_KEY 0x001a ULUSB-11 Key -product COREGA CGWLUSB2GL 0x002d CG-WLUSB2GL -product COREGA CGWLUSB2GPX 0x002e CG-WLUSB2GPX -product COREGA WLUSB_11_STICK 0x7613 WLAN USB Stick 11 -product COREGA FETHER_USB_TXC 0x9601 FEther USB-TXC - -/* Creative products */ -product CREATIVE NOMAD_II 0x1002 Nomad II MP3 player -product CREATIVE NOMAD_IIMG 0x4004 Nomad II MG -product CREATIVE NOMAD 0x4106 Nomad -product CREATIVE2 VOIP_BLASTER 0x0258 Voip Blaster -product CREATIVE3 OPTICAL_MOUSE 0x0001 Notebook Optical Mouse - -/* Cambridge Silicon Radio Ltd. products */ -product CSR BT_DONGLE 0x0001 Bluetooth USB dongle -product CSR CSRDFU 0xffff USB Bluetooth Device in DFU State - -/* CTX products */ -product CTX EX1300 0x9999 Ex1300 hub - -/* Curitel products */ -product CURITEL HX550C 0x1101 CDMA 2000 1xRTT USB modem (HX-550C) -product CURITEL HX57XB 0x2101 CDMA 2000 1xRTT USB modem (HX-570/575B/PR-600) -product CURITEL PC5740 0x3701 Broadband Wireless modem - -/* CyberPower products */ -product CYBERPOWER 1500CAVRLCD 0x0501 1500CAVRLCD - -/* CyberTAN Technology products */ -product CYBERTAN TG54USB 0x1666 TG54USB - -/* Cypress Semiconductor products */ -product CYPRESS MOUSE 0x0001 mouse -product CYPRESS THERMO 0x0002 thermometer -product CYPRESS WISPY1A 0x0bad MetaGeek Wi-Spy -product CYPRESS KBDHUB 0x0101 Keyboard/Hub -product CYPRESS FMRADIO 0x1002 FM Radio -product CYPRESS USBRS232 0x5500 USB-RS232 Interface -product CYPRESS SLIM_HUB 0x6560 Slim Hub - -/* Daisy Technology products */ -product DAISY DMC 0x6901 USB MultiMedia Reader - -/* Dallas Semiconductor products */ -product DALLAS J6502 0x4201 J-6502 speakers - -/* Dell products */ -product DELL PORT 0x0058 Port Replicator -product DELL AIO926 0x5115 Photo AIO Printer 926 -product DELL BC02 0x8000 BC02 Bluetooth USB Adapter -product DELL PRISM_GT_1 0x8102 PrismGT USB 2.0 WLAN -product DELL TM350 0x8103 TrueMobile 350 Bluetooth USB Adapter -product DELL PRISM_GT_2 0x8104 PrismGT USB 2.0 WLAN -product DELL U740 0x8135 Dell U740 CDMA - -/* Delorme Paublishing products */ -product DELORME EARTHMATE 0x0100 Earthmate GPS - -/* Desknote products */ -product DESKNOTE UCR_61S2B 0x0c55 UCR-61S2B - -/* Diamond products */ -product DIAMOND RIO500USB 0x0001 Rio 500 USB - -/* Dick Smith Electronics (really C-Net) products */ -product DICKSMITH RT2573 0x9022 RT2573 -product DICKSMITH CWD854F 0x9032 C-Net CWD-854 rev F - -/* Digi International products */ -product DIGI ACCELEPORT2 0x0002 AccelePort USB 2 -product DIGI ACCELEPORT4 0x0004 AccelePort USB 4 -product DIGI ACCELEPORT8 0x0008 AccelePort USB 8 - -/* D-Link products */ -/*product DLINK DSBS25 0x0100 DSB-S25 serial*/ -product DLINK DUBE100 0x1a00 10/100 Ethernet -product DLINK DSB650TX4 0x200c 10/100 Ethernet -product DLINK DWL120E 0x3200 DWL-120 rev E -product DLINK DWL122 0x3700 DWL-122 -product DLINK DWLG120 0x3701 DWL-G120 -product DLINK DWL120F 0x3702 DWL-120 rev F -product DLINK DWLAG132 0x3a00 DWL-AG132 -product DLINK DWLAG132_NF 0x3a01 DWL-AG132 (no firmware) -product DLINK DWLG132 0x3a02 DWL-G132 -product DLINK DWLG132_NF 0x3a03 DWL-G132 (no firmware) -product DLINK DWLAG122 0x3a04 DWL-AG122 -product DLINK DWLAG122_NF 0x3a05 DWL-AG122 (no firmware) -product DLINK DWLG122 0x3c00 DWL-G122 b1 Wireless Adapter -product DLINK DUBE100B1 0x3c05 DUB-E100 rev B1 -product DLINK DSB650C 0x4000 10Mbps Ethernet -product DLINK DSB650TX1 0x4001 10/100 Ethernet -product DLINK DSB650TX 0x4002 10/100 Ethernet -product DLINK DSB650TX_PNA 0x4003 1/10/100 Ethernet -product DLINK DSB650TX3 0x400b 10/100 Ethernet -product DLINK DSB650TX2 0x4102 10/100 Ethernet -product DLINK DSB650 0xabc1 10/100 Ethernet -product DLINK2 DWLG122C1 0x3c03 DWL-G122 c1 -product DLINK2 WUA1340 0x3c04 WUA-1340 -product DLINK2 DWA111 0x3c06 DWA-111 -product DLINK2 DWA110 0x3c07 DWA-110 - -/* DMI products */ -product DMI CFSM_RW 0xa109 CF/SM Reader/Writer - -/* DrayTek products */ -product DRAYTEK VIGOR550 0x0550 Vigor550 - -/* dresden elektronik products */ -product DRESDENELEKTRONIK SENSORTERMINALBOARD 0x0001 SensorTerminalBoard - -/* Dynastream Innovations */ -product DYNASTREAM ANTDEVBOARD 0x1003 ANT dev board - -/* EIZO products */ -product EIZO HUB 0x0000 hub -product EIZO MONITOR 0x0001 monitor - -/* ELCON Systemtechnik products */ -product ELCON PLAN 0x0002 Goldpfeil P-LAN - -/* Elecom products */ -product ELECOM MOUSE29UO 0x0002 mouse 29UO -product ELECOM LDUSBTX0 0x200c LD-USB/TX -product ELECOM LDUSBTX1 0x4002 LD-USB/TX -product ELECOM LDUSBLTX 0x4005 LD-USBL/TX -product ELECOM LDUSBTX2 0x400b LD-USB/TX -product ELECOM LDUSB20 0x4010 LD-USB20 -product ELECOM UCSGT 0x5003 UC-SGT -product ELECOM UCSGT0 0x5004 UC-SGT -product ELECOM LDUSBTX3 0xabc1 LD-USB/TX - -/* Elsa products */ -product ELSA MODEM1 0x2265 ELSA Modem Board -product ELSA USB2ETHERNET 0x3000 Microlink USB2Ethernet - -/* EMS products */ -product EMS DUAL_SHOOTER 0x0003 PSX gun controller converter - -/* Entrega products */ -product ENTREGA 1S 0x0001 1S serial -product ENTREGA 2S 0x0002 2S serial -product ENTREGA 1S25 0x0003 1S25 serial -product ENTREGA 4S 0x0004 4S serial -product ENTREGA E45 0x0005 E45 Ethernet -product ENTREGA CENTRONICS 0x0006 Parallel Port -product ENTREGA XX1 0x0008 Ethernet -product ENTREGA 1S9 0x0093 1S9 serial -product ENTREGA EZUSB 0x8000 EZ-USB -/*product ENTREGA SERIAL 0x8001 DB25 Serial*/ -product ENTREGA 2U4S 0x8004 2U4S serial/usb hub -product ENTREGA XX2 0x8005 Ethernet -/*product ENTREGA SERIAL_DB9 0x8093 DB9 Serial*/ - -/* Epson products */ -product EPSON PRINTER1 0x0001 USB Printer -product EPSON PRINTER2 0x0002 ISD USB Smart Cable for Mac -product EPSON PRINTER3 0x0003 ISD USB Smart Cable -product EPSON PRINTER5 0x0005 USB Printer -product EPSON 636 0x0101 Perfection 636U / 636Photo scanner -product EPSON 610 0x0103 Perfection 610 scanner -product EPSON 1200 0x0104 Perfection 1200U / 1200Photo scanner -product EPSON 1600 0x0107 Expression 1600 scanner -product EPSON 1640 0x010a Perfection 1640SU scanner -product EPSON 1240 0x010b Perfection 1240U / 1240Photo scanner -product EPSON 640U 0x010c Perfection 640U scanner -product EPSON 1250 0x010f Perfection 1250U / 1250Photo scanner -product EPSON 1650 0x0110 Perfection 1650 scanner -product EPSON GT9700F 0x0112 GT-9700F scanner -product EPSON GT9300UF 0x011b GT-9300UF scanner -product EPSON 3200 0x011c Perfection 3200 scanner -product EPSON 1260 0x011d Perfection 1260 scanner -product EPSON 1660 0x011e Perfection 1660 scanner -product EPSON 1670 0x011f Perfection 1670 scanner -product EPSON 1270 0x0120 Perfection 1270 scanner -product EPSON 2480 0x0121 Perfection 2480 scanner -product EPSON 3590 0x0122 Perfection 3590 scanner -product EPSON 4990 0x012a Perfection 4990 Photo scanner -product EPSON STYLUS_875DC 0x0601 Stylus Photo 875DC Card Reader -product EPSON STYLUS_895 0x0602 Stylus Photo 895 Card Reader -product EPSON CX5400 0x0808 CX5400 scanner -product EPSON 3500 0x080e CX-3500/3600/3650 MFP -product EPSON RX425 0x080f Stylus Photo RX425 scanner -product EPSON DX3800 0x0818 CX3700/CX3800/DX38x0 MFP scanner -product EPSON 4800 0x0819 CX4700/CX4800/DX48x0 MFP scanner -product EPSON 4200 0x0820 CX4100/CX4200/DX4200 MFP scanner -product EPSON 5000 0x082b CX4900/CX5000/DX50x0 MFP scanner -product EPSON 6000 0x082e CX5900/CX6000/DX60x0 MFP scanner -product EPSON DX4000 0x082f DX4000 MFP scanner -product EPSON DX7400 0x0838 CX7300/CX7400/DX7400 MFP scanner -product EPSON DX8400 0x0839 CX8300/CX8400/DX8400 MFP scanner -product EPSON SX100 0x0841 SX100/NX100 MFP scanner -product EPSON NX300 0x0848 NX300 MFP scanner -product EPSON SX200 0x0849 SX200/SX205 MFP scanner -product EPSON SX400 0x084a SX400/NX400/TX400 MFP scanner - -/* e-TEK Labs products */ -product ETEK 1COM 0x8007 Serial - -/* Extended Systems products */ -product EXTENDED XTNDACCESS 0x0100 XTNDAccess IrDA - -/* FEIYA products */ -product FEIYA 5IN1 0x1132 5-in-1 Card Reader - -/* Fiberline */ -product FIBERLINE WL430U 0x6003 WL-430U - -/* Fossil, Inc products */ -product FOSSIL WRISTPDA 0x0002 Wrist PDA - -/* Freecom products */ -product FREECOM DVD 0xfc01 DVD drive - -/* Fujitsu Siemens Computers products */ -product FSC E5400 0x1009 PrismGT USB 2.0 WLAN - -/* Future Technology Devices products */ -product FTDI SERIAL_8U100AX 0x8372 8U100AX Serial -product FTDI SERIAL_8U232AM 0x6001 8U232AM Serial -product FTDI SERIAL_2232C 0x6010 FT2232C Dual port Serial -/* Gude Analog- und Digitalsysteme products also uses FTDI's id: */ -product FTDI TACTRIX_OPENPORT_13M 0xcc48 OpenPort 1.3 Mitsubishi -product FTDI TACTRIX_OPENPORT_13S 0xcc49 OpenPort 1.3 Subaru -product FTDI TACTRIX_OPENPORT_13U 0xcc4a OpenPort 1.3 Universal -product FTDI EISCOU 0xe888 Expert ISDN Control USB -product FTDI UOPTBR 0xe889 USB-RS232 OptoBridge -product FTDI EMCU2D 0xe88a Expert mouseCLOCK USB II -product FTDI PCMSFU 0xe88b Precision Clock MSF USB -product FTDI EMCU2H 0xe88c Expert mouseCLOCK USB II HBG -product FTDI MAXSTREAM 0xee18 Maxstream PKG-U -product FTDI USBSERIAL 0xfa00 Matrix Orbital USB Serial -product FTDI MX2_3 0xfa01 Matrix Orbital MX2 or MX3 -product FTDI MX4_5 0xfa02 Matrix Orbital MX4 or MX5 -product FTDI LK202 0xfa03 Matrix Orbital VK/LK202 Family -product FTDI LK204 0xfa04 Matrix Orbital VK/LK204 Family -product FTDI CFA_632 0xfc08 Crystalfontz CFA-632 USB LCD -product FTDI CFA_634 0xfc09 Crystalfontz CFA-634 USB LCD -product FTDI CFA_633 0xfc0b Crystalfontz CFA-633 USB LCD -product FTDI CFA_631 0xfc0c Crystalfontz CFA-631 USB LCD -product FTDI CFA_635 0xfc0d Crystalfontz CFA-635 USB LCD -product FTDI SEMC_DSS20 0xfc82 SEMC DSS-20 SyncStation - -/* Fuji photo products */ -product FUJIPHOTO MASS0100 0x0100 Mass Storage - -/* Fujitsu protducts */ -product FUJITSU AH_F401U 0x105b AH-F401U Air H device - -/* Garmin products */ -product GARMIN IQUE_3600 0x0004 iQue 3600 - -/* General Instruments (Motorola) products */ -product GENERALINSTMNTS SB5100 0x5100 SURFboard SB5100 Cable modem - -/* Genesys Logic products */ -product GENESYS GL620USB 0x0501 GL620USB Host-Host interface -product GENESYS GL650 0x0604 GL650 Hub -product GENESYS GL641USB 0x0700 GL641USB CompactFlash Card Reader -product GENESYS GL641USB2IDE_2 0x0701 GL641USB USB-IDE Bridge No 2 -product GENESYS GL641USB2IDE 0x0702 GL641USB USB-IDE Bridge -product GENESYS GL641USB_2 0x0760 GL641USB 6-in-1 Card Reader - -/* GIGABYTE products */ -product GIGABYTE GN54G 0x8001 GN-54G -product GIGABYTE GNBR402W 0x8002 GN-BR402W -product GIGABYTE GNWLBM101 0x8003 GN-WLBM101 -product GIGABYTE GNWBKG 0x8007 GN-WBKG -product GIGABYTE GNWB01GS 0x8008 GN-WB01GS -product GIGABYTE GNWI05GS 0x800a GN-WI05GS - -/* Gigaset products */ -product GIGASET WLAN 0x0701 WLAN -product GIGASET SMCWUSBTG 0x0710 SMCWUSBT-G -product GIGASET SMCWUSBTG_NF 0x0711 SMCWUSBT-G (no firmware) -product GIGASET AR5523 0x0712 AR5523 -product GIGASET AR5523_NF 0x0713 AR5523 (no firmware) -product GIGASET RT2573 0x0722 RT2573 - -/* Global Sun Technology product */ -product GLOBALSUN AR5523_1 0x7801 AR5523 -product GLOBALSUN AR5523_1_NF 0x7802 AR5523 (no firmware) -product GLOBALSUN AR5523_2 0x7811 AR5523 -product GLOBALSUN AR5523_2_NF 0x7812 AR5523 (no firmware) - -/* Globespan products */ -product GLOBESPAN PRISM_GT_1 0x2000 PrismGT USB 2.0 WLAN -product GLOBESPAN PRISM_GT_2 0x2002 PrismGT USB 2.0 WLAN - -/* G.Mate, Inc products */ -product GMATE YP3X00 0x1001 YP3X00 PDA - -/* GoHubs products */ -product GOHUBS GOCOM232 0x1001 GoCOM232 Serial - -/* Good Way Technology products */ -product GOODWAY GWUSB2E 0x6200 GWUSB2E -product GOODWAY RT2573 0xc019 RT2573 - -/* Gravis products */ -product GRAVIS GAMEPADPRO 0x4001 GamePad Pro - -/* GREENHOUSE products */ -product GREENHOUSE KANA21 0x0001 CF-writer with MP3 - -/* Griffin Technology */ -product GRIFFIN IMATE 0x0405 iMate, ADB Adapter - -/* Guillemot Corporation */ -product GUILLEMOT DALEADER 0xa300 DA Leader -product GUILLEMOT HWGUSB254 0xe000 HWGUSB2-54 WLAN -product GUILLEMOT HWGUSB254LB 0xe010 HWGUSB2-54-LB -product GUILLEMOT HWGUSB254V2AP 0xe020 HWGUSB2-54V2-AP - -/* Hagiwara products */ -product HAGIWARA FGSM 0x0002 FlashGate SmartMedia Card Reader -product HAGIWARA FGCF 0x0003 FlashGate CompactFlash Card Reader -product HAGIWARA FG 0x0005 FlashGate - -/* HAL Corporation products */ -product HAL IMR001 0x0011 Crossam2+USB IR commander - -/* Handspring, Inc. */ -product HANDSPRING VISOR 0x0100 Handspring Visor -product HANDSPRING TREO 0x0200 Handspring Treo -product HANDSPRING TREO600 0x0300 Handspring Treo 600 - -/* Hauppauge Computer Works */ -product HAUPPAUGE WINTV_USB_FM 0x4d12 WinTV USB FM - -/* Hawking Technologies products */ -product HAWKING UF100 0x400c 10/100 USB Ethernet - -/* Hitachi, Ltd. products */ -product HITACHI DVDCAM_DZ_MV100A 0x0004 DVD-CAM DZ-MV100A Camcorder -product HITACHI DVDCAM_USB 0x001e DVDCAM USB HS Interface - -/* HP products */ -product HP 895C 0x0004 DeskJet 895C -product HP 4100C 0x0101 Scanjet 4100C -product HP S20 0x0102 Photosmart S20 -product HP 880C 0x0104 DeskJet 880C -product HP 4200C 0x0105 ScanJet 4200C -product HP CDWRITERPLUS 0x0107 CD-Writer Plus -product HP KBDHUB 0x010c Multimedia Keyboard Hub -product HP G55XI 0x0111 OfficeJet G55xi -product HP HN210W 0x011c HN210W 802.11b WLAN -product HP 49GPLUS 0x0121 49g+ graphing calculator -product HP 6200C 0x0201 ScanJet 6200C -product HP S20b 0x0202 PhotoSmart S20 -product HP 815C 0x0204 DeskJet 815C -product HP 3300C 0x0205 ScanJet 3300C -product HP CDW8200 0x0207 CD-Writer Plus 8200e -product HP MMKEYB 0x020c Multimedia keyboard -product HP 1220C 0x0212 DeskJet 1220C -product HP 810C 0x0304 DeskJet 810C/812C -product HP 4300C 0x0305 Scanjet 4300C -product HP CDW4E 0x0307 CD-Writer+ CD-4e -product HP G85XI 0x0311 OfficeJet G85xi -product HP 1200 0x0317 LaserJet 1200 -product HP 5200C 0x0401 Scanjet 5200C -product HP 830C 0x0404 DeskJet 830C -product HP 3400CSE 0x0405 ScanJet 3400cse -product HP 6300C 0x0601 Scanjet 6300C -product HP 840C 0x0604 DeskJet 840c -product HP 2200C 0x0605 ScanJet 2200C -product HP 5300C 0x0701 Scanjet 5300C -product HP 4400C 0x0705 Scanjet 4400C -product HP 4470C 0x0805 Scanjet 4470C -product HP 82x0C 0x0b01 Scanjet 82x0C -product HP 2300D 0x0b17 Laserjet 2300d -product HP 970CSE 0x1004 Deskjet 970Cse -product HP 5400C 0x1005 Scanjet 5400C -product HP 2215 0x1016 iPAQ 22xx/Jornada 548 -product HP 568J 0x1116 Jornada 568 -product HP 930C 0x1204 DeskJet 930c -product HP P2000U 0x1801 Inkjet P-2000U -product HP 640C 0x2004 DeskJet 640c -product HP 4670V 0x3005 ScanJet 4670v -product HP P1100 0x3102 Photosmart P1100 -product HP OJ4215 0x3d11 OfficeJet 4215 -product HP HN210E 0x811c Ethernet HN210E -product HP2 C500 0x6002 PhotoSmart C500 -product HP HS2300 0x1e1d hs2300 HSDPA (aka MC8775) - -/* HTC products */ -product HTC WINMOBILE 0x00ce HTC USB Sync -product HTC PPC6700MODEM 0x00cf PPC6700 Modem -product HTC SMARTPHONE 0x0a51 SmartPhone USB Sync - -/* HUAWEI products */ -product HUAWEI MOBILE 0x1001 Huawei Mobile -product HUAWEI E220 0x1003 Huawei HSDPA modem - -/* HUAWEI 3com products */ -product HUAWEI3COM WUB320G 0x0009 Aolynk WUB320g - -/* IBM Corporation */ -product IBM USBCDROMDRIVE 0x4427 USB CD-ROM Drive - -/* Imagination Technologies products */ -product IMAGINATION DBX1 0x2107 DBX1 DSP core - -/* Inside Out Networks products */ -product INSIDEOUT EDGEPORT4 0x0001 EdgePort/4 serial ports - -/* In-System products */ -product INSYSTEM F5U002 0x0002 Parallel printer -product INSYSTEM ATAPI 0x0031 ATAPI Adapter -product INSYSTEM ISD110 0x0200 IDE Adapter ISD110 -product INSYSTEM ISD105 0x0202 IDE Adapter ISD105 -product INSYSTEM USBCABLE 0x081a USB cable -product INSYSTEM STORAGE_V2 0x5701 USB Storage Adapter V2 - -/* Intel products */ -product INTEL EASYPC_CAMERA 0x0110 Easy PC Camera -product INTEL TESTBOARD 0x9890 82930 test board - -/* Intersil products */ -product INTERSIL PRISM_GT 0x1000 PrismGT USB 2.0 WLAN -product INTERSIL PRISM_2X 0x3642 Prism2.x or Atmel WLAN - -/* Interpid Control Systems products */ -product INTREPIDCS VALUECAN 0x0601 ValueCAN CAN bus interface -product INTREPIDCS NEOVI 0x0701 NeoVI Blue vehicle bus interface - -/* I/O DATA products */ -product IODATA IU_CD2 0x0204 DVD Multi-plus unit iU-CD2 -product IODATA DVR_UEH8 0x0206 DVD Multi-plus unit DVR-UEH8 -product IODATA USBSSMRW 0x0314 USB-SSMRW SD-card -product IODATA USBSDRW 0x031e USB-SDRW SD-card -product IODATA USBETT 0x0901 USB ETT -product IODATA USBETTX 0x0904 USB ETTX -product IODATA USBETTXS 0x0913 USB ETTX -product IODATA USBWNB11A 0x0919 USB WN-B11 -product IODATA USBWNB11 0x0922 USB Airport WN-B11 -product IODATA ETGUS2 0x0930 ETG-US2 -product IODATA USBRSAQ 0x0a03 Serial USB-RSAQ1 -product IODATA2 USB2SC 0x0a09 USB2.0-SCSI Bridge USB2-SC - -/* Iomega products */ -product IOMEGA ZIP100 0x0001 Zip 100 -product IOMEGA ZIP250 0x0030 Zip 250 - -/* Ituner networks products */ -product ITUNERNET USBLCD2X20 0x0002 USB-LCD 2x20 -product ITUNERNET USBLCD4X20 0xc001 USB-LCD 4x20 - -/* Jablotron products */ -product JABLOTRON PC60B 0x0001 PC-60B - -/* Jaton products */ -product JATON EDA 0x5704 Ethernet - -/* JVC products */ -product JVC GR_DX95 0x000a GR-DX95 -product JVC MP_PRX1 0x3008 MP-PRX1 Ethernet - -/* JRC products */ -product JRC AH_J3001V_J3002V 0x0001 AirH PHONE AH-J3001V/J3002V - -/* Kawatsu products */ -product KAWATSU MH4000P 0x0003 MiniHub 4000P - -/* Keisokugiken Corp. products */ -product KEISOKUGIKEN USBDAQ 0x0068 HKS-0200 USBDAQ - -/* Kensington products */ -product KENSINGTON ORBIT 0x1003 Orbit USB/PS2 trackball -product KENSINGTON TURBOBALL 0x1005 TurboBall - -/* Keyspan products */ -product KEYSPAN USA28_NF 0x0101 USA-28 serial Adapter (no firmware) -product KEYSPAN USA28X_NF 0x0102 USA-28X serial Adapter (no firmware) -product KEYSPAN USA19_NF 0x0103 USA-19 serial Adapter (no firmware) -product KEYSPAN USA18_NF 0x0104 USA-18 serial Adapter (no firmware) -product KEYSPAN USA18X_NF 0x0105 USA-18X serial Adapter (no firmware) -product KEYSPAN USA19W_NF 0x0106 USA-19W serial Adapter (no firmware) -product KEYSPAN USA19 0x0107 USA-19 serial Adapter -product KEYSPAN USA19W 0x0108 USA-19W serial Adapter -product KEYSPAN USA49W_NF 0x0109 USA-49W serial Adapter (no firmware) -product KEYSPAN USA49W 0x010a USA-49W serial Adapter -product KEYSPAN USA19QI_NF 0x010b USA-19QI serial Adapter (no firmware) -product KEYSPAN USA19QI 0x010c USA-19QI serial Adapter -product KEYSPAN USA19Q_NF 0x010d USA-19Q serial Adapter (no firmware) -product KEYSPAN USA19Q 0x010e USA-19Q serial Adapter -product KEYSPAN USA28 0x010f USA-28 serial Adapter -product KEYSPAN USA28XXB 0x0110 USA-28X/XB serial Adapter -product KEYSPAN USA18 0x0111 USA-18 serial Adapter -product KEYSPAN USA18X 0x0112 USA-18X serial Adapter -product KEYSPAN USA28XB_NF 0x0113 USA-28XB serial Adapter (no firmware) -product KEYSPAN USA28XA_NF 0x0114 USA-28XB serial Adapter (no firmware) -product KEYSPAN USA28XA 0x0115 USA-28XA serial Adapter -product KEYSPAN USA18XA_NF 0x0116 USA-18XA serial Adapter (no firmware) -product KEYSPAN USA18XA 0x0117 USA-18XA serial Adapter -product KEYSPAN USA19QW_NF 0x0118 USA-19WQ serial Adapter (no firmware) -product KEYSPAN USA19QW 0x0119 USA-19WQ serial Adapter -product KEYSPAN USA19HA 0x0121 USA-19HS serial Adapter -product KEYSPAN UIA10 0x0201 UIA-10 remote control -product KEYSPAN UIA11 0x0202 UIA-11 remote control - -/* Kingston products */ -product KINGSTON XX1 0x0008 Ethernet -product KINGSTON KNU101TX 0x000a KNU101TX USB Ethernet - -/* Kawasaki products */ -product KLSI DUH3E10BT 0x0008 USB Ethernet -product KLSI DUH3E10BTN 0x0009 USB Ethernet - -/* Kodak products */ -product KODAK DC220 0x0100 Digital Science DC220 -product KODAK DC260 0x0110 Digital Science DC260 -product KODAK DC265 0x0111 Digital Science DC265 -product KODAK DC290 0x0112 Digital Science DC290 -product KODAK DC240 0x0120 Digital Science DC240 -product KODAK DC280 0x0130 Digital Science DC280 - -/* Konica Corp. Products */ -product KONICA CAMERA 0x0720 Digital Color Camera - -/* KYE products */ -product KYE NICHE 0x0001 Niche mouse -product KYE NETSCROLL 0x0003 Genius NetScroll mouse -product KYE FLIGHT2000 0x1004 Flight 2000 joystick -product KYE VIVIDPRO 0x2001 ColorPage Vivid-Pro scanner - -/* Kyocera products */ -product KYOCERA FINECAM_S3X 0x0100 Finecam S3x -product KYOCERA FINECAM_S4 0x0101 Finecam S4 -product KYOCERA FINECAM_S5 0x0103 Finecam S5 -product KYOCERA FINECAM_L3 0x0105 Finecam L3 -product KYOCERA AHK3001V 0x0203 AH-K3001V -product KYOCERA2 CDMA_MSM_K 0x17da Qualcomm Kyocera CDMA Technologies MSM - -/* LaCie products */ -product LACIE HD 0xa601 Hard Disk -product LACIE CDRW 0xa602 CD R/W - -/* Lexar products */ -product LEXAR JUMPSHOT 0x0001 jumpSHOT CompactFlash Reader -product LEXAR CF_READER 0xb002 USB CF Reader - -/* Lexmark products */ -product LEXMARK S2450 0x0009 Optra S 2450 - -/* Linksys products */ -product LINKSYS MAUSB2 0x0105 Camedia MAUSB-2 -product LINKSYS USB10TX1 0x200c USB10TX -product LINKSYS USB10T 0x2202 USB10T Ethernet -product LINKSYS USB100TX 0x2203 USB100TX Ethernet -product LINKSYS USB100H1 0x2204 USB100H1 Ethernet/HPNA -product LINKSYS USB10TA 0x2206 USB10TA Ethernet -product LINKSYS USB10TX2 0x400b USB10TX -product LINKSYS2 WUSB11 0x2219 WUSB11 Wireless Adapter -product LINKSYS2 USB200M 0x2226 USB 2.0 10/100 Ethernet -product LINKSYS3 WUSB11v28 0x2233 WUSB11 v2.8 Wireless Adapter -product LINKSYS4 USB1000 0x0039 USB1000 - -/* Logitech products */ -product LOGITECH M2452 0x0203 M2452 keyboard -product LOGITECH M4848 0x0301 M4848 mouse -product LOGITECH PAGESCAN 0x040f PageScan -product LOGITECH QUICKCAMWEB 0x0801 QuickCam Web -product LOGITECH QUICKCAMPRO 0x0810 QuickCam Pro -product LOGITECH QUICKCAMEXP 0x0840 QuickCam Express -product LOGITECH QUICKCAM 0x0850 QuickCam -product LOGITECH N43 0xc000 N43 -product LOGITECH N48 0xc001 N48 mouse -product LOGITECH MBA47 0xc002 M-BA47 mouse -product LOGITECH WMMOUSE 0xc004 WingMan Gaming Mouse -product LOGITECH BD58 0xc00c BD58 mouse -product LOGITECH UN58A 0xc030 iFeel Mouse -product LOGITECH UN53B 0xc032 iFeel MouseMan -product LOGITECH WMPAD 0xc208 WingMan GamePad Extreme -product LOGITECH WMRPAD 0xc20a WingMan RumblePad -product LOGITECH WMJOY 0xc281 WingMan Force joystick -product LOGITECH BB13 0xc401 USB-PS/2 Trackball -product LOGITECH RK53 0xc501 Cordless mouse -product LOGITECH RB6 0xc503 Cordless keyboard -product LOGITECH MX700 0xc506 Cordless optical mouse -product LOGITECH QUICKCAMPRO2 0xd001 QuickCam Pro - -/* Logitec Corp. products */ -product LOGITEC LDR_H443SU2 0x0033 DVD Multi-plus unit LDR-H443SU2 -product LOGITEC LDR_H443U2 0x00b3 DVD Multi-plus unit LDR-H443U2 - -/* Lucent products */ -product LUCENT EVALKIT 0x1001 USS-720 evaluation kit - -/* Luwen products */ -product LUWEN EASYDISK 0x0005 EasyDisc - -/* Macally products */ -product MACALLY MOUSE1 0x0101 mouse - -/* MCT Corp. */ -product MCT HUB0100 0x0100 Hub -product MCT DU_H3SP_USB232 0x0200 D-Link DU-H3SP USB BAY Hub -product MCT USB232 0x0210 USB-232 Interface -product MCT SITECOM_USB232 0x0230 Sitecom USB-232 Products - -/* Meizu Electronics */ -product MEIZU M6_SL 0x0140 MiniPlayer M6 (SL) - -/* Melco, Inc products */ -product MELCO LUATX1 0x0001 LUA-TX Ethernet -product MELCO LUATX5 0x0005 LUA-TX Ethernet -product MELCO LUA2TX5 0x0009 LUA2-TX Ethernet -product MELCO LUAKTX 0x0012 LUA-KTX Ethernet -product MELCO DUBPXXG 0x001c USB-IDE Bridge: DUB-PxxG -product MELCO LUAU2KTX 0x003d LUA-U2-KTX Ethernet -product MELCO KG54YB 0x005e WLI-U2-KG54-YB WLAN -product MELCO KG54 0x0066 WLI-U2-KG54 WLAN -product MELCO KG54AI 0x0067 WLI-U2-KG54-AI WLAN -product MELCO NINWIFI 0x008b Nintendo Wi-Fi -product MELCO PCOPRS1 0x00b3 PC-OP-RS1 RemoteStation -product MELCO SG54HP 0x00d8 WLI-U2-SG54HP -product MELCO G54HP 0x00d9 WLI-U2-G54HP -product MELCO KG54L 0x00da WLI-U2-KG54L -product MELCO SG54HG 0x00f4 WLI-U2-SG54HG - -/* Merlin products */ -product MERLIN V620 0x1110 Merlin V620 - -/* MetaGeek products */ -product METAGEEK WISPY1B 0x083e MetaGeek Wi-Spy -product METAGEEK WISPY24X 0x083f MetaGeek Wi-Spy 2.4x - -/* Metricom products */ -product METRICOM RICOCHET_GS 0x0001 Ricochet GS - -/* MGE UPS Systems */ -product MGE UPS1 0x0001 MGE UPS SYSTEMS PROTECTIONCENTER 1 -product MGE UPS2 0xffff MGE UPS SYSTEMS PROTECTIONCENTER 2 - -/* Micro Star International products */ -product MSI BT_DONGLE 0x1967 Bluetooth USB dongle -product MSI UB11B 0x6823 UB11B -product MSI RT2570 0x6861 RT2570 -product MSI RT2570_2 0x6865 RT2570 -product MSI RT2570_3 0x6869 RT2570 -product MSI RT2573_1 0x6874 RT2573 -product MSI RT2573_2 0x6877 RT2573 -product MSI RT2573_3 0xa861 RT2573 -product MSI RT2573_4 0xa874 RT2573 - -/* Microsoft products */ -product MICROSOFT SIDEPREC 0x0008 SideWinder Precision Pro -product MICROSOFT INTELLIMOUSE 0x0009 IntelliMouse -product MICROSOFT NATURALKBD 0x000b Natural Keyboard Elite -product MICROSOFT DDS80 0x0014 Digital Sound System 80 -product MICROSOFT SIDEWINDER 0x001a Sidewinder Precision Racing Wheel -product MICROSOFT INETPRO 0x001c Internet Keyboard Pro -product MICROSOFT TBEXPLORER 0x0024 Trackball Explorer -product MICROSOFT INTELLIEYE 0x0025 IntelliEye mouse -product MICROSOFT INETPRO2 0x002b Internet Keyboard Pro -product MICROSOFT MN510 0x006e MN510 Wireless -product MICROSOFT MN110 0x007a 10/100 USB NIC -product MICROSOFT WLINTELLIMOUSE 0x008c Wireless Optical IntelliMouse -product MICROSOFT WLNOTEBOOK 0x00b9 Wireless Optical Mouse (Model 1023) -product MICROSOFT COMFORT3000 0x00d1 Comfort Optical Mouse 3000 (Model 1043) -product MICROSOFT WLNOTEBOOK2 0x00e1 Wireless Optical Mouse 3000 (Model 1056) -product MICROSOFT WLNOTEBOOK3 0x00d2 Wireless Optical Mouse 3000 (Model 1049) -product MICROSOFT WLUSBMOUSE 0x00b9 Wireless USB Mouse -product MICROSOFT XBOX360 0x0292 XBOX 360 WLAN - -/* Microtech products */ -product MICROTECH SCSIDB25 0x0004 USB-SCSI-DB25 -product MICROTECH SCSIHD50 0x0005 USB-SCSI-HD50 -product MICROTECH DPCM 0x0006 USB CameraMate -product MICROTECH FREECOM 0xfc01 Freecom USB-IDE - -/* Microtek products */ -product MICROTEK 336CX 0x0094 Phantom 336CX - C3 scanner -product MICROTEK X6U 0x0099 ScanMaker X6 - X6U -product MICROTEK C6 0x009a Phantom C6 scanner -product MICROTEK 336CX2 0x00a0 Phantom 336CX - C3 scanner -product MICROTEK V6USL 0x00a3 ScanMaker V6USL -product MICROTEK V6USL2 0x80a3 ScanMaker V6USL -product MICROTEK V6UL 0x80ac ScanMaker V6UL - -/* Microtune, Inc. products */ -product MICROTUNE BT_DONGLE 0x1000 Bluetooth USB dongle - -/* Midiman products */ -product MIDIMAN MIDISPORT2X2 0x1001 Midisport 2x2 - -/* MindsAtWork products */ -product MINDSATWORK WALLET 0x0001 Digital Wallet - -/* Minolta Co., Ltd. */ -product MINOLTA 2300 0x4001 Dimage 2300 -product MINOLTA S304 0x4007 Dimage S304 -product MINOLTA X 0x4009 Dimage X -product MINOLTA 5400 0x400e Dimage 5400 -product MINOLTA F300 0x4011 Dimage F300 -product MINOLTA E223 0x4017 Dimage E223 - -/* Mitsumi products */ -product MITSUMI CDRRW 0x0000 CD-R/RW Drive -product MITSUMI BT_DONGLE 0x641f Bluetooth USB dongle -product MITSUMI FDD 0x6901 USB FDD - -/* Mobility products */ -product MOBILITY EA 0x0204 Ethernet -product MOBILITY EASIDOCK 0x0304 EasiDock Ethernet - -/* MosChip products */ -product MOSCHIP MCS7703 0x7703 MCS7703 Serial Port Adapter -product MOSCHIP MCS7830 0x7830 MCS7830 Ethernet - -/* Motorola products */ -product MOTOROLA MC141555 0x1555 MC141555 hub controller -product MOTOROLA SB4100 0x4100 SB4100 USB Cable Modem -product MOTOROLA2 A41XV32X 0x2a22 A41x/V32x Mobile Phones -product MOTOROLA2 E398 0x4810 E398 Mobile Phone -product MOTOROLA2 USBLAN 0x600c USBLAN -product MOTOROLA2 USBLAN2 0x6027 USBLAN - -/* MultiTech products */ -product MULTITECH ATLAS 0xf101 MT5634ZBA-USB modem - -/* Mustek products */ -product MUSTEK 1200CU 0x0001 1200 CU scanner -product MUSTEK 600CU 0x0002 600 CU scanner -product MUSTEK 1200USB 0x0003 1200 USB scanner -product MUSTEK 1200UB 0x0006 1200 UB scanner -product MUSTEK 1200USBPLUS 0x0007 1200 USB Plus scanner -product MUSTEK 1200CUPLUS 0x0008 1200 CU Plus scanner -product MUSTEK BEARPAW1200F 0x0010 BearPaw 1200F scanner -product MUSTEK BEARPAW1200TA 0x021e BearPaw 1200TA scanner -product MUSTEK 600USB 0x0873 600 USB scanner -product MUSTEK MDC800 0xa800 MDC-800 digital camera - -/* M-Systems products */ -product MSYSTEMS DISKONKEY 0x0010 DiskOnKey -product MSYSTEMS DISKONKEY2 0x0011 DiskOnKey - -/* Myson products */ -product MYSON HEDEN 0x8818 USB-IDE -product MYSON STARREADER 0x9920 USB flash card adapter - -/* National Semiconductor */ -product NATIONAL BEARPAW1200 0x1000 BearPaw 1200 -product NATIONAL BEARPAW2400 0x1001 BearPaw 2400 - -/* NEC products */ -product NEC HUB 0x55aa hub -product NEC HUB_B 0x55ab hub - -/* NEODIO products */ -product NEODIO ND3260 0x3260 8-in-1 Multi-format Flash Controller -product NEODIO ND5010 0x5010 Multi-format Flash Controller - -/* Netac products */ -product NETAC CF_CARD 0x1060 USB-CF-Card -product NETAC ONLYDISK 0x0003 OnlyDisk - -/* NetChip Technology Products */ -product NETCHIP TURBOCONNECT 0x1080 Turbo-Connect -product NETCHIP CLIK_40 0xa140 USB Clik! 40 -product NETCHIP ETHERNETGADGET 0xa4a2 Linux Ethernet/RNDIS gadget on pxa210/25x/26x - -/* Netgear products */ -product NETGEAR EA101 0x1001 Ethernet -product NETGEAR EA101X 0x1002 Ethernet -product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1 -product NETGEAR FA120 0x1040 USB 2.0 Ethernet -product NETGEAR WG111V2_2 0x4240 PrismGT USB 2.0 WLAN -product NETGEAR WG111U 0x4300 WG111U -product NETGEAR WG111U_NF 0x4301 WG111U (no firmware) -product NETGEAR WG111V2 0x6a00 WG111V2 -product NETGEAR2 MA101 0x4100 MA101 -product NETGEAR2 MA101B 0x4102 MA101 Rev B -product NETGEAR3 WG111T 0x4250 WG111T -product NETGEAR3 WG111T_NF 0x4251 WG111T (no firmware) -product NETGEAR3 WPN111 0x5f00 WPN111 -product NETGEAR3 WPN111_NF 0x5f01 WPN111 (no firmware) - -/* Nikon products */ -product NIKON E990 0x0102 Digital Camera E990 -product NIKON LS40 0x4000 CoolScan LS40 ED -product NIKON D300 0x041a Digital Camera D300 - -/* NovaTech Products */ -product NOVATECH NV902 0x9020 NovaTech NV-902W -product NOVATECH RT2573 0x9021 RT2573 - -/* Novatel Wireless products */ -product NOVATEL V640 0x1100 Merlin V620 -product NOVATEL CDMA_MODEM 0x1110 Novatel Wireless Merlin CDMA -product NOVATEL V620 0x1110 Merlin V620 -product NOVATEL V740 0x1120 Merlin V740 -product NOVATEL V720 0x1130 Merlin V720 -product NOVATEL U740 0x1400 Merlin U740 -product NOVATEL U740_2 0x1410 Merlin U740 -product NOVATEL U870 0x1420 Merlin U870 -product NOVATEL XU870 0x1430 Merlin XU870 -product NOVATEL X950D 0x1450 Merlin X950D -product NOVATEL ES620 0x2100 ES620 CDMA -product NOVATEL U720 0x2110 Merlin U720 -product NOVATEL U727 0x4100 Merlin U727 CDMA -product NOVATEL MC950D 0x4400 Novatel MC950D HSUPA -product NOVATEL ZEROCD 0x5010 Novatel ZeroCD -product NOVATEL ZEROCD2 0x5030 Novatel ZeroCD -product NOVATEL U760 0x6000 Novatel U760 -product NOVATEL2 FLEXPACKGPS 0x0100 NovAtel FlexPack GPS receiver - -/* Merlin products */ -product MERLIN V620 0x1110 Merlin V620 - -/* Olympus products */ -product OLYMPUS C1 0x0102 C-1 Digital Camera -product OLYMPUS C700 0x0105 C-700 Ultra Zoom - -/* OmniVision Technologies, Inc. products */ -product OMNIVISION OV511 0x0511 OV511 Camera -product OMNIVISION OV511PLUS 0xa511 OV511+ Camera - -/* OnSpec Electronic, Inc. */ -product ONSPEC SDS_HOTFIND_D 0x0400 SDS-infrared.com Hotfind-D Infrared Camera -product ONSPEC MDCFE_B_CF_READER 0xa000 MDCFE-B USB CF Reader -product ONSPEC CFMS_RW 0xa001 SIIG/Datafab Memory Stick+CF Reader/Writer -product ONSPEC READER 0xa003 Datafab-based Reader -product ONSPEC CFSM_READER 0xa005 PNY/Datafab CF+SM Reader -product ONSPEC CFSM_READER2 0xa006 Simple Tech/Datafab CF+SM Reader -product ONSPEC MDSM_B_READER 0xa103 MDSM-B reader -product ONSPEC CFSM_COMBO 0xa109 USB to CF + SM Combo (LC1) -product ONSPEC UCF100 0xa400 FlashLink UCF-100 CompactFlash Reader -product ONSPEC2 IMAGEMATE_SDDR55 0xa103 ImageMate SDDR55 - -/* Option products */ -product OPTION VODAFONEMC3G 0x5000 Vodafone Mobile Connect 3G datacard -product OPTION GT3G 0x6000 GlobeTrotter 3G datacard -product OPTION GT3GQUAD 0x6300 GlobeTrotter 3G QUAD datacard -product OPTION GT3GPLUS 0x6600 GlobeTrotter 3G+ datacard -product OPTION GTICON322 0xd033 GlobeTrotter Icon322 storage -product OPTION GTMAX36 0x6701 GlobeTrotter Max 3.6 Modem -product OPTION GTMAXHSUPA 0x7001 GlobeTrotter HSUPA - -/* OQO */ -product OQO WIFI01 0x0002 model 01 WiFi interface -product OQO BT01 0x0003 model 01 Bluetooth interface -product OQO ETHER01PLUS 0x7720 model 01+ Ethernet -product OQO ETHER01 0x8150 model 01 Ethernet interface - -/* Palm Computing, Inc. product */ -product PALM SERIAL 0x0080 USB Serial -product PALM M500 0x0001 Palm m500 -product PALM M505 0x0002 Palm m505 -product PALM M515 0x0003 Palm m515 -product PALM I705 0x0020 Palm i705 -product PALM TUNGSTEN_Z 0x0031 Palm Tungsten Z -product PALM M125 0x0040 Palm m125 -product PALM M130 0x0050 Palm m130 -product PALM TUNGSTEN_T 0x0060 Palm Tungsten T -product PALM ZIRE31 0x0061 Palm Zire 31 -product PALM ZIRE 0x0070 Palm Zire - -/* Panasonic products */ -product PANASONIC LS120CAM 0x0901 LS-120 Camera -product PANASONIC KXL840AN 0x0d01 CD-R Drive KXL-840AN -product PANASONIC KXLRW32AN 0x0d09 CD-R Drive KXL-RW32AN -product PANASONIC KXLCB20AN 0x0d0a CD-R Drive KXL-CB20AN -product PANASONIC KXLCB35AN 0x0d0e DVD-ROM & CD-R/RW -product PANASONIC SDCAAE 0x1b00 MultiMediaCard - -/* Peracom products */ -product PERACOM SERIAL1 0x0001 Serial -product PERACOM ENET 0x0002 Ethernet -product PERACOM ENET3 0x0003 At Home Ethernet -product PERACOM ENET2 0x0005 Ethernet - -/* Philips products */ -product PHILIPS DSS350 0x0101 DSS 350 Digital Speaker System -product PHILIPS DSS 0x0104 DSS XXX Digital Speaker System -product PHILIPS HUB 0x0201 hub -product PHILIPS PCA646VC 0x0303 PCA646VC PC Camera -product PHILIPS PCVC680K 0x0308 PCVC680K Vesta Pro PC Camera -product PHILIPS DSS150 0x0471 DSS 150 Digital Speaker System -product PHILIPS SNU5600 0x1236 SNU5600 -product PHILIPS UM10016 0x1552 ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit -product PHILIPS DIVAUSB 0x1801 DIVA USB mp3 player - -/* Philips Semiconductor products */ -product PHILIPSSEMI HUB1122 0x1122 hub - -/* P.I. Engineering products */ -product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter - -/* Planex Communications products */ -product PLANEX GW_US11H 0x14ea GW-US11H WLAN -product PLANEX2 GW_US11S 0x3220 GW-US11S WLAN -product PLANEX2 GW_US54GXS 0x5303 GW-US54GXS WLAN -product PLANEX2 GWUS54HP 0xab01 GW-US54HP -product PLANEX2 GWUS54MINI2 0xab50 GW-US54Mini2 -product PLANEX2 GWUS54SG 0xc002 GW-US54SG -product PLANEX2 GWUS54GZL 0xc007 GW-US54GZL -product PLANEX2 GWUS54GD 0xed01 GW-US54GD -product PLANEX2 GWUSMM 0xed02 GW-USMM -product PLANEX3 GWUS54GZ 0xab10 GW-US54GZ -product PLANEX3 GU1000T 0xab11 GU-1000T -product PLANEX3 GWUS54MINI 0xab13 GW-US54Mini - -/* Plextor Corp. */ -product PLEXTOR 40_12_40U 0x0011 PlexWriter 40/12/40U - -/* PLX products */ -product PLX TESTBOARD 0x9060 test board - -/* PNY products */ -product PNY ATTACHE2 0x0010 USB 2.0 Flash Drive - -/* PortGear products */ -product PORTGEAR EA8 0x0008 Ethernet -product PORTGEAR EA9 0x0009 Ethernet - -/* Portsmith products */ -product PORTSMITH EEA 0x3003 Express Ethernet - -/* Primax products */ -product PRIMAX G2X300 0x0300 G2-200 scanner -product PRIMAX G2E300 0x0301 G2E-300 scanner -product PRIMAX G2300 0x0302 G2-300 scanner -product PRIMAX G2E3002 0x0303 G2E-300 scanner -product PRIMAX 9600 0x0340 Colorado USB 9600 scanner -product PRIMAX 600U 0x0341 Colorado 600u scanner -product PRIMAX 6200 0x0345 Visioneer 6200 scanner -product PRIMAX 19200 0x0360 Colorado USB 19200 scanner -product PRIMAX 1200U 0x0361 Colorado 1200u scanner -product PRIMAX G600 0x0380 G2-600 scanner -product PRIMAX 636I 0x0381 ReadyScan 636i -product PRIMAX G2600 0x0382 G2-600 scanner -product PRIMAX G2E600 0x0383 G2E-600 scanner -product PRIMAX COMFORT 0x4d01 Comfort -product PRIMAX MOUSEINABOX 0x4d02 Mouse-in-a-Box -product PRIMAX PCGAUMS1 0x4d04 Sony PCGA-UMS1 - -/* Prolific products */ -product PROLIFIC PL2301 0x0000 PL2301 Host-Host interface -product PROLIFIC PL2302 0x0001 PL2302 Host-Host interface -product PROLIFIC RSAQ2 0x04bb PL2303 Serial (IODATA USB-RSAQ2) -product PROLIFIC PL2303 0x2303 PL2303 Serial (ATEN/IOGEAR UC232A) -product PROLIFIC PL2305 0x2305 Parallel printer -product PROLIFIC ATAPI4 0x2307 ATAPI-4 Controller -product PROLIFIC PL2501 0x2501 PL2501 Host-Host interface -product PROLIFIC PHAROS 0xaaa0 Prolific Pharos -product PROLIFIC RSAQ3 0xaaa2 PL2303 Serial Adapter (IODATA USB-RSAQ3) -product PROLIFIC2 WSIM 0x2001 Willcom WSIM - -/* Putercom products */ -product PUTERCOM UPA100 0x047e USB-1284 BRIDGE - -/* Qcom products */ -product QCOM RT2573 0x6196 RT2573 -product QCOM RT2573_2 0x6229 RT2573 - -/* Qualcomm products */ -product QUALCOMM CDMA_MSM 0x6000 CDMA Technologies MSM phone -product QUALCOMM2 RWT_FCT 0x3100 RWT FCT-CDMA 2000 1xRTT modem -product QUALCOMM2 CDMA_MSM 0x3196 CDMA Technologies MSM modem -product QUALCOMMINC CDMA_MSM 0x0001 CDMA Technologies MSM modem -product QUALCOMMINC ZTE_STOR 0x2000 USB ZTE Storage -product QUALCOMMINC AC8700 0xfffe CDMA 1xEVDO USB modem - -/* Qtronix products */ -product QTRONIX 980N 0x2011 Scorpion-980N keyboard - -/* Quickshot products */ -product QUICKSHOT STRIKEPAD 0x6238 USB StrikePad - -/* Radio Shack */ -product RADIOSHACK USBCABLE 0x4026 USB to Serial Cable - -/* Rainbow Technologies products */ -product RAINBOW IKEY2000 0x1200 i-Key 2000 - -/* Ralink Technology products */ -product RALINK RT2570 0x1706 RT2500USB Wireless Adapter -product RALINK RT2570_2 0x2570 RT2500USB Wireless Adapter -product RALINK RT2573 0x2573 RT2501USB Wireless Adapter -product RALINK RT2671 0x2671 RT2601USB Wireless Adapter -product RALINK RT2570_3 0x9020 RT2500USB Wireless Adapter -product RALINK RT2573_2 0x9021 RT2501USB Wireless Adapter - -/* ReakTek products */ -/* Green House and CompUSA OEM this part */ -product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet -product REALTEK RTL8187 0x8187 RTL8187 Wireless Adapter - -/* Ricoh products */ -product RICOH VGPVCC2 0x1830 VGP-VCC2 Camera -product RICOH VGPVCC3 0x1832 VGP-VCC3 Camera -product RICOH VGPVCC2_2 0x1833 VGP-VCC2 Camera -product RICOH VGPVCC2_3 0x1834 VGP-VCC2 Camera -product RICOH VGPVCC7 0x183a VGP-VCC7 Camera -product RICOH VGPVCC8 0x183b VGP-VCC8 Camera - -/* Roland products */ -product ROLAND UM1 0x0009 UM-1 MIDI I/F -product ROLAND UM880N 0x0014 EDIROL UM-880 MIDI I/F (native) -product ROLAND UM880G 0x0015 EDIROL UM-880 MIDI I/F (generic) - -/* Rockfire products */ -product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB - -/* RATOC Systems products */ -product RATOC REXUSB60 0xb000 REX-USB60 - -/* Sagem products */ -product SAGEM USBSERIAL 0x0027 USB-Serial Controller -product SAGEM XG760A 0x004a XG-760A -product SAGEM XG76NA 0x0062 XG-76NA - -/* Samsung products */ -product SAMSUNG ML6060 0x3008 ML-6060 laser printer -product SAMSUNG YP_U2 0x5050 YP-U2 MP3 Player -product SAMSUNG I500 0x6601 I500 Palm USB Phone - -/* Samsung Techwin products */ -product SAMSUNG_TECHWIN DIGIMAX_410 0x000a Digimax 410 - -/* SanDisk products */ -product SANDISK SDDR05A 0x0001 ImageMate SDDR-05a -product SANDISK SDDR31 0x0002 ImageMate SDDR-31 -product SANDISK SDDR05 0x0005 ImageMate SDDR-05 -product SANDISK SDDR12 0x0100 ImageMate SDDR-12 -product SANDISK SDDR09 0x0200 ImageMate SDDR-09 -product SANDISK SDDR75 0x0810 ImageMate SDDR-75 -product SANDISK SDCZ2_256 0x7104 Cruzer Mini 256MB -product SANDISK SDCZ4_128 0x7112 Cruzer Micro 128MB -product SANDISK SDCZ4_256 0x7113 Cruzer Micro 256MB - -/* Sanyo Electric products */ -product SANYO SCP4900 0x0701 Sanyo SCP-4900 USB Phone - -/* ScanLogic products */ -product SCANLOGIC SL11R 0x0002 SL11R IDE Adapter -product SCANLOGIC 336CX 0x0300 Phantom 336CX - C3 scanner - -/* Senao products */ -product SENAO NUB8301 0x2000 NUB-8301 - -/* ShanTou products */ -product SHANTOU ST268 0x0268 ST268 -product SHANTOU DM9601 0x9601 DM 9601 - -/* Shark products */ -product SHARK PA 0x0400 Pocket Adapter - -/* Sharp products */ -product SHARP SL5500 0x8004 Zaurus SL-5500 PDA -product SHARP SLA300 0x8005 Zaurus SL-A300 PDA -product SHARP SL5600 0x8006 Zaurus SL-5600 PDA -product SHARP SLC700 0x8007 Zaurus SL-C700 PDA -product SHARP SLC750 0x9031 Zaurus SL-C750 PDA -product SHARP WZERO3ES 0x9123 W-ZERO3 ES Smartphone - -/* Shuttle Technology products */ -product SHUTTLE EUSB 0x0001 E-USB Bridge -product SHUTTLE EUSCSI 0x0002 eUSCSI Bridge -product SHUTTLE SDDR09 0x0003 ImageMate SDDR09 -product SHUTTLE EUSBCFSM 0x0005 eUSB SmartMedia / CompactFlash Adapter -product SHUTTLE ZIOMMC 0x0006 eUSB MultiMediaCard Adapter -product SHUTTLE HIFD 0x0007 Sony Hifd -product SHUTTLE EUSBATAPI 0x0009 eUSB ATA/ATAPI Adapter -product SHUTTLE CF 0x000a eUSB CompactFlash Adapter -product SHUTTLE EUSCSI_B 0x000b eUSCSI Bridge -product SHUTTLE EUSCSI_C 0x000c eUSCSI Bridge -product SHUTTLE CDRW 0x0101 CD-RW Device -product SHUTTLE EUSBORCA 0x0325 eUSB ORCA Quad Reader - -/* Siemens products */ -product SIEMENS SPEEDSTREAM 0x1001 SpeedStream -product SIEMENS SPEEDSTREAM22 0x1022 SpeedStream 1022 -product SIEMENS2 WLL013 0x001b WLL013 -product SIEMENS2 ES75 0x0034 GSM module MC35 -product SIEMENS2 WL54G 0x3c06 54g USB Network Adapter -product SIEMENS3 SX1 0x0001 SX1 -product SIEMENS3 X65 0x0003 X65 -product SIEMENS3 X75 0x0004 X75 - -/* Sierra Wireless products */ -product SIERRA AIRCARD580 0x0112 Sierra Wireless AirCard 580 -product SIERRA AIRCARD595 0x0019 Sierra Wireless AirCard 595 -product SIERRA AC595U 0x0120 Sierra Wireless AirCard 595U -product SIERRA AC597E 0x0021 Sierra Wireless AirCard 597E -product SIERRA C597 0x0023 Sierra Wireless Compass 597 -product SIERRA AC875 0x6820 Sierra Wireless AirCard 875 -product SIERRA AC880 0x6850 Sierra Wireless AirCard 880 -product SIERRA AC881 0x6851 Sierra Wireless AirCard 881 -product SIERRA AC880E 0x6852 Sierra Wireless AirCard 880E -product SIERRA AC881E 0x6853 Sierra Wireless AirCard 881E -product SIERRA AC880U 0x6855 Sierra Wireless AirCard 880U -product SIERRA AC881U 0x6856 Sierra Wireless AirCard 881U -product SIERRA AC885U 0x6880 Sierra Wireless AirCard 885U -product SIERRA EM5625 0x0017 EM5625 -product SIERRA MC5720 0x0218 MC5720 Wireless Modem -product SIERRA MC5720_2 0x0018 MC5720 -product SIERRA MC5725 0x0020 MC5725 -product SIERRA MINI5725 0x0220 Sierra Wireless miniPCI 5275 -product SIERRA MC8755_2 0x6802 MC8755 -product SIERRA MC8765 0x6803 MC8765 -product SIERRA MC8755 0x6804 MC8755 -product SIERRA AC875U 0x6812 AC875U HSDPA USB Modem -product SIERRA MC8755_3 0x6813 MC8755 HSDPA -product SIERRA MC8775_2 0x6815 MC8775 -product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA -product SIERRA MC8780 0x6832 MC8780 -product SIERRA MC8781 0x6833 MC8781 -product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer - -/* Sigmatel products */ -product SIGMATEL I_BEAD100 0x8008 i-Bead 100 MP3 Player - -/* SIIG products */ -/* Also: Omnidirectional Control Technology products */ -product SIIG DIGIFILMREADER 0x0004 DigiFilm-Combo Reader -product SIIG WINTERREADER 0x0330 WINTERREADER Reader -product SIIG2 USBTOETHER 0x0109 USB TO Ethernet -product SIIG2 US2308 0x0421 Serial - -/* Silicom products */ -product SILICOM U2E 0x0001 U2E -product SILICOM GPE 0x0002 Psion Gold Port Ethernet - -/* SI Labs */ -product SILABS POLOLU 0x803b Pololu Serial -product SILABS ARGUSISP 0x8066 Argussoft ISP -product SILABS CRUMB128 0x807a Crumb128 board -product SILABS DEGREE 0x80ca Degree Controls Inc -product SILABS TRAQMATE 0x80ed Track Systems Traqmate -product SILABS SUUNTO 0x80f6 Suunto Sports Instrument -product SILABS BURNSIDE 0x813d Burnside Telecon Deskmobile -product SILABS HELICOM 0x815e Helicomm IP-Link 1220-DVM -product SILABS CP2102 0xea60 SILABS USB UART -product SILABS LIPOWSKY_JTAG 0x81c8 Lipowsky Baby-JTAG -product SILABS LIPOWSKY_LIN 0x81e2 Lipowsky Baby-LIN -product SILABS LIPOWSKY_HARP 0x8218 Lipowsky HARP-1 -product SILABS CP2102 0xea60 SILABS USB UARTa -product SILABS CP210X_2 0xea61 CP210x Serial -product SILABS2 DCU11CLONE 0xaa26 DCU-11 clone - -/* Silicon Portals Inc. */ -product SILICONPORTALS YAPPH_NF 0x0200 YAP Phone (no firmware) -product SILICONPORTALS YAPPHONE 0x0201 YAP Phone - -/* Sirius Technologies products */ -product SIRIUS ROADSTER 0x0001 NetComm Roadster II 56 USB - -/* Sitecom products */ -product SITECOM LN029 0x182d USB 2.0 Ethernet -product SITECOM SERIAL 0x2068 USB to serial cable (v2) -product SITECOM2 WL022 0x182d WL-022 - -/* Sitecom Europe products */ -product SITECOMEU LN028 0x061c LN-028 -product SITECOMEU WL113 0x9071 WL-113 -product SITECOMEU ZD1211B 0x9075 ZD1211B -product SITECOMEU WL172 0x90ac WL-172 -product SITECOMEU WL113R2 0x9712 WL-113 rev 2 - -/* Skanhex Technology products */ -product SKANHEX MD_7425 0x410a MD 7425 Camera -product SKANHEX SX_520Z 0x5200 SX 520z Camera - -/* SmartBridges products */ -product SMARTBRIDGES SMARTLINK 0x0001 SmartLink USB Ethernet -product SMARTBRIDGES SMARTNIC 0x0003 smartNIC 2 PnP Ethernet - -/* SMC products */ -product SMC 2102USB 0x0100 10Mbps Ethernet -product SMC 2202USB 0x0200 10/100 Ethernet -product SMC 2206USB 0x0201 EZ Connect USB Ethernet -product SMC 2862WG 0xee13 EZ Connect Wireless Adapter -product SMC2 2020HUB 0x2020 USB Hub -product SMC3 2662WUSB 0xa002 2662W-AR Wireless - -/* SOHOware products */ -product SOHOWARE NUB100 0x9100 10/100 USB Ethernet -product SOHOWARE NUB110 0x9110 10/100 USB Ethernet - -/* SOLID YEAR products */ -product SOLIDYEAR KEYBOARD 0x2101 Solid Year USB keyboard - -/* SONY products */ -product SONY DSC 0x0010 DSC cameras -product SONY MS_NW_MS7 0x0025 Memorystick NW-MS7 -product SONY PORTABLE_HDD_V2 0x002b Portable USB Harddrive V2 -product SONY MSACUS1 0x002d Memorystick MSAC-US1 -product SONY HANDYCAM 0x002e Handycam -product SONY MSC 0x0032 MSC memory stick slot -product SONY CLIE_35 0x0038 Sony Clie v3.5 -product SONY MS_PEG_N760C 0x0058 PEG N760c Memorystick -product SONY CLIE_40 0x0066 Sony Clie v4.0 -product SONY MS_MSC_U03 0x0069 Memorystick MSC-U03 -product SONY CLIE_40_MS 0x006d Sony Clie v4.0 Memory Stick slot -product SONY CLIE_S360 0x0095 Sony Clie s360 -product SONY CLIE_41_MS 0x0099 Sony Clie v4.1 Memory Stick slot -product SONY CLIE_41 0x009a Sony Clie v4.1 -product SONY CLIE_NX60 0x00da Sony Clie nx60 -product SONY CLIE_TH55 0x0144 Sony Clie th55 -product SONY CLIE_TJ37 0x0169 Sony Clie tj37 -product SONY RF_RECEIVER 0x01db Sony RF mouse/kbd Receiver VGP-WRC1 - -/* Sony Ericsson products */ -product SONYERICSSON DCU10 0x0528 USB Cable - -/* SOURCENEXT products */ -product SOURCENEXT KEIKAI8 0x039f KeikaiDenwa 8 -product SOURCENEXT KEIKAI8_CHG 0x012e KeikaiDenwa 8 with charger - -/* SparkLAN products */ -product SPARKLAN RT2573 0x0004 RT2573 - -/* Sphairon Access Systems GmbH products */ -product SPHAIRON UB801R 0x0110 UB801R - -/* Stelera Wireless products */ -product STELERA ZEROCD 0x1000 Zerocd Installer -product STELERA C105 0x1002 Stelera/Bandrish C105 USB - -/* STMicroelectronics products */ -product STMICRO BIOCPU 0x2016 Biometric Coprocessor -product STMICRO COMMUNICATOR 0x7554 USB Communicator - -/* STSN products */ -product STSN STSN0001 0x0001 Internet Access Device - -/* SUN Corporation products */ -product SUNTAC DS96L 0x0003 SUNTAC U-Cable type D2 -product SUNTAC PS64P1 0x0005 SUNTAC U-Cable type P1 -product SUNTAC VS10U 0x0009 SUNTAC Slipper U -product SUNTAC IS96U 0x000a SUNTAC Ir-Trinity -product SUNTAC AS64LX 0x000b SUNTAC U-Cable type A3 -product SUNTAC AS144L4 0x0011 SUNTAC U-Cable type A4 - -/* Sun Microsystems products */ -product SUN KEYBOARD 0x0005 Type 6 USB keyboard -/* XXX The above is a North American PC style keyboard possibly */ -product SUN MOUSE 0x0100 Type 6 USB mouse - -/* Supra products */ -product DIAMOND2 SUPRAEXPRESS56K 0x07da Supra Express 56K modem -product DIAMOND2 SUPRA2890 0x0b4a SupraMax 2890 56K Modem -product DIAMOND2 RIO600USB 0x5001 Rio 600 USB -product DIAMOND2 RIO800USB 0x5002 Rio 800 USB - -/* Surecom Technology products */ -product SURECOM RT2570 0x11f3 RT2570 -product SURECOM RT2573 0x31f3 RT2573 - -/* Sweex products */ -product SWEEX ZD1211 0x1809 ZD1211 - -/* System TALKS, Inc. */ -product SYSTEMTALKS SGCX2UL 0x1920 SGC-X2UL - -/* Tapwave products */ -product TAPWAVE ZODIAC 0x0100 Zodiac - -/* Taugagreining products */ -product TAUGA CAMERAMATE 0x0005 CameraMate (DPCM_USB) - -/* TDK products */ -product TDK UPA9664 0x0115 USB-PDC Adapter UPA9664 -product TDK UCA1464 0x0116 USB-cdmaOne Adapter UCA1464 -product TDK UHA6400 0x0117 USB-PHS Adapter UHA6400 -product TDK UPA6400 0x0118 USB-PHS Adapter UPA6400 -product TDK BT_DONGLE 0x0309 Bluetooth USB dongle - -/* TEAC products */ -product TEAC FD05PUB 0x0000 FD-05PUB floppy - -/* Tekram Technology products */ -product TEKRAM QUICKWLAN 0x1630 QuickWLAN -product TEKRAM ZD1211_1 0x5630 ZD1211 -product TEKRAM ZD1211_2 0x6630 ZD1211 - -/* Telex Communications products */ -product TELEX MIC1 0x0001 Enhanced USB Microphone - -/* Ten X Technology, Inc. */ -product TENX UAUDIO0 0xf211 USB audio headset - -/* Texas Intel products */ -product TI UTUSB41 0x1446 UT-USB41 hub -product TI TUSB2046 0x2046 TUSB2046 hub - -/* Thrustmaster products */ -product THRUST FUSION_PAD 0xa0a3 Fusion Digital Gamepad - -/* Topre Corporation products */ -product TOPRE HHKB 0x0100 HHKB Professional - -/* Toshiba Corporation products */ -product TOSHIBA POCKETPC_E740 0x0706 PocketPC e740 - -/* Trek Technology products */ -product TREK THUMBDRIVE 0x1111 ThumbDrive -product TREK MEMKEY 0x8888 IBM USB Memory Key -product TREK THUMBDRIVE_8MB 0x9988 ThumbDrive_8MB - -/* Tripp-Lite products */ -product TRIPPLITE U209 0x2008 Serial - -/* Trumpion products */ -product TRUMPION T33520 0x1001 T33520 USB Flash Card Controller -product TRUMPION C3310 0x1100 Comotron C3310 MP3 player -product TRUMPION MP3 0x1200 MP3 player - -/* TwinMOS */ -product TWINMOS G240 0xa006 G240 -product TWINMOS MDIV 0x1325 Memory Disk IV - -/* Ubiquam products */ -product UBIQUAM UALL 0x3100 CDMA 1xRTT USB Modem (U-100/105/200/300/520) - -/* Ultima products */ -product ULTIMA 1200UBPLUS 0x4002 1200 UB Plus scanner - -/* UMAX products */ -product UMAX ASTRA1236U 0x0002 Astra 1236U Scanner -product UMAX ASTRA1220U 0x0010 Astra 1220U Scanner -product UMAX ASTRA2000U 0x0030 Astra 2000U Scanner -product UMAX ASTRA2100U 0x0130 Astra 2100U Scanner -product UMAX ASTRA2200U 0x0230 Astra 2200U Scanner -product UMAX ASTRA3400 0x0060 Astra 3400 Scanner - -/* U-MEDIA Communications products */ -product UMEDIA TEW444UBEU 0x3006 TEW-444UB EU -product UMEDIA TEW444UBEU_NF 0x3007 TEW-444UB EU (no firmware) -product UMEDIA TEW429UB_A 0x300a TEW-429UB_A -product UMEDIA TEW429UB 0x300b TEW-429UB -product UMEDIA TEW429UBC1 0x300d TEW-429UB C1 -product UMEDIA ALL0298V2 0x3204 ALL0298 v2 -product UMEDIA AR5523_2 0x3205 AR5523 -product UMEDIA AR5523_2_NF 0x3206 AR5523 (no firmware) - -/* Universal Access products */ -product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter - -/* U.S. Robotics products */ -product USR USR5423 0x0121 USR5423 WLAN - -/* VIA Technologies products */ -product VIA USB2IDEBRIDGE 0x6204 USB 2.0 IDE Bridge - -/* USI products */ -product USI MC60 0x10c5 MC60 Serial - -/* VidzMedia products */ -product VIDZMEDIA MONSTERTV 0x4fb1 MonsterTV P2H - -/* Vision products */ -product VISION VC6452V002 0x0002 CPiA Camera - -/* Visioneer products */ -product VISIONEER 7600 0x0211 OneTouch 7600 -product VISIONEER 5300 0x0221 OneTouch 5300 -product VISIONEER 3000 0x0224 Scanport 3000 -product VISIONEER 6100 0x0231 OneTouch 6100 -product VISIONEER 6200 0x0311 OneTouch 6200 -product VISIONEER 8100 0x0321 OneTouch 8100 -product VISIONEER 8600 0x0331 OneTouch 8600 - -/* Vivitar products */ -product VIVITAR 35XX 0x0003 Vivicam 35Xx - -/* VTech products */ -product VTECH RT2570 0x3012 RT2570 -product VTECH ZD1211B 0x3014 ZD1211B - -/* Wacom products */ -product WACOM CT0405U 0x0000 CT-0405-U Tablet -product WACOM GRAPHIRE 0x0010 Graphire -product WACOM GRAPHIRE3_4X5 0x0013 Graphire 3 4x5 -product WACOM INTUOSA5 0x0021 Intuos A5 -product WACOM GD0912U 0x0022 Intuos 9x12 Graphics Tablet -/* WCH products*/ -product WCH CH341SER 0x5523 CH341/CH340 USB-Serial Bridge -/* Western Digital products */ -product WESTERN COMBO 0x0200 Firewire USB Combo -product WESTERN EXTHDD 0x0400 External HDD -product WESTERN HUB 0x0500 USB HUB -product WESTERN MYBOOK 0x0901 MyBook External HDD - -/* Windbond Electronics */ -product WINBOND UH104 0x5518 4-port USB Hub - -/* WinMaxGroup products */ -product WINMAXGROUP FLASH64MC 0x6660 USB Flash Disk 64M-C - -/* Wistron NeWeb products */ -product WISTRONNEWEB UR045G 0x0427 PrismGT USB 2.0 WLAN -product WISTRONNEWEB UR055G 0x0711 UR055G -product WISTRONNEWEB AR5523_1 0x0826 AR5523 -product WISTRONNEWEB AR5523_1_NF 0x0827 AR5523 (no firmware) -product WISTRONNEWEB AR5523_2 0x082a AR5523 -product WISTRONNEWEB AR5523_2_NF 0x0829 AR5523 (no firmware) - -/* Xerox products */ -product XEROX WCM15 0xffef WorkCenter M15 - -/* Xirlink products */ -product XIRLINK PCCAM 0x8080 IBM PC Camera - -/* Xyratex products */ -product XYRATEX PRISM_GT_1 0x2000 PrismGT USB 2.0 WLAN -product XYRATEX PRISM_GT_2 0x2002 PrismGT USB 2.0 WLAN - -/* Y-E Data products */ -product YEDATA FLASHBUSTERU 0x0000 Flashbuster-U - -/* Yamaha products */ -product YAMAHA UX256 0x1000 UX256 MIDI I/F -product YAMAHA UX96 0x1008 UX96 MIDI I/F -product YAMAHA RTA54I 0x4000 NetVolante RTA54i Broadband&ISDN Router -product YAMAHA RTA55I 0x4004 NetVolante RTA55i Broadband VoIP Router -product YAMAHA RTW65B 0x4001 NetVolante RTW65b Broadband Wireless Router -product YAMAHA RTW65I 0x4002 NetVolante RTW65i Broadband&ISDN Wireless Router - -/* Yano products */ -product YANO U640MO 0x0101 U640MO-03 -product YANO FW800HD 0x05fc METALWEAR-HDD - -/* Yiso Wireless Co. products */ -product YISO C893 0xc893 CDMA 2000 1xEVDO PC Card - -/* Z-Com products */ -product ZCOM M4Y750 0x0001 M4Y-750 -product ZCOM XI725 0x0002 XI-725/726 -product ZCOM XI735 0x0005 XI-735 -product ZCOM XG703A 0x0008 PrismGT USB 2.0 WLAN -product ZCOM ZD1211 0x0011 ZD1211 -product ZCOM AR5523 0x0012 AR5523 -product ZCOM AR5523_NF 0x0013 AR5523 driver (no firmware) -product ZCOM ZD1211B 0x001a ZD1211B - -/* Zinwell products */ -product ZINWELL RT2570 0x0260 RT2570 - -/* Zoom Telephonics, Inc. products */ -product ZOOM 2986L 0x9700 2986L Fax modem - -/* Zoran Microelectronics products */ -product ZORAN EX20DSC 0x4343 Digital Camera EX-20 DSC - -/* Zydas Technology Corporation products */ -product ZYDAS ZD1211 0x1211 ZD1211 WLAN abg -product ZYDAS ZD1211B 0x1215 ZD1211B - -/* ZyXEL Communication Co. products */ -product ZYXEL OMNI56K 0x1500 Omni 56K Plus -product ZYXEL 980N 0x2011 Scorpion-980N keyboard -product ZYXEL ZYAIRG220 0x3401 ZyAIR G-220 -product ZYXEL G200V2 0x3407 G-200 v2 -product ZYXEL AG225H 0x3409 AG-225H -product ZYXEL M202 0x340a M-202 -product ZYXEL G220V2 0x340f G-220 v2 -product ZYXEL G202 0x3410 G-202 diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c deleted file mode 100644 index a733bbf..0000000 --- a/sys/dev/usb/usbdi.c +++ /dev/null @@ -1,1383 +0,0 @@ -/* $NetBSD: usbdi.c,v 1.106 2004/10/24 12:52:40 augustss Exp $ */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 1998 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/param.h> -#include <sys/systm.h> -#include <sys/module.h> -#include <sys/bus.h> -#include "usb_if.h" -#if defined(DIAGNOSTIC) && defined(__i386__) -#include <machine/cpu.h> -#endif -#include <sys/malloc.h> -#include <sys/proc.h> - -#include <machine/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usb_mem.h> -#include <dev/usb/usb_quirks.h> - -#include "usb_if.h" -#define delay(d) DELAY(d) - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -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); -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); -static int usbd_xfer_isread(usbd_xfer_handle xfer); -static void usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg, - int error); -static void usbd_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg, - int error); - -static int usbd_nbuses = 0; - -void -usbd_init(void) -{ - usbd_nbuses++; -} - -void -usbd_finish(void) -{ - --usbd_nbuses; -} - -static __inline int -usbd_xfer_isread(usbd_xfer_handle xfer) -{ - if (xfer->rqflags & URQ_REQUEST) - return (xfer->request.bmRequestType & UT_READ); - else - return (xfer->pipe->endpoint->edesc->bEndpointAddress & - UE_DIR_IN); -} - -#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) -{ - usbd_xfer_handle xfer; - - printf("usbd_dump_queue: pipe=%p\n", pipe); - STAILQ_FOREACH(xfer, &pipe->queue, next) { - 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 -usbd_open_pipe(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe) -{ - return (usbd_open_pipe_ival(iface, address, flags, pipe, - USBD_DEFAULT_INTERVAL)); -} - -usbd_status -usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe, int ival) -{ - usbd_pipe_handle p; - struct usbd_endpoint *ep; - usbd_status err; - int i; - - DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n", - iface, address, flags)); - - for (i = 0; i < iface->idesc->bNumEndpoints; i++) { - ep = &iface->endpoints[i]; - if (ep->edesc == NULL) - return (USBD_IOERROR); - if (ep->edesc->bEndpointAddress == address) - goto found; - } - return (USBD_BAD_ADDRESS); - found: - if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0) - return (USBD_IN_USE); - err = usbd_setup_pipe(iface->device, iface, ep, ival, &p); - if (err) - return (err); - LIST_INSERT_HEAD(&iface->pipes, p, next); - *pipe = p; - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address, - u_int8_t flags, usbd_pipe_handle *pipe, - usbd_private_handle priv, void *buffer, u_int32_t len, - usbd_callback cb, int ival) -{ - usbd_status err; - usbd_xfer_handle xfer; - usbd_pipe_handle ipipe; - - DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n", - address, flags, len)); - - err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, - &ipipe, ival); - if (err) - return (err); - xfer = usbd_alloc_xfer(iface->device); - if (xfer == NULL) { - err = USBD_NOMEM; - goto bad1; - } - usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags, - USBD_NO_TIMEOUT, cb); - ipipe->intrxfer = xfer; - ipipe->repeat = 1; - *pipe = ipipe; - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS && err) - goto bad2; - return (USBD_NORMAL_COMPLETION); - - bad2: - ipipe->intrxfer = NULL; - ipipe->repeat = 0; - usbd_free_xfer(xfer); - bad1: - usbd_close_pipe(ipipe); - return (err); -} - -usbd_status -usbd_close_pipe(usbd_pipe_handle pipe) -{ -#ifdef DIAGNOSTIC - if (pipe == NULL) { - printf("usbd_close_pipe: pipe==NULL\n"); - return (USBD_NORMAL_COMPLETION); - } -#endif - - if (--pipe->refcnt != 0) - return (USBD_NORMAL_COMPLETION); - if (! STAILQ_EMPTY(&pipe->queue)) - return (USBD_PENDING_REQUESTS); - LIST_REMOVE(pipe, next); - pipe->endpoint->refcnt--; - pipe->methods->close(pipe); - if (pipe->intrxfer != NULL) - usbd_free_xfer(pipe->intrxfer); - free(pipe, M_USB); - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_transfer(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - struct usb_dma_mapping *dmap = &xfer->dmamap; - usbd_status err; - u_int size; - int s; - - DPRINTFN(5,("%s: xfer=%p, flags=0x%b, rqflags=0x%b, " - "length=%d, buffer=%p, allocbuf=%p, pipe=%p, running=%d\n", - __func__, xfer, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS, - xfer->length, xfer->buffer, xfer->allocbuf, pipe, pipe->running)); -#ifdef USB_DEBUG - if (usbdebug > 5) - usbd_dump_queue(pipe); -#endif - xfer->done = 0; - - if (pipe->aborting) - return (USBD_CANCELLED); - - size = xfer->length; - /* If there is no buffer, allocate one. */ - if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) { - bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag; - -#ifdef DIAGNOSTIC - if (xfer->rqflags & URQ_AUTO_DMABUF) - printf("usbd_transfer: has old buffer!\n"); -#endif - err = bus_dmamap_create(tag, 0, &dmap->map); - if (err) - return (USBD_NOMEM); - - xfer->rqflags |= URQ_AUTO_DMABUF; - err = bus_dmamap_load(tag, dmap->map, xfer->buffer, size, - usbd_start_transfer, xfer, 0); - if (err != 0 && err != EINPROGRESS) { - xfer->rqflags &= ~URQ_AUTO_DMABUF; - bus_dmamap_destroy(tag, dmap->map); - return (USBD_INVAL); - } - } else if (size != 0) { - usbd_start_transfer(xfer, dmap->segs, dmap->nsegs, 0); - } else { - usbd_start_transfer(xfer, NULL, 0, 0); - } - - if (!(xfer->flags & USBD_SYNCHRONOUS)) - return (xfer->done ? USBD_NORMAL_COMPLETION : USBD_IN_PROGRESS); - - /* Sync transfer, wait for completion. */ - s = splusb(); - while (!xfer->done) { - if (pipe->device->bus->use_polling) - panic("usbd_transfer: not done"); - tsleep(xfer, PRIBIO, "usbsyn", 0); - } - splx(s); - return (xfer->status); -} - -static void -usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - usbd_xfer_handle xfer = arg; - usbd_pipe_handle pipe = xfer->pipe; - struct usb_dma_mapping *dmap = &xfer->dmamap; - bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag; - int err, i; - - if (error != 0) { - KASSERT(xfer->rqflags & URQ_AUTO_DMABUF, - ("usbd_start_transfer: error with non-auto buf")); - if (nseg > 0) - bus_dmamap_unload(tag, dmap->map); - bus_dmamap_destroy(tag, dmap->map); - /* XXX */ - usb_insert_transfer(xfer); - xfer->status = USBD_IOERROR; - usb_transfer_complete(xfer); - return; - } - - if (segs != dmap->segs) { - for (i = 0; i < nseg; i++) - dmap->segs[i] = segs[i]; - } - dmap->nsegs = nseg; - - if (nseg > 0) { - if (!usbd_xfer_isread(xfer)) { - /* - * Copy data if it is not already in the correct - * buffer. - */ - if (!(xfer->flags & USBD_NO_COPY) && - xfer->allocbuf != NULL && - xfer->buffer != xfer->allocbuf) - memcpy(xfer->allocbuf, xfer->buffer, - xfer->length); - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE); - } else if (xfer->rqflags & URQ_REQUEST) { - /* - * Even if we have no data portion we still need to - * sync the dmamap for the request data in the SETUP - * packet. - */ - bus_dmamap_sync(tag, dmap->map, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - } else - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREREAD); - } - err = pipe->methods->transfer(xfer); - if (err != USBD_IN_PROGRESS && err) { - if (xfer->rqflags & URQ_AUTO_DMABUF) { - bus_dmamap_unload(tag, dmap->map); - bus_dmamap_destroy(tag, dmap->map); - xfer->rqflags &= ~URQ_AUTO_DMABUF; - } - xfer->status = err; - usb_transfer_complete(xfer); - return; - } -} - -/* Like usbd_transfer(), but waits for completion. */ -usbd_status -usbd_sync_transfer(usbd_xfer_handle xfer) -{ - xfer->flags |= USBD_SYNCHRONOUS; - return (usbd_transfer(xfer)); -} - -struct usbd_allocstate { - usbd_xfer_handle xfer; - int done; - int error; - int waiting; -}; - -void * -usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) -{ - struct usbd_allocstate allocstate; - struct usb_dma_mapping *dmap = &xfer->dmamap; - bus_dma_tag_t tag = xfer->device->bus->buffer_dmatag; - void *buf; - usbd_status err; - int error, s; - - KASSERT((xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) == 0, - ("usbd_alloc_buffer: xfer already has a buffer")); - err = bus_dmamap_create(tag, 0, &dmap->map); - if (err) - return (NULL); - buf = malloc(size, M_USB, M_WAITOK); - - allocstate.xfer = xfer; - allocstate.done = 0; - allocstate.error = 0; - allocstate.waiting = 0; - error = bus_dmamap_load(tag, dmap->map, buf, size, usbd_alloc_callback, - &allocstate, 0); - if (error && error != EINPROGRESS) { - bus_dmamap_destroy(tag, dmap->map); - free(buf, M_USB); - return (NULL); - } - if (error == EINPROGRESS) { - /* Wait for completion. */ - s = splusb(); - allocstate.waiting = 1; - while (!allocstate.done) - tsleep(&allocstate, PRIBIO, "usbdab", 0); - splx(s); - error = allocstate.error; - } - if (error) { - bus_dmamap_unload(tag, dmap->map); - bus_dmamap_destroy(tag, dmap->map); - free(buf, M_USB); - return (NULL); - } - - xfer->allocbuf = buf; - xfer->rqflags |= URQ_DEV_DMABUF; - return (buf); -} - -void -usbd_free_buffer(usbd_xfer_handle xfer) -{ - struct usb_dma_mapping *dmap = &xfer->dmamap; - bus_dma_tag_t tag = xfer->device->bus->buffer_dmatag; - - KASSERT((xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) == - URQ_DEV_DMABUF, ("usbd_free_buffer: no/auto buffer")); - - xfer->rqflags &= ~URQ_DEV_DMABUF; - bus_dmamap_unload(tag, dmap->map); - bus_dmamap_destroy(tag, dmap->map); - free(xfer->allocbuf, M_USB); - xfer->allocbuf = NULL; -} - -void * -usbd_get_buffer(usbd_xfer_handle xfer) -{ - if (!(xfer->rqflags & URQ_DEV_DMABUF)) - return (NULL); - return (xfer->allocbuf); -} - -static void -usbd_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct usbd_allocstate *allocstate = arg; - usbd_xfer_handle xfer = allocstate->xfer; - struct usb_dma_mapping *dmap = &xfer->dmamap; - int i; - - allocstate->error = error; - if (error == 0) { - for (i = 0; i < nseg; i++) - dmap->segs[i] = segs[i]; - dmap->nsegs = nseg; - } - allocstate->done = 1; - if (allocstate->waiting) - wakeup(&allocstate); -} - -usbd_xfer_handle -usbd_alloc_xfer(usbd_device_handle dev) -{ - usbd_xfer_handle xfer; - - xfer = dev->bus->methods->allocx(dev->bus); - if (xfer == NULL) - return (NULL); - xfer->device = dev; - callout_init(&xfer->timeout_handle, 0); - DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer)); - return (xfer); -} - -usbd_status -usbd_free_xfer(usbd_xfer_handle xfer) -{ - DPRINTFN(5,("usbd_free_xfer: %p\n", xfer)); - if (xfer->rqflags & URQ_DEV_DMABUF) - usbd_free_buffer(xfer); -/* XXX Does FreeBSD need to do something similar? */ -#if defined(__NetBSD__) && defined(DIAGNOSTIC) - if (callout_pending(&xfer->timeout_handle)) { - callout_stop(&xfer->timeout_handle); - printf("usbd_free_xfer: timout_handle pending"); - } -#endif - xfer->device->bus->methods->freex(xfer->device->bus, xfer); - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - usbd_private_handle priv, void *buffer, u_int32_t length, - u_int16_t flags, u_int32_t timeout, - usbd_callback callback) -{ - xfer->pipe = pipe; - xfer->priv = priv; - xfer->buffer = buffer; - xfer->length = length; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = timeout; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->rqflags &= ~URQ_REQUEST; - xfer->nframes = 0; -} - -void -usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev, - usbd_private_handle priv, u_int32_t timeout, - usb_device_request_t *req, void *buffer, - u_int32_t length, u_int16_t flags, - usbd_callback callback) -{ - xfer->pipe = dev->default_pipe; - xfer->priv = priv; - xfer->buffer = buffer; - xfer->length = length; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = timeout; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->request = *req; - xfer->rqflags |= URQ_REQUEST; - xfer->nframes = 0; -} - -void -usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - usbd_private_handle priv, u_int16_t *frlengths, - u_int32_t nframes, u_int16_t flags, usbd_callback callback) -{ - int i; - - xfer->pipe = pipe; - xfer->priv = priv; - xfer->buffer = 0; - xfer->length = 0; - for (i = 0; i < nframes; i++) - xfer->length += frlengths[i]; - xfer->actlen = 0; - xfer->flags = flags; - xfer->timeout = USBD_NO_TIMEOUT; - xfer->status = USBD_NOT_STARTED; - xfer->callback = callback; - xfer->rqflags &= ~URQ_REQUEST; - xfer->frlengths = frlengths; - xfer->nframes = nframes; -} - -void -usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv, - void **buffer, u_int32_t *count, usbd_status *status) -{ - if (priv != NULL) - *priv = xfer->priv; - if (buffer != NULL) - *buffer = xfer->buffer; - if (count != NULL) - *count = xfer->actlen; - if (status != NULL) - *status = xfer->status; -} - -usb_config_descriptor_t * -usbd_get_config_descriptor(usbd_device_handle dev) -{ -#ifdef DIAGNOSTIC - if (dev == NULL) { - printf("usbd_get_config_descriptor: dev == NULL\n"); - return (NULL); - } -#endif - return (dev->cdesc); -} - -int -usbd_get_speed(usbd_device_handle dev) -{ - return (dev->speed); -} - -usb_interface_descriptor_t * -usbd_get_interface_descriptor(usbd_interface_handle iface) -{ -#ifdef DIAGNOSTIC - if (iface == NULL) { - printf("usbd_get_interface_descriptor: dev == NULL\n"); - return (NULL); - } -#endif - return (iface->idesc); -} - -usb_device_descriptor_t * -usbd_get_device_descriptor(usbd_device_handle dev) -{ - return (&dev->ddesc); -} - -usb_endpoint_descriptor_t * -usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index) -{ - if (index >= iface->idesc->bNumEndpoints) - return (0); - return (iface->endpoints[index].edesc); -} - -usbd_status -usbd_abort_pipe(usbd_pipe_handle pipe) -{ - usbd_status err; - int s; - -#ifdef DIAGNOSTIC - if (pipe == NULL) { - printf("usbd_close_pipe: pipe==NULL\n"); - return (USBD_NORMAL_COMPLETION); - } -#endif - s = splusb(); - err = usbd_ar_pipe(pipe); - splx(s); - return (err); -} - -usbd_status -usbd_abort_default_pipe(usbd_device_handle dev) -{ - return (usbd_abort_pipe(dev->default_pipe)); -} - -usbd_status -usbd_clear_endpoint_stall(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - usb_device_request_t req; - usbd_status err; - - DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); - - /* - * Clearing en endpoint stall resets the endpoint toggle, so - * do the same to the HC toggle. - */ - pipe->methods->cleartoggle(pipe); - - req.bmRequestType = UT_WRITE_ENDPOINT; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, UF_ENDPOINT_HALT); - USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); - USETW(req.wLength, 0); - err = usbd_do_request(dev, &req, 0); -#if 0 -XXX should we do this? - if (!err) { - pipe->state = USBD_PIPE_ACTIVE; - /* XXX activate pipe */ - } -#endif - return (err); -} - -usbd_status -usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe) -{ - usbd_device_handle dev = pipe->device; - usb_device_request_t req; - usbd_status err; - - pipe->methods->cleartoggle(pipe); - - req.bmRequestType = UT_WRITE_ENDPOINT; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, UF_ENDPOINT_HALT); - USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); - USETW(req.wLength, 0); - err = usbd_do_request_async(dev, &req, 0); - return (err); -} - -void -usbd_clear_endpoint_toggle(usbd_pipe_handle pipe) -{ - pipe->methods->cleartoggle(pipe); -} - -usbd_status -usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count) -{ -#ifdef DIAGNOSTIC - if (iface == NULL || iface->idesc == NULL) { - printf("usbd_endpoint_count: NULL pointer\n"); - return (USBD_INVAL); - } -#endif - *count = iface->idesc->bNumEndpoints; - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_interface_count(usbd_device_handle dev, u_int8_t *count) -{ - if (dev->cdesc == NULL) - return (USBD_NOT_CONFIGURED); - *count = dev->cdesc->bNumInterface; - return (USBD_NORMAL_COMPLETION); -} - -void -usbd_interface2device_handle(usbd_interface_handle iface, - usbd_device_handle *dev) -{ - *dev = iface->device; -} - -usbd_status -usbd_device2interface_handle(usbd_device_handle dev, - u_int8_t ifaceno, usbd_interface_handle *iface) -{ - if (dev->cdesc == NULL) - return (USBD_NOT_CONFIGURED); - if (ifaceno >= dev->cdesc->bNumInterface) - return (USBD_INVAL); - *iface = &dev->ifaces[ifaceno]; - return (USBD_NORMAL_COMPLETION); -} - -usbd_device_handle -usbd_pipe2device_handle(usbd_pipe_handle pipe) -{ - return (pipe->device); -} - -/* XXXX use altno */ -usbd_status -usbd_set_interface(usbd_interface_handle iface, int altidx) -{ - usb_device_request_t req; - usbd_status err; - void *endpoints; - - if (LIST_FIRST(&iface->pipes) != 0) - return (USBD_IN_USE); - - endpoints = iface->endpoints; - err = usbd_fill_iface_data(iface->device, iface->index, altidx); - if (err) - return (err); - - /* new setting works, we can free old endpoints */ - if (endpoints != NULL) - free(endpoints, M_USB); - -#ifdef DIAGNOSTIC - if (iface->idesc == NULL) { - printf("usbd_set_interface: NULL pointer\n"); - return (USBD_INVAL); - } -#endif - - req.bmRequestType = UT_WRITE_INTERFACE; - req.bRequest = UR_SET_INTERFACE; - USETW(req.wValue, iface->idesc->bAlternateSetting); - USETW(req.wIndex, iface->idesc->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(iface->device, &req, 0)); -} - -int -usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno) -{ - char *p = (char *)cdesc; - char *end = p + UGETW(cdesc->wTotalLength); - usb_interface_descriptor_t *d; - int n; - - for (n = 0; p < end; p += d->bLength) { - d = (usb_interface_descriptor_t *)p; - if (p + d->bLength <= end && - d->bDescriptorType == UDESC_INTERFACE && - d->bInterfaceNumber == ifaceno) - n++; - } - return (n); -} - -int -usbd_get_interface_altindex(usbd_interface_handle iface) -{ - return (iface->altindex); -} - -usbd_status -usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_INTERFACE; - req.bRequest = UR_GET_INTERFACE; - USETW(req.wValue, 0); - USETW(req.wIndex, iface->idesc->bInterfaceNumber); - USETW(req.wLength, 1); - return (usbd_do_request(iface->device, &req, aiface)); -} - -/*** Internal routines ***/ - -/* Dequeue all pipe operations, called at splusb(). */ -static usbd_status -usbd_ar_pipe(usbd_pipe_handle pipe) -{ - usbd_xfer_handle xfer; - - SPLUSBCHECK; - - DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); -#ifdef USB_DEBUG - if (usbdebug > 5) - usbd_dump_queue(pipe); -#endif - pipe->repeat = 0; - pipe->aborting = 1; - while ((xfer = STAILQ_FIRST(&pipe->queue)) != NULL) { - DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", - pipe, xfer, pipe->methods)); - /* Make the HC abort it (and invoke the callback). */ - pipe->methods->abort(xfer); - KASSERT(STAILQ_FIRST(&pipe->queue) != xfer, ("usbd_ar_pipe")); - /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ - } - pipe->aborting = 0; - return (USBD_NORMAL_COMPLETION); -} - -/* Called at splusb() */ -void -usb_transfer_complete(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - struct usb_dma_mapping *dmap = &xfer->dmamap; - bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag; - int sync = xfer->flags & USBD_SYNCHRONOUS; - int erred = xfer->status == USBD_CANCELLED || - xfer->status == USBD_TIMEOUT; - int repeat = pipe->repeat; - int polling; - - SPLUSBCHECK; - - DPRINTFN(5, ("%s: pipe=%p xfer=%p status=%d actlen=%d\n", - __func__, pipe, xfer, xfer->status, xfer->actlen)); - DPRINTFN(5,("%s: flags=0x%b, rqflags=0x%b, length=%d, buffer=%p\n", - __func__, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS, - xfer->length, xfer->buffer)); -#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) { - printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); - return; - } -#endif - polling = pipe->device->bus->use_polling; - /* XXXX */ - if (polling) - pipe->running = 0; - - if (xfer->actlen != 0 && usbd_xfer_isread(xfer)) { - bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_POSTREAD); - /* Copy data if it is not already in the correct buffer. */ - if (!(xfer->flags & USBD_NO_COPY) && xfer->allocbuf != NULL && - xfer->buffer != xfer->allocbuf) - memcpy(xfer->buffer, xfer->allocbuf, xfer->actlen); - } - - /* if we mapped the buffer in usbd_transfer() we unmap it here. */ - if (xfer->rqflags & URQ_AUTO_DMABUF) { - if (!repeat) { - bus_dmamap_unload(tag, dmap->map); - bus_dmamap_destroy(tag, dmap->map); - xfer->rqflags &= ~URQ_AUTO_DMABUF; - } - } - - if (!repeat) { - /* Remove request from queue. */ -#ifdef DIAGNOSTIC - xfer->busy_free = XFER_BUSY; -#endif - KASSERT(STAILQ_FIRST(&pipe->queue) == xfer, - ("usb_transfer_complete: bad dequeue")); - STAILQ_REMOVE_HEAD(&pipe->queue, next); - } - DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n", - repeat, STAILQ_FIRST(&pipe->queue))); - - /* Count completed transfers. */ - ++pipe->device->bus->stats.uds_requests - [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; - - xfer->done = 1; - if (!xfer->status && xfer->actlen < xfer->length && - !(xfer->flags & USBD_SHORT_XFER_OK)) { - DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n", - xfer->actlen, xfer->length)); - xfer->status = USBD_SHORT_XFER; - } - - /* - * For repeat operations, call the callback first, as the xfer - * will not go away and the "done" method may modify it. Otherwise - * reverse the order in case the callback wants to free or reuse - * the xfer. - */ - if (repeat) { - if (xfer->callback) - xfer->callback(xfer, xfer->priv, xfer->status); - pipe->methods->done(xfer); - } else { - pipe->methods->done(xfer); - if (xfer->callback) - xfer->callback(xfer, xfer->priv, xfer->status); - } - - if (sync && !polling) - wakeup(xfer); - - if (!repeat) { - /* XXX should we stop the queue on all errors? */ - if (erred && pipe->iface != NULL) /* not control pipe */ - pipe->running = 0; - else - usbd_start_next(pipe); - } -} - -usbd_status -usb_insert_transfer(usbd_xfer_handle xfer) -{ - usbd_pipe_handle pipe = xfer->pipe; - usbd_status err; - int s; - - DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", - pipe, pipe->running, 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(); - KASSERT(STAILQ_FIRST(&pipe->queue) != xfer, ("usb_insert_transfer")); - STAILQ_INSERT_TAIL(&pipe->queue, xfer, next); - if (pipe->running) - err = USBD_IN_PROGRESS; - else { - pipe->running = 1; - err = USBD_NORMAL_COMPLETION; - } - splx(s); - return (err); -} - -/* Called at splusb() */ -void -usbd_start_next(usbd_pipe_handle pipe) -{ - usbd_xfer_handle xfer; - usbd_status err; - - SPLUSBCHECK; - -#ifdef DIAGNOSTIC - if (pipe == NULL) { - printf("usbd_start_next: pipe == NULL\n"); - return; - } - if (pipe->methods == NULL || pipe->methods->start == NULL) { - printf("usbd_start_next: pipe=%p no start method\n", pipe); - return; - } -#endif - - /* Get next request in queue. */ - xfer = STAILQ_FIRST(&pipe->queue); - DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); - if (xfer == NULL) { - pipe->running = 0; - } else { - err = pipe->methods->start(xfer); - if (err != USBD_IN_PROGRESS) { - printf("usbd_start_next: error=%d\n", err); - pipe->running = 0; - /* XXX do what? */ - } - } -} - -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)); -} - -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) -{ - return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req, - data, flags, actlen, timo)); -} - -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) -{ - usbd_xfer_handle xfer; - usbd_status err; - -#ifdef DIAGNOSTIC -/* XXX amd64 too? */ -#if defined(__i386__) - KASSERT(curthread->td_intr_nesting_level == 0, - ("usbd_do_request: in interrupt context")); -#endif - if (dev->bus->intr_context) { - printf("usbd_do_request: not in process context\n"); - return (USBD_INVAL); - } -#endif - - xfer = usbd_alloc_xfer(dev); - if (xfer == NULL) - return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, timeout, req, - data, UGETW(req->wLength), flags, 0); - xfer->pipe = pipe; - err = usbd_sync_transfer(xfer); -#if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (xfer->actlen > xfer->length) - DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" - "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - dev->address, xfer->request.bmRequestType, - xfer->request.bRequest, UGETW(xfer->request.wValue), - UGETW(xfer->request.wIndex), - UGETW(xfer->request.wLength), - xfer->length, xfer->actlen)); -#endif - if (actlen != NULL) - *actlen = xfer->actlen; - if (err == USBD_STALLED) { - /* - * The control endpoint has stalled. Control endpoints - * should not halt, but some may do so anyway so clear - * any halt condition. - */ - usb_device_request_t treq; - usb_status_t status; - u_int16_t s; - usbd_status nerr; - - treq.bmRequestType = UT_READ_ENDPOINT; - treq.bRequest = UR_GET_STATUS; - USETW(treq.wValue, 0); - USETW(treq.wIndex, 0); - USETW(treq.wLength, sizeof(usb_status_t)); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, - &treq, &status,sizeof(usb_status_t), - 0, 0); - nerr = usbd_sync_transfer(xfer); - if (nerr) - goto bad; - s = UGETW(status.wStatus); - DPRINTF(("usbd_do_request: status = 0x%04x\n", s)); - if (!(s & UES_HALT)) - goto bad; - treq.bmRequestType = UT_WRITE_ENDPOINT; - treq.bRequest = UR_CLEAR_FEATURE; - USETW(treq.wValue, UF_ENDPOINT_HALT); - USETW(treq.wIndex, 0); - USETW(treq.wLength, 0); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, - &treq, &status, 0, 0, 0); - nerr = usbd_sync_transfer(xfer); - if (nerr) - goto bad; - } - - bad: - usbd_free_xfer(xfer); - return (err); -} - -void -usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ -#if defined(USB_DEBUG) || defined(DIAGNOSTIC) - if (xfer->actlen > xfer->length) - DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" - "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", - xfer->pipe->device->address, - xfer->request.bmRequestType, - xfer->request.bRequest, UGETW(xfer->request.wValue), - UGETW(xfer->request.wIndex), - UGETW(xfer->request.wLength), - xfer->length, xfer->actlen)); -#endif - usbd_free_xfer(xfer); -} - -/* - * Execute a request without waiting for completion. - * Can be used from interrupt context. - */ -usbd_status -usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req, - void *data) -{ - usbd_xfer_handle xfer; - usbd_status err; - - xfer = usbd_alloc_xfer(dev); - if (xfer == NULL) - return (USBD_NOMEM); - usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, - data, UGETW(req->wLength), 0, usbd_do_request_async_cb); - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS && err) { - usbd_free_xfer(xfer); - return (err); - } - return (USBD_NORMAL_COMPLETION); -} - -const struct usbd_quirks * -usbd_get_quirks(usbd_device_handle dev) -{ -#ifdef DIAGNOSTIC - if (dev == NULL) { - printf("usbd_get_quirks: dev == NULL\n"); - return 0; - } -#endif - return (dev->quirks); -} - -/* XXX do periodic free() of free list */ - -/* - * Called from keyboard driver when in polling mode. - */ -void -usbd_dopoll(usbd_interface_handle iface) -{ - iface->device->bus->methods->do_poll(iface->device->bus); -} - -void -usbd_set_polling(usbd_device_handle dev, int on) -{ - if (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); -} - -usbd_status -usbd_reset_device(usbd_device_handle dev) -{ - usbd_device_handle parent = dev->myhub; - struct usbd_port *up = dev->powersrc; - - return usbd_reset_port(parent, up->portno, &up->status); -} - - -usb_endpoint_descriptor_t * -usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address) -{ - struct usbd_endpoint *ep; - int i; - - for (i = 0; i < iface->idesc->bNumEndpoints; i++) { - ep = &iface->endpoints[i]; - if (ep->edesc->bEndpointAddress == address) - return (iface->endpoints[i].edesc); - } - return (0); -} - -/* - * usbd_ratecheck() can limit the number of error messages that occurs. - * When a device is unplugged it may take up to 0.25s for the hub driver - * to notice it. If the driver continuosly tries to do I/O operations - * this can generate a large number of messages. - */ -int -usbd_ratecheck(struct timeval *last) -{ - if (last->tv_sec == time_second) - return (0); - last->tv_sec = time_second; - return (1); -} - -/* - * Search for a vendor/product pair in an array. The item size is - * given as an argument. - */ -const struct usb_devno * -usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz, - u_int16_t vendor, u_int16_t product) -{ - while (nentries-- > 0) { - u_int16_t tproduct = tbl->ud_product; - if (tbl->ud_vendor == vendor && - (tproduct == product || tproduct == USB_PRODUCT_ANY)) - return (tbl); - tbl = (const struct usb_devno *)((const char *)tbl + sz); - } - return (NULL); -} - - -void -usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter) -{ - const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); - - iter->cur = (const uByte *)cd; - iter->end = (const uByte *)cd + UGETW(cd->wTotalLength); -} - -const usb_descriptor_t * -usb_desc_iter_next(usbd_desc_iter_t *iter) -{ - const usb_descriptor_t *desc; - - if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) { - if (iter->cur != iter->end) - printf("usb_desc_iter_next: bad descriptor\n"); - return NULL; - } - desc = (const usb_descriptor_t *)iter->cur; - if (desc->bLength == 0) { - printf("usb_desc_iter_next: descriptor length = 0\n"); - return NULL; - } - iter->cur += desc->bLength; - if (iter->cur > iter->end) { - printf("usb_desc_iter_next: descriptor length too large\n"); - return NULL; - } - return desc; -} - -usbd_status -usbd_get_string(usbd_device_handle dev, int si, char *buf, size_t len) -{ - int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE; - usb_string_descriptor_t us; - char *s; - int i, n; - u_int16_t c; - usbd_status err; - int size; - - buf[0] = '\0'; - if (len == 0) - return (USBD_NORMAL_COMPLETION); - if (si == 0) - return (USBD_INVAL); - if (dev->quirks->uq_flags & UQ_NO_STRINGS) - return (USBD_STALLED); - if (dev->langid == USBD_NOLANG) { - /* Set up default language */ - err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us, - &size); - if (err || size < 4) { - DPRINTFN(-1,("usbd_get_string: getting lang failed, using 0\n")); - dev->langid = 0; /* Well, just pick something then */ - } else { - /* Pick the first language as the default. */ - dev->langid = UGETW(us.bString[0]); - } - } - err = usbd_get_string_desc(dev, si, dev->langid, &us, &size); - if (err) - return (err); - s = buf; - n = size / 2 - 1; - for (i = 0; i < n && i < len - 1; i++) { - c = UGETW(us.bString[i]); - /* Convert from Unicode, handle buggy strings. */ - if ((c & 0xff00) == 0) - *s++ = c; - else if ((c & 0x00ff) == 0 && swap) - *s++ = c >> 8; - else - *s++ = '?'; - } - *s++ = 0; - return (USBD_NORMAL_COMPLETION); -} - -int -usbd_driver_load(module_t mod, int what, void *arg) -{ - /* XXX should implement something like a function that removes all generic devices */ - - return (0); -} diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h deleted file mode 100644 index ef59039..0000000 --- a/sys/dev/usb/usbdi.h +++ /dev/null @@ -1,289 +0,0 @@ -/* $NetBSD: usbdi.h,v 1.64 2004/10/23 13:26:34 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _USBDI_H_ -#define _USBDI_H_ - -typedef struct usbd_bus *usbd_bus_handle; -typedef struct usbd_device *usbd_device_handle; -typedef struct usbd_interface *usbd_interface_handle; -typedef struct usbd_pipe *usbd_pipe_handle; -typedef struct usbd_xfer *usbd_xfer_handle; -typedef void *usbd_private_handle; - -typedef enum { /* keep in sync with usbd_status_msgs */ - USBD_NORMAL_COMPLETION = 0, /* must be 0 */ - USBD_IN_PROGRESS, /* 1 */ - /* 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_ERROR_MAX /* must be last */ -} usbd_status; - -typedef void (*usbd_callback)(usbd_xfer_handle, usbd_private_handle, - usbd_status); - -/* Open flags */ -#define USBD_EXCLUSIVE_USE 0x01 - -/* Use default (specified by ep. desc.) interval on interrupt pipe */ -#define USBD_DEFAULT_INTERVAL (-1) - -/* Request flags */ -#define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */ -#define USBD_SYNCHRONOUS 0x02 /* wait for completion */ -/* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */ -#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */ - -#define USBD_BITS "\20\1NO_COPY\2SYNCHRONOUS\4FORCE_SHORT_XFER" - -#define USBD_NO_TIMEOUT 0 -#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ - -usbd_status usbd_open_pipe(usbd_interface_handle, u_int8_t, - u_int8_t, usbd_pipe_handle *); -usbd_status usbd_close_pipe(usbd_pipe_handle); -usbd_status usbd_transfer(usbd_xfer_handle); -usbd_xfer_handle usbd_alloc_xfer(usbd_device_handle); -usbd_status usbd_free_xfer(usbd_xfer_handle); -void usbd_setup_xfer(usbd_xfer_handle, usbd_pipe_handle, - usbd_private_handle, void *, - u_int32_t, u_int16_t, u_int32_t, - usbd_callback); -void usbd_setup_default_xfer(usbd_xfer_handle, usbd_device_handle, - usbd_private_handle, u_int32_t, - usb_device_request_t *, void *, - u_int32_t, u_int16_t, usbd_callback); -void usbd_setup_isoc_xfer(usbd_xfer_handle, usbd_pipe_handle, - usbd_private_handle, u_int16_t *, - u_int32_t, u_int16_t, usbd_callback); -void usbd_get_xfer_status(usbd_xfer_handle, usbd_private_handle *, - void **, u_int32_t *, usbd_status *); -usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor - (usbd_interface_handle, u_int8_t); -usbd_status usbd_abort_pipe(usbd_pipe_handle); -usbd_status usbd_abort_default_pipe(usbd_device_handle); -usbd_status usbd_clear_endpoint_stall(usbd_pipe_handle); -usbd_status usbd_clear_endpoint_stall_async(usbd_pipe_handle); -void usbd_clear_endpoint_toggle(usbd_pipe_handle); -usbd_status usbd_endpoint_count(usbd_interface_handle, u_int8_t *); -usbd_status usbd_interface_count(usbd_device_handle, u_int8_t *); -void usbd_interface2device_handle(usbd_interface_handle, - usbd_device_handle *); -usbd_status usbd_device2interface_handle(usbd_device_handle, - u_int8_t, usbd_interface_handle *); - -usbd_device_handle usbd_pipe2device_handle(usbd_pipe_handle); -void *usbd_alloc_buffer(usbd_xfer_handle, u_int32_t); -void usbd_free_buffer(usbd_xfer_handle); -void *usbd_get_buffer(usbd_xfer_handle); -usbd_status usbd_sync_transfer(usbd_xfer_handle); -usbd_status usbd_open_pipe_intr(usbd_interface_handle, u_int8_t, - u_int8_t, usbd_pipe_handle *, - usbd_private_handle, void *, - u_int32_t, usbd_callback, int); -usbd_status usbd_do_request(usbd_device_handle, usb_device_request_t *, void *); -usbd_status usbd_do_request_async(usbd_device_handle, - usb_device_request_t *, void *); -usbd_status usbd_do_request_flags(usbd_device_handle, usb_device_request_t *, - void *, u_int16_t, int*, u_int32_t); -usbd_status usbd_do_request_flags_pipe(usbd_device_handle, usbd_pipe_handle, - usb_device_request_t *, void *, u_int16_t, int *, u_int32_t); -usb_interface_descriptor_t *usbd_get_interface_descriptor - (usbd_interface_handle); -usb_config_descriptor_t *usbd_get_config_descriptor(usbd_device_handle); -usb_device_descriptor_t *usbd_get_device_descriptor(usbd_device_handle); -int usbd_get_speed(usbd_device_handle); -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, u_int8_t *); -void usbd_fill_deviceinfo(usbd_device_handle, struct usb_device_info *, int); -int usbd_get_interface_altindex(usbd_interface_handle); - -usb_interface_descriptor_t *usbd_find_idesc(usb_config_descriptor_t *, - int, int); -usb_endpoint_descriptor_t *usbd_find_edesc(usb_config_descriptor_t *, - int, int, int); - -void usbd_dopoll(usbd_interface_handle); -void usbd_set_polling(usbd_device_handle, int); -usbd_status usbd_reset_device(usbd_device_handle); - -const char *usbd_errstr(usbd_status); - -void usbd_add_dev_event(int, usbd_device_handle); -void usbd_add_drv_event(int, usbd_device_handle, device_t); - -void usbd_devinfo(usbd_device_handle, int, char *); -const struct usbd_quirks *usbd_get_quirks(usbd_device_handle); -usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor - (usbd_interface_handle, u_int8_t); - -usbd_status usbd_reload_device_desc(usbd_device_handle); - -int usbd_ratecheck(struct timeval *last); - -usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf, - size_t len); - -/* An iterator for descriptors. */ -typedef struct { - const uByte *cur; - const uByte *end; -} usbd_desc_iter_t; -void usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter); -const usb_descriptor_t *usb_desc_iter_next(usbd_desc_iter_t *iter); - -/* - * The usb_task structs form a queue of things to run in the USB event - * thread. Normally this is just device discovery when a connect/disconnect - * has been detected. But it may also be used by drivers that need to - * perform (short) tasks that must have a process context. - */ -struct usb_task { - TAILQ_ENTRY(usb_task) next; - void (*fun)(void *); - void *arg; - int queue; -}; -#define USB_TASKQ_HC 0 -#define USB_TASKQ_DRIVER 1 -#define USB_NUM_TASKQS 2 -#define USB_TASKQ_NAMES {"usbtask-hc", "usbtask-dr"} - -void usb_add_task(usbd_device_handle, struct usb_task *, int queue); -void usb_rem_task(usbd_device_handle, struct usb_task *); -#define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->queue = -1) - -struct usb_devno { - u_int16_t ud_vendor; - u_int16_t ud_product; -}; -const struct usb_devno *usb_match_device(const struct usb_devno *, - u_int, u_int, u_int16_t, u_int16_t); -#define usb_lookup(tbl, vendor, product) \ - usb_match_device((const struct usb_devno *)(tbl), sizeof (tbl) / sizeof ((tbl)[0]), sizeof ((tbl)[0]), (vendor), (product)) -#define USB_PRODUCT_ANY 0xffff - -/* NetBSD attachment information */ - -/* Attach data */ -struct usb_attach_arg { - int port; - int configno; - int ifaceno; - int vendor; - int product; - int release; - int matchlvl; - usbd_device_handle device; /* current device */ - usbd_interface_handle iface; /* current interface */ - int usegeneric; - usbd_interface_handle *ifaces; /* all interfaces */ - int nifaces; /* number of interfaces */ -}; - -/* FreeBSD needs values less than zero */ -#define UMATCH_VENDOR_PRODUCT_REV (-10) -#define UMATCH_VENDOR_PRODUCT (-20) -#define UMATCH_VENDOR_DEVCLASS_DEVPROTO (-30) -#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO (-40) -#define UMATCH_DEVCLASS_DEVSUBCLASS (-50) -#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE (-60) -#define UMATCH_VENDOR_PRODUCT_CONF_IFACE (-70) -#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO (-80) -#define UMATCH_VENDOR_IFACESUBCLASS (-90) -#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO (-100) -#define UMATCH_IFACECLASS_IFACESUBCLASS (-110) -#define UMATCH_IFACECLASS (-120) -#define UMATCH_IFACECLASS_GENERIC (-130) -#define UMATCH_GENERIC (-140) -#define UMATCH_NONE (ENXIO) - -#define USBD_SHOW_DEVICE_CLASS 0x1 -#define USBD_SHOW_INTERFACE_CLASS 0x2 - -struct module; -int usbd_driver_load(struct module *mod, int what, void *arg); - -static inline int -usb_get_port(device_t dev) -{ - struct usb_attach_arg *uap = device_get_ivars(dev); - return (uap->port); -} - -static inline struct usbd_interface * -usb_get_iface(device_t dev) -{ - struct usb_attach_arg *uap = device_get_ivars(dev); - return (uap->iface); -} - -/* 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 -#define splusb splbio -#endif /* USB_USE_SOFTINTR */ -#define splhardusb splbio -#define IPL_USB IPL_BIO - -#endif /* _USBDI_H_ */ diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c deleted file mode 100644 index 78ea571..0000000 --- a/sys/dev/usb/usbdi_util.c +++ /dev/null @@ -1,539 +0,0 @@ -/* $NetBSD: usbdi_util.c,v 1.42 2004/12/03 08:53:40 augustss Exp $ */ - -/*- - * Copyright (c) 1998 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> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/bus.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (usbdebug) printf x -#define DPRINTFN(n,x) if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -usbd_status -usbd_get_desc(usbd_device_handle dev, int type, int index, int len, void *desc) -{ - usb_device_request_t req; - - DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n", - type, index, len)); - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, type, index); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, desc)); -} - -usbd_status -usbd_get_config_desc(usbd_device_handle dev, int confidx, - usb_config_descriptor_t *d) -{ - usbd_status err; - - DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx)); - err = usbd_get_desc(dev, UDESC_CONFIG, confidx, - USB_CONFIG_DESCRIPTOR_SIZE, d); - if (err) - return (err); - if (d->bDescriptorType != UDESC_CONFIG) { - DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc " - "len=%d type=%d\n", - confidx, d->bLength, d->bDescriptorType)); - return (USBD_INVAL); - } - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_get_config_desc_full(usbd_device_handle dev, int conf, void *d, int size) -{ - DPRINTFN(3,("usbd_get_config_desc_full: conf=%d\n", conf)); - return (usbd_get_desc(dev, UDESC_CONFIG, conf, size, d)); -} - -usbd_status -usbd_get_device_desc(usbd_device_handle dev, usb_device_descriptor_t *d) -{ - DPRINTFN(3,("usbd_get_device_desc:\n")); - return (usbd_get_desc(dev, UDESC_DEVICE, - 0, USB_DEVICE_DESCRIPTOR_SIZE, d)); -} - -usbd_status -usbd_get_device_status(usbd_device_handle dev, usb_status_t *st) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(usb_status_t)); - return (usbd_do_request(dev, &req, st)); -} - -usbd_status -usbd_get_hub_status(usbd_device_handle dev, usb_hub_status_t *st) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_CLASS_DEVICE; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(usb_hub_status_t)); - return (usbd_do_request(dev, &req, st)); -} - -usbd_status -usbd_set_address(usbd_device_handle dev, int addr) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return usbd_do_request(dev, &req, 0); -} - -usbd_status -usbd_get_port_status(usbd_device_handle dev, int port, usb_port_status_t *ps) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_CLASS_OTHER; - req.bRequest = UR_GET_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, port); - USETW(req.wLength, sizeof *ps); - return (usbd_do_request(dev, &req, ps)); -} - -usbd_status -usbd_clear_hub_feature(usbd_device_handle dev, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_DEVICE; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_hub_feature(usbd_device_handle dev, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_DEVICE; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_clear_port_feature(usbd_device_handle dev, int port, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_OTHER; - req.bRequest = UR_CLEAR_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, port); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_port_feature(usbd_device_handle dev, int port, int sel) -{ - usb_device_request_t req; - - req.bmRequestType = UT_WRITE_CLASS_OTHER; - req.bRequest = UR_SET_FEATURE; - USETW(req.wValue, sel); - USETW(req.wIndex, port); - USETW(req.wLength, 0); - 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) -{ - usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); - usbd_device_handle dev; - usb_device_request_t req; - - 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); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_PROTOCOL; - USETW(req.wValue, report); - USETW(req.wIndex, id->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_report(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; - - DPRINTFN(4, ("usbd_set_report: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, data)); -} - -usbd_status -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; - - DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request_async(dev, &req, data)); -} - -usbd_status -usbd_get_report(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; - - DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_REPORT; - USETW2(req.wValue, type, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, len); - return (usbd_do_request(dev, &req, data)); -} - -usbd_status -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; - - DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id)); - if (ifd == NULL) - return (USBD_IOERROR); - usbd_interface2device_handle(iface, &dev); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_IDLE; - USETW2(req.wValue, duration, id); - USETW(req.wIndex, ifd->bInterfaceNumber); - USETW(req.wLength, 0); - return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_get_report_descriptor(usbd_device_handle dev, int ifcno, - int size, void *d) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_INTERFACE; - req.bRequest = UR_GET_DESCRIPTOR; - USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */ - USETW(req.wIndex, ifcno); - USETW(req.wLength, size); - return (usbd_do_request(dev, &req, d)); -} - -usb_hid_descriptor_t * -usbd_get_hid_descriptor(usbd_interface_handle ifc) -{ - usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); - usbd_device_handle dev; - usb_config_descriptor_t *cdesc; - usb_hid_descriptor_t *hd; - char *p, *end; - - if (idesc == NULL) - return (NULL); - usbd_interface2device_handle(ifc, &dev); - cdesc = usbd_get_config_descriptor(dev); - - p = (char *)idesc + idesc->bLength; - end = (char *)cdesc + UGETW(cdesc->wTotalLength); - - for (; p < end; p += hd->bLength) { - hd = (usb_hid_descriptor_t *)p; - if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID) - return (hd); - if (hd->bDescriptorType == UDESC_INTERFACE) - break; - } - return (NULL); -} - -usbd_status -usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep, - struct malloc_type *mem) -{ - usb_interface_descriptor_t *id; - usb_hid_descriptor_t *hid; - usbd_device_handle dev; - usbd_status err; - - usbd_interface2device_handle(ifc, &dev); - id = usbd_get_interface_descriptor(ifc); - if (id == NULL) - return (USBD_INVAL); - hid = usbd_get_hid_descriptor(ifc); - if (hid == NULL) - return (USBD_IOERROR); - *sizep = UGETW(hid->descrs[0].wDescriptorLength); - *descp = malloc(*sizep, mem, M_NOWAIT); - if (*descp == NULL) - return (USBD_NOMEM); - err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, - *sizep, *descp); - if (err) { - free(*descp, mem); - *descp = NULL; - return (err); - } - return (USBD_NORMAL_COMPLETION); -} - -usbd_status -usbd_get_config(usbd_device_handle dev, u_int8_t *conf) -{ - usb_device_request_t req; - - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_CONFIG; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - return (usbd_do_request(dev, &req, conf)); -} - -static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); -static void -usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - wakeup(xfer); -} - -usbd_status -usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl) -{ - usbd_status err; - int s, error; - - usbd_setup_xfer(xfer, pipe, 0, buf, *size, - flags, timeout, usbd_bulk_transfer_cb); - DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size)); - s = splusb(); /* don't want callback until tsleep() */ - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS) { - splx(s); - return (err); - } - error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0); - splx(s); - if (error) { - DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error)); - usbd_abort_pipe(pipe); - return (USBD_INTERRUPTED); - } - usbd_get_xfer_status(xfer, NULL, NULL, size, &err); - DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size)); - if (err) { - DPRINTF(("usbd_bulk_transfer: error=%d\n", err)); - usbd_clear_endpoint_stall(pipe); - } - return (err); -} - -static void usbd_intr_transfer_cb(usbd_xfer_handle xfer, - usbd_private_handle priv, usbd_status status); -static void -usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv, - usbd_status status) -{ - wakeup(xfer); -} - -usbd_status -usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl) -{ - usbd_status err; - int s, error; - - usbd_setup_xfer(xfer, pipe, 0, buf, *size, - flags, timeout, usbd_intr_transfer_cb); - DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size)); - s = splusb(); /* don't want callback until tsleep() */ - err = usbd_transfer(xfer); - if (err != USBD_IN_PROGRESS) { - splx(s); - return (err); - } - error = tsleep(xfer, PZERO | PCATCH, lbl, 0); - splx(s); - if (error) { - DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error)); - usbd_abort_pipe(pipe); - return (USBD_INTERRUPTED); - } - usbd_get_xfer_status(xfer, NULL, NULL, size, &err); - DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size)); - if (err) { - DPRINTF(("usbd_intr_transfer: error=%d\n", err)); - usbd_clear_endpoint_stall(pipe); - } - return (err); -} - -void -usb_detach_wait(device_t dv) -{ - DPRINTF(("usb_detach_wait: waiting for %s\n", device_get_nameunit(dv))); - if (tsleep(dv, PZERO, "usbdet", hz * 60)) - printf("usb_detach_wait: %s didn't detach\n", - device_get_nameunit(dv)); - DPRINTF(("usb_detach_wait: %s done\n", device_get_nameunit(dv))); -} - -void -usb_detach_wakeup(device_t dv) -{ - DPRINTF(("usb_detach_wakeup: for %s\n", device_get_nameunit(dv))); - wakeup(dv); -} - -const usb_descriptor_t * -usb_find_desc(usbd_device_handle dev, int type, int subtype) -{ - usbd_desc_iter_t iter; - const usb_descriptor_t *desc; - - usb_desc_iter_init(dev, &iter); - for (;;) { - desc = usb_desc_iter_next(&iter); - if (!desc || (desc->bDescriptorType == type && - (subtype == USBD_SUBTYPE_ANY || - subtype == desc->bDescriptorSubtype))) - break; - } - return desc; -} diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h deleted file mode 100644 index b535f0c..0000000 --- a/sys/dev/usb/usbdi_util.h +++ /dev/null @@ -1,98 +0,0 @@ -/* $NetBSD: usbdi_util.h,v 1.31 2004/12/03 08:53:40 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -#ifndef _USBI_UTIL_H_ -#define _USBI_UTIL_H_ -usbd_status usbd_get_desc(usbd_device_handle dev, int type, - int index, int len, void *desc); -usbd_status usbd_get_config_desc(usbd_device_handle, int, - usb_config_descriptor_t *); -usbd_status usbd_get_config_desc_full(usbd_device_handle, int, void *, int); -usbd_status usbd_get_device_desc(usbd_device_handle dev, - usb_device_descriptor_t *d); -usbd_status usbd_set_address(usbd_device_handle dev, int addr); -usbd_status usbd_get_port_status(usbd_device_handle, - int, usb_port_status_t *); -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_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); -struct usb_hid_descriptor *usbd_get_hid_descriptor(usbd_interface_handle ifc); -usbd_status usbd_set_report(usbd_interface_handle iface, int type, int id, - void *data,int len); -usbd_status usbd_set_report_async(usbd_interface_handle iface, int type, - int id, void *data, int len); -usbd_status usbd_get_report(usbd_interface_handle iface, int type, int id, - void *data, int len); -usbd_status usbd_set_idle(usbd_interface_handle iface, int duration, int id); -usbd_status usbd_read_report_desc(usbd_interface_handle ifc, void **descp, - int *sizep, struct malloc_type *mem); -usbd_status usbd_get_config(usbd_device_handle dev, u_int8_t *conf); -usbd_status usbd_get_string_desc(usbd_device_handle dev, int sindex, - int langid,usb_string_descriptor_t *sdesc, - int *sizep); -void usbd_delay_ms(usbd_device_handle, u_int); - - -usbd_status usbd_set_config_no(usbd_device_handle dev, int no, int msg); -usbd_status usbd_set_config_index(usbd_device_handle dev, int index, int msg); - -usbd_status usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl); - -usbd_status usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, - u_int16_t flags, u_int32_t timeout, void *buf, - u_int32_t *size, char *lbl); - -void usb_detach_wait(device_t); -void usb_detach_wakeup(device_t); - -const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type, - int subtype); -#define USBD_SUBTYPE_ANY (~0) - -#endif /* _USBI_UTIL_H_ */ diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h deleted file mode 100644 index 603d691..0000000 --- a/sys/dev/usb/usbdivar.h +++ /dev/null @@ -1,322 +0,0 @@ -/* $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - -/* From usb_mem.h */ -struct usb_dma_block; -typedef struct { - struct usb_dma_block *block; - u_int offs; - u_int len; -} usb_dma_t; - -struct usbd_xfer; -struct usbd_pipe; - -struct usbd_endpoint { - usb_endpoint_descriptor_t *edesc; - int refcnt; - int savedtoggle; -}; - -struct usbd_bus_methods { - usbd_status (*open_pipe)(struct usbd_pipe *pipe); - void (*soft_intr)(void *); - void (*do_poll)(struct usbd_bus *); - usbd_status (*allocm)(struct usbd_bus *, usb_dma_t *, - u_int32_t bufsize); - void (*freem)(struct usbd_bus *, usb_dma_t *); - struct usbd_xfer * (*allocx)(struct usbd_bus *); - void (*freex)(struct usbd_bus *, struct usbd_xfer *); -}; - -struct usbd_pipe_methods { - usbd_status (*transfer)(usbd_xfer_handle xfer); - usbd_status (*start)(usbd_xfer_handle xfer); - void (*abort)(usbd_xfer_handle xfer); - void (*close)(usbd_pipe_handle pipe); - void (*cleartoggle)(usbd_pipe_handle pipe); - void (*done)(usbd_xfer_handle xfer); -}; - -struct usbd_tt { - struct usbd_hub *hub; -}; - -struct usbd_port { - usb_port_status_t status; - u_int16_t power; /* mA of current on port */ - u_int8_t portno; - u_int8_t restartcnt; -#define USBD_RESTART_MAX 5 - struct usbd_device *device; /* Connected device */ - struct usbd_device *parent; /* The ports hub */ - struct usbd_tt *tt; /* Transaction translator (if any) */ -}; - -struct usbd_hub { - usbd_status (*explore)(usbd_device_handle hub); - void *hubsoftc; - usb_hub_descriptor_t hubdesc; - struct usbd_port ports[1]; -}; - -struct usb_softc; - -/*****/ - -struct usbd_bus { - /* Filled by HC driver */ - device_t bdev; /* base device, host adapter */ - struct usbd_bus_methods *methods; - u_int32_t pipe_size; /* size of a pipe struct */ - /* Filled by usb driver */ - struct usbd_device *root_hub; - usbd_device_handle devices[USB_MAX_DEVICES]; - char needs_explore;/* a hub a signalled a change */ - char use_polling; - struct usb_softc *usbctl; - struct usb_device_stats stats; - int intr_context; - u_int no_intrs; - int usbrev; /* USB revision */ -#define USBREV_UNKNOWN 0 -#define USBREV_PRE_1_0 1 -#define USBREV_1_0 2 -#define USBREV_1_1 3 -#define USBREV_2_0 4 -#define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1", "2.0" } - -#ifdef USB_USE_SOFTINTR -#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS - void *soft; /* soft interrupt cookie */ -#else - struct callout softi; -#endif -#endif - - bus_dma_tag_t parent_dmatag; /* Base DMA tag */ - bus_dma_tag_t buffer_dmatag; /* Tag for transfer buffers */ -}; - -struct usbd_device { - struct usbd_bus *bus; /* our controller */ - struct usbd_pipe *default_pipe; /* pipe 0 */ - 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 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_port *myhsport; /* closest high speed port */ - struct usbd_endpoint def_ep; /* for pipe 0 */ - usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */ - struct usbd_interface *ifaces; /* array of all interfaces */ - usb_device_descriptor_t ddesc; /* device descriptor */ - usb_config_descriptor_t *cdesc; /* full config descr */ - const struct usbd_quirks *quirks; /* device quirks, always set */ - struct usbd_hub *hub; /* only if this is a hub */ - device_t *subdevs; /* sub-devices, 0 terminated */ - uint8_t *ifacenums; /* sub-device interfacenumbers */ -}; - -struct usbd_interface { - struct usbd_device *device; - usb_interface_descriptor_t *idesc; - int index; - int altindex; - struct usbd_endpoint *endpoints; - void *priv; - LIST_HEAD(, usbd_pipe) pipes; -}; - -struct usbd_pipe { - struct usbd_interface *iface; - struct usbd_device *device; - struct usbd_endpoint *endpoint; - int refcnt; - char running; - char aborting; - STAILQ_HEAD(, usbd_xfer) queue; - LIST_ENTRY(usbd_pipe) next; - - usbd_xfer_handle intrxfer; /* used for repeating requests */ - char repeat; - int interval; - - /* Filled by HC driver. */ - struct usbd_pipe_methods *methods; -}; - -#define USB_DMA_NSEG (btoc(MAXPHYS) + 1) - -/* DMA-capable memory buffer. */ -struct usb_dma_mapping { - bus_dma_segment_t segs[USB_DMA_NSEG]; /* The physical segments. */ - int nsegs; /* Number of segments. */ - bus_dmamap_t map; /* DMA mapping. */ -}; - -struct usbd_xfer { - struct usbd_pipe *pipe; - void *priv; - void *buffer; - u_int32_t length; - u_int32_t actlen; - u_int16_t flags; - u_int32_t timeout; - usbd_status status; - usbd_callback callback; - __volatile char done; -#ifdef DIAGNOSTIC - u_int32_t busy_free; -#define XFER_FREE 0x46524545 -#define XFER_BUSY 0x42555359 -#define XFER_ONQU 0x4f4e5155 -#endif - - /* For control pipe */ - usb_device_request_t request; - - /* For isoc */ - u_int16_t *frlengths; - int nframes; - - /* For memory allocation */ - struct usbd_device *device; - struct usb_dma_mapping dmamap; - void *allocbuf; - - int rqflags; -#define URQ_REQUEST 0x01 -#define URQ_AUTO_DMABUF 0x10 -#define URQ_DEV_DMABUF 0x20 - - STAILQ_ENTRY(usbd_xfer) next; - - void *hcpriv; /* private use by the HC driver */ - - struct callout timeout_handle; -}; - -#define URQ_BITS "\20\1REQUEST\5AUTO_DMABUF\6DEV_DMABUF" - -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); -usbd_status usbd_reset_port(usbd_device_handle dev, - int port, usb_port_status_t *ps); -usbd_status usbd_setup_pipe(usbd_device_handle dev, - usbd_interface_handle iface, - struct usbd_endpoint *, int, - usbd_pipe_handle *pipe); -usbd_status usbd_new_device(device_t parent, - usbd_bus_handle bus, int depth, - int lowspeed, int port, - struct usbd_port *); -void usbd_remove_device(usbd_device_handle, struct usbd_port *); -int usbd_printBCD(char *cp, int bcd); -usbd_status usbd_fill_iface_data(usbd_device_handle dev, int i, int a); -void usb_free_device(usbd_device_handle); - -usbd_status usb_insert_transfer(usbd_xfer_handle xfer); -void usb_transfer_complete(usbd_xfer_handle xfer); -void usb_disconnect_port(struct usbd_port *up, device_t); - -/* Routines from usb.c */ -void usb_needs_explore(usbd_device_handle); -void usb_schedsoftintr(struct usbd_bus *); - -/* - * XXX This check is extremely bogus. Bad Bad Bad. - */ -#if defined(DIAGNOSTIC) && 0 -#define SPLUSBCHECK \ - do { int _s = splusb(), _su = splusb(); \ - if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \ - _s, _su, __FILE__, __LINE__); \ - splx(_s); \ - } while (0) -#else -#define SPLUSBCHECK -#endif - -/* Locator stuff. */ - -/* XXX these values are used to statically bind some elements in the USB tree - * to specific driver instances. This should be somehow emulated in FreeBSD - * but can be done later on. - * The values are copied from the files.usb file in the NetBSD sources. - */ -#define UHUBCF_PORT_DEFAULT -1 -#define UHUBCF_CONFIGURATION_DEFAULT -1 -#define UHUBCF_INTERFACE_DEFAULT -1 -#define UHUBCF_VENDOR_DEFAULT -1 -#define UHUBCF_PRODUCT_DEFAULT -1 -#define UHUBCF_RELEASE_DEFAULT -1 - -#define uhubcf_port cf_loc[UHUBCF_PORT] -#define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION] -#define uhubcf_interface cf_loc[UHUBCF_INTERFACE] -#define uhubcf_vendor cf_loc[UHUBCF_VENDOR] -#define uhubcf_product cf_loc[UHUBCF_PRODUCT] -#define uhubcf_release cf_loc[UHUBCF_RELEASE] -#define UHUB_UNK_PORT UHUBCF_PORT_DEFAULT /* wildcarded 'port' */ -#define UHUB_UNK_CONFIGURATION UHUBCF_CONFIGURATION_DEFAULT /* wildcarded 'configuration' */ -#define UHUB_UNK_INTERFACE UHUBCF_INTERFACE_DEFAULT /* wildcarded 'interface' */ -#define UHUB_UNK_VENDOR UHUBCF_VENDOR_DEFAULT /* wildcarded 'vendor' */ -#define UHUB_UNK_PRODUCT UHUBCF_PRODUCT_DEFAULT /* wildcarded 'product' */ -#define UHUB_UNK_RELEASE UHUBCF_RELEASE_DEFAULT /* wildcarded 'release' */ - diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h deleted file mode 100644 index 8e0ecd5..0000000 --- a/sys/dev/usb/usbhid.h +++ /dev/null @@ -1,185 +0,0 @@ -/* $NetBSD: usbhid.h,v 1.9 2000/09/03 19:09:14 augustss Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 1998 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. - */ - - -#ifndef _USBHID_H_ -#define _USBHID_H_ - -#define UR_GET_HID_DESCRIPTOR 0x06 -#define UDESC_HID 0x21 -#define UDESC_REPORT 0x22 -#define UDESC_PHYSICAL 0x23 -#define UR_SET_HID_DESCRIPTOR 0x07 -#define UR_GET_REPORT 0x01 -#define UR_SET_REPORT 0x09 -#define UR_GET_IDLE 0x02 -#define UR_SET_IDLE 0x0a -#define UR_GET_PROTOCOL 0x03 -#define UR_SET_PROTOCOL 0x0b - -typedef struct usb_hid_descriptor { - uByte bLength; - uByte bDescriptorType; - uWord bcdHID; - uByte bCountryCode; - uByte bNumDescriptors; - struct { - uByte bDescriptorType; - uWord wDescriptorLength; - } descrs[1]; -} UPACKED usb_hid_descriptor_t; -#define USB_HID_DESCRIPTOR_SIZE(n) (9+(n)*3) - -/* Usage pages */ -#define HUP_UNDEFINED 0x0000 -#define HUP_GENERIC_DESKTOP 0x0001 -#define HUP_SIMULATION 0x0002 -#define HUP_VR_CONTROLS 0x0003 -#define HUP_SPORTS_CONTROLS 0x0004 -#define HUP_GAMING_CONTROLS 0x0005 -#define HUP_KEYBOARD 0x0007 -#define HUP_LEDS 0x0008 -#define HUP_BUTTON 0x0009 -#define HUP_ORDINALS 0x000a -#define HUP_TELEPHONY 0x000b -#define HUP_CONSUMER 0x000c -#define HUP_DIGITIZERS 0x000d -#define HUP_PHYSICAL_IFACE 0x000e -#define HUP_UNICODE 0x0010 -#define HUP_ALPHANUM_DISPLAY 0x0014 -#define HUP_MONITOR 0x0080 -#define HUP_MONITOR_ENUM_VAL 0x0081 -#define HUP_VESA_VC 0x0082 -#define HUP_VESA_CMD 0x0083 -#define HUP_POWER 0x0084 -#define HUP_BATTERY_SYSTEM 0x0085 -#define HUP_BARCODE_SCANNER 0x008b -#define HUP_SCALE 0x008c -#define HUP_CAMERA_CONTROL 0x0090 -#define HUP_ARCADE 0x0091 -#define HUP_MICROSOFT 0xff00 - -/* Usages, generic desktop */ -#define HUG_POINTER 0x0001 -#define HUG_MOUSE 0x0002 -#define HUG_JOYSTICK 0x0004 -#define HUG_GAME_PAD 0x0005 -#define HUG_KEYBOARD 0x0006 -#define HUG_KEYPAD 0x0007 -#define HUG_X 0x0030 -#define HUG_Y 0x0031 -#define HUG_Z 0x0032 -#define HUG_RX 0x0033 -#define HUG_RY 0x0034 -#define HUG_RZ 0x0035 -#define HUG_SLIDER 0x0036 -#define HUG_DIAL 0x0037 -#define HUG_WHEEL 0x0038 -#define HUG_HAT_SWITCH 0x0039 -#define HUG_COUNTED_BUFFER 0x003a -#define HUG_BYTE_COUNT 0x003b -#define HUG_MOTION_WAKEUP 0x003c -#define HUG_VX 0x0040 -#define HUG_VY 0x0041 -#define HUG_VZ 0x0042 -#define HUG_VBRX 0x0043 -#define HUG_VBRY 0x0044 -#define HUG_VBRZ 0x0045 -#define HUG_VNO 0x0046 -#define HUG_TWHEEL 0x0048 // M$ Wireless Intellimouse Wheel -#define HUG_SYSTEM_CONTROL 0x0080 -#define HUG_SYSTEM_POWER_DOWN 0x0081 -#define HUG_SYSTEM_SLEEP 0x0082 -#define HUG_SYSTEM_WAKEUP 0x0083 -#define HUG_SYSTEM_CONTEXT_MENU 0x0084 -#define HUG_SYSTEM_MAIN_MENU 0x0085 -#define HUG_SYSTEM_APP_MENU 0x0086 -#define HUG_SYSTEM_MENU_HELP 0x0087 -#define HUG_SYSTEM_MENU_EXIT 0x0088 -#define HUG_SYSTEM_MENU_SELECT 0x0089 -#define HUG_SYSTEM_MENU_RIGHT 0x008a -#define HUG_SYSTEM_MENU_LEFT 0x008b -#define HUG_SYSTEM_MENU_UP 0x008c -#define HUG_SYSTEM_MENU_DOWN 0x008d - -/* Usages Digitizers */ -#define HUD_UNDEFINED 0x0000 -#define HUD_TIP_PRESSURE 0x0030 -#define HUD_BARREL_PRESSURE 0x0031 -#define HUD_IN_RANGE 0x0032 -#define HUD_TOUCH 0x0033 -#define HUD_UNTOUCH 0x0034 -#define HUD_TAP 0x0035 -#define HUD_QUALITY 0x0036 -#define HUD_DATA_VALID 0x0037 -#define HUD_TRANSDUCER_INDEX 0x0038 -#define HUD_TABLET_FKEYS 0x0039 -#define HUD_PROGRAM_CHANGE_KEYS 0x003a -#define HUD_BATTERY_STRENGTH 0x003b -#define HUD_INVERT 0x003c -#define HUD_X_TILT 0x003d -#define HUD_Y_TILT 0x003e -#define HUD_AZIMUTH 0x003f -#define HUD_ALTITUDE 0x0040 -#define HUD_TWIST 0x0041 -#define HUD_TIP_SWITCH 0x0042 -#define HUD_SEC_TIP_SWITCH 0x0043 -#define HUD_BARREL_SWITCH 0x0044 -#define HUD_ERASER 0x0045 -#define HUD_TABLET_PICK 0x0046 - -#define HID_USAGE2(p,u) (((p) << 16) | u) - -#define UHID_INPUT_REPORT 0x01 -#define UHID_OUTPUT_REPORT 0x02 -#define UHID_FEATURE_REPORT 0x03 - -/* Bits in the input/output/feature items */ -#define HIO_CONST 0x001 -#define HIO_VARIABLE 0x002 -#define HIO_RELATIVE 0x004 -#define HIO_WRAP 0x008 -#define HIO_NONLINEAR 0x010 -#define HIO_NOPREF 0x020 -#define HIO_NULLSTATE 0x040 -#define HIO_VOLATILE 0x080 -#define HIO_BUFBYTES 0x100 - -#endif /* _USBHID_H_ */ diff --git a/sys/dev/usb/uscanner.c b/sys/dev/usb/uscanner.c deleted file mode 100644 index bff3a48..0000000 --- a/sys/dev/usb/uscanner.c +++ /dev/null @@ -1,723 +0,0 @@ -/* $NetBSD: uscanner.c,v 1.30 2002/07/11 21:14:36 augustss Exp$ */ - -/* Also already merged from NetBSD: - * $NetBSD: uscanner.c,v 1.33 2002/09/23 05:51:24 simonb Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * Copyright (c) 2000 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 - * and Nick Hibma (n_hibma@qubesoft.com). - * - * 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/module.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/conf.h> -#include <sys/sysctl.h> -#include <sys/uio.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include "usbdevs.h" - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uscannerdebug) printf x -#define DPRINTFN(n,x) if (uscannerdebug>(n)) printf x -int uscannerdebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uscanner, CTLFLAG_RW, 0, "USB uscanner"); -SYSCTL_INT(_hw_usb_uscanner, OID_AUTO, debug, CTLFLAG_RW, - &uscannerdebug, 0, "uscanner debug level"); -#else -#define DPRINTF(x) -#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[] = { - - /* - * These first two entries are duplicates of known-working units, - * so one can patch them to test support for newer devices - * without rebuilding the module. - */ - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_6000 }, 0 }, /* duplicate */ - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_6000 }, 0 }, /* duplicate */ - - /* Acer Peripherals */ - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_4300U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640BT }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U }, 0 }, - {{ USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_1240U }, 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 }, - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_N676U }, 0 }, - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_N1220U }, 0 }, - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_D660U }, 0 }, - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_N1240U }, 0 }, - {{ USB_VENDOR_CANON, USB_PRODUCT_CANON_LIDE25 }, 0 }, - - /* Kye */ - {{ USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO }, 0 }, - - /* HP */ - {{ USB_VENDOR_HP, USB_PRODUCT_HP_2200C }, 0 }, - {{ 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_4470C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_4670V }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_S20 }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_5200C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_5300C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_5400C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_6200C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_6300C }, 0 }, - {{ USB_VENDOR_HP, USB_PRODUCT_HP_82x0C }, 0 }, - - /* 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 }, - - /* Minolta */ - {{ USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_5400 }, 0 }, - - /* Mustek */ - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200F }, 0 }, - {{ USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200TA }, 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 }, - - /* Nikon */ - {{ USB_VENDOR_NIKON, USB_PRODUCT_NIKON_LS40 }, 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_6200 }, 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_1250 }, 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_1660 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1670 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1260 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1270 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_RX425 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3200 }, USC_KEEP_OPEN }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F }, USC_KEEP_OPEN }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9300UF }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_2480 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3500 }, USC_KEEP_OPEN }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3590 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4200 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4800 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4990 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_5000 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_6000 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_CX5400 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX7400 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX8400 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_CX5400 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX3800 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX4000 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_NX300 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_SX200 }, 0 }, - {{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_SX400 }, 0 }, - - /* 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_ASTRA2100U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U }, 0 }, - {{ USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA3400 }, 0 }, - - /* Visioneer */ - {{ USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_3000 }, 0 }, - {{ 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 }, - -}; -#define uscanner_lookup(v, p) ((const struct uscan_info *)usb_lookup(uscanner_devs, v, p)) - -#define USCANNER_BUFFERSIZE 1024 - -struct uscanner_softc { - device_t sc_dev; /* base device */ - usbd_device_handle sc_udev; - usbd_interface_handle sc_iface; - struct cdev *dev; - - u_int sc_dev_flags; - - usbd_pipe_handle sc_bulkin_pipe; - int sc_bulkin; - usbd_xfer_handle sc_bulkin_xfer; - void *sc_bulkin_buffer; - int sc_bulkin_bufferlen; - int sc_bulkin_datalen; - - usbd_pipe_handle sc_bulkout_pipe; - int sc_bulkout; - usbd_xfer_handle sc_bulkout_xfer; - void *sc_bulkout_buffer; - int sc_bulkout_bufferlen; - int sc_bulkout_datalen; - - u_char sc_state; -#define USCANNER_OPEN 0x01 /* opened */ - - int sc_refcnt; - u_char sc_dying; -}; - -d_open_t uscanneropen; -d_close_t uscannerclose; -d_read_t uscannerread; -d_write_t uscannerwrite; -d_poll_t uscannerpoll; - - -static struct cdevsw uscanner_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = uscanneropen, - .d_close = uscannerclose, - .d_read = uscannerread, - .d_write = uscannerwrite, - .d_poll = uscannerpoll, - .d_name = "uscanner", -}; - -static int uscanner_do_read(struct uscanner_softc *, struct uio *, int); -static int uscanner_do_write(struct uscanner_softc *, struct uio *, int); -static void uscanner_do_close(struct uscanner_softc *); - -#define USCANNERUNIT(n) (dev2unit(n)) - -static device_probe_t uscanner_match; -static device_attach_t uscanner_attach; -static device_detach_t uscanner_detach; - -static device_method_t uscanner_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uscanner_match), - DEVMETHOD(device_attach, uscanner_attach), - DEVMETHOD(device_detach, uscanner_detach), - - { 0, 0 } -}; - -static driver_t uscanner_driver = { - "uscanner", - uscanner_methods, - sizeof(struct uscanner_softc) -}; - -static devclass_t uscanner_devclass; - -static int -uscanner_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id; - - if (uaa->iface == NULL) - return UMATCH_NONE; /* do not grab the entire device */ - - if (uscanner_lookup(uaa->vendor, uaa->product) == NULL) - return UMATCH_NONE; /* not in the list of known devices */ - id = usbd_get_interface_descriptor(uaa->iface); - if (id == NULL) - return UMATCH_NONE; - - /* - * There isn't a specific UICLASS for scanners, many vendors use - * UICLASS_VENDOR, so detecting the right interface is not so easy. - * But certainly we can exclude PRINTER and MASS - which some - * multifunction devices implement. - */ - if (id->bInterfaceClass == UICLASS_PRINTER || - id->bInterfaceClass == UICLASS_MASS) - return UMATCH_NONE; - - return UMATCH_VENDOR_PRODUCT; /* ok we found it */ -} - -static int -uscanner_attach(device_t self) -{ - struct uscanner_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usb_interface_descriptor_t *id = 0; - usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL; - int i; - usbd_status err; - int ifnum; - - sc->sc_dev = self; - sc->sc_dev_flags = uscanner_lookup(uaa->vendor, uaa->product)->flags; - sc->sc_udev = uaa->device; - - id = usbd_get_interface_descriptor(uaa->iface); - ifnum = id->bInterfaceNumber; -#if 0 - /* - * This was in the original driver, but we cannot change the - * configuration of the whole device while attaching only to - * one of its interfaces. This can kill other already-attached - * driver, and/or possibly prevent this driver from attaching - * if an error occurs in set_config_no. - * If a device need setting the configuration, this must be done - * before attaching drivers to the various interfaces. - */ - err = usbd_set_config_no(uaa->device, 1, 1); /* XXX */ - if (err) { - printf("%s: setting config no failed\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } -#endif - err = usbd_device2interface_handle(sc->sc_udev, ifnum, &sc->sc_iface); - if (!err && sc->sc_iface) - id = usbd_get_interface_descriptor(sc->sc_iface); - if (err || id == 0) { - printf("%s: could not get interface descriptor, err=%d,id=%p\n", - device_get_nameunit(sc->sc_dev), err, id); - return ENXIO; - } - - /* Find the two first bulk endpoints */ - for (i = 0 ; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); - if (ed == 0) { - printf("%s: could not read endpoint descriptor\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkin = ed; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT - && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { - ed_bulkout = ed; - } - - if (ed_bulkin && ed_bulkout) /* found all we need */ - break; - } - - /* Verify that we goething sensible */ - if (ed_bulkin == NULL || ed_bulkout == NULL) { - printf("%s: bulk-in and/or bulk-out endpoint not found\n", - device_get_nameunit(sc->sc_dev)); - return ENXIO; - } - - sc->sc_bulkin = ed_bulkin->bEndpointAddress; - sc->sc_bulkout = ed_bulkout->bEndpointAddress; - - /* the main device, ctrl endpoint */ - sc->dev = make_dev(&uscanner_cdevsw, device_get_unit(sc->sc_dev), - UID_ROOT, GID_OPERATOR, 0644, "%s", device_get_nameunit(sc->sc_dev)); - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,sc->sc_dev); - - return 0; -} - -int -uscanneropen(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct uscanner_softc *sc; - int unit = USCANNERUNIT(dev); - usbd_status err; - - sc = devclass_get_softc(uscanner_devclass, unit); - if (sc == NULL) - return (ENXIO); - - DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n", - flag, mode, unit)); - - if (sc->sc_dying) - return (ENXIO); - - if (sc->sc_state & USCANNER_OPEN) - return (EBUSY); - - sc->sc_state |= USCANNER_OPEN; - - sc->sc_bulkin_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); - sc->sc_bulkout_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK); - /* No need to check buffers for NULL since we have WAITOK */ - - sc->sc_bulkin_bufferlen = USCANNER_BUFFERSIZE; - 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", - device_get_nameunit(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", - device_get_nameunit(sc->sc_dev), sc->sc_bulkout); - uscanner_do_close(sc); - return (EIO); - } - } - - sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_bulkin_xfer == NULL) { - uscanner_do_close(sc); - return (ENOMEM); - } - sc->sc_bulkout_xfer = usbd_alloc_xfer(sc->sc_udev); - if (sc->sc_bulkout_xfer == NULL) { - uscanner_do_close(sc); - return (ENOMEM); - } - - return (0); /* success */ -} - -int -uscannerclose(struct cdev *dev, int flag, int mode, struct thread *p) -{ - struct uscanner_softc *sc; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - DPRINTFN(5, ("uscannerclose: flag=%d, mode=%d, unit=%d\n", - flag, mode, USCANNERUNIT(dev))); - -#ifdef DIAGNOSTIC - if (!(sc->sc_state & USCANNER_OPEN)) { - printf("uscannerclose: not open\n"); - return (EINVAL); - } -#endif - - uscanner_do_close(sc); - - return (0); -} - -void -uscanner_do_close(struct uscanner_softc *sc) -{ - if (sc->sc_bulkin_xfer) { - usbd_free_xfer(sc->sc_bulkin_xfer); - sc->sc_bulkin_xfer = NULL; - } - if (sc->sc_bulkout_xfer) { - usbd_free_xfer(sc->sc_bulkout_xfer); - 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_buffer) { - free(sc->sc_bulkin_buffer, M_USBDEV); - sc->sc_bulkin_buffer = NULL; - } - if (sc->sc_bulkout_buffer) { - free(sc->sc_bulkout_buffer, M_USBDEV); - sc->sc_bulkout_buffer = NULL; - } - - sc->sc_state &= ~USCANNER_OPEN; -} - -static int -uscanner_do_read(struct uscanner_softc *sc, struct uio *uio, int flag) -{ - u_int32_t n, tn; - usbd_status err; - int error = 0; - - DPRINTFN(5, ("%s: uscannerread\n", device_get_nameunit(sc->sc_dev))); - - if (sc->sc_dying) - return (EIO); - - while ((n = min(sc->sc_bulkin_bufferlen, uio->uio_resid)) != 0) { - DPRINTFN(1, ("uscannerread: start transfer %d bytes\n",n)); - tn = n; - - err = usbd_bulk_transfer( - sc->sc_bulkin_xfer, sc->sc_bulkin_pipe, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, - sc->sc_bulkin_buffer, &tn, - "uscnrb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else if (err == USBD_TIMEOUT) - error = ETIMEDOUT; - else - error = EIO; - break; - } - DPRINTFN(1, ("uscannerread: got %d bytes\n", tn)); - error = uiomove(sc->sc_bulkin_buffer, tn, uio); - if (error || tn < n) - break; - } - - return (error); -} - -int -uscannerread(struct cdev *dev, struct uio *uio, int flag) -{ - struct uscanner_softc *sc; - int error; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - sc->sc_refcnt++; - error = uscanner_do_read(sc, uio, flag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - - return (error); -} - -static int -uscanner_do_write(struct uscanner_softc *sc, struct uio *uio, int flag) -{ - u_int32_t n; - int error = 0; - usbd_status err; - - DPRINTFN(5, ("%s: uscanner_do_write\n", device_get_nameunit(sc->sc_dev))); - - if (sc->sc_dying) - return (EIO); - - while ((n = min(sc->sc_bulkout_bufferlen, uio->uio_resid)) != 0) { - error = uiomove(sc->sc_bulkout_buffer, n, uio); - if (error) - break; - DPRINTFN(1, ("uscanner_do_write: transfer %d bytes\n", n)); - err = usbd_bulk_transfer( - sc->sc_bulkout_xfer, sc->sc_bulkout_pipe, - 0, USBD_NO_TIMEOUT, - sc->sc_bulkout_buffer, &n, - "uscnwb"); - if (err) { - if (err == USBD_INTERRUPTED) - error = EINTR; - else - error = EIO; - break; - } - } - - return (error); -} - -int -uscannerwrite(struct cdev *dev, struct uio *uio, int flag) -{ - struct uscanner_softc *sc; - int error; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - sc->sc_refcnt++; - error = uscanner_do_write(sc, uio, flag); - if (--sc->sc_refcnt < 0) - usb_detach_wakeup(sc->sc_dev); - return (error); -} - -static int -uscanner_detach(device_t self) -{ - struct uscanner_softc *sc = device_get_softc(self); - int s; - - DPRINTF(("uscanner_detach: sc=%p\n", sc)); - - 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) - usbd_abort_pipe(sc->sc_bulkin_pipe); - if (sc->sc_bulkout_pipe != NULL) - usbd_abort_pipe(sc->sc_bulkout_pipe); - - s = splusb(); - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away. */ - usb_detach_wait(sc->sc_dev); - } - splx(s); - - /* destroy the device for the control endpoint */ - destroy_dev(sc->dev); - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - return (0); -} - -int -uscannerpoll(struct cdev *dev, int events, struct thread *p) -{ - struct uscanner_softc *sc; - int revents = 0; - - sc = devclass_get_softc(uscanner_devclass, USCANNERUNIT(dev)); - if (sc->sc_dying) - return (EIO); - - /* - * We have no easy way of determining if a read will - * yield any data or a write will happen. - * Pretend they will. - */ - revents |= events & - (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM); - - return (revents); -} - -MODULE_DEPEND(uscanner, usb, 1, 1, 1); -DRIVER_MODULE(uscanner, uhub, uscanner_driver, uscanner_devclass, usbd_driver_load, 0); diff --git a/sys/dev/usb/uslcom.c b/sys/dev/usb/uslcom.c deleted file mode 100644 index edb13c5..0000000 --- a/sys/dev/usb/uslcom.c +++ /dev/null @@ -1,419 +0,0 @@ -/* $FreeBSD$ */ -/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */ - -/* - * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/bus.h> -#include <sys/tty.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> - -#include "usbdevs.h" -#include <dev/usb/ucomvar.h> - -#ifdef USLCOM_DEBUG -#define DPRINTFN(n, x) do { if (uslcomdebug > (n)) printf x; } while (0) -int uslcomdebug = 1; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define USLCOMBUFSZ 256 -#define USLCOM_CONFIG_NO 0 -#define USLCOM_IFACE_NO 0 - -#define USLCOM_SET_DATA_BITS(x) (x << 8) - -#define USLCOM_WRITE 0x41 -#define USLCOM_READ 0xc1 - -#define USLCOM_UART 0x00 -#define USLCOM_BAUD_RATE 0x01 -#define USLCOM_DATA 0x03 -#define USLCOM_BREAK 0x05 -#define USLCOM_CTRL 0x07 - -#define USLCOM_UART_DISABLE 0x00 -#define USLCOM_UART_ENABLE 0x01 - -#define USLCOM_CTRL_DTR_ON 0x0001 -#define USLCOM_CTRL_DTR_SET 0x0100 -#define USLCOM_CTRL_RTS_ON 0x0002 -#define USLCOM_CTRL_RTS_SET 0x0200 -#define USLCOM_CTRL_CTS 0x0010 -#define USLCOM_CTRL_DSR 0x0020 -#define USLCOM_CTRL_DCD 0x0080 - - -#define USLCOM_BAUD_REF 0x384000 - -#define USLCOM_STOP_BITS_1 0x00 -#define USLCOM_STOP_BITS_2 0x02 - -#define USLCOM_PARITY_NONE 0x00 -#define USLCOM_PARITY_ODD 0x10 -#define USLCOM_PARITY_EVEN 0x20 - -#define USLCOM_BREAK_OFF 0x00 -#define USLCOM_BREAK_ON 0x01 - - -struct uslcom_softc { - struct ucom_softc sc_ucom; - device_t sc_dev; - usbd_device_handle sc_udev; - - u_char sc_msr; - u_char sc_lsr; - - u_char sc_dying; -}; - -void uslcom_get_status(void *, int portno, u_char *lsr, u_char *msr); -void uslcom_set(void *, int, int, int); -int uslcom_param(void *, int, struct termios *); -int uslcom_open(void *sc, int portno); -void uslcom_close(void *, int); -void uslcom_break(void *sc, int portno, int onoff); - -struct ucom_callback uslcom_callback = { - uslcom_get_status, - uslcom_set, - uslcom_param, - NULL, - uslcom_open, - uslcom_close, - NULL, - NULL, -}; - -static const struct usb_devno uslcom_devs[] = { - { USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER }, - { USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD }, - { USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128 }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREE }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BURNSIDE }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_HELICOM }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP2102 }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2 }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUUNTO }, - { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TRAQMATE }, - { USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE }, - { USB_VENDOR_USI, USB_PRODUCT_USI_MC60 } -}; - -static device_probe_t uslcom_match; -static device_attach_t uslcom_attach; -static device_detach_t uslcom_detach; - -static device_method_t uslcom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uslcom_match), - DEVMETHOD(device_attach, uslcom_attach), - DEVMETHOD(device_detach, uslcom_detach), - { 0, 0 } -}; - -static driver_t uslcom_driver = { - "ucom", - uslcom_methods, - sizeof (struct uslcom_softc) -}; - -DRIVER_MODULE(uslcom, uhub, uslcom_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uslcom, usb, 1, 1, 1); -MODULE_DEPEND(uslcom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uslcom, 1); - -static int -uslcom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return UMATCH_NONE; - - return (usb_lookup(uslcom_devs, uaa->vendor, uaa->product) != NULL) ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE; -} - -static int -uslcom_attach(device_t self) -{ - struct uslcom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - struct ucom_softc* ucom; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - int i; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - sc->sc_dev = self; - sc->sc_udev = uaa->device; - - if (usbd_set_config_index(sc->sc_udev, USLCOM_CONFIG_NO, 1) != 0) { - device_printf(self, "could not set configuration no\n"); - sc->sc_dying = 1; - return ENXIO; - } - - /* get the first interface handle */ - error = usbd_device2interface_handle(sc->sc_udev, USLCOM_IFACE_NO, - &ucom->sc_iface); - if (error != 0) { - device_printf(self, "could not get interface handle\n"); - sc->sc_dying = 1; - return ENXIO; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(self, "no endpoint descriptor found for %d\n", - i); - sc->sc_dying = 1; - return ENXIO; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; - } - - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - device_printf(self, "missing endpoint\n"); - sc->sc_dying = 1; - return ENXIO; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = USLCOMBUFSZ; - ucom->sc_obufsize = USLCOMBUFSZ; - ucom->sc_ibufsizepad = USLCOMBUFSZ; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uslcom_callback; - - DPRINTF(("uslcom: in = 0x%x, out = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - - ucom_attach(&sc->sc_ucom); - return 0; -} - -static int -uslcom_detach(device_t self) -{ - struct uslcom_softc *sc = device_get_softc(self); - - sc->sc_dying = 1; - return ucom_detach(&sc->sc_ucom); -} - -int -uslcom_open(void *vsc, int portno) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - usbd_status err; - - if (sc->sc_dying) - return (EIO); - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_UART; - USETW(req.wValue, USLCOM_UART_ENABLE); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); -} - -void -uslcom_close(void *vsc, int portno) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - - if (sc->sc_dying) - return; - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_UART; - USETW(req.wValue, USLCOM_UART_DISABLE); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_udev, &req, NULL); -} - -void -uslcom_set(void *vsc, int portno, int reg, int onoff) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - int ctl; - - switch (reg) { - case UCOM_SET_DTR: - ctl = onoff ? USLCOM_CTRL_DTR_ON : 0; - ctl |= USLCOM_CTRL_DTR_SET; - break; - case UCOM_SET_RTS: - ctl = onoff ? USLCOM_CTRL_RTS_ON : 0; - ctl |= USLCOM_CTRL_RTS_SET; - break; - case UCOM_SET_BREAK: - uslcom_break(sc, portno, onoff); - return; - default: - return; - } - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_CTRL; - USETW(req.wValue, ctl); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_udev, &req, NULL); -} - -int -uslcom_param(void *vsc, int portno, struct termios *t) -{ - struct uslcom_softc *sc = (struct uslcom_softc *)vsc; - usbd_status err; - usb_device_request_t req; - int data; - - if (t->c_ospeed <= 0 || t->c_ospeed > 921600) - return (EINVAL); - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_BAUD_RATE; - USETW(req.wValue, USLCOM_BAUD_REF / t->c_ospeed); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CSTOPB)) - data = USLCOM_STOP_BITS_2; - else - data = USLCOM_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - data |= USLCOM_PARITY_ODD; - else - data |= USLCOM_PARITY_EVEN; - } else - data |= USLCOM_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - data |= USLCOM_SET_DATA_BITS(5); - break; - case CS6: - data |= USLCOM_SET_DATA_BITS(6); - break; - case CS7: - data |= USLCOM_SET_DATA_BITS(7); - break; - case CS8: - data |= USLCOM_SET_DATA_BITS(8); - break; - } - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_DATA; - USETW(req.wValue, data); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (err) - return (EIO); - -#if 0 - /* XXX flow control */ - if (ISSET(t->c_cflag, CRTSCTS)) - /* rts/cts flow ctl */ - } else if (ISSET(t->c_iflag, IXON|IXOFF)) { - /* xon/xoff flow ctl */ - } else { - /* disable flow ctl */ - } -#endif - - return (0); -} - -void -uslcom_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) -{ - struct uslcom_softc *sc = vsc; - - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; -} - -void -uslcom_break(void *vsc, int portno, int onoff) -{ - struct uslcom_softc *sc = vsc; - usb_device_request_t req; - int brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF; - - req.bmRequestType = USLCOM_WRITE; - req.bRequest = USLCOM_BREAK; - USETW(req.wValue, brk); - USETW(req.wIndex, portno); - USETW(req.wLength, 0); - usbd_do_request(sc->sc_udev, &req, NULL); -} diff --git a/sys/dev/usb/uvisor.c b/sys/dev/usb/uvisor.c deleted file mode 100644 index 6c4470e..0000000 --- a/sys/dev/usb/uvisor.c +++ /dev/null @@ -1,639 +0,0 @@ -/* $NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $ */ -/* $FreeBSD$ */ - -/* Also already merged from NetBSD: - * $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $ - * $NetBSD: uvisor.c,v 1.13 2002/02/11 15:11:49 augustss Exp $ - * $NetBSD: uvisor.c,v 1.14 2002/02/27 23:00:03 augustss Exp $ - * $NetBSD: uvisor.c,v 1.15 2002/06/16 15:01:31 augustss Exp $ - * $NetBSD: uvisor.c,v 1.16 2002/07/11 21:14:36 augustss Exp $ - * $NetBSD: uvisor.c,v 1.17 2002/08/13 11:38:15 augustss Exp $ - * $NetBSD: uvisor.c,v 1.18 2003/02/05 00:50:14 augustss Exp $ - * $NetBSD: uvisor.c,v 1.19 2003/02/07 18:12:37 augustss Exp $ - * $NetBSD: uvisor.c,v 1.20 2003/04/11 01:30:10 simonb Exp $ - */ - - -/*- - * Copyright (c) 2000 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. - */ - -/* - * Handspring Visor (Palmpilot compatible PDA) driver - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/tty.h> -#include <sys/sysctl.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbhid.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" - -#include <dev/usb/ucomvar.h> - -#ifdef USB_DEBUG -#define DPRINTF(x) if (uvisordebug) printf x -#define DPRINTFN(n,x) if (uvisordebug>(n)) printf x -int uvisordebug = 0; -SYSCTL_NODE(_hw_usb, OID_AUTO, uvisor, CTLFLAG_RW, 0, "USB uvisor"); -SYSCTL_INT(_hw_usb_uvisor, OID_AUTO, debug, CTLFLAG_RW, - &uvisordebug, 0, "uvisor debug level"); -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -#define UVISOR_CONFIG_INDEX 0 -#define UVISOR_IFACE_INDEX 0 -#define UVISOR_MODVER 1 - -/* From the Linux driver */ -/* - * UVISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that - * are available to be transfered to the host for the specified endpoint. - * Currently this is not used, and always returns 0x0001 - */ -#define UVISOR_REQUEST_BYTES_AVAILABLE 0x01 - -/* - * UVISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host - * is now closing the pipe. An empty packet is sent in response. - */ -#define UVISOR_CLOSE_NOTIFICATION 0x02 - -/* - * UVISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to - * get the endpoints used by the connection. - */ -#define UVISOR_GET_CONNECTION_INFORMATION 0x03 - - -/* - * UVISOR_GET_CONNECTION_INFORMATION returns data in the following format - */ -#define UVISOR_MAX_CONN 8 -struct uvisor_connection_info { - uWord num_ports; - struct { - uByte port_function_id; - uByte port; - } connections[UVISOR_MAX_CONN]; -}; -#define UVISOR_CONNECTION_INFO_SIZE 18 - -/* struct uvisor_connection_info.connection[x].port defines: */ -#define UVISOR_ENDPOINT_1 0x01 -#define UVISOR_ENDPOINT_2 0x02 - -/* struct uvisor_connection_info.connection[x].port_function_id defines: */ -#define UVISOR_FUNCTION_GENERIC 0x00 -#define UVISOR_FUNCTION_DEBUGGER 0x01 -#define UVISOR_FUNCTION_HOTSYNC 0x02 -#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 0x44 - -struct uvisor_palm_connection_info { - uByte num_ports; - uByte endpoint_numbers_different; - uWord reserved1; - struct { - uDWord port_function_id; - uByte port; - uByte end_point_info; - uWord reserved; - } connections[UVISOR_MAX_CONN]; -}; - - -/* - * Crank down UVISORBUFSIZE from 1024 to 64 to avoid a problem where - * the Palm device and the USB host controller deadlock. The USB host - * controller is expecting an early-end-of-transmission packet with 0 - * data, and the Palm doesn't send one because it's already - * communicated the amount of data it's going to send in a header - * (which ucom/uvisor are oblivious to). This is the problem that has - * been known on the pilot-link lists as the "[Free]BSD USB problem", - * but not understood. - */ -#define UVISORIBUFSIZE 64 -#define UVISOROBUFSIZE 1024 - -struct uvisor_softc { - struct ucom_softc sc_ucom; - u_int16_t sc_flags; -}; - -static usbd_status uvisor_init(struct uvisor_softc *); - -/*static usbd_status clie_3_5_init(struct uvisor_softc *);*/ - -static void uvisor_close(void *, int); - -struct ucom_callback uvisor_callback = { - NULL, - NULL, - NULL, - NULL, - NULL, - uvisor_close, - NULL, - NULL, -}; - -static device_probe_t uvisor_match; -static device_attach_t uvisor_attach; -static device_detach_t uvisor_detach; -static device_method_t uvisor_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uvisor_match), - DEVMETHOD(device_attach, uvisor_attach), - DEVMETHOD(device_detach, uvisor_detach), - { 0, 0 } -}; - - -static driver_t uvisor_driver = { - "ucom", - uvisor_methods, - sizeof (struct uvisor_softc) -}; - -DRIVER_MODULE(uvisor, uhub, uvisor_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uvisor, usb, 1, 1, 1); -MODULE_DEPEND(uvisor, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uvisor, UVISOR_MODVER); - -struct uvisor_type { - struct usb_devno uv_dev; - u_int16_t uv_flags; -#define PALM4 0x0001 -#define VISOR 0x0002 -#define PALM35 0x0004 -}; -static const struct uvisor_type uvisor_devs[] = { - {{ USB_VENDOR_ACEECA, USB_PRODUCT_ACEECA_MEZ1000 }, PALM4 }, - {{ USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_IQUE_3600 }, PALM4 }, - {{ USB_VENDOR_FOSSIL, USB_PRODUCT_FOSSIL_WRISTPDA }, PALM4 }, - {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR }, VISOR }, - {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO }, PALM4 }, - {{ USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M500 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M505 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M515 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_I705 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M125 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_M130 }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE }, PALM4 }, - {{ USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31 }, PALM4 }, - {{ USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I500 }, PALM4 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40 }, 0 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41 }, PALM4 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360 }, PALM4 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60 }, PALM4 }, - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35 }, PALM35 }, -/* {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_25 }, PALM4 },*/ -/* {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TH55 }, PALM4 }, */ /* See PR 80935 */ - {{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TJ37 }, PALM4 }, - {{ USB_VENDOR_TAPWAVE, USB_PRODUCT_TAPWAVE_ZODIAC }, PALM4 }, -}; -#define uvisor_lookup(v, p) ((const struct uvisor_type *)usb_lookup(uvisor_devs, v, p)) - - -static int -uvisor_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - 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); -} - -static int -uvisor_attach(device_t self) -{ - struct uvisor_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - int i; - usbd_status err; - struct ucom_softc *ucom; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - DPRINTFN(10,("\nuvisor_attach: sc=%p\n", sc)); - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UVISOR_CONFIG_INDEX, 1); - if (err) { - device_printf(self, "failed to set configuration, err=%s\n", - usbd_errstr(err)); - goto bad; - } - - err = usbd_device2interface_handle(dev, UVISOR_IFACE_INDEX, &iface); - if (err) { - device_printf(self, "failed to get interface, err=%s\n", - usbd_errstr(err)); - goto bad; - } - - sc->sc_flags = uvisor_lookup(uaa->vendor, uaa->product)->uv_flags; - - id = usbd_get_interface_descriptor(iface); - - ucom->sc_udev = dev; - ucom->sc_iface = iface; - - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - int addr, dir, attr; - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - device_printf(self, - "could not read endpoint descriptor: %s\n", - usbd_errstr(err)); - goto bad; - } - - addr = ed->bEndpointAddress; - dir = UE_GET_DIR(ed->bEndpointAddress); - attr = ed->bmAttributes & UE_XFERTYPE; - if (dir == UE_DIR_IN && attr == UE_BULK) - ucom->sc_bulkin_no = addr; - else if (dir == UE_DIR_OUT && attr == UE_BULK) - ucom->sc_bulkout_no = addr; - else { - device_printf(self, "unexpected endpoint\n"); - goto bad; - } - } - if (ucom->sc_bulkin_no == -1) { - device_printf(self, "Could not find data bulk in\n"); - goto bad; - } - if (ucom->sc_bulkout_no == -1) { - device_printf(self, "Could not find data bulk out\n"); - goto bad; - } - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UVISORIBUFSIZE; - ucom->sc_obufsize = UVISOROBUFSIZE; - ucom->sc_ibufsizepad = UVISORIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uvisor_callback; - -#if 0 - if (uaa->vendor == USB_VENDOR_SONY && - uaa->product == USB_PRODUCT_SONY_CLIE_35) - err = clie_3_5_init(sc); - else -#endif - err = uvisor_init(sc); - - if (err) { - device_printf(ucom->sc_dev, "init failed, %s\n", - usbd_errstr(err)); - goto bad; - } - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev, - ucom->sc_dev); - - DPRINTF(("uvisor: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - - return 0; - -bad: - DPRINTF(("uvisor_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - return ENXIO; -} - -#if 0 - -int -uvisor_activate(device_t self, enum devact act) -{ - struct uvisor_softc *sc = (struct uvisor_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); -} - -#endif - -static int -uvisor_detach(device_t self) -{ - struct uvisor_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uvisor_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev, - sc->sc_ucom.sc_dev); - - return (rv); -} - -usbd_status -uvisor_init(struct uvisor_softc *sc) -{ - usbd_status err; - usb_device_request_t req; - struct uvisor_connection_info coninfo; - struct uvisor_palm_connection_info pconinfo; - int actlen; - uWord avail; - char buffer[256]; - - if (sc->sc_flags & VISOR) { - DPRINTF(("uvisor_init: getting connection info\n")); - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; - req.bRequest = UVISOR_GET_CONNECTION_INFORMATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); - err = usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, &coninfo, - USBD_SHORT_XFER_OK, &actlen, - USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - } -#ifdef USB_DEBUG - { - int i, np; - char *string; - - np = UGETW(coninfo.num_ports); - device_printf(sc->sc_ucom.sc_dev, "Number of ports: %d\n", np); - for (i = 0; i < np; ++i) { - switch (coninfo.connections[i].port_function_id) { - case UVISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case UVISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case UVISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case UVISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; - } - device_printf(sc->sc_ucom.sc_dev, - "port %d, is for %s\n", - coninfo.connections[i].port, string); - } - } -#endif - - if (sc->sc_flags & PALM4) { - int port; - /* 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_flags(sc->sc_ucom.sc_udev, &req, &pconinfo, - USBD_SHORT_XFER_OK, &actlen, - USBD_DEFAULT_TIMEOUT); - if (err) - return (err); - - if (pconinfo.endpoint_numbers_different) { - port = pconinfo.connections[0].end_point_info; - sc->sc_ucom.sc_bulkin_no = (port >> 4) | UE_DIR_IN; - sc->sc_ucom.sc_bulkout_no = (port & 0xf) | UE_DIR_OUT; - } else { - port = pconinfo.connections[0].port; - sc->sc_ucom.sc_bulkin_no = port | UE_DIR_IN; - sc->sc_ucom.sc_bulkout_no = port | UE_DIR_OUT; - } -#if 0 - 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_ucom.sc_udev, &req, buffer); - if (err) - return (err); -#endif - } - - if (sc->sc_flags & PALM35) { - /* get the config number */ - DPRINTF(("clie_3_5_init: getting config info\n")); - req.bmRequestType = UT_READ; - req.bRequest = UR_GET_CONFIG; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - - /* get the interface number */ - DPRINTF(("clie_3_5_init: get the interface number\n")); - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_INTERFACE; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.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; - USETW(req.wValue, 0); - USETW(req.wIndex, 5); - USETW(req.wLength, sizeof avail); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, &avail); - if (err) - return (err); - DPRINTF(("uvisor_init: avail=%d\n", UGETW(avail))); - - DPRINTF(("uvisor_init: done\n")); - return (err); -} - -#if 0 -usbd_status -clie_3_5_init(struct uvisor_softc *sc) -{ - usbd_status err; - usb_device_request_t req; - char buffer[256]; - - /* - * Note that PEG-300 series devices expect the following two calls. - */ - - /* get the config number */ - DPRINTF(("clie_3_5_init: getting config info\n")); - req.bmRequestType = UT_READ; - req.bRequest = UR_GET_CONFIG; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - - /* get the interface number */ - DPRINTF(("clie_3_5_init: get the interface number\n")); - req.bmRequestType = UT_READ_DEVICE; - req.bRequest = UR_GET_INTERFACE; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 1); - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, buffer); - if (err) - return (err); - -#ifdef USB_DEBUG - { - struct uvisor_connection_info coninfo; - int i, np; - char *string; - - np = UGETW(coninfo.num_ports); - DPRINTF(("%s: Number of ports: %d\n", device_get_nameunit(sc->sc_ucom.sc_dev), np)); - for (i = 0; i < np; ++i) { - switch (coninfo.connections[i].port_function_id) { - case UVISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case UVISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case UVISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case UVISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; - } - DPRINTF(("%s: port %d, is for %s\n", - device_get_nameunit(sc->sc_ucom.sc_dev), coninfo.connections[i].port, - string)); - } - } -#endif - - DPRINTF(("clie_3_5_init: done\n")); - return (err); -} -#endif - -void -uvisor_close(void *addr, int portno) -{ - struct uvisor_softc *sc = addr; - usb_device_request_t req; - struct uvisor_connection_info coninfo; /* XXX ? */ - int actlen; - - if (sc->sc_ucom.sc_dying) - return; - - req.bmRequestType = UT_READ_VENDOR_ENDPOINT; /* XXX read? */ - req.bRequest = UVISOR_CLOSE_NOTIFICATION; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE); - (void)usbd_do_request_flags(sc->sc_ucom.sc_udev, &req, &coninfo, - USBD_SHORT_XFER_OK, &actlen, - USBD_DEFAULT_TIMEOUT); -} diff --git a/sys/dev/usb/uvscom.c b/sys/dev/usb/uvscom.c deleted file mode 100644 index ac311f7..0000000 --- a/sys/dev/usb/uvscom.c +++ /dev/null @@ -1,906 +0,0 @@ -/* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */ -/*- - * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama@jp.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. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * uvscom: SUNTAC Slipper U VS-10U driver. - * Slipper U is a PC Card to USB converter for data communication card - * adapter. It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in, - * P-in m@ater and various data communication card adapters. - */ - -#include "opt_uvscom.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/fcntl.h> -#include <sys/conf.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/file.h> -#include <sys/bus.h> -#include <sys/ioccom.h> -#include <sys/selinfo.h> -#include <sys/proc.h> -#include <sys/poll.h> -#include <sys/sysctl.h> -#include <sys/taskqueue.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbcdc.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include "usbdevs.h" -#include <dev/usb/usb_quirks.h> - -#include <dev/usb/ucomvar.h> - -SYSCTL_NODE(_hw_usb, OID_AUTO, uvscom, CTLFLAG_RW, 0, "USB uvscom"); -#ifdef USB_DEBUG -static int uvscomdebug = 0; -SYSCTL_INT(_hw_usb_uvscom, OID_AUTO, debug, CTLFLAG_RW, - &uvscomdebug, 0, "uvscom debug level"); - -#define DPRINTFN(n, x) do { \ - if (uvscomdebug > (n)) \ - printf x; \ - } while (0) -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) - -#define UVSCOM_MODVER 1 /* module version */ - -#define UVSCOM_CONFIG_INDEX 0 -#define UVSCOM_IFACE_INDEX 0 - -#ifndef UVSCOM_INTR_INTERVAL -#define UVSCOM_INTR_INTERVAL 100 /* mS */ -#endif - -#define UVSCOM_UNIT_WAIT 5 - -/* Request */ -#define UVSCOM_SET_SPEED 0x10 -#define UVSCOM_LINE_CTL 0x11 -#define UVSCOM_SET_PARAM 0x12 -#define UVSCOM_READ_STATUS 0xd0 -#define UVSCOM_SHUTDOWN 0xe0 - -/* UVSCOM_SET_SPEED parameters */ -#define UVSCOM_SPEED_150BPS 0x00 -#define UVSCOM_SPEED_300BPS 0x01 -#define UVSCOM_SPEED_600BPS 0x02 -#define UVSCOM_SPEED_1200BPS 0x03 -#define UVSCOM_SPEED_2400BPS 0x04 -#define UVSCOM_SPEED_4800BPS 0x05 -#define UVSCOM_SPEED_9600BPS 0x06 -#define UVSCOM_SPEED_19200BPS 0x07 -#define UVSCOM_SPEED_38400BPS 0x08 -#define UVSCOM_SPEED_57600BPS 0x09 -#define UVSCOM_SPEED_115200BPS 0x0a - -/* UVSCOM_LINE_CTL parameters */ -#define UVSCOM_BREAK 0x40 -#define UVSCOM_RTS 0x02 -#define UVSCOM_DTR 0x01 -#define UVSCOM_LINE_INIT 0x08 - -/* UVSCOM_SET_PARAM parameters */ -#define UVSCOM_DATA_MASK 0x03 -#define UVSCOM_DATA_BIT_8 0x03 -#define UVSCOM_DATA_BIT_7 0x02 -#define UVSCOM_DATA_BIT_6 0x01 -#define UVSCOM_DATA_BIT_5 0x00 - -#define UVSCOM_STOP_MASK 0x04 -#define UVSCOM_STOP_BIT_2 0x04 -#define UVSCOM_STOP_BIT_1 0x00 - -#define UVSCOM_PARITY_MASK 0x18 -#define UVSCOM_PARITY_EVEN 0x18 -#if 0 -#define UVSCOM_PARITY_UNK 0x10 -#endif -#define UVSCOM_PARITY_ODD 0x08 -#define UVSCOM_PARITY_NONE 0x00 - -/* Status bits */ -#define UVSCOM_TXRDY 0x04 -#define UVSCOM_RXRDY 0x01 - -#define UVSCOM_DCD 0x08 -#define UVSCOM_NOCARD 0x04 -#define UVSCOM_DSR 0x02 -#define UVSCOM_CTS 0x01 -#define UVSCOM_USTAT_MASK (UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS) - -struct uvscom_softc { - struct ucom_softc sc_ucom; - - int sc_iface_number;/* interface number */ - - usbd_interface_handle sc_intr_iface; /* interrupt interface */ - int sc_intr_number; /* interrupt number */ - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ - u_char *sc_intr_buf; /* interrupt buffer */ - int sc_isize; - - u_char sc_dtr; /* current DTR state */ - u_char sc_rts; /* current RTS state */ - - u_char sc_lsr; /* Local status register */ - u_char sc_msr; /* uvscom status register */ - - uint16_t sc_lcr; /* Line control */ - u_char sc_usr; /* unit status */ - - struct task sc_task; -}; - -/* - * These are the maximum number of bytes transferred per frame. - * The output buffer size cannot be increased due to the size encoding. - */ -#define UVSCOMIBUFSIZE 512 -#define UVSCOMOBUFSIZE 64 - -#ifndef UVSCOM_DEFAULT_OPKTSIZE -#define UVSCOM_DEFAULT_OPKTSIZE 8 -#endif - -static usbd_status uvscom_shutdown(struct uvscom_softc *); -static usbd_status uvscom_reset(struct uvscom_softc *); -static usbd_status uvscom_set_line_coding(struct uvscom_softc *, - uint16_t, uint16_t); -static usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t); -static usbd_status uvscom_set_crtscts(struct uvscom_softc *); -static void uvscom_get_status(void *, int, u_char *, u_char *); -static void uvscom_dtr(struct uvscom_softc *, int); -static void uvscom_rts(struct uvscom_softc *, int); -static void uvscom_break(struct uvscom_softc *, int); - -static void uvscom_set(void *, int, int, int); -static void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); -static int uvscom_param(void *, int, struct termios *); -static int uvscom_open(void *, int); -static void uvscom_close(void *, int); -static void uvscom_notify(void *, int); - -struct ucom_callback uvscom_callback = { - uvscom_get_status, - uvscom_set, - uvscom_param, - NULL, - uvscom_open, - uvscom_close, - NULL, - NULL -}; - -static const struct usb_devno uvscom_devs [] = { - /* SUNTAC U-Cable type A4 */ - { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 }, - /* SUNTAC U-Cable type D2 */ - { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L }, - /* SUNTAC Ir-Trinity */ - { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U }, - /* SUNTAC U-Cable type P1 */ - { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 }, - /* SUNTAC Slipper U */ - { USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U }, -}; -#define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p) - -static device_probe_t uvscom_match; -static device_attach_t uvscom_attach; -static device_detach_t uvscom_detach; - -static device_method_t uvscom_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uvscom_match), - DEVMETHOD(device_attach, uvscom_attach), - DEVMETHOD(device_detach, uvscom_detach), - { 0, 0 } -}; - -static driver_t uvscom_driver = { - "ucom", - uvscom_methods, - sizeof (struct uvscom_softc) -}; - -DRIVER_MODULE(uvscom, uhub, uvscom_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uvscom, usb, 1, 1, 1); -MODULE_DEPEND(uvscom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); -MODULE_VERSION(uvscom, UVSCOM_MODVER); - -static int uvscomobufsiz = UVSCOM_DEFAULT_OPKTSIZE; -static int uvscominterval = UVSCOM_INTR_INTERVAL; - -static int -sysctl_hw_usb_uvscom_opktsize(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = uvscomobufsiz; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - if (0 < val && val <= UVSCOMOBUFSIZE) - uvscomobufsiz = val; - else - err = EINVAL; - - return (err); -} - -static int -sysctl_hw_usb_uvscom_interval(SYSCTL_HANDLER_ARGS) -{ - int err, val; - - val = uvscominterval; - err = sysctl_handle_int(oidp, &val, 0, req); - if (err != 0 || req->newptr == NULL) - return (err); - if (0 < val && val <= 1000) - uvscominterval = val; - else - err = EINVAL; - - return (err); -} - -SYSCTL_PROC(_hw_usb_uvscom, OID_AUTO, opktsize, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_usb_uvscom_opktsize, - "I", "uvscom output packet size"); -SYSCTL_PROC(_hw_usb_uvscom, OID_AUTO, interval, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_usb_uvscom_interval, - "I", "uvscom interrpt pipe interval"); - -static int -uvscom_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->iface != NULL) - return (UMATCH_NONE); - - return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ? - UMATCH_VENDOR_PRODUCT : UMATCH_NONE); -} - -static int -uvscom_attach(device_t self) -{ - struct uvscom_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - usbd_device_handle dev = uaa->device; - struct ucom_softc *ucom; - usb_config_descriptor_t *cdesc; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status err; - int i; - - ucom = &sc->sc_ucom; - ucom->sc_dev = self; - ucom->sc_udev = dev; - ucom->sc_iface = uaa->iface; - - DPRINTF(("uvscom attach: sc = %p\n", sc)); - - /* initialize endpoints */ - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - sc->sc_intr_number = -1; - sc->sc_intr_pipe = NULL; - - /* Move the device into the configured state. */ - err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1); - if (err) { - device_printf(self, "failed to set configuration, err=%s\n", - usbd_errstr(err)); - goto error; - } - - /* get the config descriptor */ - cdesc = usbd_get_config_descriptor(ucom->sc_udev); - - if (cdesc == NULL) { - device_printf(self, "failed to get configuration descriptor\n"); - goto error; - } - - /* get the common interface */ - err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX, - &ucom->sc_iface); - if (err) { - device_printf(self, "failed to get interface, err=%s\n", - usbd_errstr(err)); - goto error; - } - - id = usbd_get_interface_descriptor(ucom->sc_iface); - sc->sc_iface_number = id->bInterfaceNumber; - - /* Find endpoints */ - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i); - if (ed == NULL) { - device_printf(self, "no endpoint descriptor for %d\n", - i); - goto error; - } - - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkin_no = ed->bEndpointAddress; - } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { - ucom->sc_bulkout_no = 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 (ucom->sc_bulkin_no == -1) { - device_printf(self, "Could not find data bulk in\n"); - goto error; - } - if (ucom->sc_bulkout_no == -1) { - device_printf(self, "Could not find data bulk out\n"); - goto error; - } - if (sc->sc_intr_number == -1) { - device_printf(self, "Could not find interrupt in\n"); - goto error; - } - - sc->sc_dtr = sc->sc_rts = 0; - sc->sc_lcr = UVSCOM_LINE_INIT; - - ucom->sc_parent = sc; - ucom->sc_portno = UCOM_UNK_PORTNO; - /* bulkin, bulkout set above */ - ucom->sc_ibufsize = UVSCOMIBUFSIZE; - ucom->sc_obufsize = uvscomobufsiz; - ucom->sc_ibufsizepad = UVSCOMIBUFSIZE; - ucom->sc_opkthdrlen = 0; - ucom->sc_callback = &uvscom_callback; - - err = uvscom_reset(sc); - - if (err) { - device_printf(self, "reset failed, %s\n", usbd_errstr(err)); - goto error; - } - - DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n", - ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); - - TASK_INIT(&sc->sc_task, 0, uvscom_notify, sc); - ucom_attach(&sc->sc_ucom); - return 0; - -error: - ucom->sc_dying = 1; - return ENXIO; -} - -static int -uvscom_detach(device_t self) -{ - struct uvscom_softc *sc = device_get_softc(self); - int rv = 0; - - DPRINTF(("uvscom_detach: sc = %p\n", sc)); - - sc->sc_ucom.sc_dying = 1; - - 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; - } - - rv = ucom_detach(&sc->sc_ucom); - - return (rv); -} - -static usbd_status -uvscom_readstat(struct uvscom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - uint16_t r; - - DPRINTF(("%s: send readstat\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UVSCOM_READ_STATUS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 2); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, &r); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uvscom_readstat: %s\n", - usbd_errstr(err)); - return (err); - } - - DPRINTF(("%s: uvscom_readstat: r = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), r)); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_shutdown(struct uvscom_softc *sc) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: send shutdown\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SHUTDOWN; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uvscom_shutdown: %s\n", - usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_reset(struct uvscom_softc *sc) -{ - DPRINTF(("%s: uvscom_reset\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_crtscts(struct uvscom_softc *sc) -{ - DPRINTF(("%s: uvscom_set_crtscts\n", device_get_nameunit(sc->sc_ucom.sc_dev))); - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_line(struct uvscom_softc *sc, uint16_t line) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: uvscom_set_line: %04x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), line)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_LINE_CTL; - USETW(req.wValue, line); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uvscom_set_line: %s\n", - usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static usbd_status -uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls) -{ - usb_device_request_t req; - usbd_status err; - - DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), lsp, ls)); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SET_SPEED; - USETW(req.wValue, lsp); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uvscom_set_line_coding: %s\n", - usbd_errstr(err)); - return (err); - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UVSCOM_SET_PARAM; - USETW(req.wValue, ls); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - err = usbd_do_request(sc->sc_ucom.sc_udev, &req, NULL); - if (err) { - device_printf(sc->sc_ucom.sc_dev, "uvscom_set_line_coding: %s\n", - usbd_errstr(err)); - return (err); - } - - return (USBD_NORMAL_COMPLETION); -} - -static void -uvscom_dtr(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_dtr: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (sc->sc_dtr == onoff) - return; /* no change */ - - sc->sc_dtr = onoff; - - if (onoff) - SET(sc->sc_lcr, UVSCOM_DTR); - else - CLR(sc->sc_lcr, UVSCOM_DTR); - - uvscom_set_line(sc, sc->sc_lcr); -} - -static void -uvscom_rts(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_rts: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (sc->sc_rts == onoff) - return; /* no change */ - - sc->sc_rts = onoff; - - if (onoff) - SET(sc->sc_lcr, UVSCOM_RTS); - else - CLR(sc->sc_lcr, UVSCOM_RTS); - - uvscom_set_line(sc, sc->sc_lcr); -} - -static void -uvscom_break(struct uvscom_softc *sc, int onoff) -{ - DPRINTF(("%s: uvscom_break: onoff = %d\n", - device_get_nameunit(sc->sc_ucom.sc_dev), onoff)); - - if (onoff) - uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK)); -} - -static void -uvscom_set(void *addr, int portno, int reg, int onoff) -{ - struct uvscom_softc *sc = addr; - - switch (reg) { - case UCOM_SET_DTR: - uvscom_dtr(sc, onoff); - break; - case UCOM_SET_RTS: - uvscom_rts(sc, onoff); - break; - case UCOM_SET_BREAK: - uvscom_break(sc, onoff); - break; - default: - break; - } -} - -static int -uvscom_param(void *addr, int portno, struct termios *t) -{ - struct uvscom_softc *sc = addr; - usbd_status err; - uint16_t lsp; - uint16_t ls; - - DPRINTF(("%s: uvscom_param: sc = %p\n", - device_get_nameunit(sc->sc_ucom.sc_dev), sc)); - - ls = 0; - - switch (t->c_ospeed) { - case B150: - lsp = UVSCOM_SPEED_150BPS; - break; - case B300: - lsp = UVSCOM_SPEED_300BPS; - break; - case B600: - lsp = UVSCOM_SPEED_600BPS; - break; - case B1200: - lsp = UVSCOM_SPEED_1200BPS; - break; - case B2400: - lsp = UVSCOM_SPEED_2400BPS; - break; - case B4800: - lsp = UVSCOM_SPEED_4800BPS; - break; - case B9600: - lsp = UVSCOM_SPEED_9600BPS; - break; - case B19200: - lsp = UVSCOM_SPEED_19200BPS; - break; - case B38400: - lsp = UVSCOM_SPEED_38400BPS; - break; - case B57600: - lsp = UVSCOM_SPEED_57600BPS; - break; - case B115200: - lsp = UVSCOM_SPEED_115200BPS; - break; - default: - return (EIO); - } - - if (ISSET(t->c_cflag, CSTOPB)) - SET(ls, UVSCOM_STOP_BIT_2); - else - SET(ls, UVSCOM_STOP_BIT_1); - - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) - SET(ls, UVSCOM_PARITY_ODD); - else - SET(ls, UVSCOM_PARITY_EVEN); - } else - SET(ls, UVSCOM_PARITY_NONE); - - switch (ISSET(t->c_cflag, CSIZE)) { - case CS5: - SET(ls, UVSCOM_DATA_BIT_5); - break; - case CS6: - SET(ls, UVSCOM_DATA_BIT_6); - break; - case CS7: - SET(ls, UVSCOM_DATA_BIT_7); - break; - case CS8: - SET(ls, UVSCOM_DATA_BIT_8); - break; - default: - return (EIO); - } - - err = uvscom_set_line_coding(sc, lsp, ls); - if (err) - return (EIO); - - if (ISSET(t->c_cflag, CRTSCTS)) { - err = uvscom_set_crtscts(sc); - if (err) - return (EIO); - } - - return (0); -} - -static int -uvscom_open(void *addr, int portno) -{ - struct uvscom_softc *sc = addr; - int err; - int i; - - if (sc->sc_ucom.sc_dying) - return (ENXIO); - - DPRINTF(("uvscom_open: sc = %p\n", sc)); - - /* change output packet size */ - sc->sc_ucom.sc_obufsize = uvscomobufsiz; - - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { - DPRINTF(("uvscom_open: open interrupt pipe.\n")); - - sc->sc_usr = 0; /* clear unit status */ - - err = uvscom_readstat(sc); - if (err) { - DPRINTF(("%s: uvscom_open: readstat faild\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - - sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); - err = usbd_open_pipe_intr(sc->sc_ucom.sc_iface, - sc->sc_intr_number, - USBD_SHORT_XFER_OK, - &sc->sc_intr_pipe, - sc, - sc->sc_intr_buf, - sc->sc_isize, - uvscom_intr, - uvscominterval); - if (err) { - device_printf(sc->sc_ucom.sc_dev, - "cannot open interrupt pipe (addr %d)\n", - sc->sc_intr_number); - return (ENXIO); - } - } else { - DPRINTF(("uvscom_open: did not open interrupt pipe.\n")); - } - - if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) { - /* unit is not ready */ - - for (i = UVSCOM_UNIT_WAIT; i > 0; --i) { - pause("uvsop", hz); /* XXX */ - if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK)) - break; - } - if (i == 0) { - DPRINTF(("%s: unit is not ready\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - - /* check PC Card was inserted */ - if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) { - DPRINTF(("%s: no card\n", - device_get_nameunit(sc->sc_ucom.sc_dev))); - return (ENXIO); - } - } - - return (0); -} - -static void -uvscom_close(void *addr, int portno) -{ - struct uvscom_softc *sc = addr; - int err; - - if (sc->sc_ucom.sc_dying) - return; - - DPRINTF(("uvscom_close: close\n")); - - uvscom_shutdown(sc); - - if (sc->sc_intr_pipe != NULL) { - err = usbd_abort_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "abort interrupt pipe failed: %s\n", - usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_intr_pipe); - if (err) - device_printf(sc->sc_ucom.sc_dev, - "close interrupt pipe failed: %s\n", - usbd_errstr(err)); - free(sc->sc_intr_buf, M_USBDEV); - sc->sc_intr_pipe = NULL; - } -} - -static void -uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) -{ - struct uvscom_softc *sc = priv; - u_char *buf = sc->sc_intr_buf; - u_char pstatus; - - if (sc->sc_ucom.sc_dying) - return; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - - device_printf(sc->sc_ucom.sc_dev, - "uvscom_intr: abnormal status: %s\n", - usbd_errstr(status)); - usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); - return; - } - - DPRINTFN(2, ("%s: uvscom status = %02x %02x\n", - device_get_nameunit(sc->sc_ucom.sc_dev), buf[0], buf[1])); - - sc->sc_lsr = sc->sc_msr = 0; - sc->sc_usr = buf[1]; - - pstatus = buf[0]; - if (ISSET(pstatus, UVSCOM_TXRDY)) - SET(sc->sc_lsr, ULSR_TXRDY); - if (ISSET(pstatus, UVSCOM_RXRDY)) - SET(sc->sc_lsr, ULSR_RXRDY); - - pstatus = buf[1]; - if (ISSET(pstatus, UVSCOM_CTS)) - SET(sc->sc_msr, SER_CTS); - if (ISSET(pstatus, UVSCOM_DSR)) - SET(sc->sc_msr, SER_DSR); - if (ISSET(pstatus, UVSCOM_DCD)) - SET(sc->sc_msr, SER_DCD); - - /* Deferred notifying to the ucom layer */ - taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); -} - -static void -uvscom_notify(void *arg, int count) -{ - struct uvscom_softc *sc; - - sc = (struct uvscom_softc *)arg; - if (sc->sc_ucom.sc_dying) - return; - ucom_status_change(&sc->sc_ucom); -} - -static void -uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr) -{ - struct uvscom_softc *sc = addr; - - if (lsr != NULL) - *lsr = sc->sc_lsr; - if (msr != NULL) - *msr = sc->sc_msr; -} diff --git a/sys/dev/usb/uxb360gp_rdesc.h b/sys/dev/usb/uxb360gp_rdesc.h deleted file mode 100644 index b5a43f9..0000000 --- a/sys/dev/usb/uxb360gp_rdesc.h +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * Copyright (c) 2005 Ed Schouten <ed@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$ - */ - -/* - * The descriptor has no output report format, thus preventing you from - * controlling the LEDs and the built-in rumblers. - */ -static const uByte uhid_xb360gp_report_descr[] = { - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x05, /* USAGE (Gamepad) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - /* Unused */ - 0x75, 0x08, /* REPORT SIZE (8) */ - 0x95, 0x01, /* REPORT COUNT (1) */ - 0x81, 0x01, /* INPUT (Constant) */ - /* Byte count */ - 0x75, 0x08, /* REPORT SIZE (8) */ - 0x95, 0x01, /* REPORT COUNT (1) */ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x3b, /* USAGE (Byte Count) */ - 0x81, 0x01, /* INPUT (Constant) */ - /* D-Pad */ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x01, /* USAGE (Pointer) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x75, 0x01, /* REPORT SIZE (1) */ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */ - 0x95, 0x04, /* REPORT COUNT (4) */ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x90, /* USAGE (D-Pad Up) */ - 0x09, 0x91, /* USAGE (D-Pad Down) */ - 0x09, 0x93, /* USAGE (D-Pad Left) */ - 0x09, 0x92, /* USAGE (D-Pad Right) */ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */ - 0xc0, /* END COLLECTION */ - /* Buttons 5-11 */ - 0x75, 0x01, /* REPORT SIZE (1) */ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */ - 0x95, 0x07, /* REPORT COUNT (7) */ - 0x05, 0x09, /* USAGE PAGE (Button) */ - 0x09, 0x08, /* USAGE (Button 8) */ - 0x09, 0x07, /* USAGE (Button 7) */ - 0x09, 0x09, /* USAGE (Button 9) */ - 0x09, 0x0a, /* USAGE (Button 10) */ - 0x09, 0x05, /* USAGE (Button 5) */ - 0x09, 0x06, /* USAGE (Button 6) */ - 0x09, 0x0b, /* USAGE (Button 11) */ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */ - /* Unused */ - 0x75, 0x01, /* REPORT SIZE (1) */ - 0x95, 0x01, /* REPORT COUNT (1) */ - 0x81, 0x01, /* INPUT (Constant) */ - /* Buttons 1-4 */ - 0x75, 0x01, /* REPORT SIZE (1) */ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL MAXIMUM (1) */ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */ - 0x45, 0x01, /* PHYSICAL MAXIMUM (1) */ - 0x95, 0x04, /* REPORT COUNT (4) */ - 0x05, 0x09, /* USAGE PAGE (Button) */ - 0x19, 0x01, /* USAGE MINIMUM (Button 1) */ - 0x29, 0x04, /* USAGE MAXIMUM (Button 4) */ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */ - /* Triggers */ - 0x75, 0x08, /* REPORT SIZE (8) */ - 0x15, 0x00, /* LOGICAL MINIMUM (0) */ - 0x26, 0xff, 0x00, /* LOGICAL MAXIMUM (255) */ - 0x35, 0x00, /* PHYSICAL MINIMUM (0) */ - 0x46, 0xff, 0x00, /* PHYSICAL MAXIMUM (255) */ - 0x95, 0x02, /* REPORT SIZE (2) */ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x32, /* USAGE (Z) */ - 0x09, 0x35, /* USAGE (Rz) */ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */ - /* Sticks */ - 0x75, 0x10, /* REPORT SIZE (16) */ - 0x16, 0x00, 0x80, /* LOGICAL MINIMUM (-32768) */ - 0x26, 0xff, 0x7f, /* LOGICAL MAXIMUM (32767) */ - 0x36, 0x00, 0x80, /* PHYSICAL MINIMUM (-32768) */ - 0x46, 0xff, 0x7f, /* PHYSICAL MAXIMUM (32767) */ - 0x95, 0x04, /* REPORT COUNT (4) */ - 0x05, 0x01, /* USAGE PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x09, 0x33, /* USAGE (Rx) */ - 0x09, 0x34, /* USAGE (Ry) */ - 0x81, 0x02, /* INPUT (Data, Variable, Absolute) */ - /* Unused */ - 0x75, 0x30, /* REPORT SIZE (48) */ - 0x95, 0x01, /* REPORT COUNT (1) */ - 0x81, 0x01, /* INPUT (Constant) */ - 0xc0, /* END COLLECTION */ -}; |