[Midnightbsd-cvs] src [9518] stable/0.8/sys: Upgrade USB stack to FreeBSD 9-stable version.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Fri Aug 18 22:11:51 EDT 2017
Revision: 9518
http://svnweb.midnightbsd.org/src/?rev=9518
Author: laffer1
Date: 2017-08-18 22:11:51 -0400 (Fri, 18 Aug 2017)
Log Message:
-----------
Upgrade USB stack to FreeBSD 9-stable version. (from yesterday)
Modified Paths:
--------------
stable/0.8/sys/dev/usb/controller/at91dci.c
stable/0.8/sys/dev/usb/controller/at91dci.h
stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c
stable/0.8/sys/dev/usb/controller/atmegadci.c
stable/0.8/sys/dev/usb/controller/atmegadci.h
stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c
stable/0.8/sys/dev/usb/controller/avr32dci.c
stable/0.8/sys/dev/usb/controller/avr32dci.h
stable/0.8/sys/dev/usb/controller/ehci.c
stable/0.8/sys/dev/usb/controller/ehci.h
stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c
stable/0.8/sys/dev/usb/controller/ehci_mv.c
stable/0.8/sys/dev/usb/controller/ehci_pci.c
stable/0.8/sys/dev/usb/controller/ehcireg.h
stable/0.8/sys/dev/usb/controller/musb_otg.c
stable/0.8/sys/dev/usb/controller/musb_otg.h
stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c
stable/0.8/sys/dev/usb/controller/ohci.c
stable/0.8/sys/dev/usb/controller/ohci.h
stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c
stable/0.8/sys/dev/usb/controller/ohci_pci.c
stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c
stable/0.8/sys/dev/usb/controller/ohcireg.h
stable/0.8/sys/dev/usb/controller/uhci.c
stable/0.8/sys/dev/usb/controller/uhci.h
stable/0.8/sys/dev/usb/controller/uhci_pci.c
stable/0.8/sys/dev/usb/controller/uhcireg.h
stable/0.8/sys/dev/usb/controller/usb_controller.c
stable/0.8/sys/dev/usb/controller/uss820dci.c
stable/0.8/sys/dev/usb/controller/uss820dci.h
stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c
stable/0.8/sys/dev/usb/controller/xhci.c
stable/0.8/sys/dev/usb/controller/xhci.h
stable/0.8/sys/dev/usb/controller/xhci_pci.c
stable/0.8/sys/dev/usb/controller/xhcireg.h
stable/0.8/sys/dev/usb/input/atp.c
stable/0.8/sys/dev/usb/input/uep.c
stable/0.8/sys/dev/usb/input/uhid.c
stable/0.8/sys/dev/usb/input/ukbd.c
stable/0.8/sys/dev/usb/input/ums.c
stable/0.8/sys/dev/usb/input/usb_rdesc.h
stable/0.8/sys/dev/usb/misc/udbp.c
stable/0.8/sys/dev/usb/misc/udbp.h
stable/0.8/sys/dev/usb/misc/ufm.c
stable/0.8/sys/dev/usb/net/if_aue.c
stable/0.8/sys/dev/usb/net/if_auereg.h
stable/0.8/sys/dev/usb/net/if_axe.c
stable/0.8/sys/dev/usb/net/if_axereg.h
stable/0.8/sys/dev/usb/net/if_cdce.c
stable/0.8/sys/dev/usb/net/if_cdcereg.h
stable/0.8/sys/dev/usb/net/if_cue.c
stable/0.8/sys/dev/usb/net/if_cuereg.h
stable/0.8/sys/dev/usb/net/if_ipheth.c
stable/0.8/sys/dev/usb/net/if_iphethvar.h
stable/0.8/sys/dev/usb/net/if_kue.c
stable/0.8/sys/dev/usb/net/if_kuefw.h
stable/0.8/sys/dev/usb/net/if_kuereg.h
stable/0.8/sys/dev/usb/net/if_mos.c
stable/0.8/sys/dev/usb/net/if_mosreg.h
stable/0.8/sys/dev/usb/net/if_rue.c
stable/0.8/sys/dev/usb/net/if_ruereg.h
stable/0.8/sys/dev/usb/net/if_udav.c
stable/0.8/sys/dev/usb/net/if_udavreg.h
stable/0.8/sys/dev/usb/net/if_usie.c
stable/0.8/sys/dev/usb/net/if_usievar.h
stable/0.8/sys/dev/usb/net/ruephy.c
stable/0.8/sys/dev/usb/net/ruephyreg.h
stable/0.8/sys/dev/usb/net/uhso.c
stable/0.8/sys/dev/usb/net/usb_ethernet.c
stable/0.8/sys/dev/usb/net/usb_ethernet.h
stable/0.8/sys/dev/usb/quirk/usb_quirk.c
stable/0.8/sys/dev/usb/quirk/usb_quirk.h
stable/0.8/sys/dev/usb/serial/u3g.c
stable/0.8/sys/dev/usb/serial/uark.c
stable/0.8/sys/dev/usb/serial/ubsa.c
stable/0.8/sys/dev/usb/serial/ubser.c
stable/0.8/sys/dev/usb/serial/uchcom.c
stable/0.8/sys/dev/usb/serial/ucycom.c
stable/0.8/sys/dev/usb/serial/ufoma.c
stable/0.8/sys/dev/usb/serial/uftdi.c
stable/0.8/sys/dev/usb/serial/uftdi_reg.h
stable/0.8/sys/dev/usb/serial/ugensa.c
stable/0.8/sys/dev/usb/serial/uipaq.c
stable/0.8/sys/dev/usb/serial/ulpt.c
stable/0.8/sys/dev/usb/serial/umcs.c
stable/0.8/sys/dev/usb/serial/umcs.h
stable/0.8/sys/dev/usb/serial/umct.c
stable/0.8/sys/dev/usb/serial/umodem.c
stable/0.8/sys/dev/usb/serial/umoscom.c
stable/0.8/sys/dev/usb/serial/uplcom.c
stable/0.8/sys/dev/usb/serial/usb_serial.c
stable/0.8/sys/dev/usb/serial/usb_serial.h
stable/0.8/sys/dev/usb/serial/uslcom.c
stable/0.8/sys/dev/usb/serial/uvisor.c
stable/0.8/sys/dev/usb/serial/uvscom.c
stable/0.8/sys/dev/usb/storage/rio500_usb.h
stable/0.8/sys/dev/usb/storage/umass.c
stable/0.8/sys/dev/usb/storage/urio.c
stable/0.8/sys/dev/usb/storage/ustorage_fs.c
stable/0.8/sys/dev/usb/template/usb_template.c
stable/0.8/sys/dev/usb/template/usb_template.h
stable/0.8/sys/dev/usb/template/usb_template_audio.c
stable/0.8/sys/dev/usb/template/usb_template_cdce.c
stable/0.8/sys/dev/usb/template/usb_template_kbd.c
stable/0.8/sys/dev/usb/template/usb_template_modem.c
stable/0.8/sys/dev/usb/template/usb_template_mouse.c
stable/0.8/sys/dev/usb/template/usb_template_msc.c
stable/0.8/sys/dev/usb/template/usb_template_mtp.c
stable/0.8/sys/dev/usb/ufm_ioctl.h
stable/0.8/sys/dev/usb/usb.h
stable/0.8/sys/dev/usb/usb_bus.h
stable/0.8/sys/dev/usb/usb_busdma.c
stable/0.8/sys/dev/usb/usb_busdma.h
stable/0.8/sys/dev/usb/usb_cdc.h
stable/0.8/sys/dev/usb/usb_compat_linux.c
stable/0.8/sys/dev/usb/usb_compat_linux.h
stable/0.8/sys/dev/usb/usb_controller.h
stable/0.8/sys/dev/usb/usb_core.c
stable/0.8/sys/dev/usb/usb_core.h
stable/0.8/sys/dev/usb/usb_debug.c
stable/0.8/sys/dev/usb/usb_debug.h
stable/0.8/sys/dev/usb/usb_dev.c
stable/0.8/sys/dev/usb/usb_dev.h
stable/0.8/sys/dev/usb/usb_device.c
stable/0.8/sys/dev/usb/usb_device.h
stable/0.8/sys/dev/usb/usb_dynamic.c
stable/0.8/sys/dev/usb/usb_dynamic.h
stable/0.8/sys/dev/usb/usb_endian.h
stable/0.8/sys/dev/usb/usb_error.c
stable/0.8/sys/dev/usb/usb_freebsd.h
stable/0.8/sys/dev/usb/usb_generic.c
stable/0.8/sys/dev/usb/usb_generic.h
stable/0.8/sys/dev/usb/usb_handle_request.c
stable/0.8/sys/dev/usb/usb_hid.c
stable/0.8/sys/dev/usb/usb_hub.c
stable/0.8/sys/dev/usb/usb_hub.h
stable/0.8/sys/dev/usb/usb_if.m
stable/0.8/sys/dev/usb/usb_ioctl.h
stable/0.8/sys/dev/usb/usb_lookup.c
stable/0.8/sys/dev/usb/usb_mbuf.c
stable/0.8/sys/dev/usb/usb_mbuf.h
stable/0.8/sys/dev/usb/usb_msctest.c
stable/0.8/sys/dev/usb/usb_msctest.h
stable/0.8/sys/dev/usb/usb_parse.c
stable/0.8/sys/dev/usb/usb_pci.h
stable/0.8/sys/dev/usb/usb_pf.c
stable/0.8/sys/dev/usb/usb_pf.h
stable/0.8/sys/dev/usb/usb_process.c
stable/0.8/sys/dev/usb/usb_process.h
stable/0.8/sys/dev/usb/usb_request.c
stable/0.8/sys/dev/usb/usb_request.h
stable/0.8/sys/dev/usb/usb_transfer.c
stable/0.8/sys/dev/usb/usb_transfer.h
stable/0.8/sys/dev/usb/usb_util.c
stable/0.8/sys/dev/usb/usb_util.h
stable/0.8/sys/dev/usb/usbdevs
stable/0.8/sys/dev/usb/usbdi.h
stable/0.8/sys/dev/usb/usbdi_util.h
stable/0.8/sys/dev/usb/usbhid.h
stable/0.8/sys/dev/usb/wlan/if_rum.c
stable/0.8/sys/dev/usb/wlan/if_rumfw.h
stable/0.8/sys/dev/usb/wlan/if_rumreg.h
stable/0.8/sys/dev/usb/wlan/if_rumvar.h
stable/0.8/sys/dev/usb/wlan/if_run.c
stable/0.8/sys/dev/usb/wlan/if_runreg.h
stable/0.8/sys/dev/usb/wlan/if_runvar.h
stable/0.8/sys/dev/usb/wlan/if_uath.c
stable/0.8/sys/dev/usb/wlan/if_uathreg.h
stable/0.8/sys/dev/usb/wlan/if_uathvar.h
stable/0.8/sys/dev/usb/wlan/if_upgt.c
stable/0.8/sys/dev/usb/wlan/if_upgtvar.h
stable/0.8/sys/dev/usb/wlan/if_ural.c
stable/0.8/sys/dev/usb/wlan/if_uralreg.h
stable/0.8/sys/dev/usb/wlan/if_uralvar.h
stable/0.8/sys/dev/usb/wlan/if_urtw.c
stable/0.8/sys/dev/usb/wlan/if_urtwreg.h
stable/0.8/sys/dev/usb/wlan/if_urtwvar.h
stable/0.8/sys/dev/usb/wlan/if_zyd.c
stable/0.8/sys/dev/usb/wlan/if_zydfw.h
stable/0.8/sys/dev/usb/wlan/if_zydreg.h
stable/0.8/sys/fs/devfs/devfs_int.h
stable/0.8/sys/kern/kern_conf.c
stable/0.8/sys/sys/conf.h
Added Paths:
-----------
stable/0.8/sys/dev/usb/input/wsp.c
stable/0.8/sys/dev/usb/net/if_axge.c
stable/0.8/sys/dev/usb/net/if_axgereg.h
stable/0.8/sys/dev/usb/net/if_urndis.c
stable/0.8/sys/dev/usb/net/if_urndisreg.h
stable/0.8/sys/dev/usb/uftdiio.h
Property Changed:
----------------
stable/0.8/sys/fs/devfs/devfs_int.h
Modified: stable/0.8/sys/dev/usb/controller/at91dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/at91dci.c 257040 2013-10-24 06:06:17Z hselasky $");
/*-
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -2277,10 +2277,6 @@
if (udev->device_index != sc->sc_rt_addr) {
- if (udev->flags.usb_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
if (udev->speed != USB_SPEED_FULL) {
/* not supported */
return;
Modified: stable/0.8/sys/dev/usb/controller/at91dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/at91dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
/*-
* Copyright (c) 2006 ATMEL
* Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
Modified: stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/at91dci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
/*-
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -159,6 +159,7 @@
sc->sc_dci.sc_bus.parent = dev;
sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
sc->sc_dci.sc_bus.devices_max = AT91_MAX_DEVICES;
+ sc->sc_dci.sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
@@ -261,14 +262,8 @@
at91_udp_detach(device_t dev)
{
struct at91_udp_softc *sc = device_get_softc(dev);
- device_t bdev;
int err;
- if (sc->sc_dci.sc_bus.bdev) {
- bdev = sc->sc_dci.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(dev);
Modified: stable/0.8/sys/dev/usb/controller/atmegadci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/atmegadci.c 257040 2013-10-24 06:06:17Z hselasky $");
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -2110,10 +2110,6 @@
if (udev->device_index != sc->sc_rt_addr) {
- if (udev->flags.usb_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
if (udev->speed != USB_SPEED_FULL) {
/* not supported */
return;
Modified: stable/0.8/sys/dev/usb/controller/atmegadci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/atmegadci.h 229096 2011-12-31 14:22:02Z hselasky $ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/atmegadci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -101,6 +101,7 @@
sc->sc_otg.sc_bus.parent = dev;
sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES;
+ sc->sc_otg.sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
@@ -154,14 +155,8 @@
atmegadci_detach(device_t dev)
{
struct atmegadci_super_softc *sc = device_get_softc(dev);
- device_t bdev;
int err;
- if (sc->sc_otg.sc_bus.bdev) {
- bdev = sc->sc_otg.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(dev);
Modified: stable/0.8/sys/dev/usb/controller/avr32dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/avr32dci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/avr32dci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/avr32dci.c 257040 2013-10-24 06:06:17Z hselasky $");
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -2054,10 +2054,6 @@
if (udev->device_index != sc->sc_rt_addr) {
- if (udev->flags.usb_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
if ((udev->speed != USB_SPEED_FULL) &&
(udev->speed != USB_SPEED_HIGH)) {
/* not supported */
Modified: stable/0.8/sys/dev/usb/controller/avr32dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/avr32dci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/avr32dci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/avr32dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/controller/ehci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci.c 273887 2014-10-31 07:59:07Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -212,7 +212,7 @@
return (0);
}
}
- device_printf(sc->sc_bus.bdev, "Reset timeout\n");
+ device_printf(sc->sc_bus.bdev, "reset timeout\n");
return (USB_ERR_IOERROR);
}
@@ -256,7 +256,7 @@
DPRINTF("HCC uses 64-bit structures\n");
/* MUST clear segment register if 64 bit capable */
- EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
+ EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
}
usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
@@ -287,7 +287,7 @@
}
}
if (hcr) {
- device_printf(sc->sc_bus.bdev, "Run timeout\n");
+ device_printf(sc->sc_bus.bdev, "run timeout\n");
return (USB_ERR_IOERROR);
}
return (USB_ERR_NORMAL_COMPLETION);
@@ -1195,9 +1195,16 @@
(status & EHCI_QTD_PINGSTATE) ? "[PING]" : "");
}
#endif
-
- return ((status & EHCI_QTD_HALTED) ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
+ if (status & EHCI_QTD_HALTED) {
+ if ((xfer->xroot->udev->parent_hs_hub != NULL) ||
+ (xfer->xroot->udev->address != 0)) {
+ /* try to separate I/O errors from STALL */
+ if (EHCI_QTD_GET_CERR(status) == 0)
+ return (USB_ERR_IOERROR);
+ }
+ return (USB_ERR_STALLED);
+ }
+ return (USB_ERR_NORMAL_COMPLETION);
}
static void
@@ -1651,12 +1658,17 @@
}
td->len = 0;
+ /* properly reset reserved fields */
td->qtd_buffer[0] = 0;
+ td->qtd_buffer[1] = 0;
+ td->qtd_buffer[2] = 0;
+ td->qtd_buffer[3] = 0;
+ td->qtd_buffer[4] = 0;
td->qtd_buffer_hi[0] = 0;
-
- td->qtd_buffer[1] = 0;
td->qtd_buffer_hi[1] = 0;
-
+ td->qtd_buffer_hi[2] = 0;
+ td->qtd_buffer_hi[3] = 0;
+ td->qtd_buffer_hi[4] = 0;
} else {
uint8_t x;
@@ -1711,6 +1723,12 @@
htohc32(temp->sc,
buf_res.physaddr & (~0xFFF));
td->qtd_buffer_hi[x] = 0;
+
+ /* properly reset reserved fields */
+ while (++x < EHCI_QTD_NBUFFERS) {
+ td->qtd_buffer[x] = 0;
+ td->qtd_buffer_hi[x] = 0;
+ }
}
if (td_next) {
@@ -1998,6 +2016,18 @@
qh->qh_qtd.qtd_altnext =
htohc32(temp.sc, EHCI_LINK_TERMINATE);
+ /* properly reset reserved fields */
+ qh->qh_qtd.qtd_buffer[0] = 0;
+ qh->qh_qtd.qtd_buffer[1] = 0;
+ qh->qh_qtd.qtd_buffer[2] = 0;
+ qh->qh_qtd.qtd_buffer[3] = 0;
+ qh->qh_qtd.qtd_buffer[4] = 0;
+ qh->qh_qtd.qtd_buffer_hi[0] = 0;
+ qh->qh_qtd.qtd_buffer_hi[1] = 0;
+ qh->qh_qtd.qtd_buffer_hi[2] = 0;
+ qh->qh_qtd.qtd_buffer_hi[3] = 0;
+ qh->qh_qtd.qtd_buffer_hi[4] = 0;
+
usb_pc_cpu_flush(qh->page_cache);
if (xfer->xroot->udev->flags.self_suspended == 0) {
@@ -2228,10 +2258,26 @@
}
static void
+ehci_doorbell_async(struct ehci_softc *sc)
+{
+ uint32_t temp;
+
+ /*
+ * XXX Performance quirk: Some Host Controllers have a too low
+ * interrupt rate. Issue an IAAD to stimulate the Host
+ * Controller after queueing the BULK transfer.
+ *
+ * XXX Force the host controller to refresh any QH caches.
+ */
+ temp = EOREAD4(sc, EHCI_USBCMD);
+ if (!(temp & EHCI_CMD_IAAD))
+ EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
+}
+
+static void
ehci_device_bulk_start(struct usb_xfer *xfer)
{
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- uint32_t temp;
/* setup TD's and QH */
ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
@@ -2246,13 +2292,7 @@
if (sc->sc_flags & EHCI_SCFLG_IAADBUG)
return;
- /* XXX Performance quirk: Some Host Controllers have a too low
- * interrupt rate. Issue an IAAD to stimulate the Host
- * Controller after queueing the BULK transfer.
- */
- temp = EOREAD4(sc, EHCI_USBCMD);
- if (!(temp & EHCI_CMD_IAAD))
- EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
+ ehci_doorbell_async(sc);
}
struct usb_pipe_methods ehci_device_bulk_methods =
@@ -3705,10 +3745,6 @@
edesc->bEndpointAddress, udev->flags.usb_mode,
sc->sc_addr);
- if (udev->flags.usb_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
if (udev->device_index != sc->sc_addr) {
if ((udev->speed != USB_SPEED_HIGH) &&
@@ -3752,7 +3788,7 @@
* Wait until the hardware has finished any possible use of
* the transfer descriptor(s) and QH
*/
- *pus = (188); /* microseconds */
+ *pus = (1125); /* microseconds */
}
static void
@@ -3873,6 +3909,41 @@
return;
}
+static void
+ehci_start_dma_delay_second(struct usb_xfer *xfer)
+{
+ struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
+
+ DPRINTF("\n");
+
+ /* trigger doorbell */
+ ehci_doorbell_async(sc);
+
+ /* give the doorbell 4ms */
+ usbd_transfer_timeout_ms(xfer,
+ (void (*)(void *))&usb_dma_delay_done_cb, 4);
+}
+
+/*
+ * Ring the doorbell twice before freeing any DMA descriptors. Some host
+ * controllers apparently cache the QH descriptors and need a message
+ * that the cache needs to be discarded.
+ */
+static void
+ehci_start_dma_delay(struct usb_xfer *xfer)
+{
+ struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
+
+ DPRINTF("\n");
+
+ /* trigger doorbell */
+ ehci_doorbell_async(sc);
+
+ /* give the doorbell 4ms */
+ usbd_transfer_timeout_ms(xfer,
+ (void (*)(void *))&ehci_start_dma_delay_second, 4);
+}
+
struct usb_bus_methods ehci_bus_methods =
{
.endpoint_init = ehci_ep_init,
@@ -3885,4 +3956,5 @@
.set_hw_power_sleep = ehci_set_hw_power_sleep,
.roothub_exec = ehci_roothub_exec,
.xfer_poll = ehci_do_poll,
+ .start_dma_delay = ehci_start_dma_delay,
};
Modified: stable/0.8/sys/dev/usb/controller/ehci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ehci.h 242776 2012-11-08 16:17:52Z hselasky $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_ixp4xx.c 308403 2016-11-07 09:23:07Z hselasky $");
#include "opt_bus.h"
@@ -107,6 +107,7 @@
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -206,14 +207,8 @@
{
struct ixp_ehci_softc *isc = device_get_softc(self);
ehci_softc_t *sc = &isc->base;
- device_t bdev;
int err;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
Modified: stable/0.8/sys/dev/usb/controller/ehci_mv.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_mv.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_mv.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_mv.c 308403 2016-11-07 09:23:07Z hselasky $");
#include "opt_bus.h"
@@ -123,6 +123,7 @@
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -238,14 +239,8 @@
mv_ehci_detach(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
- device_t bdev;
int err;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
Modified: stable/0.8/sys/dev/usb/controller/ehci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_pci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_pci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
/*
* USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
@@ -120,10 +120,16 @@
case 0x43961002:
return ("AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller");
+ case 0x1d268086:
+ return ("Intel Patsburg USB 2.0 controller");
+ case 0x1d2d8086:
+ return ("Intel Patsburg USB 2.0 controller");
case 0x1e268086:
return ("Intel Panther Point USB 2.0 controller");
case 0x1e2d8086:
return ("Intel Panther Point USB 2.0 controller");
+ case 0x1f2c8086:
+ return ("Intel Avoton USB 2.0 controller");
case 0x25ad8086:
return "Intel 6300ESB USB 2.0 controller";
case 0x24cd8086:
@@ -152,6 +158,14 @@
return ("Intel PCH USB 2.0 controller USB-A");
case 0x3b3c8086:
return ("Intel PCH USB 2.0 controller USB-B");
+ case 0x8c268086:
+ return ("Intel Lynx Point USB 2.0 controller USB-A");
+ case 0x8c2d8086:
+ return ("Intel Lynx Point USB 2.0 controller USB-B");
+ case 0x8ca68086:
+ return ("Intel Wildcat Point USB 2.0 controller USB-A");
+ case 0x8cad8086:
+ return ("Intel Wildcat Point USB 2.0 controller USB-B");
case 0x00e01033:
return ("NEC uPD 720100 USB 2.0 controller");
@@ -165,7 +179,7 @@
case 0x00e810de:
return "NVIDIA nForce3 250 USB 2.0 controller";
case 0x005b10de:
- return "NVIDIA nForce4 USB 2.0 controller";
+ return "NVIDIA nForce CK804 USB 2.0 controller";
case 0x036d10de:
return "NVIDIA nForce MCP55 USB 2.0 controller";
case 0x03f210de:
@@ -264,6 +278,7 @@
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -452,13 +467,7 @@
ehci_pci_detach(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
- device_t bdev;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
Modified: stable/0.8/sys/dev/usb/controller/ehcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehcireg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehcireg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ehcireg.h 214349 2010-10-25 15:51:43Z nwhitehorn $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/musb_otg.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/musb_otg.c 279280 2015-02-25 12:26:45Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -90,6 +90,8 @@
&musbotgdebug, 0, "Debug level");
#endif
+#define MAX_NAK_TO 16
+
/* prototypes */
struct usb_bus_methods musbotg_bus_methods;
@@ -98,17 +100,35 @@
struct usb_pipe_methods musbotg_device_intr_methods;
struct usb_pipe_methods musbotg_device_isoc_methods;
-static musbotg_cmd_t musbotg_setup_rx;
-static musbotg_cmd_t musbotg_setup_data_rx;
-static musbotg_cmd_t musbotg_setup_data_tx;
-static musbotg_cmd_t musbotg_setup_status;
-static musbotg_cmd_t musbotg_data_rx;
-static musbotg_cmd_t musbotg_data_tx;
+/* Control transfers: Device mode */
+static musbotg_cmd_t musbotg_dev_ctrl_setup_rx;
+static musbotg_cmd_t musbotg_dev_ctrl_data_rx;
+static musbotg_cmd_t musbotg_dev_ctrl_data_tx;
+static musbotg_cmd_t musbotg_dev_ctrl_status;
+
+/* Control transfers: Host mode */
+static musbotg_cmd_t musbotg_host_ctrl_setup_tx;
+static musbotg_cmd_t musbotg_host_ctrl_data_rx;
+static musbotg_cmd_t musbotg_host_ctrl_data_tx;
+static musbotg_cmd_t musbotg_host_ctrl_status_rx;
+static musbotg_cmd_t musbotg_host_ctrl_status_tx;
+
+/* Bulk, Interrupt, Isochronous: Device mode */
+static musbotg_cmd_t musbotg_dev_data_rx;
+static musbotg_cmd_t musbotg_dev_data_tx;
+
+/* Bulk, Interrupt, Isochronous: Host mode */
+static musbotg_cmd_t musbotg_host_data_rx;
+static musbotg_cmd_t musbotg_host_data_tx;
+
static void musbotg_device_done(struct usb_xfer *, usb_error_t);
static void musbotg_do_poll(struct usb_bus *);
static void musbotg_standard_done(struct usb_xfer *);
static void musbotg_interrupt_poll(struct musbotg_softc *);
static void musbotg_root_intr(struct musbotg_softc *);
+static int musbotg_channel_alloc(struct musbotg_softc *, struct musbotg_td *td);
+static void musbotg_channel_free(struct musbotg_softc *, struct musbotg_td *td);
+static void musbotg_ep_int_set(struct musbotg_softc *sc, int channel, int on);
/*
* Here is a configuration that the chip supports.
@@ -123,6 +143,64 @@
}
};
+static int
+musbotg_channel_alloc(struct musbotg_softc *sc, struct musbotg_td *td)
+{
+ int ch;
+ int ep;
+
+ ep = td->ep_no;
+
+ /* In device mode each EP got its own channel */
+ if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+ musbotg_ep_int_set(sc, ep, 1);
+ return (ep);
+ }
+
+ /*
+ * All control transactions go through EP0
+ */
+ if (ep == 0) {
+ if (sc->sc_channel_mask & (1 << 0))
+ return (-1);
+ sc->sc_channel_mask |= (1 << 0);
+ musbotg_ep_int_set(sc, ep, 1);
+ return (0);
+ }
+
+ for (ch = 1; ch < MUSB2_EP_MAX; ch++) {
+ if (!(sc->sc_channel_mask & (1 << ch))) {
+ sc->sc_channel_mask |= (1 << ch);
+ musbotg_ep_int_set(sc, ch, 1);
+ return (ch);
+ }
+ }
+
+ DPRINTFN(-1, "No available channels. Mask: %04x\n", sc->sc_channel_mask);
+
+ return (-1);
+}
+
+static void
+musbotg_channel_free(struct musbotg_softc *sc, struct musbotg_td *td)
+{
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ if (sc->sc_mode == MUSB2_DEVICE_MODE)
+ return;
+
+ if (td == NULL)
+ return;
+ if (td->channel == -1)
+ return;
+
+ musbotg_ep_int_set(sc, td->channel, 0);
+ sc->sc_channel_mask &= ~(1 << td->channel);
+
+ td->channel = -1;
+}
+
static void
musbotg_get_hw_ep_profile(struct usb_device *udev,
const struct usb_hw_ep_profile **ppf, uint8_t ep_addr)
@@ -213,6 +291,46 @@
}
static void
+musbotg_suspend_host(struct musbotg_softc *sc)
+{
+ uint8_t temp;
+
+ if (sc->sc_flags.status_suspend) {
+ return;
+ }
+
+ temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ temp |= MUSB2_MASK_SUSPMODE;
+ MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+ sc->sc_flags.status_suspend = 1;
+}
+
+static void
+musbotg_wakeup_host(struct musbotg_softc *sc)
+{
+ uint8_t temp;
+
+ if (!(sc->sc_flags.status_suspend)) {
+ return;
+ }
+
+ temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ temp &= ~MUSB2_MASK_SUSPMODE;
+ temp |= MUSB2_MASK_RESUME;
+ MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+
+ /* wait 20 milliseconds */
+ /* Wait for reset to complete. */
+ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
+
+ temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ temp &= ~MUSB2_MASK_RESUME;
+ MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+
+ sc->sc_flags.status_suspend = 0;
+}
+
+static void
musbotg_wakeup_peer(struct musbotg_softc *sc)
{
uint8_t temp;
@@ -243,7 +361,7 @@
}
static uint8_t
-musbotg_setup_rx(struct musbotg_td *td)
+musbotg_dev_ctrl_setup_rx(struct musbotg_td *td)
{
struct musbotg_softc *sc;
struct usb_device_request req;
@@ -253,6 +371,15 @@
/* get pointer to softc */
sc = MUSBOTG_PC2SC(td->pc);
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
/* select endpoint 0 */
MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
@@ -269,8 +396,10 @@
/* do not stall at this point */
td->did_stall = 1;
/* wait for interrupt */
+ DPRINTFN(1, "CSR0 DATAEND\n");
goto not_complete;
}
+
if (csr & MUSB2_MASK_CSR0L_SENTSTALL) {
/* clear SENTSTALL */
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
@@ -289,31 +418,37 @@
sc->sc_ep0_busy = 0;
}
if (sc->sc_ep0_busy) {
+ DPRINTFN(1, "EP0 BUSY\n");
goto not_complete;
}
if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
goto not_complete;
}
- /* clear did stall flag */
- td->did_stall = 0;
/* get the packet byte count */
count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
/* verify data length */
if (count != td->remainder) {
- DPRINTFN(0, "Invalid SETUP packet "
+ DPRINTFN(1, "Invalid SETUP packet "
"length, %d bytes\n", count);
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+ /* don't clear stall */
+ td->did_stall = 1;
goto not_complete;
}
if (count != sizeof(req)) {
- DPRINTFN(0, "Unsupported SETUP packet "
+ DPRINTFN(1, "Unsupported SETUP packet "
"length, %d bytes\n", count);
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+ /* don't clear stall */
+ td->did_stall = 1;
goto not_complete;
}
+ /* clear did stall flag */
+ td->did_stall = 0;
+
/* receive data */
bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
MUSB2_REG_EPFIFO(0), (void *)&req, sizeof(req));
@@ -337,6 +472,8 @@
} else {
sc->sc_dv_addr = 0xFF;
}
+
+ musbotg_channel_free(sc, td);
return (0); /* complete */
not_complete:
@@ -350,10 +487,117 @@
return (1); /* not complete */
}
+static uint8_t
+musbotg_host_ctrl_setup_tx(struct musbotg_td *td)
+{
+ struct musbotg_softc *sc;
+ struct usb_device_request req;
+ uint8_t csr, csrh;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ /* select endpoint 0 */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+ /* read out FIFO status */
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ /* Not ready yet yet */
+ if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+ return (1);
+
+ /* Failed */
+ if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+ MUSB2_MASK_CSR0L_ERROR))
+ {
+ /* Clear status bit */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+ td->error = 1;
+ }
+
+ if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+ DPRINTFN(1, "NAK timeout\n");
+
+ if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+ csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+ csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ }
+ }
+
+ csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ td->error = 1;
+ }
+
+ if (td->error) {
+ musbotg_channel_free(sc, td);
+ return (0);
+ }
+
+ /* Fifo is not empty and there is no NAK timeout */
+ if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+ return (1);
+
+ /* check if we are complete */
+ if (td->remainder == 0) {
+ /* we are complete */
+ musbotg_channel_free(sc, td);
+ return (0);
+ }
+
+ /* copy data into real buffer */
+ usbd_copy_out(td->pc, 0, &req, sizeof(req));
+
+ /* send data */
+ bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), (void *)&req, sizeof(req));
+
+ /* update offset and remainder */
+ td->offset += sizeof(req);
+ td->remainder -= sizeof(req);
+
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_TXPKTRDY |
+ MUSB2_MASK_CSR0L_SETUPPKT);
+
+ /* Just to be consistent, not used above */
+ td->transaction_started = 1;
+
+ return (1); /* in progress */
+}
+
/* Control endpoint only data handling functions (RX/TX/SYNC) */
static uint8_t
-musbotg_setup_data_rx(struct musbotg_td *td)
+musbotg_dev_ctrl_data_rx(struct musbotg_td *td)
{
struct usb_page_search buf_res;
struct musbotg_softc *sc;
@@ -496,7 +740,7 @@
}
static uint8_t
-musbotg_setup_data_tx(struct musbotg_td *td)
+musbotg_dev_ctrl_data_tx(struct musbotg_td *td)
{
struct usb_page_search buf_res;
struct musbotg_softc *sc;
@@ -614,17 +858,373 @@
}
static uint8_t
-musbotg_setup_status(struct musbotg_td *td)
+musbotg_host_ctrl_data_rx(struct musbotg_td *td)
{
+ struct usb_page_search buf_res;
struct musbotg_softc *sc;
+ uint16_t count;
uint8_t csr;
+ uint8_t got_short;
/* get pointer to softc */
sc = MUSBOTG_PC2SC(td->pc);
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
/* select endpoint 0 */
MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+ /* read out FIFO status */
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ got_short = 0;
+ if (!td->transaction_started) {
+ td->transaction_started = 1;
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(0),
+ td->dev_addr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(0), td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(0), td->hport);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_REQPKT);
+
+ return (1);
+ }
+
+ if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+ csr &= ~MUSB2_MASK_CSR0L_REQPKT;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ td->error = 1;
+ }
+
+ /* Failed */
+ if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+ MUSB2_MASK_CSR0L_ERROR))
+ {
+ /* Clear status bit */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+ td->error = 1;
+ }
+
+ if (td->error) {
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+
+ if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY))
+ return (1); /* not yet */
+
+ /* get the packet byte count */
+ count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
+
+ /* verify the packet byte count */
+ if (count != td->max_frame_size) {
+ if (count < td->max_frame_size) {
+ /* we have a short packet */
+ td->short_pkt = 1;
+ got_short = 1;
+ } else {
+ /* invalid USB packet */
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+ }
+ /* verify the packet byte count */
+ if (count > td->remainder) {
+ /* invalid USB packet */
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+ while (count > 0) {
+ uint32_t temp;
+
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > count) {
+ buf_res.length = count;
+ }
+ /* check for unaligned memory address */
+ if (USB_P2U(buf_res.buffer) & 3) {
+
+ temp = count & ~3;
+
+ if (temp) {
+ /* receive data 4 bytes at a time */
+ bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), sc->sc_bounce_buf,
+ temp / 4);
+ }
+ temp = count & 3;
+ if (temp) {
+ /* receive data 1 byte at a time */
+ bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0),
+ (void *)(&sc->sc_bounce_buf[count / 4]), temp);
+ }
+ usbd_copy_in(td->pc, td->offset,
+ sc->sc_bounce_buf, count);
+
+ /* update offset and remainder */
+ td->offset += count;
+ td->remainder -= count;
+ break;
+ }
+ /* check if we can optimise */
+ if (buf_res.length >= 4) {
+
+ /* receive data 4 bytes at a time */
+ bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), buf_res.buffer,
+ buf_res.length / 4);
+
+ temp = buf_res.length & ~3;
+
+ /* update counters */
+ count -= temp;
+ td->offset += temp;
+ td->remainder -= temp;
+ continue;
+ }
+ /* receive data */
+ bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), buf_res.buffer, buf_res.length);
+
+ /* update counters */
+ count -= buf_res.length;
+ td->offset += buf_res.length;
+ td->remainder -= buf_res.length;
+ }
+
+ csr &= ~MUSB2_MASK_CSR0L_RXPKTRDY;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ /* check if we are complete */
+ if ((td->remainder == 0) || got_short) {
+ if (td->short_pkt) {
+ /* we are complete */
+
+ musbotg_channel_free(sc, td);
+ return (0);
+ }
+ /* else need to receive a zero length packet */
+ }
+
+ td->transaction_started = 1;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_REQPKT);
+
+ return (1); /* not complete */
+}
+
+static uint8_t
+musbotg_host_ctrl_data_tx(struct musbotg_td *td)
+{
+ struct usb_page_search buf_res;
+ struct musbotg_softc *sc;
+ uint16_t count;
+ uint8_t csr, csrh;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* No free EPs */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ /* select endpoint */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+ /* read out FIFO status */
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+ MUSB2_MASK_CSR0L_ERROR)) {
+ /* clear status bits */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ td->error = 1;
+ }
+
+ if (csr & MUSB2_MASK_CSR0L_NAKTIMO ) {
+
+ if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+ csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+ csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ }
+ }
+
+ csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ td->error = 1;
+ }
+
+
+ if (td->error) {
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ /*
+ * Wait while FIFO is empty.
+ * Do not flush it because it will cause transactions
+ * with size more then packet size. It might upset
+ * some devices
+ */
+ if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY)
+ return (1);
+
+ /* Packet still being processed */
+ if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+ return (1);
+
+ if (td->transaction_started) {
+ /* check remainder */
+ if (td->remainder == 0) {
+ if (td->short_pkt) {
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+ /* else we need to transmit a short packet */
+ }
+
+ /* We're not complete - more transactions required */
+ td->transaction_started = 0;
+ }
+
+ /* check for short packet */
+ count = td->max_frame_size;
+ if (td->remainder < count) {
+ /* we have a short packet */
+ td->short_pkt = 1;
+ count = td->remainder;
+ }
+
+ while (count > 0) {
+ uint32_t temp;
+
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > count) {
+ buf_res.length = count;
+ }
+ /* check for unaligned memory address */
+ if (USB_P2U(buf_res.buffer) & 3) {
+
+ usbd_copy_out(td->pc, td->offset,
+ sc->sc_bounce_buf, count);
+
+ temp = count & ~3;
+
+ if (temp) {
+ /* transmit data 4 bytes at a time */
+ bus_space_write_multi_4(sc->sc_io_tag,
+ sc->sc_io_hdl, MUSB2_REG_EPFIFO(0),
+ sc->sc_bounce_buf, temp / 4);
+ }
+ temp = count & 3;
+ if (temp) {
+ /* receive data 1 byte at a time */
+ bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0),
+ ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+ }
+ /* update offset and remainder */
+ td->offset += count;
+ td->remainder -= count;
+ break;
+ }
+ /* check if we can optimise */
+ if (buf_res.length >= 4) {
+
+ /* transmit data 4 bytes at a time */
+ bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), buf_res.buffer,
+ buf_res.length / 4);
+
+ temp = buf_res.length & ~3;
+
+ /* update counters */
+ count -= temp;
+ td->offset += temp;
+ td->remainder -= temp;
+ continue;
+ }
+ /* transmit data */
+ bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(0), buf_res.buffer,
+ buf_res.length);
+
+ /* update counters */
+ count -= buf_res.length;
+ td->offset += buf_res.length;
+ td->remainder -= buf_res.length;
+ }
+
+ /* Function address */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+ /* TX NAK timeout */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_TXPKTRDY);
+
+ td->transaction_started = 1;
+
+ return (1); /* not complete */
+}
+
+static uint8_t
+musbotg_dev_ctrl_status(struct musbotg_td *td)
+{
+ struct musbotg_softc *sc;
+ uint8_t csr;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ /* select endpoint 0 */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
if (sc->sc_ep0_busy) {
sc->sc_ep0_busy = 0;
sc->sc_ep0_cmd |= MUSB2_MASK_CSR0L_DATAEND;
@@ -644,12 +1244,167 @@
/* write function address */
musbotg_set_address(sc, sc->sc_dv_addr);
}
+
+ musbotg_channel_free(sc, td);
return (0); /* complete */
}
static uint8_t
-musbotg_data_rx(struct musbotg_td *td)
+musbotg_host_ctrl_status_rx(struct musbotg_td *td)
{
+ struct musbotg_softc *sc;
+ uint8_t csr, csrh;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ /* select endpoint 0 */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+ if (!td->transaction_started) {
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(0),
+ td->dev_addr);
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(0), td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(0), td->hport);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+ /* RX NAK timeout */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+ td->transaction_started = 1;
+
+ /* Disable PING */
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_RXCSRH);
+ csrh |= MUSB2_MASK_CSR0H_PING_DIS;
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, csrh);
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_STATUSPKT |
+ MUSB2_MASK_CSR0L_REQPKT);
+
+ return (1); /* Just started */
+
+ }
+
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+
+ DPRINTFN(4, "IN STATUS csr=0x%02x\n", csr);
+
+ if (csr & MUSB2_MASK_CSR0L_RXPKTRDY) {
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+ csr &= ~ (MUSB2_MASK_CSR0L_STATUSPKT |
+ MUSB2_MASK_CSR0L_REQPKT);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+ td->error = 1;
+ }
+
+ /* Failed */
+ if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+ MUSB2_MASK_CSR0L_ERROR))
+ {
+ /* Clear status bit */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+ td->error = 1;
+ }
+
+ if (td->error) {
+ musbotg_channel_free(sc, td);
+ return (0);
+ }
+
+ return (1); /* Not ready yet */
+}
+
+static uint8_t
+musbotg_host_ctrl_status_tx(struct musbotg_td *td)
+{
+ struct musbotg_softc *sc;
+ uint8_t csr;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d/%d [%d@%d.%d/%02x]\n", td->channel, td->transaction_started,
+ td->dev_addr,td->haddr,td->hport, td->transfer_type);
+
+ /* select endpoint 0 */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ /* Not yet */
+ if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+ return (1);
+
+ /* Failed */
+ if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+ MUSB2_MASK_CSR0L_ERROR))
+ {
+ /* Clear status bit */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ if (td->transaction_started) {
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, MUSB2_MASK_CSR0H_PING_DIS);
+
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+ /* TX NAK timeout */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+ td->transaction_started = 1;
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_STATUSPKT |
+ MUSB2_MASK_CSR0L_TXPKTRDY);
+
+ return (1); /* wait for interrupt */
+}
+
+static uint8_t
+musbotg_dev_data_rx(struct musbotg_td *td)
+{
struct usb_page_search buf_res;
struct musbotg_softc *sc;
uint16_t count;
@@ -663,8 +1418,15 @@
/* get pointer to softc */
sc = MUSBOTG_PC2SC(td->pc);
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
/* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
repeat:
/* read out FIFO status */
@@ -678,10 +1440,11 @@
MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
MUSB2_MASK_CSRL_RXPKTRDY);
}
+
/* check status */
- if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY)) {
- return (1); /* not complete */
- }
+ if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY))
+ return (1); /* not complete */
+
/* get the packet byte count */
count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
@@ -698,6 +1461,7 @@
} else {
/* invalid USB packet */
td->error = 1;
+ musbotg_channel_free(sc, td);
return (0); /* we are complete */
}
}
@@ -705,6 +1469,7 @@
if (count > td->remainder) {
/* invalid USB packet */
td->error = 1;
+ musbotg_channel_free(sc, td);
return (0); /* we are complete */
}
while (count > 0) {
@@ -724,7 +1489,7 @@
if (temp) {
/* receive data 4 bytes at a time */
bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), sc->sc_bounce_buf,
+ MUSB2_REG_EPFIFO(td->channel), sc->sc_bounce_buf,
temp / 4);
}
temp = count & 3;
@@ -731,7 +1496,7 @@
if (temp) {
/* receive data 1 byte at a time */
bus_space_read_multi_1(sc->sc_io_tag,
- sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
+ sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
((void *)&sc->sc_bounce_buf[count / 4]), temp);
}
usbd_copy_in(td->pc, td->offset,
@@ -747,7 +1512,7 @@
/* receive data 4 bytes at a time */
bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
buf_res.length / 4);
temp = buf_res.length & ~3;
@@ -760,7 +1525,7 @@
}
/* receive data */
bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
buf_res.length);
/* update counters */
@@ -776,6 +1541,7 @@
if ((td->remainder == 0) || got_short) {
if (td->short_pkt) {
/* we are complete */
+ musbotg_channel_free(sc, td);
return (0);
}
/* else need to receive a zero length packet */
@@ -787,7 +1553,7 @@
}
static uint8_t
-musbotg_data_tx(struct musbotg_td *td)
+musbotg_dev_data_tx(struct musbotg_td *td)
{
struct usb_page_search buf_res;
struct musbotg_softc *sc;
@@ -800,8 +1566,15 @@
/* get pointer to softc */
sc = MUSBOTG_PC2SC(td->pc);
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* EP0 is busy, wait */
+ if (td->channel == -1)
+ return (1);
+
/* select endpoint */
- MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
repeat:
@@ -845,7 +1618,7 @@
if (temp) {
/* transmit data 4 bytes at a time */
bus_space_write_multi_4(sc->sc_io_tag,
- sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
+ sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
sc->sc_bounce_buf, temp / 4);
}
temp = count & 3;
@@ -852,7 +1625,7 @@
if (temp) {
/* receive data 1 byte at a time */
bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no),
+ MUSB2_REG_EPFIFO(td->channel),
((void *)&sc->sc_bounce_buf[count / 4]), temp);
}
/* update offset and remainder */
@@ -865,7 +1638,7 @@
/* transmit data 4 bytes at a time */
bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
buf_res.length / 4);
temp = buf_res.length & ~3;
@@ -878,7 +1651,7 @@
}
/* transmit data */
bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
- MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
buf_res.length);
/* update counters */
@@ -887,6 +1660,9 @@
td->remainder -= buf_res.length;
}
+ /* Max packet size */
+ MUSB2_WRITE_2(sc, MUSB2_REG_TXMAXP, td->reg_max_packet);
+
/* write command */
MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
MUSB2_MASK_CSRL_TXPKTRDY);
@@ -894,6 +1670,7 @@
/* check remainder */
if (td->remainder == 0) {
if (td->short_pkt) {
+ musbotg_channel_free(sc, td);
return (0); /* complete */
}
/* else we need to transmit a short packet */
@@ -905,6 +1682,433 @@
}
static uint8_t
+musbotg_host_data_rx(struct musbotg_td *td)
+{
+ struct usb_page_search buf_res;
+ struct musbotg_softc *sc;
+ uint16_t count;
+ uint8_t csr, csrh;
+ uint8_t to;
+ uint8_t got_short;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* No free EPs */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ to = 8; /* don't loop forever! */
+ got_short = 0;
+
+ /* select endpoint */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
+
+repeat:
+ /* read out FIFO status */
+ csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ if (!td->transaction_started) {
+ /* Function address */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(td->channel),
+ td->dev_addr);
+
+ /* SPLIT transaction */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(td->channel),
+ td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(td->channel),
+ td->hport);
+
+ /* RX NAK timeout */
+ if (td->transfer_type & MUSB2_MASK_TI_PROTO_ISOC)
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, 0);
+ else
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+ /* Protocol, speed, device endpoint */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+ /* Max packet size */
+ MUSB2_WRITE_2(sc, MUSB2_REG_RXMAXP, td->reg_max_packet);
+
+ /* Data Toggle */
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_RXCSRH);
+ DPRINTFN(4, "csrh=0x%02x\n", csrh);
+
+ csrh |= MUSB2_MASK_CSRH_RXDT_WREN;
+ if (td->toggle)
+ csrh |= MUSB2_MASK_CSRH_RXDT_VAL;
+ else
+ csrh &= ~MUSB2_MASK_CSRH_RXDT_VAL;
+
+ /* Set data toggle */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, csrh);
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
+ MUSB2_MASK_CSRL_RXREQPKT);
+
+ td->transaction_started = 1;
+ return (1);
+ }
+
+ /* clear NAK timeout */
+ if (csr & MUSB2_MASK_CSRL_RXNAKTO) {
+ DPRINTFN(4, "NAK Timeout\n");
+ if (csr & MUSB2_MASK_CSRL_RXREQPKT) {
+ csr &= ~MUSB2_MASK_CSRL_RXREQPKT;
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, csr);
+
+ csr &= ~MUSB2_MASK_CSRL_RXNAKTO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, csr);
+ }
+
+ td->error = 1;
+ }
+
+ if (csr & MUSB2_MASK_CSRL_RXERROR) {
+ DPRINTFN(4, "RXERROR\n");
+ td->error = 1;
+ }
+
+ if (csr & MUSB2_MASK_CSRL_RXSTALL) {
+ DPRINTFN(4, "RXSTALL\n");
+ td->error = 1;
+ }
+
+ if (td->error) {
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+
+ if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY)) {
+ /* No data available yet */
+ return (1);
+ }
+
+ td->toggle ^= 1;
+ /* get the packet byte count */
+ count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
+ DPRINTFN(4, "count=0x%04x\n", count);
+
+ /*
+ * Check for short or invalid packet:
+ */
+ if (count != td->max_frame_size) {
+ if (count < td->max_frame_size) {
+ /* we have a short packet */
+ td->short_pkt = 1;
+ got_short = 1;
+ } else {
+ /* invalid USB packet */
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+ }
+
+ /* verify the packet byte count */
+ if (count > td->remainder) {
+ /* invalid USB packet */
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* we are complete */
+ }
+
+ while (count > 0) {
+ uint32_t temp;
+
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > count) {
+ buf_res.length = count;
+ }
+ /* check for unaligned memory address */
+ if (USB_P2U(buf_res.buffer) & 3) {
+
+ temp = count & ~3;
+
+ if (temp) {
+ /* receive data 4 bytes at a time */
+ bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel), sc->sc_bounce_buf,
+ temp / 4);
+ }
+ temp = count & 3;
+ if (temp) {
+ /* receive data 1 byte at a time */
+ bus_space_read_multi_1(sc->sc_io_tag,
+ sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
+ ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+ }
+ usbd_copy_in(td->pc, td->offset,
+ sc->sc_bounce_buf, count);
+
+ /* update offset and remainder */
+ td->offset += count;
+ td->remainder -= count;
+ break;
+ }
+ /* check if we can optimise */
+ if (buf_res.length >= 4) {
+
+ /* receive data 4 bytes at a time */
+ bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+ buf_res.length / 4);
+
+ temp = buf_res.length & ~3;
+
+ /* update counters */
+ count -= temp;
+ td->offset += temp;
+ td->remainder -= temp;
+ continue;
+ }
+ /* receive data */
+ bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+ buf_res.length);
+
+ /* update counters */
+ count -= buf_res.length;
+ td->offset += buf_res.length;
+ td->remainder -= buf_res.length;
+ }
+
+ /* clear status bits */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, 0);
+
+ /* check if we are complete */
+ if ((td->remainder == 0) || got_short) {
+ if (td->short_pkt) {
+ /* we are complete */
+ musbotg_channel_free(sc, td);
+ return (0);
+ }
+ /* else need to receive a zero length packet */
+ }
+
+ /* Reset transaction state and restart */
+ td->transaction_started = 0;
+
+ if (--to)
+ goto repeat;
+
+ return (1); /* not complete */
+}
+
+static uint8_t
+musbotg_host_data_tx(struct musbotg_td *td)
+{
+ struct usb_page_search buf_res;
+ struct musbotg_softc *sc;
+ uint16_t count;
+ uint8_t csr, csrh;
+
+ /* get pointer to softc */
+ sc = MUSBOTG_PC2SC(td->pc);
+
+ if (td->channel == -1)
+ td->channel = musbotg_channel_alloc(sc, td);
+
+ /* No free EPs */
+ if (td->channel == -1)
+ return (1);
+
+ DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+ /* select endpoint */
+ MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
+
+ /* read out FIFO status */
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ DPRINTFN(4, "csr=0x%02x\n", csr);
+
+ if (csr & (MUSB2_MASK_CSRL_TXSTALLED |
+ MUSB2_MASK_CSRL_TXERROR)) {
+ /* clear status bits */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ if (csr & MUSB2_MASK_CSRL_TXNAKTO) {
+ /*
+ * Flush TX FIFO before clearing NAK TO
+ */
+ if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
+ csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
+ csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+ csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+ }
+ }
+
+ csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+ td->error = 1;
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+
+ /*
+ * Wait while FIFO is empty.
+ * Do not flush it because it will cause transactions
+ * with size more then packet size. It might upset
+ * some devices
+ */
+ if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY)
+ return (1);
+
+ /* Packet still being processed */
+ if (csr & MUSB2_MASK_CSRL_TXPKTRDY)
+ return (1);
+
+ if (td->transaction_started) {
+ /* check remainder */
+ if (td->remainder == 0) {
+ if (td->short_pkt) {
+ musbotg_channel_free(sc, td);
+ return (0); /* complete */
+ }
+ /* else we need to transmit a short packet */
+ }
+
+ /* We're not complete - more transactions required */
+ td->transaction_started = 0;
+ }
+
+ /* check for short packet */
+ count = td->max_frame_size;
+ if (td->remainder < count) {
+ /* we have a short packet */
+ td->short_pkt = 1;
+ count = td->remainder;
+ }
+
+ while (count > 0) {
+ uint32_t temp;
+
+ usbd_get_page(td->pc, td->offset, &buf_res);
+
+ /* get correct length */
+ if (buf_res.length > count) {
+ buf_res.length = count;
+ }
+ /* check for unaligned memory address */
+ if (USB_P2U(buf_res.buffer) & 3) {
+
+ usbd_copy_out(td->pc, td->offset,
+ sc->sc_bounce_buf, count);
+
+ temp = count & ~3;
+
+ if (temp) {
+ /* transmit data 4 bytes at a time */
+ bus_space_write_multi_4(sc->sc_io_tag,
+ sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
+ sc->sc_bounce_buf, temp / 4);
+ }
+ temp = count & 3;
+ if (temp) {
+ /* receive data 1 byte at a time */
+ bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel),
+ ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+ }
+ /* update offset and remainder */
+ td->offset += count;
+ td->remainder -= count;
+ break;
+ }
+ /* check if we can optimise */
+ if (buf_res.length >= 4) {
+
+ /* transmit data 4 bytes at a time */
+ bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+ buf_res.length / 4);
+
+ temp = buf_res.length & ~3;
+
+ /* update counters */
+ count -= temp;
+ td->offset += temp;
+ td->remainder -= temp;
+ continue;
+ }
+ /* transmit data */
+ bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+ MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+ buf_res.length);
+
+ /* update counters */
+ count -= buf_res.length;
+ td->offset += buf_res.length;
+ td->remainder -= buf_res.length;
+ }
+
+ /* Function address */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(td->channel),
+ td->dev_addr);
+
+ /* SPLIT transaction */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(td->channel),
+ td->haddr);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(td->channel),
+ td->hport);
+
+ /* TX NAK timeout */
+ if (td->transfer_type & MUSB2_MASK_TI_PROTO_ISOC)
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, 0);
+ else
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+ /* Protocol, speed, device endpoint */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+ /* Max packet size */
+ MUSB2_WRITE_2(sc, MUSB2_REG_TXMAXP, td->reg_max_packet);
+
+ if (!td->transaction_started) {
+ csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+ DPRINTFN(4, "csrh=0x%02x\n", csrh);
+
+ csrh |= MUSB2_MASK_CSRH_TXDT_WREN;
+ if (td->toggle)
+ csrh |= MUSB2_MASK_CSRH_TXDT_VAL;
+ else
+ csrh &= ~MUSB2_MASK_CSRH_TXDT_VAL;
+
+ /* Set data toggle */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+ }
+
+ /* write command */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSRL_TXPKTRDY);
+
+ /* Update Data Toggle */
+ td->toggle ^= 1;
+ td->transaction_started = 1;
+
+ return (1); /* not complete */
+}
+
+static uint8_t
musbotg_xfer_do_fifo(struct usb_xfer *xfer)
{
struct musbotg_softc *sc;
@@ -911,13 +2115,16 @@
struct musbotg_td *td;
DPRINTFN(8, "\n");
+ sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
td = xfer->td_transfer_cache;
while (1) {
+
if ((td->func) (td)) {
/* operation in progress */
break;
}
+
if (((void *)td) == xfer->td_transfer_last) {
goto done;
}
@@ -939,13 +2146,10 @@
td = td->obj_next;
xfer->td_transfer_cache = td;
}
+
return (1); /* not complete */
-
done:
- sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
/* compute all actual lengths */
-
musbotg_standard_done(xfer);
return (0); /* complete */
@@ -995,8 +2199,20 @@
}
void
-musbotg_interrupt(struct musbotg_softc *sc)
+musbotg_connect_interrupt(struct musbotg_softc *sc)
{
+ USB_BUS_LOCK(&sc->sc_bus);
+ sc->sc_flags.change_connect = 1;
+
+ /* complete root HUB interrupt endpoint */
+ musbotg_root_intr(sc);
+ USB_BUS_UNLOCK(&sc->sc_bus);
+}
+
+void
+musbotg_interrupt(struct musbotg_softc *sc,
+ uint16_t rxstat, uint16_t txstat, uint8_t stat)
+{
uint16_t rx_status;
uint16_t tx_status;
uint8_t usb_status;
@@ -1013,11 +2229,21 @@
/* read all FIFO interrupts */
rx_status = MUSB2_READ_2(sc, MUSB2_REG_INTRX);
tx_status = MUSB2_READ_2(sc, MUSB2_REG_INTTX);
+ rx_status |= rxstat;
+ tx_status |= txstat;
+ usb_status |= stat;
+ /* Clear platform flags after first time */
+ rxstat = 0;
+ txstat = 0;
+ stat = 0;
+
/* check for any bus state change interrupts */
if (usb_status & (MUSB2_MASK_IRESET |
- MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP)) {
+ MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP |
+ MUSB2_MASK_ICONN | MUSB2_MASK_IDISC |
+ MUSB2_MASK_IVBUSERR)) {
DPRINTFN(4, "real bus interrupt 0x%08x\n", usb_status);
@@ -1080,6 +2306,27 @@
MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, temp);
}
}
+ if (usb_status &
+ (MUSB2_MASK_ICONN | MUSB2_MASK_IDISC))
+ sc->sc_flags.change_connect = 1;
+
+ /*
+ * Host Mode: There is no IRESET so assume bus is
+ * always in reset state once device is connected.
+ */
+ if (sc->sc_mode == MUSB2_HOST_MODE) {
+ /* check for VBUS error in USB host mode */
+ if (usb_status & MUSB2_MASK_IVBUSERR) {
+ temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+ temp |= MUSB2_MASK_SESS;
+ MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+ }
+ if (usb_status & MUSB2_MASK_ICONN)
+ sc->sc_flags.status_bus_reset = 1;
+ if (usb_status & MUSB2_MASK_IDISC)
+ sc->sc_flags.status_bus_reset = 0;
+ }
+
/* complete root HUB interrupt endpoint */
musbotg_root_intr(sc);
}
@@ -1117,9 +2364,15 @@
td->offset = temp->offset;
td->remainder = temp->len;
td->error = 0;
+ td->transaction_started = 0;
td->did_stall = temp->did_stall;
td->short_pkt = temp->short_pkt;
td->alt_next = temp->setup_alt_next;
+ td->channel = temp->channel;
+ td->dev_addr = temp->dev_addr;
+ td->haddr = temp->haddr;
+ td->hport = temp->hport;
+ td->transfer_type = temp->transfer_type;
}
static void
@@ -1130,11 +2383,18 @@
struct musbotg_td *td;
uint32_t x;
uint8_t ep_no;
+ uint8_t xfer_type;
+ enum usb_dev_speed speed;
+ int tx;
+ int dev_addr;
DPRINTFN(8, "addr=%d endpt=%d sumlen=%d speed=%d\n",
xfer->address, UE_GET_ADDR(xfer->endpointno),
xfer->sumlen, usbd_get_speed(xfer->xroot->udev));
+ sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
+ ep_no = (xfer->endpointno & UE_ADDR);
+
temp.max_frame_size = xfer->max_frame_size;
td = xfer->td_start[0];
@@ -1142,7 +2402,10 @@
xfer->td_transfer_cache = td;
/* setup temp */
+ dev_addr = xfer->address;
+ xfer_type = xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE;
+
temp.pc = NULL;
temp.td = NULL;
temp.td_next = xfer->td_start[0];
@@ -1149,16 +2412,63 @@
temp.offset = 0;
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
temp.did_stall = !xfer->flags_int.control_stall;
+ temp.channel = -1;
+ temp.dev_addr = dev_addr;
+ temp.haddr = xfer->xroot->udev->hs_hub_addr;
+ temp.hport = xfer->xroot->udev->hs_port_no;
- sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
- ep_no = (xfer->endpointno & UE_ADDR);
+ if (xfer->flags_int.usb_mode == USB_MODE_HOST) {
+ speed = usbd_get_speed(xfer->xroot->udev);
+ switch (speed) {
+ case USB_SPEED_LOW:
+ temp.transfer_type = MUSB2_MASK_TI_SPEED_LO;
+ break;
+ case USB_SPEED_FULL:
+ temp.transfer_type = MUSB2_MASK_TI_SPEED_FS;
+ break;
+ case USB_SPEED_HIGH:
+ temp.transfer_type = MUSB2_MASK_TI_SPEED_HS;
+ break;
+ default:
+ temp.transfer_type = 0;
+ DPRINTFN(-1, "Invalid USB speed: %d\n", speed);
+ break;
+ }
+
+ switch (xfer_type) {
+ case UE_CONTROL:
+ temp.transfer_type |= MUSB2_MASK_TI_PROTO_CTRL;
+ break;
+ case UE_ISOCHRONOUS:
+ temp.transfer_type |= MUSB2_MASK_TI_PROTO_ISOC;
+ break;
+ case UE_BULK:
+ temp.transfer_type |= MUSB2_MASK_TI_PROTO_BULK;
+ break;
+ case UE_INTERRUPT:
+ temp.transfer_type |= MUSB2_MASK_TI_PROTO_INTR;
+ break;
+ default:
+ DPRINTFN(-1, "Invalid USB transfer type: %d\n",
+ xfer_type);
+ break;
+ }
+
+ temp.transfer_type |= ep_no;
+ td->toggle = xfer->endpoint->toggle_next;
+ }
+
/* check if we should prepend a setup message */
if (xfer->flags_int.control_xfr) {
if (xfer->flags_int.control_hdr) {
- temp.func = &musbotg_setup_rx;
+ if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
+ temp.func = &musbotg_dev_ctrl_setup_rx;
+ else
+ temp.func = &musbotg_host_ctrl_setup_tx;
+
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.short_pkt = temp.len ? 1 : 0;
@@ -1170,17 +2480,39 @@
x = 0;
}
+ tx = 0;
+
if (x != xfer->nframes) {
- if (xfer->endpointno & UE_DIR_IN) {
- if (xfer->flags_int.control_xfr)
- temp.func = &musbotg_setup_data_tx;
- else
- temp.func = &musbotg_data_tx;
+ if (xfer->endpointno & UE_DIR_IN)
+ tx = 1;
+
+ if (xfer->flags_int.usb_mode == USB_MODE_HOST) {
+ tx = !tx;
+
+ if (tx) {
+ if (xfer->flags_int.control_xfr)
+ temp.func = &musbotg_host_ctrl_data_tx;
+ else
+ temp.func = &musbotg_host_data_tx;
+ } else {
+ if (xfer->flags_int.control_xfr)
+ temp.func = &musbotg_host_ctrl_data_rx;
+ else
+ temp.func = &musbotg_host_data_rx;
+ }
+
} else {
- if (xfer->flags_int.control_xfr)
- temp.func = &musbotg_setup_data_rx;
- else
- temp.func = &musbotg_data_rx;
+ if (tx) {
+ if (xfer->flags_int.control_xfr)
+ temp.func = &musbotg_dev_ctrl_data_tx;
+ else
+ temp.func = &musbotg_dev_data_tx;
+ } else {
+ if (xfer->flags_int.control_xfr)
+ temp.func = &musbotg_dev_ctrl_data_rx;
+ else
+ temp.func = &musbotg_dev_data_rx;
+ }
}
/* setup "pc" pointer */
@@ -1211,9 +2543,14 @@
} else {
- /* regular data transfer */
-
- temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
+ if (xfer->flags_int.isochronous_xfr) {
+ /* isochronous data transfer */
+ /* don't force short */
+ temp.short_pkt = 1;
+ } else {
+ /* regular data transfer */
+ temp.short_pkt = (xfer->flags.force_short_xfer ? 0 : 1);
+ }
}
musbotg_setup_standard_chain_sub(&temp);
@@ -1241,7 +2578,14 @@
* Send a DATA1 message and invert the current
* endpoint direction.
*/
- temp.func = &musbotg_setup_status;
+ if (sc->sc_mode == MUSB2_DEVICE_MODE)
+ temp.func = &musbotg_dev_ctrl_status;
+ else {
+ if (xfer->endpointno & UE_DIR_IN)
+ temp.func = musbotg_host_ctrl_status_tx;
+ else
+ temp.func = musbotg_host_ctrl_status_rx;
+ }
musbotg_setup_standard_chain_sub(&temp);
}
}
@@ -1264,11 +2608,9 @@
}
static void
-musbotg_ep_int_set(struct usb_xfer *xfer, uint8_t on)
+musbotg_ep_int_set(struct musbotg_softc *sc, int channel, int on)
{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
uint16_t temp;
- uint8_t ep_no = xfer->endpointno & UE_ADDR;
/*
* Only enable the endpoint interrupt when we are
@@ -1275,7 +2617,12 @@
* actually waiting for data, hence we are dealing
* with level triggered interrupts !
*/
- if (ep_no == 0) {
+ DPRINTFN(1, "ep_no=%d, on=%d\n", channel, on);
+
+ if (channel == -1)
+ return;
+
+ if (channel == 0) {
temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
if (on)
temp |= MUSB2_MASK_EPINT(0);
@@ -1284,23 +2631,23 @@
MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
} else {
- if (USB_GET_DATA_ISREAD(xfer)) {
- temp = MUSB2_READ_2(sc, MUSB2_REG_INTRXE);
- if (on)
- temp |= MUSB2_MASK_EPINT(ep_no);
- else
- temp &= ~MUSB2_MASK_EPINT(ep_no);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, temp);
+ temp = MUSB2_READ_2(sc, MUSB2_REG_INTRXE);
+ if (on)
+ temp |= MUSB2_MASK_EPINT(channel);
+ else
+ temp &= ~MUSB2_MASK_EPINT(channel);
+ MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, temp);
- } else {
- temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
- if (on)
- temp |= MUSB2_MASK_EPINT(ep_no);
- else
- temp &= ~MUSB2_MASK_EPINT(ep_no);
- MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
- }
+ temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
+ if (on)
+ temp |= MUSB2_MASK_EPINT(channel);
+ else
+ temp &= ~MUSB2_MASK_EPINT(channel);
+ MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
}
+
+ if (sc->sc_ep_int_set)
+ sc->sc_ep_int_set(sc, channel, on);
}
static void
@@ -1311,8 +2658,6 @@
/* poll one time */
if (musbotg_xfer_do_fifo(xfer)) {
- musbotg_ep_int_set(xfer, 1);
-
DPRINTFN(14, "enabled interrupts on endpoint\n");
/* put transfer on interrupt queue */
@@ -1354,6 +2699,8 @@
do {
len = td->remainder;
+ xfer->endpoint->toggle_next = td->toggle;
+
if (xfer->aframes != xfer->nframes) {
/*
* Verify the length and subtract
@@ -1456,17 +2803,22 @@
static void
musbotg_device_done(struct usb_xfer *xfer, usb_error_t error)
{
+ struct musbotg_td *td;
+ struct musbotg_softc *sc;
+
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
- DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n",
+ DPRINTFN(1, "xfer=%p, endpoint=%p, error=%d\n",
xfer, xfer->endpoint, error);
- if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+ DPRINTFN(14, "disabled interrupts on endpoint\n");
- musbotg_ep_int_set(xfer, 0);
+ sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
+ td = xfer->td_transfer_cache;
- DPRINTFN(14, "disabled interrupts on endpoint\n");
- }
+ if (td && (td->channel != -1))
+ musbotg_channel_free(sc, td);
+
/* dequeue transfer and start next transfer */
usbd_transfer_done(xfer, error);
}
@@ -1709,11 +3061,15 @@
if (sc->sc_clocks_on) {
(sc->sc_clocks_on) (sc->sc_clocks_arg);
}
+
/* wait a little for things to stabilise */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
/* disable all interrupts */
+ temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+ DPRINTF("pre-DEVCTL=0x%02x\n", temp);
+
MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0);
MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, 0);
MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, 0);
@@ -1725,6 +3081,7 @@
/* wait a little bit (10ms) */
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
+
/* disable double packet buffering */
MUSB2_WRITE_2(sc, MUSB2_REG_RXDBDIS, 0xFFFF);
MUSB2_WRITE_2(sc, MUSB2_REG_TXDBDIS, 0xFFFF);
@@ -1734,11 +3091,20 @@
MUSB2_WRITE_1(sc, MUSB2_REG_POWER,
MUSB2_MASK_HSENAB | MUSB2_MASK_ISOUPD);
- /* clear Session bit, if set */
+ if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+ /* clear Session bit, if set */
+ temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+ temp &= ~MUSB2_MASK_SESS;
+ MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+ } else {
+ /* Enter session for Host mode */
+ temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+ temp |= MUSB2_MASK_SESS;
+ MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+ }
- temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
- temp &= ~MUSB2_MASK_SESS;
- MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+ /* wait a little for things to stabilise */
+ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 10);
DPRINTF("DEVCTL=0x%02x\n", temp);
@@ -1806,7 +3172,12 @@
if (dynfifo) {
if (frx && (temp <= nrx)) {
- if (temp < 8) {
+ if (temp == 1) {
+ frx = 12; /* 4K */
+ MUSB2_WRITE_1(sc, MUSB2_REG_RXFIFOSZ,
+ MUSB2_VAL_FIFOSZ_4096 |
+ MUSB2_MASK_FIFODB);
+ } else if (temp < 8) {
frx = 10; /* 1K */
MUSB2_WRITE_1(sc, MUSB2_REG_RXFIFOSZ,
MUSB2_VAL_FIFOSZ_512 |
@@ -1823,7 +3194,12 @@
offset += (1 << frx);
}
if (ftx && (temp <= ntx)) {
- if (temp < 8) {
+ if (temp == 1) {
+ ftx = 12; /* 4K */
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXFIFOSZ,
+ MUSB2_VAL_FIFOSZ_4096 |
+ MUSB2_MASK_FIFODB);
+ } else if (temp < 8) {
ftx = 10; /* 1K */
MUSB2_WRITE_1(sc, MUSB2_REG_TXFIFOSZ,
MUSB2_VAL_FIFOSZ_512 |
@@ -1874,8 +3250,11 @@
/* turn on default interrupts */
- MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE,
- MUSB2_MASK_IRESET);
+ if (sc->sc_mode == MUSB2_HOST_MODE)
+ MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0xff);
+ else
+ MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE,
+ MUSB2_MASK_IRESET);
musbotg_clocks_off(sc);
@@ -2229,6 +3608,7 @@
uint16_t len;
uint16_t value;
uint16_t index;
+ uint8_t reg;
usb_error_t err;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -2408,6 +3788,13 @@
len = sizeof(musbotg_devd);
ptr = (const void *)&musbotg_devd;
goto tr_valid;
+ case UDESC_DEVICE_QUALIFIER:
+ if (value & 0xff) {
+ goto tr_stalled;
+ }
+ len = sizeof(musbotg_odevd);
+ ptr = (const void *)&musbotg_odevd;
+ goto tr_valid;
case UDESC_CONFIG:
if (value & 0xff) {
goto tr_stalled;
@@ -2492,7 +3879,10 @@
switch (value) {
case UHF_PORT_SUSPEND:
- musbotg_wakeup_peer(sc);
+ if (sc->sc_mode == MUSB2_HOST_MODE)
+ musbotg_wakeup_host(sc);
+ else
+ musbotg_wakeup_peer(sc);
break;
case UHF_PORT_ENABLE:
@@ -2499,13 +3889,23 @@
sc->sc_flags.port_enabled = 0;
break;
- case UHF_PORT_TEST:
- case UHF_PORT_INDICATOR:
case UHF_C_PORT_ENABLE:
+ sc->sc_flags.change_enabled = 0;
+ break;
+
case UHF_C_PORT_OVER_CURRENT:
+ sc->sc_flags.change_over_current = 0;
+ break;
+
case UHF_C_PORT_RESET:
+ sc->sc_flags.change_reset = 0;
+ break;
+
+ case UHF_PORT_TEST:
+ case UHF_PORT_INDICATOR:
/* nops */
break;
+
case UHF_PORT_POWER:
sc->sc_flags.port_powered = 0;
musbotg_pull_down(sc);
@@ -2534,7 +3934,35 @@
sc->sc_flags.port_enabled = 1;
break;
case UHF_PORT_SUSPEND:
+ if (sc->sc_mode == MUSB2_HOST_MODE)
+ musbotg_suspend_host(sc);
+ break;
+
case UHF_PORT_RESET:
+ if (sc->sc_mode == MUSB2_HOST_MODE) {
+ reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ reg |= MUSB2_MASK_RESET;
+ MUSB2_WRITE_1(sc, MUSB2_REG_POWER, reg);
+
+ /* Wait for 20 msec */
+ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 5);
+
+ reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ reg &= ~MUSB2_MASK_RESET;
+ MUSB2_WRITE_1(sc, MUSB2_REG_POWER, reg);
+
+ /* determine line speed */
+ reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+ if (reg & MUSB2_MASK_HSMODE)
+ sc->sc_flags.status_high_speed = 1;
+ else
+ sc->sc_flags.status_high_speed = 0;
+
+ sc->sc_flags.change_reset = 1;
+ } else
+ err = USB_ERR_IOERROR;
+ break;
+
case UHF_PORT_TEST:
case UHF_PORT_INDICATOR:
/* nops */
@@ -2564,7 +3992,10 @@
}
/* Select Device Side Mode */
- value = UPS_PORT_MODE_DEVICE;
+ if (sc->sc_mode == MUSB2_DEVICE_MODE)
+ value = UPS_PORT_MODE_DEVICE;
+ else
+ value = 0;
if (sc->sc_flags.status_high_speed) {
value |= UPS_HIGH_SPEED;
@@ -2575,6 +4006,10 @@
if (sc->sc_flags.port_enabled) {
value |= UPS_PORT_ENABLED;
}
+
+ if (sc->sc_flags.port_over_current)
+ value |= UPS_OVERCURRENT_INDICATOR;
+
if (sc->sc_flags.status_vbus &&
sc->sc_flags.status_bus_reset) {
value |= UPS_CURRENT_CONNECT_STATUS;
@@ -2589,16 +4024,22 @@
if (sc->sc_flags.change_connect) {
value |= UPS_C_CONNECT_STATUS;
- if (sc->sc_flags.status_vbus &&
- sc->sc_flags.status_bus_reset) {
- /* reset EP0 state */
- sc->sc_ep0_busy = 0;
- sc->sc_ep0_cmd = 0;
+ if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+ if (sc->sc_flags.status_vbus &&
+ sc->sc_flags.status_bus_reset) {
+ /* reset EP0 state */
+ sc->sc_ep0_busy = 0;
+ sc->sc_ep0_cmd = 0;
+ }
}
}
- if (sc->sc_flags.change_suspend) {
+ if (sc->sc_flags.change_suspend)
value |= UPS_C_SUSPEND;
- }
+ if (sc->sc_flags.change_reset)
+ value |= UPS_C_PORT_RESET;
+ if (sc->sc_flags.change_over_current)
+ value |= UPS_C_OVERCURRENT_INDICATOR;
+
USETW(sc->sc_hub_temp.ps.wPortChange, value);
len = sizeof(sc->sc_hub_temp.ps);
goto tr_valid;
@@ -2623,7 +4064,6 @@
static void
musbotg_xfer_setup(struct usb_setup_params *parm)
{
- const struct usb_hw_ep_profile *pf;
struct musbotg_softc *sc;
struct usb_xfer *xfer;
void *last_obj;
@@ -2640,7 +4080,7 @@
* reasonable dummies:
*/
parm->hc_max_packet_size = 0x400;
- parm->hc_max_frame_size = 0x400;
+ parm->hc_max_frame_size = 0xc00;
if ((parm->methods == &musbotg_device_isoc_methods) ||
(parm->methods == &musbotg_device_intr_methods))
@@ -2685,12 +4125,14 @@
*/
last_obj = NULL;
+ ep_no = xfer->endpointno & UE_ADDR;
+
/*
- * get profile stuff
+ * Check for a valid endpoint profile in USB device mode:
*/
- if (ntd) {
+ if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+ const struct usb_hw_ep_profile *pf;
- ep_no = xfer->endpointno & UE_ADDR;
musbotg_get_hw_ep_profile(parm->udev, &pf, ep_no);
if (pf == NULL) {
@@ -2698,9 +4140,6 @@
parm->err = USB_ERR_INVAL;
return;
}
- } else {
- ep_no = 0;
- pf = NULL;
}
/* align data */
@@ -2716,6 +4155,8 @@
/* init TD */
td->max_frame_size = xfer->max_frame_size;
+ td->reg_max_packet = xfer->max_packet_size |
+ ((xfer->max_packet_count - 1) << 11);
td->ep_no = ep_no;
td->obj_next = last_obj;
@@ -2734,6 +4175,17 @@
}
static void
+musbotg_get_dma_delay(struct usb_device *udev, uint32_t *pus)
+{
+ struct musbotg_softc *sc = MUSBOTG_BUS2SC(udev->bus);
+
+ if (sc->sc_mode == MUSB2_HOST_MODE)
+ *pus = 2000; /* microseconds */
+ else
+ *pus = 0;
+}
+
+static void
musbotg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
struct usb_endpoint *ep)
{
@@ -2745,16 +4197,6 @@
sc->sc_rt_addr);
if (udev->device_index != sc->sc_rt_addr) {
-
- if (udev->flags.usb_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
- if ((udev->speed != USB_SPEED_FULL) &&
- (udev->speed != USB_SPEED_HIGH)) {
- /* not supported */
- return;
- }
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
ep->methods = &musbotg_device_ctrl_methods;
@@ -2798,6 +4240,7 @@
struct usb_bus_methods musbotg_bus_methods =
{
.endpoint_init = &musbotg_ep_init,
+ .get_dma_delay = &musbotg_get_dma_delay,
.xfer_setup = &musbotg_xfer_setup,
.xfer_unsetup = &musbotg_xfer_unsetup,
.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
Modified: stable/0.8/sys/dev/usb/controller/musb_otg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/musb_otg.h 257041 2013-10-24 06:22:43Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -32,7 +32,7 @@
#ifndef _MUSB2_OTG_H_
#define _MUSB2_OTG_H_
-#define MUSB2_MAX_DEVICES (USB_MIN_DEVICES + 1)
+#define MUSB2_MAX_DEVICES USB_MAX_DEVICES
/* Common registers */
@@ -105,7 +105,8 @@
#define MUSB2_MASK_CSRL_TXSENTSTALL 0x20/* Device Mode */
#define MUSB2_MASK_CSRL_TXSTALLED 0x20 /* Host Mode */
#define MUSB2_MASK_CSRL_TXDT_CLR 0x40
-#define MUSB2_MASK_CSRL_TXINCOMP 0x80
+#define MUSB2_MASK_CSRL_TXINCOMP 0x80 /* Device mode */
+#define MUSB2_MASK_CSRL_TXNAKTO 0x80 /* Host mode */
/* Device Side Mode */
#define MUSB2_MASK_CSR0L_RXPKTRDY 0x01
@@ -118,6 +119,7 @@
#define MUSB2_MASK_CSR0L_SETUPEND_CLR 0x80
/* Host Side Mode */
+#define MUSB2_MASK_CSR0L_TXFIFONEMPTY 0x02
#define MUSB2_MASK_CSR0L_RXSTALL 0x04
#define MUSB2_MASK_CSR0L_SETUPPKT 0x08
#define MUSB2_MASK_CSR0L_ERROR 0x10
@@ -127,7 +129,7 @@
#define MUSB2_REG_TXCSRH (0x0003 + MUSB2_REG_INDEXED_CSR)
#define MUSB2_MASK_CSRH_TXDT_VAL 0x01 /* Host Mode */
-#define MUSB2_MASK_CSRH_TXDT_WR 0x02 /* Host Mode */
+#define MUSB2_MASK_CSRH_TXDT_WREN 0x02 /* Host Mode */
#define MUSB2_MASK_CSRH_TXDMAREQMODE 0x04
#define MUSB2_MASK_CSRH_TXDT_SWITCH 0x08
#define MUSB2_MASK_CSRH_TXDMAREQENA 0x10
@@ -138,14 +140,16 @@
#define MUSB2_MASK_CSR0H_FFLUSH 0x01 /* Device Side flush FIFO */
#define MUSB2_MASK_CSR0H_DT 0x02 /* Host Side data toggle */
-#define MUSB2_MASK_CSR0H_DT_SET 0x04 /* Host Side */
+#define MUSB2_MASK_CSR0H_DT_WREN 0x04 /* Host Side */
#define MUSB2_MASK_CSR0H_PING_DIS 0x08 /* Host Side */
#define MUSB2_REG_RXCSRL (0x0006 + MUSB2_REG_INDEXED_CSR)
#define MUSB2_MASK_CSRL_RXPKTRDY 0x01
#define MUSB2_MASK_CSRL_RXFIFOFULL 0x02
-#define MUSB2_MASK_CSRL_RXOVERRUN 0x04
-#define MUSB2_MASK_CSRL_RXDATAERR 0x08
+#define MUSB2_MASK_CSRL_RXOVERRUN 0x04 /* Device Mode */
+#define MUSB2_MASK_CSRL_RXERROR 0x04 /* Host Mode */
+#define MUSB2_MASK_CSRL_RXDATAERR 0x08 /* Device Mode */
+#define MUSB2_MASK_CSRL_RXNAKTO 0x08 /* Host Mode */
#define MUSB2_MASK_CSRL_RXFFLUSH 0x10
#define MUSB2_MASK_CSRL_RXSENDSTALL 0x20/* Device Mode */
#define MUSB2_MASK_CSRL_RXREQPKT 0x20 /* Host Mode */
@@ -156,7 +160,7 @@
#define MUSB2_REG_RXCSRH (0x0007 + MUSB2_REG_INDEXED_CSR)
#define MUSB2_MASK_CSRH_RXINCOMP 0x01
#define MUSB2_MASK_CSRH_RXDT_VAL 0x02 /* Host Mode */
-#define MUSB2_MASK_CSRH_RXDT_SET 0x04 /* Host Mode */
+#define MUSB2_MASK_CSRH_RXDT_WREN 0x04 /* Host Mode */
#define MUSB2_MASK_CSRH_RXDMAREQMODE 0x08
#define MUSB2_MASK_CSRH_RXNYET 0x10
#define MUSB2_MASK_CSRH_RXDMAREQENA 0x20
@@ -273,10 +277,13 @@
#define MUSB2_REG_TXHUBPORT(n) (0x0083 + (8*(n)))
#define MUSB2_REG_RXFADDR(n) (0x0084 + (8*(n)))
#define MUSB2_REG_RXHADDR(n) (0x0086 + (8*(n)))
-#define MUSB2_REG_RXHPORT(n) (0x0087 + (8*(n)))
+#define MUSB2_REG_RXHUBPORT(n) (0x0087 + (8*(n)))
#define MUSB2_EP_MAX 16 /* maximum number of endpoints */
+#define MUSB2_DEVICE_MODE 0
+#define MUSB2_HOST_MODE 1
+
#define MUSB2_READ_2(sc, reg) \
bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
@@ -309,7 +316,9 @@
uint32_t offset;
uint32_t remainder;
uint16_t max_frame_size; /* packet_size * mult */
+ uint16_t reg_max_packet;
uint8_t ep_no;
+ uint8_t transfer_type;
uint8_t error:1;
uint8_t alt_next:1;
uint8_t short_pkt:1;
@@ -316,6 +325,12 @@
uint8_t support_multi_buffer:1;
uint8_t did_stall:1;
uint8_t dma_enabled:1;
+ uint8_t transaction_started:1;
+ uint8_t dev_addr;
+ uint8_t toggle;
+ int8_t channel;
+ uint8_t haddr;
+ uint8_t hport;
};
struct musbotg_std_temp {
@@ -333,6 +348,11 @@
*/
uint8_t setup_alt_next;
uint8_t did_stall;
+ uint8_t dev_addr;
+ int8_t channel;
+ uint8_t haddr;
+ uint8_t hport;
+ uint8_t transfer_type;
};
struct musbotg_config_desc {
@@ -349,6 +369,9 @@
struct musbotg_flags {
uint8_t change_connect:1;
uint8_t change_suspend:1;
+ uint8_t change_reset:1;
+ uint8_t change_over_current:1;
+ uint8_t change_enabled:1;
uint8_t status_suspend:1; /* set if suspended */
uint8_t status_vbus:1; /* set if present */
uint8_t status_bus_reset:1; /* set if reset complete */
@@ -358,6 +381,7 @@
uint8_t clocks_off:1;
uint8_t port_powered:1;
uint8_t port_enabled:1;
+ uint8_t port_over_current:1;
uint8_t d_pulled_up:1;
};
@@ -376,6 +400,7 @@
void (*sc_clocks_on) (void *arg);
void (*sc_clocks_off) (void *arg);
+ void (*sc_ep_int_set) (struct musbotg_softc *sc, int ep, int on);
void *sc_clocks_arg;
uint32_t sc_bounce_buf[(1024 * 3) / 4]; /* bounce buffer */
@@ -390,8 +415,12 @@
uint8_t sc_conf_data; /* copy of hardware register */
uint8_t sc_hub_idata[1];
+ uint16_t sc_channel_mask; /* 16 endpoints */
struct musbotg_flags sc_flags;
+ uint8_t sc_id;
+ uint8_t sc_mode;
+ void *sc_platform_data;
};
/* prototypes */
@@ -398,7 +427,9 @@
usb_error_t musbotg_init(struct musbotg_softc *sc);
void musbotg_uninit(struct musbotg_softc *sc);
-void musbotg_interrupt(struct musbotg_softc *sc);
+void musbotg_interrupt(struct musbotg_softc *sc,
+ uint16_t rxstat, uint16_t txstat, uint8_t stat);
void musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on);
+void musbotg_connect_interrupt(struct musbotg_softc *sc);
#endif /* _MUSB2_OTG_H_ */
Modified: stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/musb_otg_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -94,6 +94,26 @@
#endif
}
+static void
+musbotg_wrapper_interrupt(void *arg)
+{
+
+ /*
+ * Nothing to do.
+ * Main driver takes care about everything
+ */
+ musbotg_interrupt(arg, 0, 0, 0);
+}
+
+static void
+musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on)
+{
+ /*
+ * Nothing to do.
+ * Main driver takes care about everything
+ */
+}
+
static int
musbotg_probe(device_t dev)
{
@@ -117,6 +137,7 @@
sc->sc_otg.sc_bus.parent = dev;
sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;
+ sc->sc_otg.sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
@@ -147,12 +168,16 @@
}
device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);
+ sc->sc_otg.sc_id = 0;
+ sc->sc_otg.sc_platform_data = sc;
+ sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE;
+
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+ NULL, (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+ (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#endif
if (err) {
sc->sc_otg.sc_intr_hdl = NULL;
@@ -179,14 +204,8 @@
musbotg_detach(device_t dev)
{
struct musbotg_super_softc *sc = device_get_softc(dev);
- device_t bdev;
int err;
- if (sc->sc_otg.sc_bus.bdev) {
- bdev = sc->sc_otg.sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(dev);
Modified: stable/0.8/sys/dev/usb/controller/ohci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci.c 257040 2013-10-24 06:06:17Z hselasky $");
/*
* USB Open Host Controller driver.
@@ -2314,6 +2314,7 @@
}
v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
DPRINTFN(9, "port status=0x%04x\n", v);
+ v &= ~UPS_PORT_MODE_DEVICE; /* force host mode */
USETW(sc->sc_hub_desc.ps.wPortStatus, v);
USETW(sc->sc_hub_desc.ps.wPortChange, v >> 16);
len = sizeof(sc->sc_hub_desc.ps);
@@ -2550,10 +2551,6 @@
edesc->bEndpointAddress, udev->flags.usb_mode,
sc->sc_addr);
- if (udev->flags.usb_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
if (udev->device_index != sc->sc_addr) {
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
Modified: stable/0.8/sys/dev/usb/controller/ohci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ohci.h 229096 2011-12-31 14:22:02Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_atmelarm.c 278279 2015-02-05 20:15:42Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -91,6 +91,7 @@
sc->sc_ohci.sc_bus.parent = dev;
sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
+ sc->sc_ohci.sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
Modified: stable/0.8/sys/dev/usb/controller/ohci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_pci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_pci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
/*
* USB Open Host Controller driver.
@@ -154,6 +154,8 @@
case 0x00d710de:
return ("nVidia nForce3 USB Controller");
+ case 0x005a10de:
+ return ("nVidia nForce CK804 USB Controller");
case 0x036c10de:
return ("nVidia nForce MCP55 USB Controller");
case 0x03f110de:
@@ -209,6 +211,7 @@
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
@@ -329,13 +332,7 @@
ohci_pci_detach(device_t self)
{
ohci_softc_t *sc = device_get_softc(self);
- device_t bdev;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
Modified: stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_s3c24x0.c 308403 2016-11-07 09:23:07Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -84,6 +84,7 @@
sc->sc_bus.parent = dev;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
@@ -147,14 +148,8 @@
ohci_s3c24x0_detach(device_t dev)
{
struct ohci_softc *sc = device_get_softc(dev);
- device_t bdev;
int err;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(dev);
Modified: stable/0.8/sys/dev/usb/controller/ohcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohcireg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohcireg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ohcireg.h 204632 2010-03-03 10:18:03Z joel $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/uhci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uhci.c 261106 2014-01-24 07:57:21Z hselasky $");
/*
* USB Universal Host Controller driver.
@@ -1176,8 +1176,13 @@
(status & UHCI_TD_SPD) ? "[SPD]" : "");
}
#endif
- return (status & UHCI_TD_STALLED) ?
- USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION;
+ if (status & UHCI_TD_STALLED) {
+ /* try to separate I/O errors from STALL */
+ if (UHCI_TD_GET_ERRCNT(status) == 0)
+ return (USB_ERR_IOERROR);
+ return (USB_ERR_STALLED);
+ }
+ return (USB_ERR_NORMAL_COMPLETION);
}
static void
@@ -3029,10 +3034,6 @@
edesc->bEndpointAddress, udev->flags.usb_mode,
sc->sc_addr);
- if (udev->flags.usb_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
if (udev->device_index != sc->sc_addr) {
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
Modified: stable/0.8/sys/dev/usb/controller/uhci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uhci.h 293147 2016-01-04 07:29:19Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -97,7 +97,7 @@
#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_SET_MAXLEN(l) (((l)-1U) << 21)
#define UHCI_TD_GET_MAXLEN(s) ((((s) >> 21) + 1) & 0x7ff)
#define UHCI_TD_MAXLEN_MASK 0xffe00000
volatile uint32_t td_buffer;
Modified: stable/0.8/sys/dev/usb/controller/uhci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci_pci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci_pci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uhci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
/* Universal Host Controller Interface
*
@@ -77,6 +77,7 @@
#include "usb_if.h"
#define PCI_UHCI_VENDORID_INTEL 0x8086
+#define PCI_UHCI_VENDORID_HP 0x103c
#define PCI_UHCI_VENDORID_VIA 0x1106
/* PIIX4E has no separate stepping */
@@ -222,6 +223,9 @@
case 0x76028086:
return ("Intel 82372FB/82468GX USB controller");
+ case 0x3300103c:
+ return ("HP iLO Standard Virtual USB controller");
+
case 0x30381106:
return ("VIA 83C572 USB controller");
@@ -261,6 +265,7 @@
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = UHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
@@ -308,6 +313,9 @@
case PCI_UHCI_VENDORID_INTEL:
sprintf(sc->sc_vendor, "Intel");
break;
+ case PCI_UHCI_VENDORID_HP:
+ sprintf(sc->sc_vendor, "HP");
+ break;
case PCI_UHCI_VENDORID_VIA:
sprintf(sc->sc_vendor, "VIA");
break;
@@ -379,13 +387,7 @@
uhci_pci_detach(device_t self)
{
uhci_softc_t *sc = device_get_softc(self);
- device_t bdev;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
Modified: stable/0.8/sys/dev/usb/controller/uhcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhcireg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhcireg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uhcireg.h 204632 2010-03-03 10:18:03Z joel $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/usb_controller.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/usb_controller.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/usb_controller.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/usb_controller.c 278291 2015-02-05 21:37:59Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -56,6 +56,7 @@
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_dynamic.h>
#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_dev.h>
#include <dev/usb/usb_hub.h>
#include <dev/usb/usb_controller.h>
@@ -126,7 +127,7 @@
/* Device Only Drivers */
DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
-DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usbus, uss820dci, usb_driver, usb_devclass, 0, 0);
/*------------------------------------------------------------------------*
* usb_probe
@@ -205,6 +206,11 @@
usb_proc_mwait(&bus->explore_proc,
&bus->detach_msg[0], &bus->detach_msg[1]);
+#if USB_HAVE_UGEN
+ /* Wait for cleanup to complete */
+ usb_proc_mwait(&bus->explore_proc,
+ &bus->cleanup_msg[0], &bus->cleanup_msg[1]);
+#endif
USB_BUS_UNLOCK(bus);
/* Get rid of USB callback processes */
@@ -278,6 +284,28 @@
}
/*------------------------------------------------------------------------*
+ * usb_bus_reset_async_locked
+ *------------------------------------------------------------------------*/
+void
+usb_bus_reset_async_locked(struct usb_bus *bus)
+{
+ USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
+
+ DPRINTF("\n");
+
+ if (bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL ||
+ bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL) {
+ DPRINTF("Reset already pending\n");
+ return;
+ }
+
+ device_printf(bus->parent, "Resetting controller\n");
+
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->reset_msg[0], &bus->reset_msg[1]);
+}
+
+/*------------------------------------------------------------------------*
* usb_shutdown
*------------------------------------------------------------------------*/
static int
@@ -292,7 +320,7 @@
return (0);
}
- device_printf(bus->bdev, "Controller shutdown\n");
+ DPRINTF("%s: Controller shutdown\n", device_get_nameunit(bus->bdev));
USB_BUS_LOCK(bus);
usb_proc_msignal(&bus->explore_proc,
@@ -304,7 +332,8 @@
}
USB_BUS_UNLOCK(bus);
- device_printf(bus->bdev, "Controller shutdown complete\n");
+ DPRINTF("%s: Controller shutdown complete\n",
+ device_get_nameunit(bus->bdev));
return (0);
}
@@ -326,8 +355,14 @@
if (bus->no_explore != 0)
return;
- if (udev && udev->hub) {
+ if (udev != NULL) {
+ USB_BUS_UNLOCK(bus);
+ uhub_explore_handle_re_enumerate(udev);
+ USB_BUS_LOCK(bus);
+ }
+ if (udev != NULL && udev->hub != NULL) {
+
if (bus->do_probe) {
bus->do_probe = 0;
bus->driver_added_refcount++;
@@ -399,7 +434,7 @@
/*------------------------------------------------------------------------*
* usb_bus_suspend
*
- * This function is used to suspend the USB contoller.
+ * This function is used to suspend the USB controller.
*------------------------------------------------------------------------*/
static void
usb_bus_suspend(struct usb_proc_msg *pm)
@@ -409,6 +444,8 @@
usb_error_t err;
uint8_t do_unlock;
+ DPRINTF("\n");
+
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
@@ -454,7 +491,7 @@
/*------------------------------------------------------------------------*
* usb_bus_resume
*
- * This function is used to resume the USB contoller.
+ * This function is used to resume the USB controller.
*------------------------------------------------------------------------*/
static void
usb_bus_resume(struct usb_proc_msg *pm)
@@ -464,6 +501,8 @@
usb_error_t err;
uint8_t do_unlock;
+ DPRINTF("\n");
+
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
@@ -513,9 +552,31 @@
}
/*------------------------------------------------------------------------*
+ * usb_bus_reset
+ *
+ * This function is used to reset the USB controller.
+ *------------------------------------------------------------------------*/
+static void
+usb_bus_reset(struct usb_proc_msg *pm)
+{
+ struct usb_bus *bus;
+
+ DPRINTF("\n");
+
+ bus = ((struct usb_bus_msg *)pm)->bus;
+
+ if (bus->bdev == NULL || bus->no_explore != 0)
+ return;
+
+ /* a suspend and resume will reset the USB controller */
+ usb_bus_suspend(pm);
+ usb_bus_resume(pm);
+}
+
+/*------------------------------------------------------------------------*
* usb_bus_shutdown
*
- * This function is used to shutdown the USB contoller.
+ * This function is used to shutdown the USB controller.
*------------------------------------------------------------------------*/
static void
usb_bus_shutdown(struct usb_proc_msg *pm)
@@ -558,7 +619,33 @@
USB_BUS_LOCK(bus);
}
+/*------------------------------------------------------------------------*
+ * usb_bus_cleanup
+ *
+ * This function is used to cleanup leftover USB character devices.
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_UGEN
static void
+usb_bus_cleanup(struct usb_proc_msg *pm)
+{
+ struct usb_bus *bus;
+ struct usb_fs_privdata *pd;
+
+ bus = ((struct usb_bus_msg *)pm)->bus;
+
+ while ((pd = LIST_FIRST(&bus->pd_cleanup_list)) != NULL) {
+
+ LIST_REMOVE(pd, pd_next);
+ USB_BUS_UNLOCK(bus);
+
+ usb_destroy_dev_sync(pd);
+
+ USB_BUS_LOCK(bus);
+ }
+}
+#endif
+
+static void
usb_power_wdog(void *arg)
{
struct usb_bus *bus = arg;
@@ -728,11 +815,24 @@
bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
bus->resume_msg[1].bus = bus;
+ bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset;
+ bus->reset_msg[0].bus = bus;
+ bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset;
+ bus->reset_msg[1].bus = bus;
+
bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
bus->shutdown_msg[0].bus = bus;
bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
bus->shutdown_msg[1].bus = bus;
+#if USB_HAVE_UGEN
+ LIST_INIT(&bus->pd_cleanup_list);
+ bus->cleanup_msg[0].hdr.pm_callback = &usb_bus_cleanup;
+ bus->cleanup_msg[0].bus = bus;
+ bus->cleanup_msg[1].hdr.pm_callback = &usb_bus_cleanup;
+ bus->cleanup_msg[1].bus = bus;
+#endif
+
/* Create USB explore and callback processes */
if (usb_proc_create(&bus->giant_callback_proc,
@@ -830,7 +930,7 @@
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
- dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
+ dmat, &bus->bus_mtx, NULL, bus->dma_bits, USB_BUS_DMA_TAG_MAX);
#endif
if ((bus->devices_max > USB_MAX_DEVICES) ||
(bus->devices_max < USB_MIN_DEVICES) ||
Modified: stable/0.8/sys/dev/usb/controller/uss820dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uss820dci.c 262457 2014-02-24 20:29:39Z dim $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
* All rights reserved.
@@ -2004,6 +2004,13 @@
len = sizeof(uss820dci_devd);
ptr = (const void *)&uss820dci_devd;
goto tr_valid;
+ case UDESC_DEVICE_QUALIFIER:
+ if (value & 0xff) {
+ goto tr_stalled;
+ }
+ len = sizeof(uss820dci_odevd);
+ ptr = (const void *)&uss820dci_odevd;
+ goto tr_valid;
case UDESC_CONFIG:
if (value & 0xff) {
goto tr_stalled;
@@ -2331,10 +2338,6 @@
if (udev->device_index != sc->sc_rt_addr) {
- if (udev->flags.usb_mode != USB_MODE_DEVICE) {
- /* not supported */
- return;
- }
if (udev->speed != USB_SPEED_FULL) {
/* not supported */
return;
Modified: stable/0.8/sys/dev/usb/controller/uss820dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uss820dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
/*-
* Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uss820dci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
@@ -77,7 +77,7 @@
};
static driver_t uss820dci_driver = {
- .name = "uss820",
+ .name = "uss820dci",
.methods = uss820dci_methods,
.size = sizeof(struct uss820dci_softc),
};
@@ -84,8 +84,8 @@
static devclass_t uss820dci_devclass;
-DRIVER_MODULE(uss820, atmelarm, uss820dci_driver, uss820dci_devclass, 0, 0);
-MODULE_DEPEND(uss820, usb, 1, 1, 1);
+DRIVER_MODULE(uss820dci, atmelarm, uss820dci_driver, uss820dci_devclass, 0, 0);
+MODULE_DEPEND(uss820dci, usb, 1, 1, 1);
static const char *const uss820_desc = "USS820 USB Device Controller";
@@ -107,6 +107,7 @@
sc->sc_bus.parent = dev;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = USS820_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -168,14 +169,8 @@
uss820_atmelarm_detach(device_t dev)
{
struct uss820dci_softc *sc = device_get_softc(dev);
- device_t bdev;
int err;
- if (sc->sc_bus.bdev) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(dev, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(dev);
Modified: stable/0.8/sys/dev/usb/controller/xhci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/xhci.c 315253 2017-03-14 15:30:46Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -86,6 +86,8 @@
#ifdef USB_DEBUG
static int xhcidebug;
static int xhciroute;
+static int xhcipolling;
+static int xhcidma32;
static SYSCTL_NODE(_hw_usb, OID_AUTO, xhci, CTLFLAG_RW, 0, "USB XHCI");
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
@@ -92,10 +94,17 @@
&xhcidebug, 0, "Debug level");
TUNABLE_INT("hw.usb.xhci.debug", &xhcidebug);
SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN,
- &xhciroute, 0, "Routing bitmap for switching EHCI ports to XHCI controller");
+ &xhciroute, 0, "Routing bitmap for switching EHCI ports to the XHCI controller");
TUNABLE_INT("hw.usb.xhci.xhci_port_route", &xhciroute);
+SYSCTL_INT(_hw_usb_xhci, OID_AUTO, use_polling, CTLFLAG_RW | CTLFLAG_TUN,
+ &xhcipolling, 0, "Set to enable software interrupt polling for the XHCI controller");
+TUNABLE_INT("hw.usb.xhci.use_polling", &xhcipolling);
+SYSCTL_INT(_hw_usb_xhci, OID_AUTO, dma32, CTLFLAG_RWTUN,
+ &xhcidma32, 0, "Set to only use 32-bit DMA for the XHCI controller");
+TUNABLE_INT("hw.usb.xhci.dma32", &xhcidma32);
#else
#define xhciroute 0
+#define xhcidma32 0
#endif
#define XHCI_INTR_ENDPT 1
@@ -131,8 +140,8 @@
static usb_proc_callback_t xhci_configure_msg;
static usb_error_t xhci_configure_device(struct usb_device *);
static usb_error_t xhci_configure_endpoint(struct usb_device *,
- struct usb_endpoint_descriptor *, uint64_t, uint16_t,
- uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
+ struct usb_endpoint_descriptor *, struct xhci_endpoint_ext *,
+ uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
static usb_error_t xhci_configure_mask(struct usb_device *,
uint32_t, uint8_t);
static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -181,11 +190,21 @@
}
#endif
+uint8_t
+xhci_use_polling(void)
+{
+#ifdef USB_DEBUG
+ return (xhcipolling != 0);
+#else
+ return (0);
+#endif
+}
+
static void
xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
{
struct xhci_softc *sc = XHCI_BUS2SC(bus);
- uint8_t i;
+ uint16_t i;
cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg,
sizeof(struct xhci_hw_root), XHCI_PAGE_SIZE);
@@ -193,7 +212,7 @@
cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg,
sizeof(struct xhci_dev_ctx_addr), XHCI_PAGE_SIZE);
- for (i = 0; i != XHCI_MAX_SCRATCHPADS; i++) {
+ for (i = 0; i != sc->sc_noscratch; i++) {
cb(bus, &sc->sc_hw.scratch_pc[i], &sc->sc_hw.scratch_pg[i],
XHCI_PAGE_SIZE, XHCI_PAGE_SIZE);
}
@@ -253,111 +272,97 @@
}
#endif
-usb_error_t
-xhci_start_controller(struct xhci_softc *sc)
+static int
+xhci_reset_command_queue_locked(struct xhci_softc *sc)
{
struct usb_page_search buf_res;
struct xhci_hw_root *phwr;
- struct xhci_dev_ctx_addr *pdctxa;
uint64_t addr;
uint32_t temp;
- uint16_t i;
DPRINTF("\n");
- sc->sc_capa_off = 0;
- sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
- sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
- sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
+ temp = XREAD4(sc, oper, XHCI_CRCR_LO);
+ if (temp & XHCI_CRCR_LO_CRR) {
+ DPRINTF("Command ring running\n");
+ temp &= ~(XHCI_CRCR_LO_CS | XHCI_CRCR_LO_CA);
- DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
- DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
- DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
+ /*
+ * Try to abort the last command as per section
+ * 4.6.1.2 "Aborting a Command" of the XHCI
+ * specification:
+ */
- sc->sc_event_ccs = 1;
- sc->sc_event_idx = 0;
- sc->sc_command_ccs = 1;
- sc->sc_command_idx = 0;
+ /* stop and cancel */
+ XWRITE4(sc, oper, XHCI_CRCR_LO, temp | XHCI_CRCR_LO_CS);
+ XWRITE4(sc, oper, XHCI_CRCR_HI, 0);
- DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+ XWRITE4(sc, oper, XHCI_CRCR_LO, temp | XHCI_CRCR_LO_CA);
+ XWRITE4(sc, oper, XHCI_CRCR_HI, 0);
- temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+ /* wait 250ms */
+ usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 4);
- DPRINTF("HCS0 = 0x%08x\n", temp);
-
- if (XHCI_HCS0_CSZ(temp)) {
- sc->sc_ctx_is_64_byte = 1;
- device_printf(sc->sc_bus.parent, "64 byte context size.\n");
- } else {
- sc->sc_ctx_is_64_byte = 0;
- device_printf(sc->sc_bus.parent, "32 byte context size.\n");
+ /* check if command ring is still running */
+ temp = XREAD4(sc, oper, XHCI_CRCR_LO);
+ if (temp & XHCI_CRCR_LO_CRR) {
+ DPRINTF("Comand ring still running\n");
+ return (USB_ERR_IOERROR);
+ }
}
- /* Reset controller */
- XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
+ /* reset command ring */
+ sc->sc_command_ccs = 1;
+ sc->sc_command_idx = 0;
- for (i = 0; i != 100; i++) {
- usb_pause_mtx(NULL, hz / 100);
- temp = XREAD4(sc, oper, XHCI_USBCMD) &
- (XHCI_CMD_HCRST | XHCI_STS_CNR);
- if (!temp)
- break;
- }
+ usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
- if (temp) {
- device_printf(sc->sc_bus.parent, "Controller "
- "reset timeout.\n");
- return (USB_ERR_IOERROR);
- }
+ /* set up command ring control base address */
+ addr = buf_res.physaddr;
+ phwr = buf_res.buffer;
+ addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[0];
- if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) {
- device_printf(sc->sc_bus.parent, "Controller does "
- "not support 4K page size.\n");
- return (USB_ERR_IOERROR);
- }
+ DPRINTF("CRCR=0x%016llx\n", (unsigned long long)addr);
- temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
+ memset(phwr->hwr_commands, 0, sizeof(phwr->hwr_commands));
+ phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].qwTrb0 = htole64(addr);
- i = XHCI_HCS1_N_PORTS(temp);
+ usb_pc_cpu_flush(&sc->sc_hw.root_pc);
- if (i == 0) {
- device_printf(sc->sc_bus.parent, "Invalid number "
- "of ports: %u\n", i);
- return (USB_ERR_IOERROR);
- }
+ XWRITE4(sc, oper, XHCI_CRCR_LO, ((uint32_t)addr) | XHCI_CRCR_LO_RCS);
+ XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
- sc->sc_noport = i;
- sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp);
+ return (0);
+}
- if (sc->sc_noslot > XHCI_MAX_DEVICES)
- sc->sc_noslot = XHCI_MAX_DEVICES;
+usb_error_t
+xhci_start_controller(struct xhci_softc *sc)
+{
+ struct usb_page_search buf_res;
+ struct xhci_hw_root *phwr;
+ struct xhci_dev_ctx_addr *pdctxa;
+ usb_error_t err;
+ uint64_t addr;
+ uint32_t temp;
+ uint16_t i;
- /* setup number of device slots */
+ DPRINTF("\n");
+ sc->sc_event_ccs = 1;
+ sc->sc_event_idx = 0;
+ sc->sc_command_ccs = 1;
+ sc->sc_command_idx = 0;
+
+ err = xhci_reset_controller(sc);
+ if (err)
+ return (err);
+
+ /* set up number of device slots */
DPRINTF("CONFIG=0x%08x -> 0x%08x\n",
XREAD4(sc, oper, XHCI_CONFIG), sc->sc_noslot);
XWRITE4(sc, oper, XHCI_CONFIG, sc->sc_noslot);
- DPRINTF("Max slots: %u\n", sc->sc_noslot);
-
- temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
-
- sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
-
- if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
- device_printf(sc->sc_bus.parent, "XHCI request "
- "too many scratchpads\n");
- return (USB_ERR_NOMEM);
- }
-
- DPRINTF("Max scratch: %u\n", sc->sc_noscratch);
-
- temp = XREAD4(sc, capa, XHCI_HCSPARAMS3);
-
- sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) +
- XHCI_HCS3_U2_DEL(temp) + 250 /* us */;
-
temp = XREAD4(sc, oper, XHCI_USBSTS);
/* clear interrupts */
@@ -365,7 +370,7 @@
/* disable all device notifications */
XWRITE4(sc, oper, XHCI_DNCTRL, 0);
- /* setup device context base address */
+ /* set up device context base address */
usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res);
pdctxa = buf_res.buffer;
memset(pdctxa, 0, sizeof(*pdctxa));
@@ -389,26 +394,14 @@
XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32));
- /* Setup event table size */
-
- temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
-
- DPRINTF("HCS2=0x%08x\n", temp);
-
- temp = XHCI_HCS2_ERST_MAX(temp);
- temp = 1U << temp;
- if (temp > XHCI_MAX_RSEG)
- temp = XHCI_MAX_RSEG;
-
- sc->sc_erst_max = temp;
-
+ /* set up event table size */
DPRINTF("ERSTSZ=0x%08x -> 0x%08x\n",
- XREAD4(sc, runt, XHCI_ERSTSZ(0)), temp);
+ XREAD4(sc, runt, XHCI_ERSTSZ(0)), sc->sc_erst_max);
- XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(temp));
+ XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(sc->sc_erst_max));
- /* Setup interrupt rate */
- XWRITE4(sc, runt, XHCI_IMOD(0), XHCI_IMOD_DEFAULT);
+ /* set up interrupt rate */
+ XWRITE4(sc, runt, XHCI_IMOD(0), sc->sc_imod_default);
usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
@@ -427,7 +420,7 @@
XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr);
XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
- addr = (uint64_t)buf_res.physaddr;
+ addr = buf_res.physaddr;
DPRINTF("ERSTBA(0)=0x%016llx\n", (unsigned long long)addr);
@@ -434,13 +427,12 @@
XWRITE4(sc, runt, XHCI_ERSTBA_LO(0), (uint32_t)addr);
XWRITE4(sc, runt, XHCI_ERSTBA_HI(0), (uint32_t)(addr >> 32));
- /* Setup interrupter registers */
-
+ /* set up interrupter registers */
temp = XREAD4(sc, runt, XHCI_IMAN(0));
temp |= XHCI_IMAN_INTR_ENA;
XWRITE4(sc, runt, XHCI_IMAN(0), temp);
- /* setup command ring control base address */
+ /* set up command ring control base address */
addr = buf_res.physaddr;
addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[0];
@@ -511,9 +503,40 @@
}
usb_error_t
-xhci_init(struct xhci_softc *sc, device_t self)
+xhci_reset_controller(struct xhci_softc *sc)
{
- /* initialise some bus fields */
+ uint32_t temp = 0;
+ uint16_t i;
+
+ DPRINTF("\n");
+
+ /* Reset controller */
+ XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
+
+ for (i = 0; i != 100; i++) {
+ usb_pause_mtx(NULL, hz / 100);
+ temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) |
+ (XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR);
+ if (!temp)
+ break;
+ }
+
+ if (temp) {
+ device_printf(sc->sc_bus.parent, "Controller "
+ "reset timeout.\n");
+ return (USB_ERR_IOERROR);
+ }
+ return (0);
+}
+
+usb_error_t
+xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32)
+{
+ uint32_t temp;
+
+ DPRINTF("\n");
+
+ /* initialize some bus fields */
sc->sc_bus.parent = self;
/* set the bus revision */
@@ -522,14 +545,99 @@
/* set up the bus struct */
sc->sc_bus.methods = &xhci_bus_methods;
- /* setup devices array */
+ /* set up devices array */
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
- /* setup command queue mutex and condition varible */
- cv_init(&sc->sc_cmd_cv, "CMDQ");
- sx_init(&sc->sc_cmd_sx, "CMDQ lock");
+ /* set default cycle state in case of early interrupts */
+ sc->sc_event_ccs = 1;
+ sc->sc_command_ccs = 1;
+ /* set up bus space offsets */
+ sc->sc_capa_off = 0;
+ sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
+ sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
+ sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
+
+ DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
+ DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
+ DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
+
+ DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+
+ if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) {
+ device_printf(sc->sc_bus.parent, "Controller does "
+ "not support 4K page size.\n");
+ return (ENXIO);
+ }
+
+ temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+
+ DPRINTF("HCS0 = 0x%08x\n", temp);
+
+ /* set up context size */
+ if (XHCI_HCS0_CSZ(temp)) {
+ sc->sc_ctx_is_64_byte = 1;
+ } else {
+ sc->sc_ctx_is_64_byte = 0;
+ }
+
+ /* get DMA bits */
+ sc->sc_bus.dma_bits = (XHCI_HCS0_AC64(temp) &&
+ xhcidma32 == 0 && dma32 == 0) ? 64 : 32;
+
+ device_printf(self, "%d bytes context size, %d-bit DMA\n",
+ sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits);
+
+ temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
+
+ /* get number of device slots */
+ sc->sc_noport = XHCI_HCS1_N_PORTS(temp);
+
+ if (sc->sc_noport == 0) {
+ device_printf(sc->sc_bus.parent, "Invalid number "
+ "of ports: %u\n", sc->sc_noport);
+ return (ENXIO);
+ }
+
+ sc->sc_noport = sc->sc_noport;
+ sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp);
+
+ DPRINTF("Max slots: %u\n", sc->sc_noslot);
+
+ if (sc->sc_noslot > XHCI_MAX_DEVICES)
+ sc->sc_noslot = XHCI_MAX_DEVICES;
+
+ temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
+
+ DPRINTF("HCS2=0x%08x\n", temp);
+
+ /* get number of scratchpads */
+ sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
+
+ if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
+ device_printf(sc->sc_bus.parent, "XHCI request "
+ "too many scratchpads\n");
+ return (ENOMEM);
+ }
+
+ DPRINTF("Max scratch: %u\n", sc->sc_noscratch);
+
+ /* get event table size */
+ sc->sc_erst_max = 1U << XHCI_HCS2_ERST_MAX(temp);
+ if (sc->sc_erst_max > XHCI_MAX_RSEG)
+ sc->sc_erst_max = XHCI_MAX_RSEG;
+
+ temp = XREAD4(sc, capa, XHCI_HCSPARAMS3);
+
+ /* get maximum exit latency */
+ sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) +
+ XHCI_HCS3_U2_DEL(temp) + 250 /* us */;
+
+ /* Check if we should use the default IMOD value. */
+ if (sc->sc_imod_default == 0)
+ sc->sc_imod_default = XHCI_IMOD_DEFAULT;
+
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus,
USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) {
@@ -536,10 +644,9 @@
return (ENOMEM);
}
- sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
- sc->sc_config_msg[0].bus = &sc->sc_bus;
- sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
- sc->sc_config_msg[1].bus = &sc->sc_bus;
+ /* set up command queue mutex and condition varible */
+ cv_init(&sc->sc_cmd_cv, "CMDQ");
+ sx_init(&sc->sc_cmd_sx, "CMDQ lock");
if (usb_proc_create(&sc->sc_config_proc,
&sc->sc_bus.bus_mtx, device_get_nameunit(self), USB_PRI_MED)) {
@@ -546,6 +653,11 @@
printf("WARNING: Creation of XHCI configure "
"callback process failed.\n");
}
+ sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
+ sc->sc_config_msg[0].bus = &sc->sc_bus;
+ sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
+ sc->sc_config_msg[1].bus = &sc->sc_bus;
+
return (0);
}
@@ -569,10 +681,12 @@
case USB_HW_POWER_SUSPEND:
DPRINTF("Stopping the XHCI\n");
xhci_halt_controller(sc);
+ xhci_reset_controller(sc);
break;
case USB_HW_POWER_SHUTDOWN:
DPRINTF("Stopping the XHCI\n");
xhci_halt_controller(sc);
+ xhci_reset_controller(sc);
break;
case USB_HW_POWER_RESUME:
DPRINTF("Starting the XHCI\n");
@@ -1003,7 +1117,7 @@
* register.
*/
- addr = (uint32_t)buf_res.physaddr;
+ addr = buf_res.physaddr;
addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[i];
/* try to clear busy bit */
@@ -1025,6 +1139,7 @@
uint32_t temp;
uint8_t i;
uint8_t j;
+ uint8_t timeout = 0;
int err;
XHCI_CMD_ASSERT_LOCKED(sc);
@@ -1038,7 +1153,7 @@
/* Queue command */
USB_BUS_LOCK(&sc->sc_bus);
-
+retry:
i = sc->sc_command_idx;
j = sc->sc_command_ccs;
@@ -1109,7 +1224,35 @@
err = 0;
}
if (err != 0) {
- DPRINTFN(0, "Command timeout!\n");
+ DPRINTF("Command timeout!\n");
+ /*
+ * After some weeks of continuous operation, it has
+ * been observed that the ASMedia Technology, ASM1042
+ * SuperSpeed USB Host Controller can suddenly stop
+ * accepting commands via the command queue. Try to
+ * first reset the command queue. If that fails do a
+ * host controller reset.
+ */
+ if (timeout == 0 &&
+ xhci_reset_command_queue_locked(sc) == 0) {
+ temp = le32toh(trb->dwTrb3);
+
+ /*
+ * Avoid infinite XHCI reset loops if the set
+ * address command fails to respond due to a
+ * non-enumerating device:
+ */
+ if (XHCI_TRB_3_TYPE_GET(temp) == XHCI_TRB_TYPE_ADDRESS_DEVICE &&
+ (temp & XHCI_TRB_3_BSR_BIT) == 0) {
+ DPRINTF("Set address timeout\n");
+ } else {
+ timeout = 1;
+ goto retry;
+ }
+ } else {
+ DPRINTF("Controller reset!\n");
+ usb_bus_reset_async_locked(&sc->sc_bus);
+ }
err = USB_ERR_TIMEOUT;
trb->dwTrb2 = 0;
trb->dwTrb3 = 0;
@@ -1271,8 +1414,15 @@
pepext = xhci_get_endpoint_ext(udev,
&udev->ctrl_ep_desc);
+
+ /* ensure the control endpoint is setup again */
+ USB_BUS_LOCK(udev->bus);
+ pepext->trb_halted = 1;
+ pepext->trb_running = 0;
+ USB_BUS_UNLOCK(udev->bus);
+
err = xhci_configure_endpoint(udev,
- &udev->ctrl_ep_desc, pepext->physaddr,
+ &udev->ctrl_ep_desc, pepext,
0, 1, 1, 0, mps, mps);
if (err != 0) {
@@ -1464,34 +1614,27 @@
xhci_interrupt(struct xhci_softc *sc)
{
uint32_t status;
- uint32_t iman;
+ uint32_t temp;
USB_BUS_LOCK(&sc->sc_bus);
status = XREAD4(sc, oper, XHCI_USBSTS);
- if (status == 0)
- goto done;
- /* acknowledge interrupts */
+ /* acknowledge interrupts, if any */
+ if (status != 0) {
+ XWRITE4(sc, oper, XHCI_USBSTS, status);
+ DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+ }
- XWRITE4(sc, oper, XHCI_USBSTS, status);
+ temp = XREAD4(sc, runt, XHCI_IMAN(0));
- DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+ /* force clearing of pending interrupts */
+ if (temp & XHCI_IMAN_INTR_PEND)
+ XWRITE4(sc, runt, XHCI_IMAN(0), temp);
- if (status & XHCI_STS_EINT) {
+ /* check for event(s) */
+ xhci_interrupt_poll(sc);
- /* acknowledge pending event */
- iman = XREAD4(sc, runt, XHCI_IMAN(0));
-
- /* reset interrupt */
- XWRITE4(sc, runt, XHCI_IMAN(0), iman);
-
- DPRINTFN(16, "real interrupt (iman=0x%08x)\n", iman);
-
- /* check for event(s) */
- xhci_interrupt_poll(sc);
- }
-
if (status & (XHCI_STS_PCD | XHCI_STS_HCH |
XHCI_STS_HSE | XHCI_STS_HCE)) {
@@ -1514,7 +1657,6 @@
__FUNCTION__);
}
}
-done:
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1653,7 +1795,8 @@
/* check wLength */
if (td->td_trb[0].qwTrb0 &
htole64(XHCI_TRB_0_WLENGTH_MASK)) {
- if (td->td_trb[0].qwTrb0 & htole64(1))
+ if (td->td_trb[0].qwTrb0 &
+ htole64(XHCI_TRB_0_DIR_IN_MASK))
dword |= XHCI_TRB_3_TRT_IN;
else
dword |= XHCI_TRB_3_TRT_OUT;
@@ -1688,7 +1831,7 @@
npkt_off += buf_res.length;
}
- /* setup npkt */
+ /* set up npkt */
npkt = (len_old - npkt_off + temp->max_packet_size - 1) /
temp->max_packet_size;
@@ -1726,31 +1869,34 @@
XHCI_TRB_3_ISO_SIA_BIT;
}
if (temp->direction == UE_DIR_IN)
- dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+ dword |= XHCI_TRB_3_ISP_BIT;
break;
case XHCI_TRB_TYPE_DATA_STAGE:
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
- XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE) |
- XHCI_TRB_3_TBC_SET(temp->tbc) |
- XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+ XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE);
if (temp->direction == UE_DIR_IN)
dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+ /*
+ * Section 3.2.9 in the XHCI
+ * specification about control
+ * transfers says that we should use a
+ * normal-TRB if there are more TRBs
+ * extending the data-stage
+ * TRB. Update the "trb_type".
+ */
+ temp->trb_type = XHCI_TRB_TYPE_NORMAL;
break;
case XHCI_TRB_TYPE_STATUS_STAGE:
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
- XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE) |
- XHCI_TRB_3_TBC_SET(temp->tbc) |
- XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+ XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE);
if (temp->direction == UE_DIR_IN)
dword |= XHCI_TRB_3_DIR_IN;
break;
default: /* XHCI_TRB_TYPE_NORMAL */
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
- XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL) |
- XHCI_TRB_3_TBC_SET(temp->tbc) |
- XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+ XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL);
if (temp->direction == UE_DIR_IN)
- dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+ dword |= XHCI_TRB_3_ISP_BIT;
break;
}
td->td_trb[x].dwTrb3 = htole32(dword);
@@ -1788,7 +1934,16 @@
td->td_trb[x].dwTrb2 = htole32(dword);
dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
- XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
+ XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT |
+ /*
+ * CHAIN-BIT: Ensure that a multi-TRB IN-endpoint
+ * frame only receives a single short packet event
+ * by setting the CHAIN bit in the LINK field. In
+ * addition some XHCI controllers have problems
+ * sending a ZLP unless the CHAIN-BIT is set in
+ * the LINK TRB.
+ */
+ XHCI_TRB_3_CHAIN_BIT;
td->td_trb[x].dwTrb3 = htole32(dword);
@@ -1802,7 +1957,7 @@
if (precompute) {
precompute = 0;
- /* setup alt next pointer, if any */
+ /* set up alt next pointer, if any */
if (temp->last_frame) {
td_alt_next = NULL;
} else {
@@ -1826,9 +1981,11 @@
}
/* clear TD SIZE to zero, hence this is the last TRB */
- /* remove chain bit because this is the last TRB in the chain */
+ /* remove chain bit because this is the last data TRB in the chain */
td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
+ /* remove CHAIN-BIT from last LINK TRB */
+ td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
usb_pc_cpu_flush(td->page_cache);
@@ -1967,7 +2124,8 @@
mult = 1;
temp.isoc_delta = 0;
temp.isoc_frame = 0;
- temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE;
+ temp.trb_type = xfer->flags_int.control_did_data ?
+ XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE;
} else {
x = 0;
mult = 1;
@@ -1977,7 +2135,7 @@
}
if (x != xfer->nframes) {
- /* setup page_cache pointer */
+ /* set up page_cache pointer */
temp.pc = xfer->frbuffers + x;
/* set endpoint direction */
temp.direction = UE_GET_DIR(xfer->endpointno);
@@ -2065,7 +2223,11 @@
* Send a DATA1 message and invert the current
* endpoint direction.
*/
+#ifdef XHCI_STEP_STATUS_STAGE
temp.step_td = (xfer->nframes != 0);
+#else
+ temp.step_td = 0;
+#endif
temp.direction = UE_GET_DIR(xfer->endpointno) ^ UE_DIR_IN;
temp.len = 0;
temp.pc = NULL;
@@ -2123,7 +2285,14 @@
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
} else {
- xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
+ /*
+ * Some hardware requires that we drop the endpoint
+ * context before adding it again:
+ */
+ xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0,
+ mask & XHCI_INCTX_NON_CTRL_MASK);
+
+ /* Add new endpoint context */
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
/* find most significant set bit */
@@ -2135,27 +2304,33 @@
/* adjust */
x--;
- /* figure out maximum */
- if (x > sc->sc_hw.devs[index].context_num) {
+ /* figure out the maximum number of contexts */
+ if (x > sc->sc_hw.devs[index].context_num)
sc->sc_hw.devs[index].context_num = x;
- temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
- temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
- temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
- xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
- }
+ else
+ x = sc->sc_hw.devs[index].context_num;
+
+ /* update number of contexts */
+ temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
+ temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
+ temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
+ xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
}
+ usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc);
return (0);
}
static usb_error_t
xhci_configure_endpoint(struct usb_device *udev,
- struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
- uint16_t interval, uint8_t max_packet_count, uint8_t mult,
- uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
+ struct usb_endpoint_descriptor *edesc, struct xhci_endpoint_ext *pepext,
+ uint16_t interval, uint8_t max_packet_count,
+ uint8_t mult, uint8_t fps_shift, uint16_t max_packet_size,
+ uint16_t max_frame_size)
{
struct usb_page_search buf_inp;
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
struct xhci_input_dev_ctx *pinp;
+ uint64_t ring_addr = pepext->physaddr;
uint32_t temp;
uint8_t index;
uint8_t epno;
@@ -2186,6 +2361,10 @@
if (mult == 0)
return (USB_ERR_BAD_BUFSIZE);
+ /* store bMaxPacketSize for control endpoints */
+ pepext->trb_ep_maxp = edesc->wMaxPacketSize[0];
+ usb_pc_cpu_flush(pepext->page_cache);
+
temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
XHCI_EPCTX_0_LSA_SET(0);
@@ -2231,10 +2410,14 @@
XHCI_EPCTX_1_MAXB_SET(max_packet_count) |
XHCI_EPCTX_1_MAXP_SIZE_SET(max_packet_size);
- if ((udev->parent_hs_hub != NULL) || (udev->address != 0)) {
- if (type != UE_ISOCHRONOUS)
- temp |= XHCI_EPCTX_1_CERR_SET(3);
- }
+ /*
+ * Always enable the "three strikes and you are gone" feature
+ * except for ISOCHRONOUS endpoints. This is suggested by
+ * section 4.3.3 in the XHCI specification about device slot
+ * initialisation.
+ */
+ if (type != UE_ISOCHRONOUS)
+ temp |= XHCI_EPCTX_1_CERR_SET(3);
switch (type) {
case UE_CONTROL:
@@ -2301,7 +2484,7 @@
usb_pc_cpu_flush(pepext->page_cache);
return (xhci_configure_endpoint(xfer->xroot->udev,
- xfer->endpoint->edesc, pepext->physaddr,
+ xfer->endpoint->edesc, pepext,
xfer->interval, xfer->max_packet_count,
(ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
@@ -2461,7 +2644,11 @@
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx2, temp);
- temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
+ /*
+ * These fields should be initialized to zero, according to
+ * XHCI section 6.2.2 - slot context:
+ */
+ temp = XHCI_SCTX_3_DEV_ADDR_SET(0) |
XHCI_SCTX_3_SLOT_STATE_SET(0);
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx3, temp);
@@ -2689,6 +2876,17 @@
return (USB_ERR_NOMEM);
}
+ /* check if bMaxPacketSize changed */
+ if (xfer->flags_int.control_xfr != 0 &&
+ pepext->trb_ep_maxp != xfer->endpoint->edesc->wMaxPacketSize[0]) {
+
+ DPRINTFN(8, "Reconfigure control endpoint\n");
+
+ /* force driver to reconfigure endpoint */
+ pepext->trb_halted = 1;
+ pepext->trb_running = 0;
+ }
+
/* check for stopped condition, after putting transfer on interrupt queue */
if (pepext->trb_running == 0) {
struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
@@ -2889,7 +3087,7 @@
{
DPRINTF("\n");
- /* setup TD's and QH */
+ /* set up TD's and QH */
xhci_setup_generic_chain(xfer);
xhci_device_generic_multi_enter(xfer->endpoint, xfer);
@@ -3629,16 +3827,14 @@
xhci_configure_mask(udev, (1U << epno) | 1U, 0);
- err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+ if (epno > 1)
+ err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+ else
+ err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
if (err != 0)
DPRINTF("Could not configure endpoint %u\n", epno);
- err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
-
- if (err != 0)
- DPRINTF("Could not configure endpoint %u\n", epno);
-
XHCI_CMD_UNLOCK(sc);
return (0);
@@ -3752,10 +3948,6 @@
DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d\n",
ep, udev->address, edesc->bEndpointAddress, udev->flags.usb_mode);
- if (udev->flags.usb_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
if (udev->parent_hub == NULL) {
/* root HUB has special endpoint handling */
return;
@@ -4018,6 +4210,10 @@
sc->sc_hw.devs[index].state = XHCI_ST_ADDRESSED;
+ /* set configure mask to slot only */
+ xhci_configure_mask(udev, 1, 0);
+
+ /* deconfigure all endpoints, except EP0 */
err = xhci_cmd_configure_ep(sc, 0, 1, index);
if (err) {
Modified: stable/0.8/sys/dev/usb/controller/xhci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/xhci.h 315253 2017-03-14 15:30:46Z hselasky $ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -30,7 +30,7 @@
#define XHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128)
#define XHCI_MAX_ENDPOINTS 32 /* hardcoded - do not change */
-#define XHCI_MAX_SCRATCHPADS 32
+#define XHCI_MAX_SCRATCHPADS 256 /* theoretical max is 1023 */
#define XHCI_MAX_EVENTS (16 * 13)
#define XHCI_MAX_COMMANDS (16 * 1)
#define XHCI_MAX_RSEG 1
@@ -184,6 +184,7 @@
struct xhci_trb {
volatile uint64_t qwTrb0;
+#define XHCI_TRB_0_DIR_IN_MASK (0x80ULL << 0)
#define XHCI_TRB_0_WLENGTH_MASK (0xFFFFULL << 48)
volatile uint32_t dwTrb2;
#define XHCI_TRB_2_ERROR_GET(x) (((x) >> 24) & 0xFF)
@@ -310,11 +311,23 @@
struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
};
-#define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */
-#define XHCI_TD_PAGE_SIZE 4096 /* bytes */
-#define XHCI_TD_PAYLOAD_MAX (XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1))
+#if (USB_PAGE_SIZE < 4096)
+#error "The XHCI driver needs a pagesize above or equal to 4K"
+#endif
+/* Define the maximum payload which we will handle in a single TRB */
+#define XHCI_TD_PAYLOAD_MAX 65536 /* bytes */
+
+/* Define the maximum payload of a single scatter-gather list element */
+#define XHCI_TD_PAGE_SIZE \
+ ((USB_PAGE_SIZE < XHCI_TD_PAYLOAD_MAX) ? USB_PAGE_SIZE : XHCI_TD_PAYLOAD_MAX)
+
+/* Define the maximum length of the scatter-gather list */
+#define XHCI_TD_PAGE_NBUF \
+ (((XHCI_TD_PAYLOAD_MAX + XHCI_TD_PAGE_SIZE - 1) / XHCI_TD_PAGE_SIZE) + 1)
+
struct xhci_td {
+ /* one LINK TRB has been added to the TRB array */
struct xhci_trb td_trb[XHCI_TD_PAGE_NBUF + 1];
/*
@@ -360,6 +373,7 @@
uint8_t trb_index;
uint8_t trb_halted;
uint8_t trb_running;
+ uint8_t trb_ep_maxp;
};
enum {
@@ -431,6 +445,8 @@
struct usb_process sc_config_proc;
struct usb_bus_msg sc_config_msg[2];
+ struct usb_callout sc_callout;
+
xhci_port_route_t *sc_port_route;
union xhci_hub_desc sc_hub_desc;
@@ -440,7 +456,6 @@
struct usb_device *sc_devices[XHCI_MAX_DEVICES];
struct resource *sc_io_res;
- int sc_irq_rid;
struct resource *sc_irq_res;
void *sc_intr_hdl;
@@ -469,7 +484,11 @@
uint16_t sc_erst_max;
uint16_t sc_event_idx;
uint16_t sc_command_idx;
+ uint16_t sc_imod_default;
+ /* number of scratch pages */
+ uint16_t sc_noscratch;
+
uint8_t sc_event_ccs;
uint8_t sc_command_ccs;
/* number of XHCI device slots */
@@ -476,11 +495,10 @@
uint8_t sc_noslot;
/* number of ports on root HUB */
uint8_t sc_noport;
- /* number of scratch pages */
- uint8_t sc_noscratch;
/* root HUB device configuration */
uint8_t sc_conf;
- uint8_t sc_hub_idata[2];
+ /* root HUB port event bitmap, max 256 ports */
+ uint8_t sc_hub_idata[32];
/* size of context */
uint8_t sc_ctx_is_64_byte;
@@ -495,8 +513,10 @@
/* prototypes */
+uint8_t xhci_use_polling(void);
usb_error_t xhci_halt_controller(struct xhci_softc *);
-usb_error_t xhci_init(struct xhci_softc *, device_t);
+usb_error_t xhci_reset_controller(struct xhci_softc *);
+usb_error_t xhci_init(struct xhci_softc *, device_t, uint8_t);
usb_error_t xhci_start_controller(struct xhci_softc *);
void xhci_interrupt(struct xhci_softc *);
void xhci_uninit(struct xhci_softc *);
Modified: stable/0.8/sys/dev/usb/controller/xhci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci_pci.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci_pci.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/xhci_pci.c 315253 2017-03-14 15:30:46Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -86,10 +86,9 @@
static devclass_t xhci_devclass;
-DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, 0, 0);
+DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, NULL, NULL);
MODULE_DEPEND(xhci, usb, 1, 1, 1);
-
static const char *
xhci_pci_match(device_t self)
{
@@ -99,14 +98,29 @@
case 0x01941033:
return ("NEC uPD720200 USB 3.0 controller");
+ case 0x10001b73:
+ return ("Fresco Logic FL1000G USB 3.0 controller");
+
case 0x10421b21:
return ("ASMedia ASM1042 USB 3.0 controller");
+ case 0x11421b21:
+ return ("ASMedia ASM1042A USB 3.0 controller");
+ case 0x0f358086:
+ return ("Intel BayTrail USB 3.0 controller");
+ case 0x9c318086:
case 0x1e318086:
return ("Intel Panther Point USB 3.0 controller");
case 0x8c318086:
return ("Intel Lynx Point USB 3.0 controller");
+ case 0x8cb18086:
+ return ("Intel Wildcat Point USB 3.0 controller");
+ case 0x9cb18086:
+ return ("Broadwell Integrated PCH-LP chipset USB 3.0 controller");
+ case 0xa01b177d:
+ return ("Cavium ThunderX USB 3.0 controller");
+
default:
break;
}
@@ -135,10 +149,22 @@
static int xhci_use_msi = 1;
TUNABLE_INT("hw.usb.xhci.msi", &xhci_use_msi);
+static void
+xhci_interrupt_poll(void *_sc)
+{
+ struct xhci_softc *sc = _sc;
+ USB_BUS_UNLOCK(&sc->sc_bus);
+ xhci_interrupt(sc);
+ USB_BUS_LOCK(&sc->sc_bus);
+ usb_callout_reset(&sc->sc_callout, 1, (void *)&xhci_interrupt_poll, sc);
+}
+
static int
xhci_pci_port_route(device_t self, uint32_t set, uint32_t clear)
{
uint32_t temp;
+ uint32_t usb3_mask;
+ uint32_t usb2_mask;
temp = pci_read_config(self, PCI_XHCI_INTEL_USB3_PSSEN, 4) |
pci_read_config(self, PCI_XHCI_INTEL_XUSB2PR, 4);
@@ -146,9 +172,13 @@
temp |= set;
temp &= ~clear;
- pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
- pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
+ /* Don't set bits which the hardware doesn't support */
+ usb3_mask = pci_read_config(self, PCI_XHCI_INTEL_USB3PRM, 4);
+ usb2_mask = pci_read_config(self, PCI_XHCI_INTEL_USB2PRM, 4);
+ pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp & usb3_mask, 4);
+ pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp & usb2_mask, 4);
+
device_printf(self, "Port routing mask set to 0x%08x\n", temp);
return (0);
@@ -159,44 +189,71 @@
{
struct xhci_softc *sc = device_get_softc(self);
int count, err, rid;
+ uint8_t usemsi = 1;
+ uint8_t usedma32 = 0;
- /* XXX check for 64-bit capability */
-
- if (xhci_init(sc, self)) {
- device_printf(self, "Could not initialize softc\n");
- goto error;
- }
-
- pci_enable_busmaster(self);
-
rid = PCI_XHCI_CBMEM;
sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_io_res) {
device_printf(self, "Could not map memory\n");
- goto error;
+ return (ENOMEM);
}
sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
sc->sc_io_size = rman_get_size(sc->sc_io_res);
- sc->sc_irq_rid = 0;
- if (xhci_use_msi) {
- count = pci_msi_count(self);
- if (count >= 1) {
- count = 1;
- if (pci_alloc_msi(self, &count) == 0) {
- if (bootverbose)
- device_printf(self, "MSI enabled\n");
- sc->sc_irq_rid = 1;
- }
+ switch (pci_get_devid(self)) {
+ case 0x01941033: /* NEC uPD720200 USB 3.0 controller */
+ case 0x00141912: /* NEC uPD720201 USB 3.0 controller */
+ /* Don't use 64-bit DMA on these controllers. */
+ usedma32 = 1;
+ break;
+ case 0x10001b73: /* FL1000G */
+ /* Fresco Logic host doesn't support MSI. */
+ usemsi = 0;
+ break;
+ case 0x0f358086: /* BayTrail */
+ case 0x9c318086: /* Panther Point */
+ case 0x1e318086: /* Panther Point */
+ case 0x8c318086: /* Lynx Point */
+ case 0x8cb18086: /* Wildcat Point */
+ case 0x9cb18086: /* Broadwell Mobile Integrated */
+ /*
+ * On Intel chipsets, reroute ports from EHCI to XHCI
+ * controller and use a different IMOD value.
+ */
+ sc->sc_port_route = &xhci_pci_port_route;
+ sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP;
+ break;
+ }
+
+ if (xhci_init(sc, self, usedma32)) {
+ device_printf(self, "Could not initialize softc\n");
+ bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
+ sc->sc_io_res);
+ return (ENXIO);
+ }
+
+ pci_enable_busmaster(self);
+
+ usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0);
+
+ rid = 0;
+ if (xhci_use_msi && usemsi) {
+ count = 1;
+ if (pci_alloc_msi(self, &count) == 0) {
+ if (bootverbose)
+ device_printf(self, "MSI enabled\n");
+ rid = 1;
}
}
- sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ,
- &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE);
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | (rid != 0 ? 0 : RF_SHAREABLE));
if (sc->sc_irq_res == NULL) {
+ pci_release_msi(self);
device_printf(self, "Could not allocate IRQ\n");
- goto error;
+ /* goto error; FALLTHROUGH - use polling */
}
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
if (sc->sc_bus.bdev == NULL) {
@@ -207,27 +264,26 @@
sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));
-#if (__FreeBSD_version >= 700031)
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
-#else
- err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
- if (err) {
- device_printf(self, "Could not setup IRQ, err=%d\n", err);
- sc->sc_intr_hdl = NULL;
- goto error;
+ if (sc->sc_irq_res != NULL) {
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err != 0) {
+ bus_release_resource(self, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ pci_release_msi(self);
+ device_printf(self, "Could not setup IRQ, err=%d\n", err);
+ sc->sc_intr_hdl = NULL;
+ }
}
- /* On Intel chipsets reroute ports from EHCI to XHCI controller. */
- switch (pci_get_devid(self)) {
- case 0x1e318086: /* Panther Point */
- case 0x8c318086: /* Lynx Point */
- case 0x8cb18086: /* Wildcat Point */
- sc->sc_port_route = &xhci_pci_port_route;
- break;
- default:
- break;
+ if (sc->sc_irq_res == NULL || sc->sc_intr_hdl == NULL) {
+ if (xhci_use_polling() != 0) {
+ device_printf(self, "Interrupt polling at %dHz\n", hz);
+ USB_BUS_LOCK(&sc->sc_bus);
+ xhci_interrupt_poll(sc);
+ USB_BUS_UNLOCK(&sc->sc_bus);
+ } else
+ goto error;
}
xhci_pci_take_controller(self);
@@ -255,31 +311,25 @@
xhci_pci_detach(device_t self)
{
struct xhci_softc *sc = device_get_softc(self);
- device_t bdev;
- if (sc->sc_bus.bdev != NULL) {
- bdev = sc->sc_bus.bdev;
- device_detach(bdev);
- device_delete_child(self, bdev);
- }
/* during module unload there are lots of children leftover */
device_delete_children(self);
+ usb_callout_drain(&sc->sc_callout);
+ xhci_halt_controller(sc);
+ xhci_reset_controller(sc);
+
pci_disable_busmaster(self);
if (sc->sc_irq_res && sc->sc_intr_hdl) {
-
- xhci_halt_controller(sc);
-
bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
sc->sc_intr_hdl = NULL;
}
if (sc->sc_irq_res) {
- if (sc->sc_irq_rid == 1)
- pci_release_msi(self);
- bus_release_resource(self, SYS_RES_IRQ, sc->sc_irq_rid,
- sc->sc_irq_res);
+ bus_release_resource(self, SYS_RES_IRQ,
+ rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
sc->sc_irq_res = NULL;
+ pci_release_msi(self);
}
if (sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
Modified: stable/0.8/sys/dev/usb/controller/xhcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhcireg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhcireg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/xhcireg.h 302267 2016-06-29 10:23:19Z hselasky $ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -35,7 +35,9 @@
#define PCI_XHCI_FLADJ 0x61 /* RW frame length adjust */
#define PCI_XHCI_INTEL_XUSB2PR 0xD0 /* Intel USB2 Port Routing */
+#define PCI_XHCI_INTEL_USB2PRM 0xD4 /* Intel USB2 Port Routing Mask */
#define PCI_XHCI_INTEL_USB3_PSSEN 0xD8 /* Intel USB3 Port SuperSpeed Enable */
+#define PCI_XHCI_INTEL_USB3PRM 0xDC /* Intel USB3 Port Routing Mask */
/* XHCI capability registers */
#define XHCI_CAPLENGTH 0x00 /* RO capability */
@@ -50,8 +52,8 @@
#define XHCI_HCSPARAMS2 0x08 /* RO structual parameters 2 */
#define XHCI_HCS2_IST(x) ((x) & 0xF)
#define XHCI_HCS2_ERST_MAX(x) (((x) >> 4) & 0xF)
-#define XHCI_HCS2_SPR(x) (((x) >> 24) & 0x1)
-#define XHCI_HCS2_SPB_MAX(x) (((x) >> 27) & 0x7F)
+#define XHCI_HCS2_SPR(x) (((x) >> 26) & 0x1)
+#define XHCI_HCS2_SPB_MAX(x) ((((x) >> 16) & 0x3E0) | (((x) >> 27) & 0x1F))
#define XHCI_HCSPARAMS3 0x0C /* RO structual parameters 3 */
#define XHCI_HCS3_U1_DEL(x) ((x) & 0xFF)
#define XHCI_HCS3_U2_DEL(x) (((x) >> 16) & 0xFFFF)
@@ -166,7 +168,8 @@
#define XHCI_IMOD_IVAL_SET(x) (((x) & 0xFFFF) << 0) /* 250ns unit */
#define XHCI_IMOD_ICNT_GET(x) (((x) >> 16) & 0xFFFF) /* 250ns unit */
#define XHCI_IMOD_ICNT_SET(x) (((x) & 0xFFFF) << 16) /* 250ns unit */
-#define XHCI_IMOD_DEFAULT 0x000003E8U /* 8000 IRQ/second */
+#define XHCI_IMOD_DEFAULT 0x000001F4U /* 8000 IRQs/second */
+#define XHCI_IMOD_DEFAULT_LP 0x000003F8U /* 4000 IRQs/second - LynxPoint */
#define XHCI_ERSTSZ(n) (0x0028 + (0x20 * (n))) /* XHCI event ring segment table size */
#define XHCI_ERSTS_GET(x) ((x) & 0xFFFF)
#define XHCI_ERSTS_SET(x) ((x) & 0xFFFF)
Modified: stable/0.8/sys/dev/usb/input/atp.c
===================================================================
--- stable/0.8/sys/dev/usb/input/atp.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/atp.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/atp.c 263064 2014-03-12 07:18:39Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
Modified: stable/0.8/sys/dev/usb/input/uep.c
===================================================================
--- stable/0.8/sys/dev/usb/input/uep.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/uep.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/input/uep.c 248085 2013-03-09 02:36:32Z marius $
*/
/*
Modified: stable/0.8/sys/dev/usb/input/uhid.c
===================================================================
--- stable/0.8/sys/dev/usb/input/uhid.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/uhid.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -5,7 +5,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/uhid.c 291206 2015-11-23 13:48:28Z hselasky $");
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -518,7 +518,9 @@
*/
if (fflags & FREAD) {
/* reset flags */
+ mtx_lock(&sc->sc_mtx);
sc->sc_flags &= ~UHID_FLAG_IMMED;
+ mtx_unlock(&sc->sc_mtx);
if (usb_fifo_alloc_buffer(fifo,
sc->sc_isize + 1, UHID_FRAME_NUM)) {
@@ -734,7 +736,7 @@
if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE) {
sc->sc_repdesc_size = sizeof(uhid_graphire_report_descr);
- sc->sc_repdesc_ptr = (void *)&uhid_graphire_report_descr;
+ sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire_report_descr);
sc->sc_flags |= UHID_FLAG_STATIC_DESC;
} else if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) {
@@ -755,16 +757,27 @@
usbd_errstr(error));
}
sc->sc_repdesc_size = sizeof(uhid_graphire3_4x5_report_descr);
- sc->sc_repdesc_ptr = (void *)&uhid_graphire3_4x5_report_descr;
+ sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire3_4x5_report_descr);
sc->sc_flags |= UHID_FLAG_STATIC_DESC;
}
} else if ((uaa->info.bInterfaceClass == UICLASS_VENDOR) &&
- (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
+ (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
(uaa->info.bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD)) {
-
+ static const uint8_t reportbuf[3] = {1, 3, 0};
+ /*
+ * Turn off the four LEDs on the gamepad which
+ * are blinking by default:
+ */
+ error = usbd_req_set_report(uaa->device, NULL,
+ __DECONST(void *, reportbuf), sizeof(reportbuf),
+ uaa->info.bIfaceIndex, UHID_OUTPUT_REPORT, 0);
+ if (error) {
+ DPRINTF("set output report failed, error=%s (ignored)\n",
+ usbd_errstr(error));
+ }
/* the Xbox 360 gamepad has no report descriptor */
sc->sc_repdesc_size = sizeof(uhid_xb360gp_report_descr);
- sc->sc_repdesc_ptr = (void *)&uhid_xb360gp_report_descr;
+ sc->sc_repdesc_ptr = __DECONST(void *, &uhid_xb360gp_report_descr);
sc->sc_flags |= UHID_FLAG_STATIC_DESC;
}
if (sc->sc_repdesc_ptr == NULL) {
Modified: stable/0.8/sys/dev/usb/input/ukbd.c
===================================================================
--- stable/0.8/sys/dev/usb/input/ukbd.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/ukbd.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/ukbd.c 305646 2016-09-09 06:41:16Z hselasky $");
/*-
@@ -107,7 +107,7 @@
#define UKBD_NMOD 8 /* units */
#define UKBD_NKEYCODE 6 /* units */
#define UKBD_IN_BUF_SIZE (2*(UKBD_NMOD + (2*UKBD_NKEYCODE))) /* bytes */
-#define UKBD_IN_BUF_FULL (UKBD_IN_BUF_SIZE / 2) /* bytes */
+#define UKBD_IN_BUF_FULL ((UKBD_IN_BUF_SIZE / 2) - 1) /* bytes */
#define UKBD_NFKEY (sizeof(fkey_tab)/sizeof(fkey_tab[0])) /* units */
#define UKBD_BUFFER_SIZE 64 /* bytes */
@@ -128,7 +128,8 @@
};
enum {
- UKBD_INTR_DT,
+ UKBD_INTR_DT_0,
+ UKBD_INTR_DT_1,
UKBD_CTRL_LED,
UKBD_N_TRANSFER,
};
@@ -197,6 +198,7 @@
int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
int sc_state; /* shift/lock key state */
int sc_accents; /* accent key index (> 0) */
+ int sc_polling; /* polling recursion count */
int sc_led_size;
int sc_kbd_size;
@@ -298,6 +300,10 @@
* 0x68: F13
* 0x69: F14
* 0x6a: F15
+ *
+ * USB Apple Keyboard JIS generates:
+ * 0x90: Kana
+ * 0x91: Eisu
*/
static const uint8_t ukbd_trtab[256] = {
0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */
@@ -318,7 +324,7 @@
109, 110, 112, 118, 114, 116, 117, 119, /* 78 - 7F */
121, 120, NN, NN, NN, NN, NN, 123, /* 80 - 87 */
124, 125, 126, 127, 128, NN, NN, NN, /* 88 - 8F */
- NN, NN, NN, NN, NN, NN, NN, NN, /* 90 - 97 */
+ 129, 130, 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 */
@@ -472,7 +478,8 @@
if (sc->sc_inputs == 0 &&
(sc->sc_flags & UKBD_FLAG_GONE) == 0) {
/* start transfer, if not already started */
- usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
}
if (sc->sc_flags & UKBD_FLAG_POLLING)
@@ -948,7 +955,7 @@
static const struct usb_config ukbd_config[UKBD_N_TRANSFER] = {
- [UKBD_INTR_DT] = {
+ [UKBD_INTR_DT_0] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
@@ -957,6 +964,15 @@
.callback = &ukbd_intr_callback,
},
+ [UKBD_INTR_DT_1] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &ukbd_intr_callback,
+ },
+
[UKBD_CTRL_LED] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
@@ -1193,9 +1209,26 @@
usb_callout_init_mtx(&sc->sc_callout, &Giant, 0);
+#ifdef UKBD_NO_POLLING
err = usbd_transfer_setup(uaa->device,
&uaa->info.bIfaceIndex, sc->sc_xfer, ukbd_config,
UKBD_N_TRANSFER, sc, &Giant);
+#else
+ /*
+ * Setup the UKBD USB transfers one by one, so they are memory
+ * independent which allows for handling panics triggered by
+ * the keyboard driver itself, typically via CTRL+ALT+ESC
+ * sequences. Or if the USB keyboard driver was processing a
+ * key at the moment of panic.
+ */
+ for (n = 0; n != UKBD_N_TRANSFER; n++) {
+ err = usbd_transfer_setup(uaa->device,
+ &uaa->info.bIfaceIndex, sc->sc_xfer + n, ukbd_config + n,
+ 1, sc, &Giant);
+ if (err)
+ break;
+ }
+#endif
if (err) {
DPRINTF("error=%s\n", usbd_errstr(err));
@@ -1278,7 +1311,8 @@
}
/* start the keyboard */
- usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+ usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
return (0); /* success */
@@ -1304,7 +1338,8 @@
/* kill any stuck keys */
if (sc->sc_flags & UKBD_FLAG_ATTACHED) {
/* stop receiving events from the USB keyboard */
- usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT]);
+ usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_0]);
+ usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_1]);
/* release all leftover keys, if any */
memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
@@ -1963,7 +1998,16 @@
struct ukbd_softc *sc = kbd->kb_data;
UKBD_LOCK();
- if (on) {
+ /*
+ * Keep a reference count on polling to allow recursive
+ * cngrab() during a panic for example.
+ */
+ if (on)
+ sc->sc_polling++;
+ else if (sc->sc_polling > 0)
+ sc->sc_polling--;
+
+ if (sc->sc_polling != 0) {
sc->sc_flags |= UKBD_FLAG_POLLING;
sc->sc_poll_thread = curthread;
} else {
@@ -2051,7 +2095,7 @@
0x166, /* Sun Type 6 Find */
0x167, /* Sun Type 6 Cut */
0x125, /* Sun Type 6 Mute */
- /* 120 - 128 */
+ /* 120 - 130 */
0x11f, /* Sun Type 6 VolumeDown */
0x11e, /* Sun Type 6 VolumeUp */
0x120, /* Sun Type 6 PowerDown */
@@ -2063,6 +2107,8 @@
0x79, /* Keyboard Intl' 4 (Henkan) */
0x7b, /* Keyboard Intl' 5 (Muhenkan) */
0x5c, /* Keyboard Intl' 6 (Keypad ,) (For PC-9821 layout) */
+ 0x71, /* Apple Keyboard JIS (Kana) */
+ 0x72, /* Apple Keyboard JIS (Eisu) */
};
if ((code >= 89) && (code < (int)(89 + (sizeof(scan) / sizeof(scan[0]))))) {
Modified: stable/0.8/sys/dev/usb/input/ums.c
===================================================================
--- stable/0.8/sys/dev/usb/input/ums.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/ums.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/ums.c 308396 2016-11-07 08:17:23Z hselasky $");
/*
* HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
@@ -258,8 +258,11 @@
}
if ((info->sc_flags & UMS_FLAG_T_AXIS) &&
- (id == info->sc_iid_t))
+ (id == info->sc_iid_t)) {
dt -= hid_get_data(buf, len, &info->sc_loc_t);
+ /* T-axis is translated into button presses */
+ buttons_found |= (1UL << 5) | (1UL << 6);
+ }
for (i = 0; i < info->sc_buttons; i++) {
uint32_t mask;
@@ -287,10 +290,13 @@
dx, dy, dz, dt, dw, buttons);
/* translate T-axis into button presses until further */
- if (dt > 0)
- buttons |= 1UL << 3;
- else if (dt < 0)
- buttons |= 1UL << 4;
+ if (dt > 0) {
+ ums_put_queue(sc, 0, 0, 0, 0, buttons);
+ buttons |= 1UL << 5;
+ } else if (dt < 0) {
+ ums_put_queue(sc, 0, 0, 0, 0, buttons);
+ buttons |= 1UL << 6;
+ }
sc->sc_status.button = buttons;
sc->sc_status.dx += dx;
Modified: stable/0.8/sys/dev/usb/input/usb_rdesc.h
===================================================================
--- stable/0.8/sys/dev/usb/input/usb_rdesc.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/usb_rdesc.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/input/usb_rdesc.h 196219 2009-08-14 20:03:53Z jhb $
*
* This file contains replacements for broken HID report descriptors.
*/
Added: stable/0.8/sys/dev/usb/input/wsp.c
===================================================================
--- stable/0.8/sys/dev/usb/input/wsp.c (rev 0)
+++ stable/0.8/sys/dev/usb/input/wsp.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1397 @@
+/*-
+ * Copyright (c) 2012 Huang Wen Hui
+ * 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: stable/9/sys/dev/usb/input/wsp.c 291066 2015-11-19 10:01:50Z hselasky $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.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 <dev/usb/usbhid.h>
+
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR wsp_debug
+#include <dev/usb/usb_debug.h>
+
+#include <sys/mouse.h>
+
+#define WSP_DRIVER_NAME "wsp"
+#define WSP_BUFFER_MAX 1024
+
+#define WSP_CLAMP(x,low,high) do { \
+ if ((x) < (low)) \
+ (x) = (low); \
+ else if ((x) > (high)) \
+ (x) = (high); \
+} while (0)
+
+/* Tunables */
+static SYSCTL_NODE(_hw_usb, OID_AUTO, wsp, CTLFLAG_RW, 0, "USB wsp");
+
+#ifdef USB_DEBUG
+enum wsp_log_level {
+ WSP_LLEVEL_DISABLED = 0,
+ WSP_LLEVEL_ERROR,
+ WSP_LLEVEL_DEBUG, /* for troubleshooting */
+ WSP_LLEVEL_INFO, /* for diagnostics */
+};
+static int wsp_debug = WSP_LLEVEL_ERROR;/* the default is to only log errors */
+
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, debug, CTLFLAG_RW,
+ &wsp_debug, WSP_LLEVEL_ERROR, "WSP debug level");
+#endif /* USB_DEBUG */
+
+static struct wsp_tuning {
+ int scale_factor;
+ int z_factor;
+ int pressure_touch_threshold;
+ int pressure_untouch_threshold;
+ int pressure_tap_threshold;
+ int scr_hor_threshold;
+}
+ wsp_tuning =
+{
+ .scale_factor = 12,
+ .z_factor = 5,
+ .pressure_touch_threshold = 50,
+ .pressure_untouch_threshold = 10,
+ .pressure_tap_threshold = 120,
+ .scr_hor_threshold = 20,
+};
+
+static void
+wsp_runing_rangecheck(struct wsp_tuning *ptun)
+{
+ WSP_CLAMP(ptun->scale_factor, 1, 63);
+ WSP_CLAMP(ptun->z_factor, 1, 63);
+ WSP_CLAMP(ptun->pressure_touch_threshold, 1, 255);
+ WSP_CLAMP(ptun->pressure_untouch_threshold, 1, 255);
+ WSP_CLAMP(ptun->pressure_tap_threshold, 1, 255);
+ WSP_CLAMP(ptun->scr_hor_threshold, 1, 255);
+}
+
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scale_factor, CTLFLAG_RW,
+ &wsp_tuning.scale_factor, 0, "movement scale factor");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, z_factor, CTLFLAG_RW,
+ &wsp_tuning.z_factor, 0, "Z-axis scale factor");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_touch_threshold, CTLFLAG_RW,
+ &wsp_tuning.pressure_touch_threshold, 0, "touch pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_untouch_threshold, CTLFLAG_RW,
+ &wsp_tuning.pressure_untouch_threshold, 0, "untouch pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_tap_threshold, CTLFLAG_RW,
+ &wsp_tuning.pressure_tap_threshold, 0, "tap pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scr_hor_threshold, CTLFLAG_RW,
+ &wsp_tuning.scr_hor_threshold, 0, "horizontal scrolling threshold");
+
+/*
+ * Some tables, structures, definitions and constant values for the
+ * touchpad protocol has been copied from Linux's
+ * "drivers/input/mouse/bcm5974.c" which has the following copyright
+ * holders under GPLv2. All device specific code in this driver has
+ * been written from scratch. The decoding algorithm is based on
+ * output from FreeBSD's usbdump.
+ *
+ * Copyright (C) 2008 Henrik Rydberg (rydberg at euromail.se)
+ * Copyright (C) 2008 Scott Shawcroft (scott.shawcroft at gmail.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg at kroah.com)
+ * Copyright (C) 2005 Johannes Berg (johannes at sipsolutions.net)
+ * Copyright (C) 2005 Stelian Pop (stelian at popies.net)
+ * Copyright (C) 2005 Frank Arnold (frank at scirocco-5v-turbo.de)
+ * Copyright (C) 2005 Peter Osterlund (petero2 at telia.com)
+ * Copyright (C) 2005 Michael Hanselmann (linux-kernel at hansmi.ch)
+ * Copyright (C) 2006 Nicolas Boichat (nicolas at boichat.ch)
+ */
+
+/* button data structure */
+struct bt_data {
+ uint8_t unknown1; /* constant */
+ uint8_t button; /* left button */
+ uint8_t rel_x; /* relative x coordinate */
+ uint8_t rel_y; /* relative y coordinate */
+} __packed;
+
+/* trackpad header types */
+enum tp_type {
+ TYPE1, /* plain trackpad */
+ TYPE2, /* button integrated in trackpad */
+ TYPE3, /* additional header fields since June 2013 */
+ TYPE4 /* additional header field for pressure data */
+};
+
+/* trackpad finger data offsets, le16-aligned */
+#define FINGER_TYPE1 (13 * 2)
+#define FINGER_TYPE2 (15 * 2)
+#define FINGER_TYPE3 (19 * 2)
+#define FINGER_TYPE4 (23 * 2)
+
+/* trackpad button data offsets */
+#define BUTTON_TYPE2 15
+#define BUTTON_TYPE3 23
+#define BUTTON_TYPE4 31
+
+/* list of device capability bits */
+#define HAS_INTEGRATED_BUTTON 1
+
+/* trackpad finger data block size */
+#define FSIZE_TYPE1 (14 * 2)
+#define FSIZE_TYPE2 (14 * 2)
+#define FSIZE_TYPE3 (14 * 2)
+#define FSIZE_TYPE4 (15 * 2)
+
+/* trackpad finger header - little endian */
+struct tp_header {
+ uint8_t flag;
+ uint8_t sn0;
+ uint16_t wFixed0;
+ uint32_t dwSn1;
+ uint32_t dwFixed1;
+ uint16_t wLength;
+ uint8_t nfinger;
+ uint8_t ibt;
+ int16_t wUnknown[6];
+ uint8_t q1;
+ uint8_t q2;
+} __packed;
+
+/* trackpad finger structure - little endian */
+struct tp_finger {
+ int16_t origin; /* zero when switching track finger */
+ int16_t abs_x; /* absolute x coodinate */
+ int16_t abs_y; /* absolute y coodinate */
+ int16_t rel_x; /* relative x coodinate */
+ int16_t rel_y; /* relative y coodinate */
+ int16_t tool_major; /* tool area, major axis */
+ int16_t tool_minor; /* tool area, minor axis */
+ int16_t orientation; /* 16384 when point, else 15 bit angle */
+ int16_t touch_major; /* touch area, major axis */
+ int16_t touch_minor; /* touch area, minor axis */
+ int16_t unused[2]; /* zeros */
+ int16_t pressure; /* pressure on forcetouch touchpad */
+ int16_t multi; /* one finger: varies, more fingers:
+ * constant */
+} __packed;
+
+/* trackpad finger data size, empirically at least ten fingers */
+#define MAX_FINGERS 16
+#define SIZEOF_FINGER sizeof(struct tp_finger)
+#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER)
+
+#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
+#error "WSP_BUFFER_MAX is too small"
+#endif
+
+enum {
+ WSP_FLAG_WELLSPRING1,
+ WSP_FLAG_WELLSPRING2,
+ WSP_FLAG_WELLSPRING3,
+ WSP_FLAG_WELLSPRING4,
+ WSP_FLAG_WELLSPRING4A,
+ WSP_FLAG_WELLSPRING5,
+ WSP_FLAG_WELLSPRING6A,
+ WSP_FLAG_WELLSPRING6,
+ WSP_FLAG_WELLSPRING5A,
+ WSP_FLAG_WELLSPRING7,
+ WSP_FLAG_WELLSPRING7A,
+ WSP_FLAG_WELLSPRING8,
+ WSP_FLAG_WELLSPRING9,
+ WSP_FLAG_MAX,
+};
+
+/* device-specific configuration */
+struct wsp_dev_params {
+ uint8_t caps; /* device capability bitmask */
+ uint8_t tp_type; /* type of trackpad interface */
+ uint8_t tp_button; /* offset to button data */
+ uint8_t tp_offset; /* offset to trackpad finger data */
+ uint8_t tp_fsize; /* bytes in single finger block */
+ uint8_t tp_delta; /* offset from header to finger struct */
+ uint8_t iface_index;
+ uint8_t um_size; /* usb control message length */
+ uint8_t um_req_val; /* usb control message value */
+ uint8_t um_req_idx; /* usb control message index */
+ uint8_t um_switch_idx; /* usb control message mode switch index */
+ uint8_t um_switch_on; /* usb control message mode switch on */
+ uint8_t um_switch_off; /* usb control message mode switch off */
+};
+
+static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
+ [WSP_FLAG_WELLSPRING1] = {
+ .caps = 0,
+ .tp_type = TYPE1,
+ .tp_button = 0,
+ .tp_offset = FINGER_TYPE1,
+ .tp_fsize = FSIZE_TYPE1,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING2] = {
+ .caps = 0,
+ .tp_type = TYPE1,
+ .tp_button = 0,
+ .tp_offset = FINGER_TYPE1,
+ .tp_fsize = FSIZE_TYPE1,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING3] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING4] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING4A] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING5] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING6] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING5A] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING6A] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING7] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING7A] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE2,
+ .tp_button = BUTTON_TYPE2,
+ .tp_offset = FINGER_TYPE2,
+ .tp_fsize = FSIZE_TYPE2,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING8] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE3,
+ .tp_button = BUTTON_TYPE3,
+ .tp_offset = FINGER_TYPE3,
+ .tp_fsize = FSIZE_TYPE3,
+ .tp_delta = 0,
+ .iface_index = 0,
+ .um_size = 8,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x00,
+ .um_switch_idx = 0,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x08,
+ },
+ [WSP_FLAG_WELLSPRING9] = {
+ .caps = HAS_INTEGRATED_BUTTON,
+ .tp_type = TYPE4,
+ .tp_button = BUTTON_TYPE4,
+ .tp_offset = FINGER_TYPE4,
+ .tp_fsize = FSIZE_TYPE4,
+ .tp_delta = 2,
+ .iface_index = 2,
+ .um_size = 2,
+ .um_req_val = 0x03,
+ .um_req_idx = 0x02,
+ .um_switch_idx = 1,
+ .um_switch_on = 0x01,
+ .um_switch_off = 0x00,
+ },
+};
+
+#define WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+
+static const STRUCT_USB_HOST_ID wsp_devs[] = {
+ /* MacbookAir1.1 */
+ WSP_DEV(APPLE, WELLSPRING_ANSI, WSP_FLAG_WELLSPRING1),
+ WSP_DEV(APPLE, WELLSPRING_ISO, WSP_FLAG_WELLSPRING1),
+ WSP_DEV(APPLE, WELLSPRING_JIS, WSP_FLAG_WELLSPRING1),
+
+ /* MacbookProPenryn, aka wellspring2 */
+ WSP_DEV(APPLE, WELLSPRING2_ANSI, WSP_FLAG_WELLSPRING2),
+ WSP_DEV(APPLE, WELLSPRING2_ISO, WSP_FLAG_WELLSPRING2),
+ WSP_DEV(APPLE, WELLSPRING2_JIS, WSP_FLAG_WELLSPRING2),
+
+ /* Macbook5,1 (unibody), aka wellspring3 */
+ WSP_DEV(APPLE, WELLSPRING3_ANSI, WSP_FLAG_WELLSPRING3),
+ WSP_DEV(APPLE, WELLSPRING3_ISO, WSP_FLAG_WELLSPRING3),
+ WSP_DEV(APPLE, WELLSPRING3_JIS, WSP_FLAG_WELLSPRING3),
+
+ /* MacbookAir3,2 (unibody), aka wellspring4 */
+ WSP_DEV(APPLE, WELLSPRING4_ANSI, WSP_FLAG_WELLSPRING4),
+ WSP_DEV(APPLE, WELLSPRING4_ISO, WSP_FLAG_WELLSPRING4),
+ WSP_DEV(APPLE, WELLSPRING4_JIS, WSP_FLAG_WELLSPRING4),
+
+ /* MacbookAir3,1 (unibody), aka wellspring4 */
+ WSP_DEV(APPLE, WELLSPRING4A_ANSI, WSP_FLAG_WELLSPRING4A),
+ WSP_DEV(APPLE, WELLSPRING4A_ISO, WSP_FLAG_WELLSPRING4A),
+ WSP_DEV(APPLE, WELLSPRING4A_JIS, WSP_FLAG_WELLSPRING4A),
+
+ /* Macbook8 (unibody, March 2011) */
+ WSP_DEV(APPLE, WELLSPRING5_ANSI, WSP_FLAG_WELLSPRING5),
+ WSP_DEV(APPLE, WELLSPRING5_ISO, WSP_FLAG_WELLSPRING5),
+ WSP_DEV(APPLE, WELLSPRING5_JIS, WSP_FLAG_WELLSPRING5),
+
+ /* MacbookAir4,1 (unibody, July 2011) */
+ WSP_DEV(APPLE, WELLSPRING6A_ANSI, WSP_FLAG_WELLSPRING6A),
+ WSP_DEV(APPLE, WELLSPRING6A_ISO, WSP_FLAG_WELLSPRING6A),
+ WSP_DEV(APPLE, WELLSPRING6A_JIS, WSP_FLAG_WELLSPRING6A),
+
+ /* MacbookAir4,2 (unibody, July 2011) */
+ WSP_DEV(APPLE, WELLSPRING6_ANSI, WSP_FLAG_WELLSPRING6),
+ WSP_DEV(APPLE, WELLSPRING6_ISO, WSP_FLAG_WELLSPRING6),
+ WSP_DEV(APPLE, WELLSPRING6_JIS, WSP_FLAG_WELLSPRING6),
+
+ /* Macbook8,2 (unibody) */
+ WSP_DEV(APPLE, WELLSPRING5A_ANSI, WSP_FLAG_WELLSPRING5A),
+ WSP_DEV(APPLE, WELLSPRING5A_ISO, WSP_FLAG_WELLSPRING5A),
+ WSP_DEV(APPLE, WELLSPRING5A_JIS, WSP_FLAG_WELLSPRING5A),
+
+ /* MacbookPro10,1 (unibody, June 2012) */
+ /* MacbookPro11,1-3 (unibody, June 2013) */
+ WSP_DEV(APPLE, WELLSPRING7_ANSI, WSP_FLAG_WELLSPRING7),
+ WSP_DEV(APPLE, WELLSPRING7_ISO, WSP_FLAG_WELLSPRING7),
+ WSP_DEV(APPLE, WELLSPRING7_JIS, WSP_FLAG_WELLSPRING7),
+
+ /* MacbookPro10,2 (unibody, October 2012) */
+ WSP_DEV(APPLE, WELLSPRING7A_ANSI, WSP_FLAG_WELLSPRING7A),
+ WSP_DEV(APPLE, WELLSPRING7A_ISO, WSP_FLAG_WELLSPRING7A),
+ WSP_DEV(APPLE, WELLSPRING7A_JIS, WSP_FLAG_WELLSPRING7A),
+
+ /* MacbookAir6,2 (unibody, June 2013) */
+ WSP_DEV(APPLE, WELLSPRING8_ANSI, WSP_FLAG_WELLSPRING8),
+ WSP_DEV(APPLE, WELLSPRING8_ISO, WSP_FLAG_WELLSPRING8),
+ WSP_DEV(APPLE, WELLSPRING8_JIS, WSP_FLAG_WELLSPRING8),
+
+ /* MacbookPro12,1 MacbookPro11,4 */
+ WSP_DEV(APPLE, WELLSPRING9_ANSI, WSP_FLAG_WELLSPRING9),
+ WSP_DEV(APPLE, WELLSPRING9_ISO, WSP_FLAG_WELLSPRING9),
+ WSP_DEV(APPLE, WELLSPRING9_JIS, WSP_FLAG_WELLSPRING9),
+};
+
+#define WSP_FIFO_BUF_SIZE 8 /* bytes */
+#define WSP_FIFO_QUEUE_MAXLEN 50 /* units */
+
+enum {
+ WSP_INTR_DT,
+ WSP_N_TRANSFER,
+};
+
+struct wsp_softc {
+ struct usb_device *sc_usb_device;
+ struct mtx sc_mutex; /* for synchronization */
+ struct usb_xfer *sc_xfer[WSP_N_TRANSFER];
+ struct usb_fifo_sc sc_fifo;
+
+ const struct wsp_dev_params *sc_params; /* device configuration */
+
+ mousehw_t sc_hw;
+ mousemode_t sc_mode;
+ u_int sc_pollrate;
+ mousestatus_t sc_status;
+ u_int sc_state;
+#define WSP_ENABLED 0x01
+
+ struct tp_finger *index[MAX_FINGERS]; /* finger index data */
+ int16_t pos_x[MAX_FINGERS]; /* position array */
+ int16_t pos_y[MAX_FINGERS]; /* position array */
+ u_int sc_touch; /* touch status */
+#define WSP_UNTOUCH 0x00
+#define WSP_FIRST_TOUCH 0x01
+#define WSP_SECOND_TOUCH 0x02
+#define WSP_TOUCHING 0x04
+ int16_t pre_pos_x; /* previous position array */
+ int16_t pre_pos_y; /* previous position array */
+ int dx_sum; /* x axis cumulative movement */
+ int dy_sum; /* y axis cumulative movement */
+ int dz_sum; /* z axis cumulative movement */
+ int dz_count;
+#define WSP_DZ_MAX_COUNT 32
+ int dt_sum; /* T-axis cumulative movement */
+ int rdx; /* x axis remainder of divide by scale_factor */
+ int rdy; /* y axis remainder of divide by scale_factor */
+ int rdz; /* z axis remainder of divide by scale_factor */
+ int tp_datalen;
+ uint8_t o_ntouch; /* old touch finger status */
+ uint8_t finger; /* 0 or 1 *, check which finger moving */
+ uint16_t intr_count;
+#define WSP_TAP_THRESHOLD 3
+#define WSP_TAP_MAX_COUNT 20
+ int distance; /* the distance of 2 fingers */
+#define MAX_DISTANCE 2500 /* the max allowed distance */
+ uint8_t ibtn; /* button status in tapping */
+ uint8_t ntaps; /* finger status in tapping */
+ uint8_t scr_mode; /* scroll status in movement */
+#define WSP_SCR_NONE 0
+#define WSP_SCR_VER 1
+#define WSP_SCR_HOR 2
+ uint8_t tp_data[WSP_BUFFER_MAX] __aligned(4); /* trackpad transferred data */
+};
+
+/*
+ * function prototypes
+ */
+static usb_fifo_cmd_t wsp_start_read;
+static usb_fifo_cmd_t wsp_stop_read;
+static usb_fifo_open_t wsp_open;
+static usb_fifo_close_t wsp_close;
+static usb_fifo_ioctl_t wsp_ioctl;
+
+static struct usb_fifo_methods wsp_fifo_methods = {
+ .f_open = &wsp_open,
+ .f_close = &wsp_close,
+ .f_ioctl = &wsp_ioctl,
+ .f_start_read = &wsp_start_read,
+ .f_stop_read = &wsp_stop_read,
+ .basename[0] = WSP_DRIVER_NAME,
+};
+
+/* device initialization and shutdown */
+static int wsp_enable(struct wsp_softc *sc);
+static void wsp_disable(struct wsp_softc *sc);
+
+/* updating fifo */
+static void wsp_reset_buf(struct wsp_softc *sc);
+static void wsp_add_to_queue(struct wsp_softc *, int, int, int, uint32_t);
+
+/* Device methods. */
+static device_probe_t wsp_probe;
+static device_attach_t wsp_attach;
+static device_detach_t wsp_detach;
+static usb_callback_t wsp_intr_callback;
+
+static const struct usb_config wsp_config[WSP_N_TRANSFER] = {
+ [WSP_INTR_DT] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .flags = {
+ .pipe_bof = 0,
+ .short_xfer_ok = 1,
+ },
+ .bufsize = WSP_BUFFER_MAX,
+ .callback = &wsp_intr_callback,
+ },
+};
+
+static usb_error_t
+wsp_set_device_mode(struct wsp_softc *sc, uint8_t on)
+{
+ const struct wsp_dev_params *params = sc->sc_params;
+ uint8_t mode_bytes[8];
+ usb_error_t err;
+
+ /* Type 3 does not require a mode switch */
+ if (params->tp_type == TYPE3)
+ return 0;
+
+ err = usbd_req_get_report(sc->sc_usb_device, NULL,
+ mode_bytes, params->um_size, params->iface_index,
+ params->um_req_val, params->um_req_idx);
+
+ if (err != USB_ERR_NORMAL_COMPLETION) {
+ DPRINTF("Failed to read device mode (%d)\n", err);
+ return (err);
+ }
+
+ /*
+ * XXX Need to wait at least 250ms for hardware to get
+ * ready. The device mode handling appears to be handled
+ * asynchronously and we should not issue these commands too
+ * quickly.
+ */
+ pause("WHW", hz / 4);
+
+ mode_bytes[params->um_switch_idx] =
+ on ? params->um_switch_on : params->um_switch_off;
+
+ return (usbd_req_set_report(sc->sc_usb_device, NULL,
+ mode_bytes, params->um_size, params->iface_index,
+ params->um_req_val, params->um_req_idx));
+}
+
+static int
+wsp_enable(struct wsp_softc *sc)
+{
+ /* reset status */
+ memset(&sc->sc_status, 0, sizeof(sc->sc_status));
+ sc->sc_state |= WSP_ENABLED;
+
+ DPRINTFN(WSP_LLEVEL_INFO, "enabled wsp\n");
+ return (0);
+}
+
+static void
+wsp_disable(struct wsp_softc *sc)
+{
+ sc->sc_state &= ~WSP_ENABLED;
+ DPRINTFN(WSP_LLEVEL_INFO, "disabled wsp\n");
+}
+
+static int
+wsp_probe(device_t self)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(self);
+ struct usb_interface_descriptor *id;
+ struct usb_interface *iface;
+ uint8_t i;
+
+ if (uaa->usb_mode != USB_MODE_HOST)
+ return (ENXIO);
+
+ /* figure out first interface matching */
+ for (i = 1;; i++) {
+ iface = usbd_get_iface(uaa->device, i);
+ if (iface == NULL || i == 3)
+ return (ENXIO);
+ id = iface->idesc;
+ if ((id == NULL) ||
+ (id->bInterfaceClass != UICLASS_HID) ||
+ (id->bInterfaceProtocol != 0 &&
+ id->bInterfaceProtocol != UIPROTO_MOUSE))
+ continue;
+ break;
+ }
+ /* check if we are attaching to the first match */
+ if (uaa->info.bIfaceIndex != i)
+ return (ENXIO);
+ return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
+}
+
+static int
+wsp_attach(device_t dev)
+{
+ struct wsp_softc *sc = device_get_softc(dev);
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ usb_error_t err;
+ void *d_ptr = NULL;
+ uint16_t d_len;
+
+ DPRINTFN(WSP_LLEVEL_INFO, "sc=%p\n", sc);
+
+ /* Get HID descriptor */
+ err = usbd_req_get_hid_desc(uaa->device, NULL, &d_ptr,
+ &d_len, M_TEMP, uaa->info.bIfaceIndex);
+
+ if (err == USB_ERR_NORMAL_COMPLETION) {
+ /* Get HID report descriptor length */
+ sc->tp_datalen = hid_report_size(d_ptr, d_len, hid_input, NULL);
+ free(d_ptr, M_TEMP);
+
+ if (sc->tp_datalen <= 0 || sc->tp_datalen > WSP_BUFFER_MAX) {
+ DPRINTF("Invalid datalength or too big "
+ "datalength: %d\n", sc->tp_datalen);
+ return (ENXIO);
+ }
+ } else {
+ return (ENXIO);
+ }
+
+ sc->sc_usb_device = uaa->device;
+
+ /* get device specific configuration */
+ sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
+
+ /*
+ * By default the touchpad behaves like a HID device, sending
+ * packets with reportID = 8. Such reports contain only
+ * limited information. They encode movement deltas and button
+ * events, but do not include data from the pressure
+ * sensors. The device input mode can be switched from HID
+ * reports to raw sensor data using vendor-specific USB
+ * control commands:
+ */
+
+ /*
+ * During re-enumeration of the device we need to force the
+ * device back into HID mode before switching it to RAW
+ * mode. Else the device does not work like expected.
+ */
+ err = wsp_set_device_mode(sc, 0);
+ if (err != USB_ERR_NORMAL_COMPLETION) {
+ DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
+ return (ENXIO);
+ }
+
+ err = wsp_set_device_mode(sc, 1);
+ if (err != USB_ERR_NORMAL_COMPLETION) {
+ DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mutex, "wspmtx", NULL, MTX_DEF | MTX_RECURSE);
+
+ err = usbd_transfer_setup(uaa->device,
+ &uaa->info.bIfaceIndex, sc->sc_xfer, wsp_config,
+ WSP_N_TRANSFER, sc, &sc->sc_mutex);
+ if (err) {
+ DPRINTF("error=%s\n", usbd_errstr(err));
+ goto detach;
+ }
+ if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex,
+ &wsp_fifo_methods, &sc->sc_fifo,
+ device_get_unit(dev), -1, uaa->info.bIfaceIndex,
+ UID_ROOT, GID_OPERATOR, 0644)) {
+ goto detach;
+ }
+ device_set_usb_desc(dev);
+
+ sc->sc_hw.buttons = 3;
+ sc->sc_hw.iftype = MOUSE_IF_USB;
+ sc->sc_hw.type = MOUSE_PAD;
+ sc->sc_hw.model = MOUSE_MODEL_GENERIC;
+ sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+ sc->sc_mode.rate = -1;
+ sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
+ sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+
+ sc->sc_touch = WSP_UNTOUCH;
+ sc->scr_mode = WSP_SCR_NONE;
+
+ return (0);
+
+detach:
+ wsp_detach(dev);
+ return (ENOMEM);
+}
+
+static int
+wsp_detach(device_t dev)
+{
+ struct wsp_softc *sc = device_get_softc(dev);
+
+ (void) wsp_set_device_mode(sc, 0);
+
+ mtx_lock(&sc->sc_mutex);
+ if (sc->sc_state & WSP_ENABLED)
+ wsp_disable(sc);
+ mtx_unlock(&sc->sc_mutex);
+
+ usb_fifo_detach(&sc->sc_fifo);
+
+ usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
+
+ mtx_destroy(&sc->sc_mutex);
+
+ return (0);
+}
+
+static void
+wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct wsp_softc *sc = usbd_xfer_softc(xfer);
+ const struct wsp_dev_params *params = sc->sc_params;
+ struct usb_page_cache *pc;
+ struct tp_finger *f;
+ struct tp_header *h;
+ struct wsp_tuning tun = wsp_tuning;
+ int ntouch = 0; /* the finger number in touch */
+ int ibt = 0; /* button status */
+ int dx = 0;
+ int dy = 0;
+ int dz = 0;
+ int rdx = 0;
+ int rdy = 0;
+ int rdz = 0;
+ int len;
+ int i;
+
+ wsp_runing_rangecheck(&tun);
+
+ if (sc->dz_count == 0)
+ sc->dz_count = WSP_DZ_MAX_COUNT;
+
+ usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+
+ /* copy out received data */
+ pc = usbd_xfer_get_frame(xfer, 0);
+ usbd_copy_out(pc, 0, sc->tp_data, len);
+
+ if ((len < params->tp_offset + params->tp_fsize) ||
+ ((len - params->tp_offset) % params->tp_fsize) != 0) {
+ DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
+ len, sc->tp_data[0], sc->tp_data[1]);
+ goto tr_setup;
+ }
+
+ if (len < sc->tp_datalen) {
+ /* make sure we don't process old data */
+ memset(sc->tp_data + len, 0, sc->tp_datalen - len);
+ }
+
+ h = (struct tp_header *)(sc->tp_data);
+
+ if (params->tp_type >= TYPE2) {
+ ibt = sc->tp_data[params->tp_button];
+ ntouch = sc->tp_data[params->tp_button - 1];
+ }
+ /* range check */
+ if (ntouch < 0)
+ ntouch = 0;
+ else if (ntouch > MAX_FINGERS)
+ ntouch = MAX_FINGERS;
+
+ for (i = 0; i != ntouch; i++) {
+ f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
+ /* swap endianness, if any */
+ if (le16toh(0x1234) != 0x1234) {
+ f->origin = le16toh((uint16_t)f->origin);
+ f->abs_x = le16toh((uint16_t)f->abs_x);
+ f->abs_y = le16toh((uint16_t)f->abs_y);
+ f->rel_x = le16toh((uint16_t)f->rel_x);
+ f->rel_y = le16toh((uint16_t)f->rel_y);
+ f->tool_major = le16toh((uint16_t)f->tool_major);
+ f->tool_minor = le16toh((uint16_t)f->tool_minor);
+ f->orientation = le16toh((uint16_t)f->orientation);
+ f->touch_major = le16toh((uint16_t)f->touch_major);
+ f->touch_minor = le16toh((uint16_t)f->touch_minor);
+ f->pressure = le16toh((uint16_t)f->pressure);
+ f->multi = le16toh((uint16_t)f->multi);
+ }
+ DPRINTFN(WSP_LLEVEL_INFO,
+ "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
+ "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
+ "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
+ i, ibt, ntouch, f->origin, f->abs_x, f->abs_y,
+ f->rel_x, f->rel_y, f->tool_major, f->tool_minor, f->orientation,
+ f->touch_major, f->touch_minor, f->pressure, f->multi);
+ sc->pos_x[i] = f->abs_x;
+ sc->pos_y[i] = -f->abs_y;
+ sc->index[i] = f;
+ }
+
+ sc->sc_status.flags &= ~MOUSE_POSCHANGED;
+ sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
+ sc->sc_status.obutton = sc->sc_status.button;
+ sc->sc_status.button = 0;
+
+ if (ibt != 0) {
+ sc->sc_status.button |= MOUSE_BUTTON1DOWN;
+ sc->ibtn = 1;
+ }
+ sc->intr_count++;
+
+ if (sc->ntaps < ntouch) {
+ switch (ntouch) {
+ case 1:
+ if (sc->index[0]->touch_major > tun.pressure_tap_threshold &&
+ sc->index[0]->tool_major <= 1200)
+ sc->ntaps = 1;
+ break;
+ case 2:
+ if (sc->index[0]->touch_major > tun.pressure_tap_threshold-30 &&
+ sc->index[1]->touch_major > tun.pressure_tap_threshold-30)
+ sc->ntaps = 2;
+ break;
+ case 3:
+ if (sc->index[0]->touch_major > tun.pressure_tap_threshold-40 &&
+ sc->index[1]->touch_major > tun.pressure_tap_threshold-40 &&
+ sc->index[2]->touch_major > tun.pressure_tap_threshold-40)
+ sc->ntaps = 3;
+ break;
+ default:
+ break;
+ }
+ }
+ if (ntouch == 2) {
+ sc->distance = max(sc->distance, max(
+ abs(sc->pos_x[0] - sc->pos_x[1]),
+ abs(sc->pos_y[0] - sc->pos_y[1])));
+ }
+ if (sc->index[0]->touch_major < tun.pressure_untouch_threshold &&
+ sc->sc_status.button == 0) {
+ sc->sc_touch = WSP_UNTOUCH;
+ if (sc->intr_count < WSP_TAP_MAX_COUNT &&
+ sc->intr_count > WSP_TAP_THRESHOLD &&
+ sc->ntaps && sc->ibtn == 0) {
+ /*
+ * Add a pair of events (button-down and
+ * button-up).
+ */
+ switch (sc->ntaps) {
+ case 1:
+ if (!(params->caps & HAS_INTEGRATED_BUTTON)) {
+ wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
+ DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
+ }
+ break;
+ case 2:
+ DPRINTFN(WSP_LLEVEL_INFO, "sum_x=%5d, sum_y=%5d\n",
+ sc->dx_sum, sc->dy_sum);
+ if (sc->distance < MAX_DISTANCE && abs(sc->dx_sum) < 5 &&
+ abs(sc->dy_sum) < 5) {
+ wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON3DOWN);
+ DPRINTFN(WSP_LLEVEL_INFO, "RIGHT CLICK!\n");
+ }
+ break;
+ case 3:
+ wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON2DOWN);
+ break;
+ default:
+ /* we don't handle taps of more than three fingers */
+ break;
+ }
+ wsp_add_to_queue(sc, 0, 0, 0, 0); /* button release */
+ }
+ if ((sc->dt_sum / tun.scr_hor_threshold) != 0 &&
+ sc->ntaps == 2 && sc->scr_mode == WSP_SCR_HOR) {
+
+ /*
+ * translate T-axis into button presses
+ * until further
+ */
+ if (sc->dt_sum > 0)
+ wsp_add_to_queue(sc, 0, 0, 0, 1UL << 3);
+ else if (sc->dt_sum < 0)
+ wsp_add_to_queue(sc, 0, 0, 0, 1UL << 4);
+ }
+ sc->dz_count = WSP_DZ_MAX_COUNT;
+ sc->dz_sum = 0;
+ sc->intr_count = 0;
+ sc->ibtn = 0;
+ sc->ntaps = 0;
+ sc->finger = 0;
+ sc->distance = 0;
+ sc->dt_sum = 0;
+ sc->dx_sum = 0;
+ sc->dy_sum = 0;
+ sc->rdx = 0;
+ sc->rdy = 0;
+ sc->rdz = 0;
+ sc->scr_mode = WSP_SCR_NONE;
+ } else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
+ sc->sc_touch == WSP_UNTOUCH) { /* ignore first touch */
+ sc->sc_touch = WSP_FIRST_TOUCH;
+ } else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
+ sc->sc_touch == WSP_FIRST_TOUCH) { /* ignore second touch */
+ sc->sc_touch = WSP_SECOND_TOUCH;
+ DPRINTFN(WSP_LLEVEL_INFO, "Fist pre_x=%5d, pre_y=%5d\n",
+ sc->pre_pos_x, sc->pre_pos_y);
+ } else {
+ if (sc->sc_touch == WSP_SECOND_TOUCH)
+ sc->sc_touch = WSP_TOUCHING;
+
+ if (ntouch != 0 &&
+ sc->index[0]->touch_major >= tun.pressure_touch_threshold) {
+ dx = sc->pos_x[0] - sc->pre_pos_x;
+ dy = sc->pos_y[0] - sc->pre_pos_y;
+
+ /* Ignore movement during button is releasing */
+ if (sc->ibtn != 0 && sc->sc_status.button == 0)
+ dx = dy = 0;
+
+ /* Ignore movement if ntouch changed */
+ if (sc->o_ntouch != ntouch)
+ dx = dy = 0;
+
+ /* Ignore unexpeted movment when typing */
+ if (ntouch == 1 && sc->index[0]->tool_major > 1200)
+ dx = dy = 0;
+
+ if (sc->ibtn != 0 && ntouch == 1 &&
+ sc->intr_count < WSP_TAP_MAX_COUNT &&
+ abs(sc->dx_sum) < 1 && abs(sc->dy_sum) < 1 )
+ dx = dy = 0;
+
+ if (ntouch == 2 && sc->sc_status.button != 0) {
+ dx = sc->pos_x[sc->finger] - sc->pre_pos_x;
+ dy = sc->pos_y[sc->finger] - sc->pre_pos_y;
+
+ /*
+ * Ignore movement of switch finger or
+ * movement from ibt=0 to ibt=1
+ */
+ if (sc->index[0]->origin == 0 || sc->index[1]->origin == 0 ||
+ sc->sc_status.obutton != sc->sc_status.button) {
+ dx = dy = 0;
+ sc->finger = 0;
+ }
+ if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) <
+ (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
+ sc->finger == 0) {
+ sc->sc_touch = WSP_SECOND_TOUCH;
+ dx = dy = 0;
+ sc->finger = 1;
+ }
+ if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) >=
+ (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
+ sc->finger == 1) {
+ sc->sc_touch = WSP_SECOND_TOUCH;
+ dx = dy = 0;
+ sc->finger = 0;
+ }
+ DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, mov=%5d\n",
+ dx, dy, sc->finger);
+ }
+ if (sc->dz_count--) {
+ rdz = (dy + sc->rdz) % tun.scale_factor;
+ sc->dz_sum -= (dy + sc->rdz) / tun.scale_factor;
+ sc->rdz = rdz;
+ }
+ if ((sc->dz_sum / tun.z_factor) != 0)
+ sc->dz_count = 0;
+ }
+ rdx = (dx + sc->rdx) % tun.scale_factor;
+ dx = (dx + sc->rdx) / tun.scale_factor;
+ sc->rdx = rdx;
+
+ rdy = (dy + sc->rdy) % tun.scale_factor;
+ dy = (dy + sc->rdy) / tun.scale_factor;
+ sc->rdy = rdy;
+
+ sc->dx_sum += dx;
+ sc->dy_sum += dy;
+
+ if (ntouch == 2 && sc->sc_status.button == 0) {
+ if (sc->scr_mode == WSP_SCR_NONE &&
+ abs(sc->dx_sum) + abs(sc->dy_sum) > tun.scr_hor_threshold)
+ sc->scr_mode = abs(sc->dx_sum) >
+ abs(sc->dy_sum) * 2 ? WSP_SCR_HOR : WSP_SCR_VER;
+ DPRINTFN(WSP_LLEVEL_INFO, "scr_mode=%5d, count=%d, dx_sum=%d, dy_sum=%d\n",
+ sc->scr_mode, sc->intr_count, sc->dx_sum, sc->dy_sum);
+ if (sc->scr_mode == WSP_SCR_HOR)
+ sc->dt_sum += dx;
+ else
+ sc->dt_sum = 0;
+
+ dx = dy = 0;
+ if (sc->dz_count == 0)
+ dz = sc->dz_sum / tun.z_factor;
+ if (sc->scr_mode == WSP_SCR_HOR ||
+ abs(sc->pos_x[0] - sc->pos_x[1]) > MAX_DISTANCE ||
+ abs(sc->pos_y[0] - sc->pos_y[1]) > MAX_DISTANCE)
+ dz = 0;
+ }
+ if (ntouch == 3)
+ dx = dy = dz = 0;
+ if (sc->intr_count < WSP_TAP_MAX_COUNT &&
+ abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3)
+ dx = dy = dz = 0;
+ else
+ sc->intr_count = WSP_TAP_MAX_COUNT;
+ if (dx || dy || dz)
+ sc->sc_status.flags |= MOUSE_POSCHANGED;
+ DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, dz=%5d, sc_touch=%x, btn=%x\n",
+ dx, dy, dz, sc->sc_touch, sc->sc_status.button);
+ sc->sc_status.dx += dx;
+ sc->sc_status.dy += dy;
+ sc->sc_status.dz += dz;
+
+ wsp_add_to_queue(sc, dx, -dy, dz, sc->sc_status.button);
+ if (sc->dz_count == 0) {
+ sc->dz_sum = 0;
+ sc->rdz = 0;
+ }
+
+ }
+ sc->pre_pos_x = sc->pos_x[0];
+ sc->pre_pos_y = sc->pos_y[0];
+
+ if (ntouch == 2 && sc->sc_status.button != 0) {
+ sc->pre_pos_x = sc->pos_x[sc->finger];
+ sc->pre_pos_y = sc->pos_y[sc->finger];
+ }
+ sc->o_ntouch = ntouch;
+
+ case USB_ST_SETUP:
+tr_setup:
+ /* check if we can put more data into the FIFO */
+ if (usb_fifo_put_bytes_max(
+ sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
+ usbd_xfer_set_frame_len(xfer, 0,
+ sc->tp_datalen);
+ usbd_transfer_submit(xfer);
+ }
+ break;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* try clear stall first */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ break;
+ }
+}
+
+static void
+wsp_add_to_queue(struct wsp_softc *sc, int dx, int dy, int dz,
+ uint32_t buttons_in)
+{
+ uint32_t buttons_out;
+ uint8_t buf[8];
+
+ dx = imin(dx, 254);
+ dx = imax(dx, -256);
+ dy = imin(dy, 254);
+ dy = imax(dy, -256);
+ dz = imin(dz, 126);
+ dz = imax(dz, -128);
+
+ buttons_out = MOUSE_MSC_BUTTONS;
+ if (buttons_in & MOUSE_BUTTON1DOWN)
+ buttons_out &= ~MOUSE_MSC_BUTTON1UP;
+ else if (buttons_in & MOUSE_BUTTON2DOWN)
+ buttons_out &= ~MOUSE_MSC_BUTTON2UP;
+ else if (buttons_in & MOUSE_BUTTON3DOWN)
+ buttons_out &= ~MOUSE_MSC_BUTTON3UP;
+
+ /* Encode the mouse data in standard format; refer to mouse(4) */
+ buf[0] = sc->sc_mode.syncmask[1];
+ buf[0] |= buttons_out;
+ buf[1] = dx >> 1;
+ buf[2] = dy >> 1;
+ buf[3] = dx - (dx >> 1);
+ buf[4] = dy - (dy >> 1);
+ /* Encode extra bytes for level 1 */
+ if (sc->sc_mode.level == 1) {
+ buf[5] = dz >> 1; /* dz / 2 */
+ buf[6] = dz - (dz >> 1);/* dz - (dz / 2) */
+ buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS);
+ }
+ usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf,
+ sc->sc_mode.packetsize, 1);
+}
+
+static void
+wsp_reset_buf(struct wsp_softc *sc)
+{
+ /* reset read queue */
+ usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]);
+}
+
+static void
+wsp_start_read(struct usb_fifo *fifo)
+{
+ struct wsp_softc *sc = usb_fifo_softc(fifo);
+ int rate;
+
+ /* Check if we should override the default polling interval */
+ rate = sc->sc_pollrate;
+ /* Range check rate */
+ if (rate > 1000)
+ rate = 1000;
+ /* Check for set rate */
+ if ((rate > 0) && (sc->sc_xfer[WSP_INTR_DT] != NULL)) {
+ /* Stop current transfer, if any */
+ usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
+ /* Set new interval */
+ usbd_xfer_set_interval(sc->sc_xfer[WSP_INTR_DT], 1000 / rate);
+ /* Only set pollrate once */
+ sc->sc_pollrate = 0;
+ }
+ usbd_transfer_start(sc->sc_xfer[WSP_INTR_DT]);
+}
+
+static void
+wsp_stop_read(struct usb_fifo *fifo)
+{
+ struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+ usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
+}
+
+
+static int
+wsp_open(struct usb_fifo *fifo, int fflags)
+{
+ DPRINTFN(WSP_LLEVEL_INFO, "\n");
+
+ if (fflags & FREAD) {
+ struct wsp_softc *sc = usb_fifo_softc(fifo);
+ int rc;
+
+ if (sc->sc_state & WSP_ENABLED)
+ return (EBUSY);
+
+ if (usb_fifo_alloc_buffer(fifo,
+ WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
+ return (ENOMEM);
+ }
+ rc = wsp_enable(sc);
+ if (rc != 0) {
+ usb_fifo_free_buffer(fifo);
+ return (rc);
+ }
+ }
+ return (0);
+}
+
+static void
+wsp_close(struct usb_fifo *fifo, int fflags)
+{
+ if (fflags & FREAD) {
+ struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+ wsp_disable(sc);
+ usb_fifo_free_buffer(fifo);
+ }
+}
+
+int
+wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
+{
+ struct wsp_softc *sc = usb_fifo_softc(fifo);
+ mousemode_t mode;
+ int error = 0;
+
+ mtx_lock(&sc->sc_mutex);
+
+ switch (cmd) {
+ case MOUSE_GETHWINFO:
+ *(mousehw_t *)addr = sc->sc_hw;
+ break;
+ case MOUSE_GETMODE:
+ *(mousemode_t *)addr = sc->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)) {
+ error = EINVAL;
+ goto done;
+ }
+ sc->sc_mode.level = mode.level;
+ sc->sc_pollrate = mode.rate;
+ sc->sc_hw.buttons = 3;
+
+ if (sc->sc_mode.level == 0) {
+ sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+ sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+ } else if (sc->sc_mode.level == 1) {
+ sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
+ sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
+ }
+ wsp_reset_buf(sc);
+ break;
+ case MOUSE_GETLEVEL:
+ *(int *)addr = sc->sc_mode.level;
+ break;
+ case MOUSE_SETLEVEL:
+ if (*(int *)addr < 0 || *(int *)addr > 1) {
+ error = EINVAL;
+ goto done;
+ }
+ sc->sc_mode.level = *(int *)addr;
+ sc->sc_hw.buttons = 3;
+
+ if (sc->sc_mode.level == 0) {
+ sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+ sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+ } else if (sc->sc_mode.level == 1) {
+ sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
+ sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
+ sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
+ sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
+ }
+ wsp_reset_buf(sc);
+ break;
+ case MOUSE_GETSTATUS:{
+ mousestatus_t *status = (mousestatus_t *)addr;
+
+ *status = sc->sc_status;
+ sc->sc_status.obutton = sc->sc_status.button;
+ sc->sc_status.button = 0;
+ sc->sc_status.dx = 0;
+ sc->sc_status.dy = 0;
+ sc->sc_status.dz = 0;
+
+ if (status->dx || status->dy || status->dz)
+ status->flags |= MOUSE_POSCHANGED;
+ if (status->button != status->obutton)
+ status->flags |= MOUSE_BUTTONSCHANGED;
+ break;
+ }
+ default:
+ error = ENOTTY;
+ }
+
+done:
+ mtx_unlock(&sc->sc_mutex);
+ return (error);
+}
+
+static device_method_t wsp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, wsp_probe),
+ DEVMETHOD(device_attach, wsp_attach),
+ DEVMETHOD(device_detach, wsp_detach),
+ DEVMETHOD_END
+};
+
+static driver_t wsp_driver = {
+ .name = WSP_DRIVER_NAME,
+ .methods = wsp_methods,
+ .size = sizeof(struct wsp_softc)
+};
+
+static devclass_t wsp_devclass;
+
+DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
+MODULE_DEPEND(wsp, usb, 1, 1, 1);
+MODULE_VERSION(wsp, 1);
Property changes on: stable/0.8/sys/dev/usb/input/wsp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/misc/udbp.c
===================================================================
--- stable/0.8/sys/dev/usb/misc/udbp.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/udbp.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/misc/udbp.c 263166 2014-03-14 10:18:53Z hselasky $");
/* Driver for arbitrary double bulk pipe devices.
* The driver assumes that there will be the same driver on the other side.
@@ -290,6 +290,7 @@
static const STRUCT_USB_HOST_ID udbp_devs[] = {
{USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_TURBOCONNECT, 0)},
+ {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_GADGETZERO, 0)},
{USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301, 0)},
{USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302, 0)},
{USB_VPI(USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZLINK, 0)},
Modified: stable/0.8/sys/dev/usb/misc/udbp.h
===================================================================
--- stable/0.8/sys/dev/usb/misc/udbp.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/udbp.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
* This file was derived from src/sys/netgraph/ng_sample.h, revision 1.1
* written by Julian Elischer, Whistle Communications.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/misc/udbp.h 196219 2009-08-14 20:03:53Z jhb $
*/
#ifndef _NETGRAPH_UDBP_H_
Modified: stable/0.8/sys/dev/usb/misc/ufm.c
===================================================================
--- stable/0.8/sys/dev/usb/misc/ufm.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/ufm.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/misc/ufm.c 235000 2012-05-04 15:05:30Z hselasky $");
#include <sys/stdint.h>
Modified: stable/0.8/sys/dev/usb/net/if_aue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_aue.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_aue.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_aue.c 271356 2014-09-10 06:54:05Z hselasky $");
/*
* ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver.
@@ -208,9 +208,7 @@
static uint16_t aue_csr_read_2(struct aue_softc *, uint16_t);
static void aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
static void aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t);
-static void aue_eeprom_getword(struct aue_softc *, int, uint16_t *);
-static void aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t,
- uint16_t);
+static uint16_t aue_eeprom_getword(struct aue_softc *, int);
static void aue_reset(struct aue_softc *);
static void aue_reset_pegasus_II(struct aue_softc *);
@@ -372,11 +370,10 @@
/*
* Read a word of data stored in the EEPROM at address 'addr.'
*/
-static void
-aue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest)
+static uint16_t
+aue_eeprom_getword(struct aue_softc *sc, int addr)
{
int i;
- uint16_t word = 0;
aue_csr_write_1(sc, AUE_EE_REG, addr);
aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
@@ -391,22 +388,23 @@
if (i == AUE_TIMEOUT)
device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
- word = aue_csr_read_2(sc, AUE_EE_DATA);
- *dest = word;
+ return (aue_csr_read_2(sc, AUE_EE_DATA));
}
/*
- * Read a sequence of words from the EEPROM.
+ * Read station address(offset 0) from the EEPROM.
*/
static void
-aue_read_eeprom(struct aue_softc *sc, uint8_t *dest,
- uint16_t off, uint16_t len)
+aue_read_mac(struct aue_softc *sc, uint8_t *eaddr)
{
- uint16_t *ptr = (uint16_t *)dest;
- int i;
+ int i, offset;
+ uint16_t word;
- for (i = 0; i != len; i++, ptr++)
- aue_eeprom_getword(sc, off + i, ptr);
+ for (i = 0, offset = 0; i < ETHER_ADDR_LEN / 2; i++) {
+ word = aue_eeprom_getword(sc, offset + i);
+ eaddr[i * 2] = (uint8_t)word;
+ eaddr[i * 2 + 1] = (uint8_t)(word >> 8);
+ }
}
static int
@@ -632,7 +630,7 @@
aue_reset(sc);
/* get station address from the EEPROM */
- aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
+ aue_read_mac(sc, ue->ue_eaddr);
}
/*
@@ -747,7 +745,7 @@
if (pkt.aue_txstat0)
ifp->if_oerrors++;
- if (pkt.aue_txstat0 & (AUE_TXSTAT0_LATECOLL &
+ if (pkt.aue_txstat0 & (AUE_TXSTAT0_LATECOLL |
AUE_TXSTAT0_EXCESSCOLL))
ifp->if_collisions++;
}
Modified: stable/0.8/sys/dev/usb/net/if_auereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_auereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_auereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_auereg.h 196219 2009-08-14 20:03:53Z jhb $
*/
/*
Modified: stable/0.8/sys/dev/usb/net/if_axe.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axe.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_axe.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_axe.c 263166 2014-03-14 10:18:53Z hselasky $");
/*
* ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
@@ -159,6 +159,7 @@
AXE_DEV(COREGA, FETHER_USB2_TX, 0),
AXE_DEV(DLINK, DUBE100, 0),
AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772),
+ AXE_DEV(DLINK, DUBE100C1, AXE_FLAG_772B),
AXE_DEV(GOODWAY, GWUSB2E, 0),
AXE_DEV(IODATA, ETGUS2, AXE_FLAG_178),
AXE_DEV(JVC, MP_PRX1, 0),
Modified: stable/0.8/sys/dev/usb/net/if_axereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_axereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_axereg.h 229106 2011-12-31 14:47:35Z hselasky $
*/
/*
Added: stable/0.8/sys/dev/usb/net/if_axge.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axge.c (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_axge.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1038 @@
+/*-
+ * Copyright (c) 2013-2014 Kevin Lo
+ * 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: stable/9/sys/dev/usb/net/if_axge.c 268736 2014-07-16 06:18:02Z hselasky $");
+
+/*
+ * ASIX Electronics AX88178A/AX88179 USB 2.0/3.0 gigabit ethernet driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR axge_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/net/usb_ethernet.h>
+#include <dev/usb/net/if_axgereg.h>
+
+/*
+ * Various supported device vendors/products.
+ */
+
+static const STRUCT_USB_HOST_ID axge_devs[] = {
+#define AXGE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+ AXGE_DEV(ASIX, AX88178A),
+ AXGE_DEV(ASIX, AX88179),
+ AXGE_DEV(DLINK, DUB1312),
+ AXGE_DEV(SITECOMEU, LN032),
+#undef AXGE_DEV
+};
+
+static const struct {
+ uint8_t ctrl;
+ uint8_t timer_l;
+ uint8_t timer_h;
+ uint8_t size;
+ uint8_t ifg;
+} __packed axge_bulk_size[] = {
+ { 7, 0x4f, 0x00, 0x12, 0xff },
+ { 7, 0x20, 0x03, 0x16, 0xff },
+ { 7, 0xae, 0x07, 0x18, 0xff },
+ { 7, 0xcc, 0x4c, 0x18, 0x08 }
+};
+
+/* prototypes */
+
+static device_probe_t axge_probe;
+static device_attach_t axge_attach;
+static device_detach_t axge_detach;
+
+static usb_callback_t axge_bulk_read_callback;
+static usb_callback_t axge_bulk_write_callback;
+
+static miibus_readreg_t axge_miibus_readreg;
+static miibus_writereg_t axge_miibus_writereg;
+static miibus_statchg_t axge_miibus_statchg;
+
+static uether_fn_t axge_attach_post;
+static uether_fn_t axge_init;
+static uether_fn_t axge_stop;
+static uether_fn_t axge_start;
+static uether_fn_t axge_tick;
+static uether_fn_t axge_setmulti;
+static uether_fn_t axge_setpromisc;
+
+static int axge_read_mem(struct axge_softc *, uint8_t, uint16_t,
+ uint16_t, void *, int);
+static void axge_write_mem(struct axge_softc *, uint8_t, uint16_t,
+ uint16_t, void *, int);
+static uint8_t axge_read_cmd_1(struct axge_softc *, uint8_t, uint16_t);
+static uint16_t axge_read_cmd_2(struct axge_softc *, uint8_t, uint16_t,
+ uint16_t);
+static void axge_write_cmd_1(struct axge_softc *, uint8_t, uint16_t,
+ uint8_t);
+static void axge_write_cmd_2(struct axge_softc *, uint8_t, uint16_t,
+ uint16_t, uint16_t);
+static void axge_chip_init(struct axge_softc *);
+static void axge_reset(struct axge_softc *);
+
+static int axge_attach_post_sub(struct usb_ether *);
+static int axge_ifmedia_upd(struct ifnet *);
+static void axge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int axge_ioctl(struct ifnet *, u_long, caddr_t);
+static void axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
+static void axge_rxeof(struct usb_ether *, struct usb_page_cache *,
+ unsigned int, unsigned int, uint32_t);
+static void axge_csum_cfg(struct usb_ether *);
+
+#define AXGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
+
+#ifdef USB_DEBUG
+static int axge_debug = 0;
+
+static SYSCTL_NODE(_hw_usb, OID_AUTO, axge, CTLFLAG_RW, 0, "USB axge");
+SYSCTL_INT(_hw_usb_axge, OID_AUTO, debug, CTLFLAG_RW, &axge_debug, 0,
+ "Debug level");
+#endif
+
+static const struct usb_config axge_config[AXGE_N_TRANSFER] = {
+ [AXGE_BULK_DT_WR] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_OUT,
+ .frames = 16,
+ .bufsize = 16 * MCLBYTES,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = axge_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
+ },
+ [AXGE_BULK_DT_RD] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .bufsize = 65536,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = axge_bulk_read_callback,
+ .timeout = 0, /* no timeout */
+ },
+};
+
+static device_method_t axge_methods[] = {
+ /* Device interface. */
+ DEVMETHOD(device_probe, axge_probe),
+ DEVMETHOD(device_attach, axge_attach),
+ DEVMETHOD(device_detach, axge_detach),
+
+ /* MII interface. */
+ DEVMETHOD(miibus_readreg, axge_miibus_readreg),
+ DEVMETHOD(miibus_writereg, axge_miibus_writereg),
+ DEVMETHOD(miibus_statchg, axge_miibus_statchg),
+
+ DEVMETHOD_END
+};
+
+static driver_t axge_driver = {
+ .name = "axge",
+ .methods = axge_methods,
+ .size = sizeof(struct axge_softc),
+};
+
+static devclass_t axge_devclass;
+
+DRIVER_MODULE(axge, uhub, axge_driver, axge_devclass, NULL, NULL);
+DRIVER_MODULE(miibus, axge, miibus_driver, miibus_devclass, NULL, NULL);
+MODULE_DEPEND(axge, uether, 1, 1, 1);
+MODULE_DEPEND(axge, usb, 1, 1, 1);
+MODULE_DEPEND(axge, ether, 1, 1, 1);
+MODULE_DEPEND(axge, miibus, 1, 1, 1);
+MODULE_VERSION(axge, 1);
+
+static const struct usb_ether_methods axge_ue_methods = {
+ .ue_attach_post = axge_attach_post,
+ .ue_attach_post_sub = axge_attach_post_sub,
+ .ue_start = axge_start,
+ .ue_init = axge_init,
+ .ue_stop = axge_stop,
+ .ue_tick = axge_tick,
+ .ue_setmulti = axge_setmulti,
+ .ue_setpromisc = axge_setpromisc,
+ .ue_mii_upd = axge_ifmedia_upd,
+ .ue_mii_sts = axge_ifmedia_sts,
+};
+
+static int
+axge_read_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+ uint16_t val, void *buf, int len)
+{
+ struct usb_device_request req;
+
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = cmd;
+ USETW(req.wValue, val);
+ USETW(req.wIndex, index);
+ USETW(req.wLength, len);
+
+ return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
+}
+
+static void
+axge_write_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+ uint16_t val, void *buf, int len)
+{
+ struct usb_device_request req;
+
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = cmd;
+ USETW(req.wValue, val);
+ USETW(req.wIndex, index);
+ USETW(req.wLength, len);
+
+ if (uether_do_request(&sc->sc_ue, &req, buf, 1000)) {
+ /* Error ignored. */
+ }
+}
+
+static uint8_t
+axge_read_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg)
+{
+ uint8_t val;
+
+ axge_read_mem(sc, cmd, 1, reg, &val, 1);
+ return (val);
+}
+
+static uint16_t
+axge_read_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+ uint16_t reg)
+{
+ uint8_t val[2];
+
+ axge_read_mem(sc, cmd, index, reg, &val, 2);
+ return (UGETW(val));
+}
+
+static void
+axge_write_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg, uint8_t val)
+{
+ axge_write_mem(sc, cmd, 1, reg, &val, 1);
+}
+
+static void
+axge_write_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+ uint16_t reg, uint16_t val)
+{
+ uint8_t temp[2];
+
+ USETW(temp, val);
+ axge_write_mem(sc, cmd, index, reg, &temp, 2);
+}
+
+static int
+axge_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct axge_softc *sc;
+ uint16_t val;
+ int locked;
+
+ sc = device_get_softc(dev);
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ AXGE_LOCK(sc);
+
+ val = axge_read_cmd_2(sc, AXGE_ACCESS_PHY, reg, phy);
+
+ if (!locked)
+ AXGE_UNLOCK(sc);
+
+ return (val);
+}
+
+static int
+axge_miibus_writereg(device_t dev, int phy, int reg, int val)
+{
+ struct axge_softc *sc;
+ int locked;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_phyno != phy)
+ return (0);
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ AXGE_LOCK(sc);
+
+ axge_write_cmd_2(sc, AXGE_ACCESS_PHY, reg, phy, val);
+
+ if (!locked)
+ AXGE_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+axge_miibus_statchg(device_t dev)
+{
+ struct axge_softc *sc;
+ struct mii_data *mii;
+ struct ifnet *ifp;
+ uint8_t link_status, tmp[5];
+ uint16_t val;
+ int locked;
+
+ sc = device_get_softc(dev);
+ mii = GET_MII(sc);
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ AXGE_LOCK(sc);
+
+ ifp = uether_getifp(&sc->sc_ue);
+ if (mii == NULL || ifp == NULL ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ goto done;
+
+ sc->sc_flags &= ~AXGE_FLAG_LINK;
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ case IFM_1000_T:
+ sc->sc_flags |= AXGE_FLAG_LINK;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Lost link, do nothing. */
+ if ((sc->sc_flags & AXGE_FLAG_LINK) == 0)
+ goto done;
+
+ link_status = axge_read_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PLSR);
+
+ val = 0;
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ val |= MSR_FD;
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+ val |= MSR_TFC;
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+ val |= MSR_RFC;
+ }
+ val |= MSR_RE;
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_1000_T:
+ val |= MSR_GM | MSR_EN_125MHZ;
+ if (link_status & PLSR_USB_SS)
+ memcpy(tmp, &axge_bulk_size[0], 5);
+ else if (link_status & PLSR_USB_HS)
+ memcpy(tmp, &axge_bulk_size[1], 5);
+ else
+ memcpy(tmp, &axge_bulk_size[3], 5);
+ break;
+ case IFM_100_TX:
+ val |= MSR_PS;
+ if (link_status & (PLSR_USB_SS | PLSR_USB_HS))
+ memcpy(tmp, &axge_bulk_size[2], 5);
+ else
+ memcpy(tmp, &axge_bulk_size[3], 5);
+ break;
+ case IFM_10_T:
+ memcpy(tmp, &axge_bulk_size[3], 5);
+ break;
+ }
+ /* Rx bulk configuration. */
+ axge_write_mem(sc, AXGE_ACCESS_MAC, 5, AXGE_RX_BULKIN_QCTRL, tmp, 5);
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_MSR, val);
+done:
+ if (!locked)
+ AXGE_UNLOCK(sc);
+}
+
+static void
+axge_chip_init(struct axge_softc *sc)
+{
+ /* Power up ethernet PHY. */
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, 0);
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, EPPRCR_IPRL);
+ uether_pause(&sc->sc_ue, hz / 4);
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CLK_SELECT,
+ AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS);
+ uether_pause(&sc->sc_ue, hz / 10);
+}
+
+static void
+axge_reset(struct axge_softc *sc)
+{
+ struct usb_config_descriptor *cd;
+ usb_error_t err;
+
+ cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev);
+
+ err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx,
+ cd->bConfigurationValue);
+ if (err)
+ DPRINTF("reset failed (ignored)\n");
+
+ /* Wait a little while for the chip to get its brains in order. */
+ uether_pause(&sc->sc_ue, hz / 100);
+
+ /* Reinitialize controller to achieve full reset. */
+ axge_chip_init(sc);
+}
+
+static void
+axge_attach_post(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+
+ sc = uether_getsc(ue);
+ sc->sc_phyno = 3;
+
+ /* Initialize controller and get station address. */
+ axge_chip_init(sc);
+ axge_read_mem(sc, AXGE_ACCESS_MAC, ETHER_ADDR_LEN, AXGE_NIDR,
+ ue->ue_eaddr, ETHER_ADDR_LEN);
+}
+
+static int
+axge_attach_post_sub(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ int error;
+
+ sc = uether_getsc(ue);
+ ifp = ue->ue_ifp;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = uether_start;
+ ifp->if_ioctl = axge_ioctl;
+ ifp->if_init = uether_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_TXCSUM | IFCAP_RXCSUM;
+ ifp->if_hwassist = AXGE_CSUM_FEATURES;
+ ifp->if_capenable = ifp->if_capabilities;
+
+ mtx_lock(&Giant);
+ error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
+ uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
+ BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, MIIF_DOPAUSE);
+ mtx_unlock(&Giant);
+
+ return (error);
+}
+
+/*
+ * Set media options.
+ */
+static int
+axge_ifmedia_upd(struct ifnet *ifp)
+{
+ struct axge_softc *sc;
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+ int error;
+
+ sc = ifp->if_softc;
+ mii = GET_MII(sc);
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ PHY_RESET(miisc);
+ error = mii_mediachg(mii);
+
+ return (error);
+}
+
+/*
+ * Report current media status.
+ */
+static void
+axge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct axge_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = GET_MII(sc);
+ AXGE_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ AXGE_UNLOCK(sc);
+}
+
+/*
+ * Probe for a AX88179 chip.
+ */
+static int
+axge_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa;
+
+ uaa = device_get_ivars(dev);
+ if (uaa->usb_mode != USB_MODE_HOST)
+ return (ENXIO);
+ if (uaa->info.bConfigIndex != AXGE_CONFIG_IDX)
+ return (ENXIO);
+ if (uaa->info.bIfaceIndex != AXGE_IFACE_IDX)
+ return (ENXIO);
+
+ return (usbd_lookup_id_by_uaa(axge_devs, sizeof(axge_devs), uaa));
+}
+
+/*
+ * Attach the interface. Allocate softc structures, do ifmedia
+ * setup and ethernet/BPF attach.
+ */
+static int
+axge_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa;
+ struct axge_softc *sc;
+ struct usb_ether *ue;
+ uint8_t iface_index;
+ int error;
+
+ uaa = device_get_ivars(dev);
+ sc = device_get_softc(dev);
+ ue = &sc->sc_ue;
+
+ device_set_usb_desc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ iface_index = AXGE_IFACE_IDX;
+ error = usbd_transfer_setup(uaa->device, &iface_index,
+ sc->sc_xfer, axge_config, AXGE_N_TRANSFER, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "allocating USB transfers failed\n");
+ goto detach;
+ }
+
+ ue->ue_sc = sc;
+ ue->ue_dev = dev;
+ ue->ue_udev = uaa->device;
+ ue->ue_mtx = &sc->sc_mtx;
+ ue->ue_methods = &axge_ue_methods;
+
+ error = uether_ifattach(ue);
+ if (error) {
+ device_printf(dev, "could not attach interface\n");
+ goto detach;
+ }
+ return (0); /* success */
+
+detach:
+ axge_detach(dev);
+ return (ENXIO); /* failure */
+}
+
+static int
+axge_detach(device_t dev)
+{
+ struct axge_softc *sc;
+ struct usb_ether *ue;
+
+ sc = device_get_softc(dev);
+ ue = &sc->sc_ue;
+ usbd_transfer_unsetup(sc->sc_xfer, AXGE_N_TRANSFER);
+ uether_ifdetach(ue);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+static void
+axge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct axge_softc *sc;
+ struct usb_ether *ue;
+ struct usb_page_cache *pc;
+ int actlen;
+
+ sc = usbd_xfer_softc(xfer);
+ ue = &sc->sc_ue;
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ pc = usbd_xfer_get_frame(xfer, 0);
+ axge_rx_frame(ue, pc, actlen);
+
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ uether_rxflush(ue);
+ break;
+
+ default:
+ if (error != USB_ERR_CANCELLED) {
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ break;
+ }
+}
+
+static void
+axge_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ struct usb_page_cache *pc;
+ struct mbuf *m;
+ uint32_t txhdr;
+ int nframes, pos;
+
+ sc = usbd_xfer_softc(xfer);
+ ifp = uether_getifp(&sc->sc_ue);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ if ((sc->sc_flags & AXGE_FLAG_LINK) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
+ /*
+ * Don't send anything if there is no link or
+ * controller is busy.
+ */
+ return;
+ }
+
+ for (nframes = 0; nframes < 16 &&
+ !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
+ nframes);
+ pos = 0;
+ pc = usbd_xfer_get_frame(xfer, nframes);
+ txhdr = htole32(m->m_pkthdr.len);
+ usbd_copy_in(pc, 0, &txhdr, sizeof(txhdr));
+ txhdr = 0;
+ txhdr = htole32(txhdr);
+ usbd_copy_in(pc, 4, &txhdr, sizeof(txhdr));
+ pos += 8;
+ usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
+ pos += m->m_pkthdr.len;
+ if ((pos % usbd_xfer_max_framelen(xfer)) == 0)
+ txhdr |= 0x80008000;
+
+ /*
+ * XXX
+ * Update TX packet counter here. This is not
+ * correct way but it seems that there is no way
+ * to know how many packets are sent at the end
+ * of transfer because controller combines
+ * multiple writes into single one if there is
+ * room in TX buffer of controller.
+ */
+ ifp->if_opackets++;
+
+ /*
+ * if there's a BPF listener, bounce a copy
+ * of this frame to him:
+ */
+ BPF_MTAP(ifp, m);
+
+ m_freem(m);
+
+ /* Set frame length. */
+ usbd_xfer_set_frame_len(xfer, nframes, pos);
+ }
+ if (nframes != 0) {
+ usbd_xfer_set_frames(xfer, nframes);
+ usbd_transfer_submit(xfer);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
+ return;
+ /* NOTREACHED */
+ default:
+ ifp->if_oerrors++;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ if (error != USB_ERR_CANCELLED) {
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+
+ }
+}
+
+static void
+axge_tick(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct mii_data *mii;
+
+ sc = uether_getsc(ue);
+ mii = GET_MII(sc);
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ mii_tick(mii);
+ if ((sc->sc_flags & AXGE_FLAG_LINK) == 0) {
+ axge_miibus_statchg(ue->ue_dev);
+ if ((sc->sc_flags & AXGE_FLAG_LINK) != 0)
+ axge_start(ue);
+ }
+}
+
+static void
+axge_setmulti(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ uint32_t h;
+ uint16_t rxmode;
+ uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ sc = uether_getsc(ue);
+ ifp = uether_getifp(ue);
+ h = 0;
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR);
+ if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+ rxmode |= RCR_AMALL;
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+ return;
+ }
+ rxmode &= ~RCR_AMALL;
+
+ if_maddr_rlock(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_maddr_runlock(ifp);
+
+ axge_write_mem(sc, AXGE_ACCESS_MAC, 8, AXGE_MFA, (void *)&hashtbl, 8);
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+}
+
+static void
+axge_setpromisc(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ uint16_t rxmode;
+
+ sc = uether_getsc(ue);
+ ifp = uether_getifp(ue);
+ rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR);
+
+ if (ifp->if_flags & IFF_PROMISC)
+ rxmode |= RCR_PRO;
+ else
+ rxmode &= ~RCR_PRO;
+
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+ axge_setmulti(ue);
+}
+
+static void
+axge_start(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+
+ sc = uether_getsc(ue);
+ /*
+ * Start the USB transfers, if not already started.
+ */
+ usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_RD]);
+ usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_WR]);
+}
+
+static void
+axge_init(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ uint16_t rxmode;
+
+ sc = uether_getsc(ue);
+ ifp = uether_getifp(ue);
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ /*
+ * Cancel pending I/O and free all RX/TX buffers.
+ */
+ axge_stop(ue);
+
+ axge_reset(sc);
+
+ /* Set MAC address. */
+ axge_write_mem(sc, AXGE_ACCESS_MAC, ETHER_ADDR_LEN, AXGE_NIDR,
+ IF_LLADDR(ifp), ETHER_ADDR_LEN);
+
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34);
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52);
+
+ /* Configure TX/RX checksum offloading. */
+ axge_csum_cfg(ue);
+
+ /* Configure RX settings. */
+ rxmode = (RCR_AM | RCR_SO | RCR_DROP_CRCE);
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
+ rxmode |= RCR_IPE;
+
+ /* If we want promiscuous mode, set the allframes bit. */
+ if (ifp->if_flags & IFF_PROMISC)
+ rxmode |= RCR_PRO;
+
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxmode |= RCR_AB;
+
+ axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_MMSR,
+ MMSR_PME_TYPE | MMSR_PME_POL | MMSR_RWMP);
+
+ /* Load the multicast filter. */
+ axge_setmulti(ue);
+
+ usbd_xfer_set_stall(sc->sc_xfer[AXGE_BULK_DT_WR]);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ /* Switch to selected media. */
+ axge_ifmedia_upd(ifp);
+}
+
+static void
+axge_stop(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+
+ sc = uether_getsc(ue);
+ ifp = uether_getifp(ue);
+
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~AXGE_FLAG_LINK;
+
+ /*
+ * Stop all the transfers, if not already stopped:
+ */
+ usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_WR]);
+ usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_RD]);
+}
+
+static int
+axge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct usb_ether *ue;
+ struct axge_softc *sc;
+ struct ifreq *ifr;
+ int error, mask, reinit;
+
+ ue = ifp->if_softc;
+ sc = uether_getsc(ue);
+ ifr = (struct ifreq *)data;
+ error = 0;
+ reinit = 0;
+ if (cmd == SIOCSIFCAP) {
+ AXGE_LOCK(sc);
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+ if ((mask & IFCAP_TXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+ ifp->if_hwassist |= AXGE_CSUM_FEATURES;
+ else
+ ifp->if_hwassist &= ~AXGE_CSUM_FEATURES;
+ reinit++;
+ }
+ if ((mask & IFCAP_RXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ reinit++;
+ }
+ if (reinit > 0 && ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ else
+ reinit = 0;
+ AXGE_UNLOCK(sc);
+ if (reinit > 0)
+ uether_init(ue);
+ } else
+ error = uether_ioctl(ifp, cmd, data);
+
+ return (error);
+}
+
+static void
+axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
+{
+ uint32_t pos;
+ uint32_t pkt_cnt;
+ uint32_t rxhdr;
+ uint32_t pkt_hdr;
+ uint32_t hdr_off;
+ uint32_t pktlen;
+
+ /* verify we have enough data */
+ if (actlen < (int)sizeof(rxhdr))
+ return;
+
+ pos = 0;
+
+ usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
+ rxhdr = le32toh(rxhdr);
+
+ pkt_cnt = (uint16_t)rxhdr;
+ hdr_off = (uint16_t)(rxhdr >> 16);
+
+ while (pkt_cnt--) {
+ /* verify the header offset */
+ if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
+ DPRINTF("End of packet headers\n");
+ break;
+ }
+ if ((int)pos >= actlen) {
+ DPRINTF("Data position reached end\n");
+ break;
+ }
+ usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
+
+ pkt_hdr = le32toh(pkt_hdr);
+ pktlen = (pkt_hdr >> 16) & 0x1fff;
+ if (pkt_hdr & (AXGE_RXHDR_CRC_ERR | AXGE_RXHDR_DROP_ERR)) {
+ DPRINTF("Dropped a packet\n");
+ ue->ue_ifp->if_ierrors++;
+ }
+ if (pktlen >= 6 && (int)(pos + pktlen) <= actlen) {
+ axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
+ } else {
+ DPRINTF("Invalid packet pos=%d len=%d\n",
+ (int)pos, (int)pktlen);
+ }
+ pos += (pktlen + 7) & ~7;
+ hdr_off += sizeof(pkt_hdr);
+ }
+}
+
+static void
+axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc,
+ unsigned int offset, unsigned int len, uint32_t pkt_hdr)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+
+ ifp = ue->ue_ifp;
+ if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
+ ifp->if_ierrors++;
+ return;
+ }
+
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL) {
+ ifp->if_iqdrops++;
+ return;
+ }
+ m->m_pkthdr.rcvif = ifp;
+ m->m_len = m->m_pkthdr.len = len + ETHER_ALIGN;
+ m_adj(m, ETHER_ALIGN);
+
+ usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
+
+ ifp->if_ipackets++;
+
+ if ((pkt_hdr & (AXGE_RXHDR_L4CSUM_ERR | AXGE_RXHDR_L3CSUM_ERR)) == 0) {
+ if ((pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
+ AXGE_RXHDR_L4_TYPE_TCP ||
+ (pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
+ AXGE_RXHDR_L4_TYPE_UDP) {
+ m->m_pkthdr.csum_flags |= CSUM_DATA_VALID |
+ CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | CSUM_IP_VALID;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+
+ _IF_ENQUEUE(&ue->ue_rxq, m);
+}
+
+static void
+axge_csum_cfg(struct usb_ether *ue)
+{
+ struct axge_softc *sc;
+ struct ifnet *ifp;
+ uint8_t csum;
+
+ sc = uether_getsc(ue);
+ AXGE_LOCK_ASSERT(sc, MA_OWNED);
+ ifp = uether_getifp(ue);
+
+ csum = 0;
+ if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+ csum |= CTCR_IP | CTCR_TCP | CTCR_UDP;
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CTCR, csum);
+
+ csum = 0;
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
+ csum |= CRCR_IP | CRCR_TCP | CRCR_UDP;
+ axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CRCR, csum);
+}
Property changes on: stable/0.8/sys/dev/usb/net/if_axge.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: stable/0.8/sys/dev/usb/net/if_axgereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axgereg.h (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_axgereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2013-2014 Kevin Lo
+ * 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 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: stable/9/sys/dev/usb/net/if_axgereg.h 268222 2014-07-03 16:34:01Z hselasky $
+ */
+
+#define AXGE_ACCESS_MAC 0x01
+#define AXGE_ACCESS_PHY 0x02
+#define AXGE_ACCESS_WAKEUP 0x03
+#define AXGE_ACCESS_EEPROM 0x04
+#define AXGE_ACCESS_EFUSE 0x05
+#define AXGE_RELOAD_EEPROM_EFUSE 0x06
+#define AXGE_WRITE_EFUSE_EN 0x09
+#define AXGE_WRITE_EFUSE_DIS 0x0A
+#define AXGE_ACCESS_MFAB 0x10
+
+/* Physical link status register */
+#define AXGE_PLSR 0x02
+#define PLSR_USB_FS 0x01
+#define PLSR_USB_HS 0x02
+#define PLSR_USB_SS 0x04
+
+/* EEPROM address register */
+#define AXGE_EAR 0x07
+
+/* EEPROM data low register */
+#define AXGE_EDLR 0x08
+
+/* EEPROM data high register */
+#define AXGE_EDHR 0x09
+
+/* EEPROM command register */
+#define AXGE_ECR 0x0a
+
+/* Rx control register */
+#define AXGE_RCR 0x0b
+#define RCR_STOP 0x0000
+#define RCR_PRO 0x0001
+#define RCR_AMALL 0x0002
+#define RCR_AB 0x0008
+#define RCR_AM 0x0010
+#define RCR_AP 0x0020
+#define RCR_SO 0x0080
+#define RCR_DROP_CRCE 0x0100
+#define RCR_IPE 0x0200
+#define RCR_TX_CRC_PAD 0x0400
+
+/* Node id register */
+#define AXGE_NIDR 0x10
+
+/* Multicast filter array */
+#define AXGE_MFA 0x16
+
+/* Medium status register */
+#define AXGE_MSR 0x22
+#define MSR_GM 0x0001
+#define MSR_FD 0x0002
+#define MSR_EN_125MHZ 0x0008
+#define MSR_RFC 0x0010
+#define MSR_TFC 0x0020
+#define MSR_RE 0x0100
+#define MSR_PS 0x0200
+
+/* Monitor mode status register */
+#define AXGE_MMSR 0x24
+#define MMSR_RWLC 0x02
+#define MMSR_RWMP 0x04
+#define MMSR_RWWF 0x08
+#define MMSR_RW_FLAG 0x10
+#define MMSR_PME_POL 0x20
+#define MMSR_PME_TYPE 0x40
+#define MMSR_PME_IND 0x80
+
+/* GPIO control/status register */
+#define AXGE_GPIOCR 0x25
+
+/* Ethernet PHY power & reset control register */
+#define AXGE_EPPRCR 0x26
+#define EPPRCR_BZ 0x0010
+#define EPPRCR_IPRL 0x0020
+#define EPPRCR_AUTODETACH 0x1000
+
+#define AXGE_RX_BULKIN_QCTRL 0x2e
+
+#define AXGE_CLK_SELECT 0x33
+#define AXGE_CLK_SELECT_BCS 0x01
+#define AXGE_CLK_SELECT_ACS 0x02
+#define AXGE_CLK_SELECT_ACSREQ 0x10
+#define AXGE_CLK_SELECT_ULR 0x08
+
+/* COE Rx control register */
+#define AXGE_CRCR 0x34
+#define CRCR_IP 0x01
+#define CRCR_TCP 0x02
+#define CRCR_UDP 0x04
+#define CRCR_ICMP 0x08
+#define CRCR_IGMP 0x10
+#define CRCR_TCPV6 0x20
+#define CRCR_UDPV6 0x40
+#define CRCR_ICMPV6 0x80
+
+/* COE Tx control register */
+#define AXGE_CTCR 0x35
+#define CTCR_IP 0x01
+#define CTCR_TCP 0x02
+#define CTCR_UDP 0x04
+#define CTCR_ICMP 0x08
+#define CTCR_IGMP 0x10
+#define CTCR_TCPV6 0x20
+#define CTCR_UDPV6 0x40
+#define CTCR_ICMPV6 0x80
+
+/* Pause water level high register */
+#define AXGE_PWLHR 0x54
+
+/* Pause water level low register */
+#define AXGE_PWLLR 0x55
+
+#define AXGE_CONFIG_IDX 0 /* config number 1 */
+#define AXGE_IFACE_IDX 0
+
+#define AXGE_RXHDR_L4_TYPE_MASK 0x1c
+#define AXGE_RXHDR_L4CSUM_ERR 1
+#define AXGE_RXHDR_L3CSUM_ERR 2
+#define AXGE_RXHDR_L4_TYPE_UDP 4
+#define AXGE_RXHDR_L4_TYPE_TCP 16
+#define AXGE_RXHDR_CRC_ERR 0x20000000
+#define AXGE_RXHDR_DROP_ERR 0x80000000
+
+#define GET_MII(sc) uether_getmii(&(sc)->sc_ue)
+
+/* The interrupt endpoint is currently unused by the ASIX part. */
+enum {
+ AXGE_BULK_DT_WR,
+ AXGE_BULK_DT_RD,
+ AXGE_N_TRANSFER,
+};
+
+struct axge_softc {
+ struct usb_ether sc_ue;
+ struct mtx sc_mtx;
+ struct usb_xfer *sc_xfer[AXGE_N_TRANSFER];
+ int sc_phyno;
+
+ int sc_flags;
+#define AXGE_FLAG_LINK 0x0001 /* got a link */
+};
+
+#define AXGE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define AXGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define AXGE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
Property changes on: stable/0.8/sys/dev/usb/net/if_axgereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/net/if_cdce.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cdce.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cdce.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_cdce.c 290608 2015-11-09 11:27:31Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -1381,6 +1381,7 @@
/* check if we have a buffer */
if (m) {
+ m->m_len = m->m_pkthdr.len = temp + ETHER_ALIGN;
m_adj(m, ETHER_ALIGN);
usbd_copy_out(pc, offset, m->m_data, temp);
Modified: stable/0.8/sys/dev/usb/net/if_cdcereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cdcereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cdcereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_cdcereg.h 221077 2011-04-26 19:40:37Z hselasky $
*/
#ifndef _USB_IF_CDCEREG_H_
Modified: stable/0.8/sys/dev/usb/net/if_cue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cue.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cue.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_cue.c 248085 2013-03-09 02:36:32Z marius $");
/*
* CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate
Modified: stable/0.8/sys/dev/usb/net/if_cuereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cuereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cuereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_cuereg.h 196219 2009-08-14 20:03:53Z jhb $
*/
/*
Modified: stable/0.8/sys/dev/usb/net/if_ipheth.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_ipheth.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_ipheth.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_ipheth.c 251701 2013-06-13 20:40:39Z eadler $");
#include <sys/stdint.h>
#include <sys/stddef.h>
Modified: stable/0.8/sys/dev/usb/net/if_iphethvar.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_iphethvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_iphethvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_iphethvar.h 213805 2010-10-13 21:36:42Z hselasky $ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2009 Diego Giagio. All rights reserved.
Modified: stable/0.8/sys/dev/usb/net/if_kue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kue.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kue.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_kue.c 248085 2013-03-09 02:36:32Z marius $");
/*
* Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.
Modified: stable/0.8/sys/dev/usb/net/if_kuefw.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kuefw.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kuefw.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_kuefw.h 196219 2009-08-14 20:03:53Z jhb $
*/
/*
Modified: stable/0.8/sys/dev/usb/net/if_kuereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kuereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kuereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_kuereg.h 196219 2009-08-14 20:03:53Z jhb $
*/
/*
Modified: stable/0.8/sys/dev/usb/net/if_mos.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_mos.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_mos.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_mos.c 248085 2013-03-09 02:36:32Z marius $");
/*
* Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller
Modified: stable/0.8/sys/dev/usb/net/if_mosreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_mosreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_mosreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_mosreg.h 232876 2012-03-12 18:22:04Z hselasky $ */
/*-
* Copyright (c) 2010, 2011 Rick van der Zwet <info at rickvanderzwet.nl>
*
Modified: stable/0.8/sys/dev/usb/net/if_rue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_rue.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_rue.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_rue.c 248085 2013-03-09 02:36:32Z marius $");
/*
* RealTek RTL8150 USB to fast ethernet controller driver.
Modified: stable/0.8/sys/dev/usb/net/if_ruereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_ruereg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_ruereg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_ruereg.h 215335 2010-11-15 06:04:25Z kevlo $
*/
#define RUE_CONFIG_IDX 0 /* config number 1 */
Modified: stable/0.8/sys/dev/usb/net/if_udav.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_udav.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_udav.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
/* $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 $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_udav.c 248085 2013-03-09 02:36:32Z marius $ */
/*-
* Copyright (c) 2003
* Shingo WATANABE <nabe at nabechan.org>. All rights reserved.
@@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_udav.c 248085 2013-03-09 02:36:32Z marius $");
#include <sys/stdint.h>
#include <sys/stddef.h>
Modified: stable/0.8/sys/dev/usb/net/if_udavreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_udavreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_udavreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
/* $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 $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_udavreg.h 242819 2012-11-09 06:58:23Z hselasky $ */
/*-
* Copyright (c) 2003
* Shingo WATANABE <nabe at nabechan.org>. All rights reserved.
Added: stable/0.8/sys/dev/usb/net/if_urndis.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_urndis.c (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_urndis.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1053 @@
+/* $OpenBSD: if_urndis.c,v 1.46 2013/12/09 15:45:29 pirofti Exp $ */
+
+/*
+ * Copyright (c) 2010 Jonathan Armani <armani at openbsd.org>
+ * Copyright (c) 2010 Fabien Romano <fabien at openbsd.org>
+ * Copyright (c) 2010 Michael Knudsen <mk at openbsd.org>
+ * Copyright (c) 2014 Hans Petter Selasky <hselasky at freebsd.org>
+ * All rights reserved.
+ *
+ * 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: stable/9/sys/dev/usb/net/if_urndis.c 292793 2015-12-27 20:49:36Z marius $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR urndis_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include "usb_if.h"
+
+#include <dev/usb/net/usb_ethernet.h>
+#include <dev/usb/net/if_urndisreg.h>
+
+#include <dev/usb/usb_cdc.h>
+
+static device_probe_t urndis_probe;
+static device_attach_t urndis_attach;
+static device_detach_t urndis_detach;
+static device_suspend_t urndis_suspend;
+static device_resume_t urndis_resume;
+
+static usb_callback_t urndis_bulk_write_callback;
+static usb_callback_t urndis_bulk_read_callback;
+static usb_callback_t urndis_intr_read_callback;
+
+static uether_fn_t urndis_attach_post;
+static uether_fn_t urndis_init;
+static uether_fn_t urndis_stop;
+static uether_fn_t urndis_start;
+static uether_fn_t urndis_setmulti;
+static uether_fn_t urndis_setpromisc;
+
+static uint32_t urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_query_req *msg, uint16_t len,
+ const void **rbuf, uint16_t *rbufsz);
+static uint32_t urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_set_req *msg, uint16_t len);
+static uint32_t urndis_ctrl_handle_init(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr);
+static uint32_t urndis_ctrl_handle_query(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr, const void **buf,
+ uint16_t *bufsz);
+static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr);
+static uint32_t urndis_ctrl_init(struct urndis_softc *sc);
+static uint32_t urndis_ctrl_halt(struct urndis_softc *sc);
+
+#ifdef USB_DEBUG
+static int urndis_debug = 0;
+static SYSCTL_NODE(_hw_usb, OID_AUTO, urndis, CTLFLAG_RW, 0, "USB RNDIS-Ethernet");
+SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RW, &urndis_debug, 0,
+ "Debug level");
+#endif
+
+static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
+ [URNDIS_BULK_RX] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_RX,
+ .if_index = 0,
+ .frames = 1,
+ .bufsize = RNDIS_RX_MAXLEN,
+ .flags = {.short_xfer_ok = 1,},
+ .callback = urndis_bulk_read_callback,
+ .timeout = 0, /* no timeout */
+ .usb_mode = USB_MODE_HOST,
+ },
+
+ [URNDIS_BULK_TX] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_TX,
+ .if_index = 0,
+ .frames = RNDIS_TX_FRAMES_MAX,
+ .bufsize = (RNDIS_TX_FRAMES_MAX * RNDIS_TX_MAXLEN),
+ .flags = {
+ .force_short_xfer = 1,
+ },
+ .callback = urndis_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
+ .usb_mode = USB_MODE_HOST,
+ },
+
+ [URNDIS_INTR_RX] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_RX,
+ .if_index = 1,
+ .bufsize = 0, /* use wMaxPacketSize */
+ .flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
+ .callback = urndis_intr_read_callback,
+ .timeout = 0,
+ .usb_mode = USB_MODE_HOST,
+ },
+};
+
+static device_method_t urndis_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, urndis_probe),
+ DEVMETHOD(device_attach, urndis_attach),
+ DEVMETHOD(device_detach, urndis_detach),
+ DEVMETHOD(device_suspend, urndis_suspend),
+ DEVMETHOD(device_resume, urndis_resume),
+
+ DEVMETHOD_END
+};
+
+static driver_t urndis_driver = {
+ .name = "urndis",
+ .methods = urndis_methods,
+ .size = sizeof(struct urndis_softc),
+};
+
+static devclass_t urndis_devclass;
+
+DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL);
+MODULE_VERSION(urndis, 1);
+MODULE_DEPEND(urndis, uether, 1, 1, 1);
+MODULE_DEPEND(urndis, usb, 1, 1, 1);
+MODULE_DEPEND(urndis, ether, 1, 1, 1);
+
+static const struct usb_ether_methods urndis_ue_methods = {
+ .ue_attach_post = urndis_attach_post,
+ .ue_start = urndis_start,
+ .ue_init = urndis_init,
+ .ue_stop = urndis_stop,
+ .ue_setmulti = urndis_setmulti,
+ .ue_setpromisc = urndis_setpromisc,
+};
+
+static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
+ /* Generic RNDIS class match */
+ {USB_IFACE_CLASS(UICLASS_CDC),
+ USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
+ USB_IFACE_PROTOCOL(0xff)},
+ {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
+ USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
+ {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
+ USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
+ /* HP-WebOS */
+ {USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC),
+ USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
+ USB_IFACE_PROTOCOL(0xff)},
+};
+
+static int
+urndis_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ return (usbd_lookup_id_by_uaa(urndis_host_devs, sizeof(urndis_host_devs), uaa));
+}
+
+static void
+urndis_attach_post(struct usb_ether *ue)
+{
+
+ /* no-op */
+}
+
+static int
+urndis_attach(device_t dev)
+{
+ static struct {
+ union {
+ struct urndis_query_req query;
+ struct urndis_set_req set;
+ } hdr;
+ union {
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ uint32_t filter;
+ } ibuf;
+ } msg;
+ struct urndis_softc *sc = device_get_softc(dev);
+ struct usb_ether *ue = &sc->sc_ue;
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct usb_cdc_cm_descriptor *cmd;
+ const void *buf;
+ uint16_t bufsz;
+ uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
+ int error;
+ uint8_t i;
+
+ sc->sc_ue.ue_udev = uaa->device;
+ sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
+
+ cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
+ UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
+ if (cmd != 0) {
+ DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
+ iface_index[0] = cmd->bDataInterface;
+ }
+
+ device_set_usb_desc(dev);
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /* scan the alternate settings looking for a valid one */
+ for (i = 0; i != 32; i++) {
+ error = usbd_set_alt_interface_index(uaa->device,
+ iface_index[0], i);
+
+ if (error != 0)
+ break;
+
+ error = usbd_transfer_setup(uaa->device,
+ iface_index, sc->sc_xfer, urndis_config,
+ URNDIS_N_TRANSFER, sc, &sc->sc_mtx);
+
+ if (error == 0)
+ break;
+ }
+ if ((error != 0) || (i == 32)) {
+ device_printf(dev, "No valid alternate setting found\n");
+ goto detach;
+ }
+
+ /* Initialize device - must be done before even querying it */
+ URNDIS_LOCK(sc);
+ error = urndis_ctrl_init(sc);
+ URNDIS_UNLOCK(sc);
+ if (error != (int)RNDIS_STATUS_SUCCESS) {
+ device_printf(dev, "Unable to initialize hardware\n");
+ goto detach;
+ }
+
+ /* Determine MAC address */
+ memset(msg.ibuf.eaddr, 0, sizeof(msg.ibuf.eaddr));
+ URNDIS_LOCK(sc);
+ error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS,
+ &msg.hdr.query, sizeof(msg.hdr.query) + sizeof(msg.ibuf.eaddr),
+ &buf, &bufsz);
+ URNDIS_UNLOCK(sc);
+ if (error != (int)RNDIS_STATUS_SUCCESS) {
+ device_printf(dev, "Unable to get hardware address\n");
+ goto detach;
+ }
+ if (bufsz != ETHER_ADDR_LEN) {
+ device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
+ goto detach;
+ }
+ memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
+
+ /* Initialize packet filter */
+ sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
+ RNDIS_PACKET_TYPE_ALL_MULTICAST;
+ msg.ibuf.filter = htole32(sc->sc_filter);
+ URNDIS_LOCK(sc);
+ error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+ &msg.hdr.set, sizeof(msg.hdr.set) + sizeof(msg.ibuf.filter));
+ URNDIS_UNLOCK(sc);
+ if (error != (int)RNDIS_STATUS_SUCCESS) {
+ device_printf(dev, "Unable to set data filters\n");
+ goto detach;
+ }
+
+ ue->ue_sc = sc;
+ ue->ue_dev = dev;
+ ue->ue_udev = uaa->device;
+ ue->ue_mtx = &sc->sc_mtx;
+ ue->ue_methods = &urndis_ue_methods;
+
+ error = uether_ifattach(ue);
+ if (error) {
+ device_printf(dev, "Could not attach interface\n");
+ goto detach;
+ }
+
+ URNDIS_LOCK(sc);
+ /* start interrupt endpoint, if any */
+ usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
+ URNDIS_UNLOCK(sc);
+
+ return (0); /* success */
+
+detach:
+ (void)urndis_detach(dev);
+ return (ENXIO); /* failure */
+}
+
+static int
+urndis_detach(device_t dev)
+{
+ struct urndis_softc *sc = device_get_softc(dev);
+ struct usb_ether *ue = &sc->sc_ue;
+
+ /* stop all USB transfers first */
+ usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
+
+ uether_ifdetach(ue);
+
+ URNDIS_LOCK(sc);
+ (void)urndis_ctrl_halt(sc);
+ URNDIS_UNLOCK(sc);
+
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+static void
+urndis_start(struct usb_ether *ue)
+{
+ struct urndis_softc *sc = uether_getsc(ue);
+
+ /*
+ * Start the USB transfers, if not already started:
+ */
+ usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
+ usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
+}
+
+static void
+urndis_init(struct usb_ether *ue)
+{
+ struct urndis_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ URNDIS_LOCK_ASSERT(sc, MA_OWNED);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ /* stall data write direction, which depends on USB mode */
+ usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
+
+ /* start data transfers */
+ urndis_start(ue);
+}
+
+static void
+urndis_stop(struct usb_ether *ue)
+{
+ struct urndis_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ URNDIS_LOCK_ASSERT(sc, MA_OWNED);
+
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
+ /*
+ * stop all the transfers, if not already stopped:
+ */
+ usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
+ usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
+}
+
+static void
+urndis_setmulti(struct usb_ether *ue)
+{
+
+ /* no-op */
+}
+
+static void
+urndis_setpromisc(struct usb_ether *ue)
+{
+
+ /* no-op */
+}
+
+static int
+urndis_suspend(device_t dev)
+{
+
+ device_printf(dev, "Suspending\n");
+ return (0);
+}
+
+static int
+urndis_resume(device_t dev)
+{
+
+ device_printf(dev, "Resuming\n");
+ return (0);
+}
+
+static usb_error_t
+urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
+ uint16_t index, uint16_t value, void *buf, uint16_t buflen)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = rt;
+ req.bRequest = r;
+ USETW(req.wValue, value);
+ USETW(req.wIndex, index);
+ USETW(req.wLength, buflen);
+
+ return (usbd_do_request_flags(sc->sc_ue.ue_udev,
+ &sc->sc_mtx, &req, buf, (rt & UT_READ) ?
+ USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
+}
+
+static usb_error_t
+urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
+{
+ usb_error_t err;
+
+ err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE,
+ UCDC_SEND_ENCAPSULATED_COMMAND, sc->sc_ifaceno_ctl, 0, buf, len);
+
+ DPRINTF("%s\n", usbd_errstr(err));
+
+ return (err);
+}
+
+static struct urndis_comp_hdr *
+urndis_ctrl_recv(struct urndis_softc *sc)
+{
+ struct urndis_comp_hdr *hdr;
+ usb_error_t err;
+
+ err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE,
+ UCDC_GET_ENCAPSULATED_RESPONSE, sc->sc_ifaceno_ctl, 0,
+ sc->sc_response_buf, RNDIS_RESPONSE_LEN);
+
+ if (err != USB_ERR_NORMAL_COMPLETION)
+ return (NULL);
+
+ hdr = (struct urndis_comp_hdr *)sc->sc_response_buf;
+
+ DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
+ le32toh(hdr->rm_len));
+
+ if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
+ DPRINTF("ctrl message error: wrong size %u > %u\n",
+ le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
+ return (NULL);
+ }
+ return (hdr);
+}
+
+static uint32_t
+urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
+ const void **buf, uint16_t *bufsz)
+{
+ uint32_t rval;
+
+ DPRINTF("\n");
+
+ if (buf != NULL && bufsz != NULL) {
+ *buf = NULL;
+ *bufsz = 0;
+ }
+ switch (le32toh(hdr->rm_type)) {
+ case REMOTE_NDIS_INITIALIZE_CMPLT:
+ rval = urndis_ctrl_handle_init(sc, hdr);
+ break;
+
+ case REMOTE_NDIS_QUERY_CMPLT:
+ rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
+ break;
+
+ case REMOTE_NDIS_RESET_CMPLT:
+ rval = urndis_ctrl_handle_reset(sc, hdr);
+ break;
+
+ case REMOTE_NDIS_KEEPALIVE_CMPLT:
+ case REMOTE_NDIS_SET_CMPLT:
+ rval = le32toh(hdr->rm_status);
+ break;
+
+ default:
+ device_printf(sc->sc_ue.ue_dev,
+ "ctrl message error: unknown event 0x%x\n",
+ le32toh(hdr->rm_type));
+ rval = RNDIS_STATUS_FAILURE;
+ break;
+ }
+ return (rval);
+}
+
+static uint32_t
+urndis_ctrl_handle_init(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr)
+{
+ const struct urndis_init_comp *msg;
+
+ msg = (const struct urndis_init_comp *)hdr;
+
+ DPRINTF("len %u rid %u status 0x%x "
+ "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
+ "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
+ le32toh(msg->rm_len),
+ le32toh(msg->rm_rid),
+ le32toh(msg->rm_status),
+ le32toh(msg->rm_ver_major),
+ le32toh(msg->rm_ver_minor),
+ le32toh(msg->rm_devflags),
+ le32toh(msg->rm_medium),
+ le32toh(msg->rm_pktmaxcnt),
+ le32toh(msg->rm_pktmaxsz),
+ le32toh(msg->rm_align),
+ le32toh(msg->rm_aflistoffset),
+ le32toh(msg->rm_aflistsz));
+
+ if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
+ return (le32toh(msg->rm_status));
+ }
+ if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
+ DPRINTF("wrong device type (current type: 0x%x)\n",
+ le32toh(msg->rm_devflags));
+ return (RNDIS_STATUS_FAILURE);
+ }
+ if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
+ DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
+ le32toh(msg->rm_medium));
+ return (RNDIS_STATUS_FAILURE);
+ }
+ sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
+
+ return (le32toh(msg->rm_status));
+}
+
+static uint32_t
+urndis_ctrl_handle_query(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
+{
+ const struct urndis_query_comp *msg;
+ uint64_t limit;
+
+ msg = (const struct urndis_query_comp *)hdr;
+
+ DPRINTF("len %u rid %u status 0x%x "
+ "buflen %u bufoff %u\n",
+ le32toh(msg->rm_len),
+ le32toh(msg->rm_rid),
+ le32toh(msg->rm_status),
+ le32toh(msg->rm_infobuflen),
+ le32toh(msg->rm_infobufoffset));
+
+ *buf = NULL;
+ *bufsz = 0;
+ if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
+ return (le32toh(msg->rm_status));
+ }
+ limit = le32toh(msg->rm_infobuflen);
+ limit += le32toh(msg->rm_infobufoffset);
+ limit += RNDIS_HEADER_OFFSET;
+
+ if (limit > (uint64_t)le32toh(msg->rm_len)) {
+ DPRINTF("ctrl message error: invalid query info "
+ "len/offset/end_position(%u/%u/%u) -> "
+ "go out of buffer limit %u\n",
+ le32toh(msg->rm_infobuflen),
+ le32toh(msg->rm_infobufoffset),
+ le32toh(msg->rm_infobuflen) +
+ le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
+ le32toh(msg->rm_len));
+ return (RNDIS_STATUS_FAILURE);
+ }
+ *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET +
+ le32toh(msg->rm_infobufoffset);
+ *bufsz = le32toh(msg->rm_infobuflen);
+
+ return (le32toh(msg->rm_status));
+}
+
+static uint32_t
+urndis_ctrl_handle_reset(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr)
+{
+ const struct urndis_reset_comp *msg;
+ uint32_t rval;
+
+ msg = (const struct urndis_reset_comp *)hdr;
+
+ rval = le32toh(msg->rm_status);
+
+ DPRINTF("len %u status 0x%x "
+ "adrreset %u\n",
+ le32toh(msg->rm_len),
+ rval,
+ le32toh(msg->rm_adrreset));
+
+ if (rval != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("reset failed 0x%x\n", rval);
+ return (rval);
+ }
+ if (msg->rm_adrreset != 0) {
+ struct {
+ struct urndis_set_req hdr;
+ uint32_t filter;
+ } msg_filter;
+
+ msg_filter.filter = htole32(sc->sc_filter);
+
+ rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+ &msg_filter.hdr, sizeof(msg_filter));
+
+ if (rval != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("unable to reset data filters\n");
+ return (rval);
+ }
+ }
+ return (rval);
+}
+
+static uint32_t
+urndis_ctrl_init(struct urndis_softc *sc)
+{
+ struct urndis_init_req msg;
+ struct urndis_comp_hdr *hdr;
+ uint32_t rval;
+
+ msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
+ msg.rm_len = htole32(sizeof(msg));
+ msg.rm_rid = 0;
+ msg.rm_ver_major = htole32(1);
+ msg.rm_ver_minor = htole32(1);
+ msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
+
+ DPRINTF("type %u len %u rid %u ver_major %u "
+ "ver_minor %u max_xfersz %u\n",
+ le32toh(msg.rm_type),
+ le32toh(msg.rm_len),
+ le32toh(msg.rm_rid),
+ le32toh(msg.rm_ver_major),
+ le32toh(msg.rm_ver_minor),
+ le32toh(msg.rm_max_xfersz));
+
+ rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
+
+ if (rval != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("init failed\n");
+ return (rval);
+ }
+ if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+ DPRINTF("unable to get init response\n");
+ return (RNDIS_STATUS_FAILURE);
+ }
+ rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+
+ return (rval);
+}
+
+static uint32_t
+urndis_ctrl_halt(struct urndis_softc *sc)
+{
+ struct urndis_halt_req msg;
+ uint32_t rval;
+
+ msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
+ msg.rm_len = htole32(sizeof(msg));
+ msg.rm_rid = 0;
+
+ DPRINTF("type %u len %u rid %u\n",
+ le32toh(msg.rm_type),
+ le32toh(msg.rm_len),
+ le32toh(msg.rm_rid));
+
+ rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
+
+ if (rval != RNDIS_STATUS_SUCCESS)
+ DPRINTF("halt failed\n");
+
+ return (rval);
+}
+
+/*
+ * NB: Querying a device has the requirment of using an input buffer the size
+ * of the expected reply or larger, except for variably sized replies.
+ */
+static uint32_t
+urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_query_req *msg, uint16_t len, const void **rbuf,
+ uint16_t *rbufsz)
+{
+ struct urndis_comp_hdr *hdr;
+ uint32_t datalen, rval;
+
+ msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
+ msg->rm_len = htole32(len);
+ msg->rm_rid = 0; /* XXX */
+ msg->rm_oid = htole32(oid);
+ datalen = len - sizeof(*msg);
+ msg->rm_infobuflen = htole32(datalen);
+ if (datalen != 0) {
+ msg->rm_infobufoffset = htole32(sizeof(*msg) -
+ RNDIS_HEADER_OFFSET);
+ } else {
+ msg->rm_infobufoffset = 0;
+ }
+ msg->rm_devicevchdl = 0;
+
+ DPRINTF("type %u len %u rid %u oid 0x%x "
+ "infobuflen %u infobufoffset %u devicevchdl %u\n",
+ le32toh(msg->rm_type),
+ le32toh(msg->rm_len),
+ le32toh(msg->rm_rid),
+ le32toh(msg->rm_oid),
+ le32toh(msg->rm_infobuflen),
+ le32toh(msg->rm_infobufoffset),
+ le32toh(msg->rm_devicevchdl));
+
+ rval = urndis_ctrl_send(sc, msg, len);
+
+ if (rval != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("query failed\n");
+ return (rval);
+ }
+ if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+ DPRINTF("unable to get query response\n");
+ return (RNDIS_STATUS_FAILURE);
+ }
+ rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
+
+ return (rval);
+}
+
+static uint32_t
+urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_set_req *msg, uint16_t len)
+{
+ struct urndis_comp_hdr *hdr;
+ uint32_t datalen, rval;
+
+ msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
+ msg->rm_len = htole32(len);
+ msg->rm_rid = 0; /* XXX */
+ msg->rm_oid = htole32(oid);
+ datalen = len - sizeof(*msg);
+ msg->rm_infobuflen = htole32(datalen);
+ if (datalen != 0) {
+ msg->rm_infobufoffset = htole32(sizeof(*msg) -
+ RNDIS_HEADER_OFFSET);
+ } else {
+ msg->rm_infobufoffset = 0;
+ }
+ msg->rm_devicevchdl = 0;
+
+ DPRINTF("type %u len %u rid %u oid 0x%x "
+ "infobuflen %u infobufoffset %u devicevchdl %u\n",
+ le32toh(msg->rm_type),
+ le32toh(msg->rm_len),
+ le32toh(msg->rm_rid),
+ le32toh(msg->rm_oid),
+ le32toh(msg->rm_infobuflen),
+ le32toh(msg->rm_infobufoffset),
+ le32toh(msg->rm_devicevchdl));
+
+ rval = urndis_ctrl_send(sc, msg, len);
+
+ if (rval != RNDIS_STATUS_SUCCESS) {
+ DPRINTF("set failed\n");
+ return (rval);
+ }
+ if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+ DPRINTF("unable to get set response\n");
+ return (RNDIS_STATUS_FAILURE);
+ }
+ rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+ if (rval != RNDIS_STATUS_SUCCESS)
+ DPRINTF("set failed 0x%x\n", rval);
+
+ return (rval);
+}
+
+static void
+urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct urndis_softc *sc = usbd_xfer_softc(xfer);
+ struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
+ struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct urndis_packet_msg msg;
+ struct mbuf *m;
+ int actlen;
+ int aframes;
+ int offset;
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
+
+ DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
+
+ for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
+ /* copy out header */
+ usbd_copy_out(pc, offset, &msg, sizeof(msg));
+
+ if (le32toh(0x1234567U) != 0x1234567U) {
+ /* swap endianness */
+ msg.rm_type = le32toh(msg.rm_type);
+ msg.rm_len = le32toh(msg.rm_len);
+ msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
+ msg.rm_datalen = le32toh(msg.rm_datalen);
+ msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
+ msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
+ msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
+ msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
+ msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
+ msg.rm_vchandle = le32toh(msg.rm_vchandle);
+ msg.rm_reserved = le32toh(msg.rm_reserved);
+ }
+
+ DPRINTF("len %u data(off:%u len:%u) "
+ "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
+ msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
+ msg.rm_oobdataoffset, msg.rm_oobdatalen,
+ msg.rm_oobdataelements, msg.rm_pktinfooffset,
+ msg.rm_pktinfooffset);
+
+ /* sanity check the RNDIS header */
+ if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
+ DPRINTF("invalid type 0x%x != 0x%x\n",
+ msg.rm_type, REMOTE_NDIS_PACKET_MSG);
+ goto tr_setup;
+ } else if (msg.rm_len < (uint32_t)sizeof(msg)) {
+ DPRINTF("invalid msg len %u < %u\n",
+ msg.rm_len, (unsigned)sizeof(msg));
+ goto tr_setup;
+ } else if (msg.rm_len > (uint32_t)actlen) {
+ DPRINTF("invalid msg len %u > buffer "
+ "len %u\n", msg.rm_len, actlen);
+ goto tr_setup;
+ } else if (msg.rm_dataoffset >= (uint32_t)actlen) {
+ DPRINTF("invalid msg dataoffset %u > buffer "
+ "dataoffset %u\n", msg.rm_dataoffset, actlen);
+ goto tr_setup;
+ } else if (msg.rm_datalen > (uint32_t)actlen) {
+ DPRINTF("invalid msg datalen %u > buffer "
+ "datalen %u\n", msg.rm_datalen, actlen);
+ goto tr_setup;
+ } else if ((msg.rm_dataoffset + msg.rm_datalen +
+ (uint32_t)__offsetof(struct urndis_packet_msg,
+ rm_dataoffset)) > (uint32_t)actlen) {
+ DPRINTF("invalid dataoffset %u larger than %u\n",
+ msg.rm_dataoffset + msg.rm_datalen +
+ (uint32_t)__offsetof(struct urndis_packet_msg,
+ rm_dataoffset), actlen);
+ goto tr_setup;
+ } else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
+ ifp->if_ierrors++;
+ DPRINTF("invalid ethernet size "
+ "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
+ goto tr_setup;
+ } else if (msg.rm_datalen > (uint32_t)(MCLBYTES - ETHER_ALIGN)) {
+ ifp->if_ierrors++;
+ DPRINTF("invalid ethernet size "
+ "%u > %u\n",
+ msg.rm_datalen, (unsigned)MCLBYTES);
+ goto tr_setup;
+ } else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ } else {
+ m = m_gethdr(M_NOWAIT, MT_DATA);
+ }
+
+ /* check if we have a buffer */
+ if (m != NULL) {
+ m->m_len = m->m_pkthdr.len = msg.rm_datalen + ETHER_ALIGN;
+ m_adj(m, ETHER_ALIGN);
+
+ usbd_copy_out(pc, offset + msg.rm_dataoffset +
+ __offsetof(struct urndis_packet_msg,
+ rm_dataoffset), m->m_data, msg.rm_datalen);
+
+ /* enqueue */
+ uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
+ } else {
+ ifp->if_ierrors++;
+ }
+ offset += msg.rm_len;
+ actlen -= msg.rm_len;
+ }
+
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
+ usbd_xfer_set_frames(xfer, 1);
+ usbd_transfer_submit(xfer);
+ uether_rxflush(&sc->sc_ue); /* must be last */
+ break;
+
+ default: /* Error */
+ DPRINTFN(1, "error = %s\n", usbd_errstr(error));
+
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ usbd_xfer_set_frames(xfer, 0);
+ usbd_transfer_submit(xfer);
+ }
+ break;
+ }
+}
+
+static void
+urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct urndis_packet_msg msg;
+ struct urndis_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct mbuf *m;
+ unsigned x;
+ int actlen;
+ int aframes;
+
+ usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
+
+ DPRINTFN(1, "\n");
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
+
+ ifp->if_opackets++;
+
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ memset(&msg, 0, sizeof(msg));
+
+ for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
+ struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
+
+ usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
+
+next_pkt:
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+
+ if (m == NULL)
+ break;
+
+ if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
+ DPRINTF("Too big packet\n");
+ ifp->if_oerrors++;
+
+ /* Free buffer */
+ m_freem(m);
+ goto next_pkt;
+ }
+ msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
+ msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
+
+ msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
+ msg.rm_datalen = htole32(m->m_pkthdr.len);
+
+ /* copy in all data */
+ usbd_copy_in(pc, 0, &msg, sizeof(msg));
+ usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
+ usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
+
+ /*
+ * If there's a BPF listener, bounce a copy of
+ * this frame to him:
+ */
+ BPF_MTAP(ifp, m);
+
+ /* Free buffer */
+ m_freem(m);
+ }
+ if (x != 0) {
+ usbd_xfer_set_frames(xfer, x);
+ usbd_transfer_submit(xfer);
+ }
+ break;
+
+ default: /* Error */
+ DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
+
+ /* count output errors */
+ ifp->if_oerrors++;
+
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ break;
+ }
+}
+
+static void
+urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ int actlen;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+
+ DPRINTF("Received %d bytes\n", actlen);
+
+ /* TODO: decode some indications */
+
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ break;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* start clear stall */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ break;
+ }
+}
Property changes on: stable/0.8/sys/dev/usb/net/if_urndis.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: stable/0.8/sys/dev/usb/net/if_urndisreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_urndisreg.h (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_urndisreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,296 @@
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_urndisreg.h 262362 2014-02-23 13:20:08Z hselasky $ */
+/* $OpenBSD: if_urndisreg.h,v 1.19 2013/11/21 14:08:05 mpi Exp $ */
+
+/*
+ * Copyright (c) 2010 Jonathan Armani <armani at openbsd.org>
+ * Copyright (c) 2010 Fabien Romano <fabien at openbsd.org>
+ * Copyright (c) 2010 Michael Knudsen <mk at openbsd.org>
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef _IF_URNDISREG_H_
+#define _IF_URNDISREG_H_
+
+#define RNDIS_RESPONSE_LEN 1024 /* bytes */
+#define RNDIS_RX_MAXLEN (16 * 1024)
+#define RNDIS_TX_FRAMES_MAX 8
+#define RNDIS_TX_MAXLEN MCLBYTES
+
+enum {
+ URNDIS_BULK_RX,
+ URNDIS_BULK_TX,
+ URNDIS_INTR_RX,
+ URNDIS_N_TRANSFER,
+};
+
+struct urndis_softc {
+
+ struct usb_ether sc_ue;
+ struct mtx sc_mtx;
+
+ /* RNDIS device info */
+ uint32_t sc_lim_pktsz;
+ uint32_t sc_filter;
+
+ struct usb_device *sc_udev;
+ struct usb_xfer *sc_xfer[URNDIS_N_TRANSFER];
+
+ uint8_t sc_ifaceno_ctl;
+ uint8_t sc_response_buf[RNDIS_RESPONSE_LEN] __aligned(4);
+};
+
+#define URNDIS_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define URNDIS_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define URNDIS_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, (what))
+
+#define RNDIS_STATUS_BUFFER_OVERFLOW 0x80000005L
+#define RNDIS_STATUS_FAILURE 0xC0000001L
+#define RNDIS_STATUS_INVALID_DATA 0xC0010015L
+#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BL
+#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CL
+#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBL
+#define RNDIS_STATUS_PENDING STATUS_PENDING /* XXX */
+#define RNDIS_STATUS_RESOURCES 0xC000009AL
+#define RNDIS_STATUS_SUCCESS 0x00000000L
+
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_SUPPORTED_GUIDS 0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
+#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
+#define OID_GEN_MACHINE_NAME 0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
+#define OID_GEN_VLAN_ID 0x0001021C
+
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+
+#define RNDIS_MEDIUM_802_3 0x00000000
+
+/* Device flags */
+#define RNDIS_DF_CONNECTIONLESS 0x00000001
+#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
+
+/*
+ * RNDIS data message
+ */
+#define REMOTE_NDIS_PACKET_MSG 0x00000001
+
+struct urndis_packet_msg {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_dataoffset;
+ uint32_t rm_datalen;
+ uint32_t rm_oobdataoffset;
+ uint32_t rm_oobdatalen;
+ uint32_t rm_oobdataelements;
+ uint32_t rm_pktinfooffset;
+ uint32_t rm_pktinfolen;
+ uint32_t rm_vchandle;
+ uint32_t rm_reserved;
+};
+
+/*
+ * RNDIS control messages
+ */
+struct urndis_comp_hdr {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_status;
+};
+
+/* Initialize the device. */
+#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002
+#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002
+
+struct urndis_init_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_ver_major;
+ uint32_t rm_ver_minor;
+ uint32_t rm_max_xfersz;
+};
+
+struct urndis_init_comp {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_status;
+ uint32_t rm_ver_major;
+ uint32_t rm_ver_minor;
+ uint32_t rm_devflags;
+ uint32_t rm_medium;
+ uint32_t rm_pktmaxcnt;
+ uint32_t rm_pktmaxsz;
+ uint32_t rm_align;
+ uint32_t rm_aflistoffset;
+ uint32_t rm_aflistsz;
+};
+
+/* Halt the device. No response sent. */
+#define REMOTE_NDIS_HALT_MSG 0x00000003
+
+struct urndis_halt_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+};
+
+/* Send a query object. */
+#define REMOTE_NDIS_QUERY_MSG 0x00000004
+#define REMOTE_NDIS_QUERY_CMPLT 0x80000004
+
+struct urndis_query_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_oid;
+ uint32_t rm_infobuflen;
+ uint32_t rm_infobufoffset;
+ uint32_t rm_devicevchdl;
+};
+
+struct urndis_query_comp {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_status;
+ uint32_t rm_infobuflen;
+ uint32_t rm_infobufoffset;
+};
+
+/* Send a set object request. */
+#define REMOTE_NDIS_SET_MSG 0x00000005
+#define REMOTE_NDIS_SET_CMPLT 0x80000005
+
+struct urndis_set_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_oid;
+ uint32_t rm_infobuflen;
+ uint32_t rm_infobufoffset;
+ uint32_t rm_devicevchdl;
+};
+
+struct urndis_set_comp {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_status;
+};
+
+#define REMOTE_NDIS_SET_PARAM_NUMERIC 0x00000000
+#define REMOTE_NDIS_SET_PARAM_STRING 0x00000002
+
+struct urndis_set_parameter {
+ uint32_t rm_nameoffset;
+ uint32_t rm_namelen;
+ uint32_t rm_type;
+ uint32_t rm_valueoffset;
+ uint32_t rm_valuelen;
+};
+
+/* Perform a soft reset on the device. */
+#define REMOTE_NDIS_RESET_MSG 0x00000006
+#define REMOTE_NDIS_RESET_CMPLT 0x80000006
+
+struct urndis_reset_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+};
+
+struct urndis_reset_comp {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_status;
+ uint32_t rm_adrreset;
+};
+
+/* 802.3 link-state or undefined message error. */
+#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007
+
+/* Keepalive messsage. May be sent by device. */
+#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008
+#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008
+
+struct urndis_keepalive_req {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+};
+
+struct urndis_keepalive_comp {
+ uint32_t rm_type;
+ uint32_t rm_len;
+ uint32_t rm_rid;
+ uint32_t rm_status;
+};
+
+/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */
+#define RNDIS_PACKET_TYPE_DIRECTED 0x00000001
+#define RNDIS_PACKET_TYPE_MULTICAST 0x00000002
+#define RNDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define RNDIS_PACKET_TYPE_BROADCAST 0x00000008
+#define RNDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
+#define RNDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
+#define RNDIS_PACKET_TYPE_SMT 0x00000040
+#define RNDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
+#define RNDIS_PACKET_TYPE_GROUP 0x00001000
+#define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000
+#define RNDIS_PACKET_TYPE_FUNCTIONAL 0x00004000
+#define RNDIS_PACKET_TYPE_MAC_FRAME 0x00008000
+
+/* RNDIS offsets */
+#define RNDIS_HEADER_OFFSET 8 /* bytes */
+#define RNDIS_DATA_OFFSET ((uint32_t)(sizeof(struct urndis_packet_msg) - RNDIS_HEADER_OFFSET))
+
+#endif /* _IF_URNDISREG_H_ */
Property changes on: stable/0.8/sys/dev/usb/net/if_urndisreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/net/if_usie.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_usie.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_usie.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_usie.c 248085 2013-03-09 02:36:32Z marius $");
#include <sys/param.h>
#include <sys/systm.h>
Modified: stable/0.8/sys/dev/usb/net/if_usievar.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_usievar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_usievar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_usievar.h 223864 2011-07-08 10:58:56Z hselasky $ */
/*-
* Copyright (c) 2011 Anybots Inc
Modified: stable/0.8/sys/dev/usb/net/ruephy.c
===================================================================
--- stable/0.8/sys/dev/usb/net/ruephy.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/ruephy.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/ruephy.c 235000 2012-05-04 15:05:30Z hselasky $");
/*
* driver for RealTek RTL8150 internal PHY
Modified: stable/0.8/sys/dev/usb/net/ruephyreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/ruephyreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/ruephyreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/ruephyreg.h 227229 2011-11-06 17:23:49Z marius $
*/
#ifndef _RUEPHYREG_H_
Modified: stable/0.8/sys/dev/usb/net/uhso.c
===================================================================
--- stable/0.8/sys/dev/usb/net/uhso.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/uhso.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
*
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/uhso.c 301447 2016-06-05 15:05:53Z pfg $");
#include <sys/param.h>
#include <sys/types.h>
@@ -268,6 +268,8 @@
UHSO_DEV(OPTION, ICON401, UHSO_AUTO_IFACE),
/* Option GlobeTrotter Module 382 */
UHSO_DEV(OPTION, GMT382, UHSO_AUTO_IFACE),
+ /* Option GTM661W */
+ UHSO_DEV(OPTION, GTM661W, UHSO_AUTO_IFACE),
/* Option iCON EDGE */
UHSO_DEV(OPTION, ICONEDGE, UHSO_STATIC_IFACE),
/* Option Module HSxPA */
@@ -556,8 +558,6 @@
mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
ucom_ref(&sc->sc_super_ucom);
- sc->sc_ucom = NULL;
- sc->sc_ttys = 0;
sc->sc_radio = 1;
id = usbd_get_interface_descriptor(uaa->iface);
@@ -677,9 +677,6 @@
UHSO_CTRL_MAX);
}
}
-
- free(sc->sc_tty, M_USBDEV);
- free(sc->sc_ucom, M_USBDEV);
}
if (sc->sc_ifp != NULL) {
@@ -707,6 +704,8 @@
uhso_free_softc(struct uhso_softc *sc)
{
if (ucom_unref(&sc->sc_super_ucom)) {
+ free(sc->sc_tty, M_USBDEV);
+ free(sc->sc_ucom, M_USBDEV);
mtx_destroy(&sc->sc_mtx);
device_free_softc(sc);
}
@@ -814,6 +813,8 @@
UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port));
case UHSO_PORT_TYPE_DIAG:
case UHSO_PORT_TYPE_DIAG2:
+ case UHSO_PORT_TYPE_GPS:
+ case UHSO_PORT_TYPE_GPSCTL:
case UHSO_PORT_TYPE_CTL:
case UHSO_PORT_TYPE_APP:
case UHSO_PORT_TYPE_APP2:
@@ -1222,6 +1223,7 @@
ht->ht_muxport);
/* FALLTHROUGH */
case USB_ST_SETUP:
+tr_setup:
pc = usbd_xfer_get_frame(xfer, 1);
if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc,
0, 32, &actlen)) {
@@ -1252,7 +1254,8 @@
UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
if (error == USB_ERR_CANCELLED)
break;
- break;
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
}
}
Modified: stable/0.8/sys/dev/usb/net/usb_ethernet.c
===================================================================
--- stable/0.8/sys/dev/usb/net/usb_ethernet.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/usb_ethernet.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.c 262594 2014-02-28 01:35:24Z rodrigc $ */
/*-
* Copyright (c) 2009 Andrew Thompson (thompsa at FreeBSD.org)
*
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.c 262594 2014-02-28 01:35:24Z rodrigc $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -207,6 +207,7 @@
sysctl_ctx_init(&ue->ue_sysctl_ctx);
error = 0;
+ CURVNET_SET_QUIET(vnet0);
ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
device_printf(ue->ue_dev, "could not allocate ifnet\n");
@@ -254,6 +255,8 @@
if (ifp->if_capabilities & IFCAP_VLAN_MTU)
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+ CURVNET_RESTORE();
+
snprintf(num, sizeof(num), "%u", ue->ue_unit);
ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
&SYSCTL_NODE_CHILDREN(_net, ue),
@@ -267,6 +270,7 @@
return;
fail:
+ CURVNET_RESTORE();
free_unr(ueunit, ue->ue_unit);
if (ue->ue_ifp != NULL) {
if_free(ue->ue_ifp);
Modified: stable/0.8/sys/dev/usb/net/usb_ethernet.h
===================================================================
--- stable/0.8/sys/dev/usb/net/usb_ethernet.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/usb_ethernet.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.h 229105 2011-12-31 14:45:43Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.h 229105 2011-12-31 14:45:43Z hselasky $
*/
#ifndef _USB_ETHERNET_H_
Modified: stable/0.8/sys/dev/usb/quirk/usb_quirk.c
===================================================================
--- stable/0.8/sys/dev/usb/quirk/usb_quirk.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/quirk/usb_quirk.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/quirk/usb_quirk.c 315250 2017-03-14 15:25:49Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -61,6 +61,7 @@
#define USB_DEV_QUIRKS_MAX 384
#define USB_SUB_QUIRKS_MAX 8
+#define USB_QUIRK_ENVROOT "hw.usb.quirk."
struct usb_quirk_entry {
uint16_t vid;
@@ -97,6 +98,7 @@
USB_QUIRK(REALTEK, RTL8153, 0x0000, 0xffff, UQ_CFG_INDEX_1),
USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
+ USB_QUIRK(CISCOLINKSYS, USB3GIGV1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
/* Quirks for printer devices */
USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
@@ -133,6 +135,8 @@
USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* Quirk for Corsair Vengeance K70 keyboard */
USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
+ /* Quirk for Corsair STRAFE Gaming keyboard */
+ USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
/* umodem(4) device quirks */
USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
@@ -513,6 +517,7 @@
/* Non-standard USB AUDIO devices */
USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206),
/*
* Quirks for manufacturers which USB devices does not respond
@@ -526,6 +531,9 @@
/* DYMO LabelManager Pnp */
USB_QUIRK(DYMO, LABELMANAGERPNP, 0x0000, 0xffff, UQ_MSC_DYMO_EJECT),
+
+ /* Holtek USB gaming keyboard */
+ USB_QUIRK(HOLTEK, F85, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
};
#undef USB_QUIRK_VP
#undef USB_QUIRK
@@ -597,6 +605,7 @@
[UQ_AU_VENDOR_CLASS] = "UQ_AU_VENDOR_CLASS",
[UQ_SINGLE_CMD_MIDI] = "UQ_SINGLE_CMD_MIDI",
[UQ_MSC_DYMO_EJECT] = "UQ_MSC_DYMO_EJECT",
+ [UQ_AU_SET_SPDIF_CM6206] = "UQ_AU_SET_SPDIF_CM6206",
};
/*------------------------------------------------------------------------*
@@ -607,11 +616,35 @@
static const char *
usb_quirkstr(uint16_t quirk)
{
- return ((quirk < USB_QUIRK_MAX) ?
- usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
+ return ((quirk < USB_QUIRK_MAX && usb_quirk_str[quirk] != NULL) ?
+ usb_quirk_str[quirk] : "UQ_UNKNOWN");
}
/*------------------------------------------------------------------------*
+ * usb_strquirk
+ *
+ * This function converts a string into a USB quirk code.
+ *
+ * Returns:
+ * Less than USB_QUIRK_MAX: Quirk code
+ * Else: Quirk code not found
+ *------------------------------------------------------------------------*/
+static uint16_t
+usb_strquirk(const char *str, size_t len)
+{
+ const char *quirk;
+ uint16_t x;
+
+ for (x = 0; x != USB_QUIRK_MAX; x++) {
+ quirk = usb_quirkstr(x);
+ if (strncmp(str, quirk, len) == 0 &&
+ quirk[len] == 0)
+ break;
+ }
+ return (x);
+}
+
+/*------------------------------------------------------------------------*
* usb_test_quirk_by_info
*
* Returns:
@@ -656,8 +689,6 @@
return (1);
}
}
- /* no quirk found */
- break;
}
mtx_unlock(&usb_quirk_mtx);
done:
@@ -853,12 +884,122 @@
return (ENOIOCTL);
}
+/*------------------------------------------------------------------------*
+ * usb_quirk_strtou16
+ *
+ * Helper function to scan a 16-bit integer.
+ *------------------------------------------------------------------------*/
+static uint16_t
+usb_quirk_strtou16(const char **pptr, const char *name, const char *what)
+{
+ unsigned long value;
+ char *end;
+
+ value = strtoul(*pptr, &end, 0);
+ if (value > 65535 || *pptr == end || (*end != ' ' && *end != '\t')) {
+ printf("%s: %s 16-bit %s value set to zero\n",
+ name, what, *end == 0 ? "incomplete" : "invalid");
+ return (0);
+ }
+ *pptr = end + 1;
+ return ((uint16_t)value);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_quirk_add_entry_from_str
+ *
+ * Add a USB quirk entry from string.
+ * "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]"
+ *------------------------------------------------------------------------*/
static void
+usb_quirk_add_entry_from_str(const char *name, const char *env)
+{
+ struct usb_quirk_entry entry = { };
+ struct usb_quirk_entry *new;
+ uint16_t quirk_idx;
+ uint16_t quirk;
+ const char *end;
+
+ /* check for invalid environment variable */
+ if (name == NULL || env == NULL)
+ return;
+
+ if (bootverbose)
+ printf("Adding USB QUIRK '%s' = '%s'\n", name, env);
+
+ /* parse device information */
+ entry.vid = usb_quirk_strtou16(&env, name, "Vendor ID");
+ entry.pid = usb_quirk_strtou16(&env, name, "Product ID");
+ entry.lo_rev = usb_quirk_strtou16(&env, name, "Low revision");
+ entry.hi_rev = usb_quirk_strtou16(&env, name, "High revision");
+
+ /* parse quirk information */
+ quirk_idx = 0;
+ while (*env != 0 && quirk_idx != USB_SUB_QUIRKS_MAX) {
+ /* skip whitespace before quirks */
+ while (*env == ' ' || *env == '\t')
+ env++;
+
+ /* look for quirk separation character */
+ end = strchr(env, ',');
+ if (end == NULL)
+ end = env + strlen(env);
+
+ /* lookup quirk in string table */
+ quirk = usb_strquirk(env, end - env);
+ if (quirk < USB_QUIRK_MAX) {
+ entry.quirks[quirk_idx++] = quirk;
+ } else {
+ printf("%s: unknown USB quirk '%.*s' (skipped)\n",
+ name, (int)(end - env), env);
+ }
+ env = end;
+
+ /* skip quirk delimiter, if any */
+ if (*env != 0)
+ env++;
+ }
+
+ /* register quirk */
+ if (quirk_idx != 0) {
+ if (*env != 0) {
+ printf("%s: Too many USB quirks, only %d allowed!\n",
+ name, USB_SUB_QUIRKS_MAX);
+ }
+ mtx_lock(&usb_quirk_mtx);
+ new = usb_quirk_get_entry(entry.vid, entry.pid,
+ entry.lo_rev, entry.hi_rev, 1);
+ if (new == NULL)
+ printf("%s: USB quirks table is full!\n", name);
+ else
+ memcpy(new->quirks, entry.quirks, sizeof(entry.quirks));
+ mtx_unlock(&usb_quirk_mtx);
+ } else {
+ printf("%s: No USB quirks found!\n", name);
+ }
+}
+
+static void
usb_quirk_init(void *arg)
{
+ char envkey[sizeof(USB_QUIRK_ENVROOT) + 2]; /* 2 digits max, 0 to 99 */
+ int i;
+
/* initialize mutex */
mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
+ /* look for quirks defined by the environment variable */
+ for (i = 0; i != 100; i++) {
+ snprintf(envkey, sizeof(envkey), USB_QUIRK_ENVROOT "%d", i);
+
+ /* Stop at first undefined var */
+ if (!testenv(envkey))
+ break;
+
+ /* parse environment variable */
+ usb_quirk_add_entry_from_str(envkey, getenv(envkey));
+ }
+
/* register our function */
usb_test_quirk_p = &usb_test_quirk_by_info;
usb_quirk_ioctl_p = &usb_quirk_ioctl;
Modified: stable/0.8/sys/dev/usb/quirk/usb_quirk.h
===================================================================
--- stable/0.8/sys/dev/usb/quirk/usb_quirk.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/quirk/usb_quirk.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/quirk/usb_quirk.h 315250 2017-03-14 15:25:49Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -110,6 +110,7 @@
UQ_AU_VENDOR_CLASS, /* audio device uses vendor and not audio class */
UQ_SINGLE_CMD_MIDI, /* at most one command per USB packet */
UQ_MSC_DYMO_EJECT, /* ejects Dymo MSC device */
+ UQ_AU_SET_SPDIF_CM6206, /* enable S/PDIF audio output */
USB_QUIRK_MAX
};
Modified: stable/0.8/sys/dev/usb/serial/u3g.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/u3g.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/u3g.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/serial/u3g.c 306958 2016-10-10 11:48:23Z hselasky $
*/
/*
@@ -75,16 +75,9 @@
#define U3G_MAXPORTS 12
#define U3G_CONFIG_INDEX 0
#define U3G_BSIZE 2048
+#define U3G_TXSIZE (U3G_BSIZE / U3G_TXFRAMES)
+#define U3G_TXFRAMES 4
-#define U3GSP_GPRS 0
-#define U3GSP_EDGE 1
-#define U3GSP_CDMA 2
-#define U3GSP_UMTS 3
-#define U3GSP_HSDPA 4
-#define U3GSP_HSUPA 5
-#define U3GSP_HSPA 6
-#define U3GSP_MAX 7
-
/* Eject methods; See also usb_quirks.h:UQ_MSC_EJECT_* */
#define U3GINIT_HUAWEI 1 /* Requires Huawei init command */
#define U3GINIT_SIERRA 2 /* Requires Sierra init command */
@@ -95,7 +88,8 @@
#define U3GINIT_WAIT 7 /* Device reappears after a delay */
#define U3GINIT_SAEL_M460 8 /* Requires vendor init */
#define U3GINIT_HUAWEISCSI 9 /* Requires Huawei SCSI init command */
-#define U3GINIT_TCT 10 /* Requires TCT Mobile init command */
+#define U3GINIT_HUAWEISCSI2 10 /* Requires Huawei SCSI init command (2) */
+#define U3GINIT_TCT 11 /* Requires TCT Mobile init command */
enum {
U3G_BULK_WR,
@@ -153,6 +147,7 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = U3G_BSIZE,/* bytes */
+ .frames = U3G_TXFRAMES,
.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
.callback = &u3g_write_callback,
},
@@ -244,9 +239,13 @@
U3G_DEV(DELL, U740, 0),
U3G_DEV(DLINK, DWR510_CD, U3GINIT_SCSIEJECT),
U3G_DEV(DLINK, DWR510, 0),
+ U3G_DEV(DLINK, DWM157_CD, U3GINIT_SCSIEJECT),
+ U3G_DEV(DLINK, DWM157, 0),
U3G_DEV(DLINK3, DWM652, 0),
U3G_DEV(HP, EV2200, 0),
U3G_DEV(HP, HS2300, 0),
+ U3G_DEV(HP, UN2420_QDL, 0),
+ U3G_DEV(HP, UN2420, 0),
U3G_DEV(HUAWEI, E1401, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E1402, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E1403, U3GINIT_HUAWEI),
@@ -317,9 +316,12 @@
U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E392, U3GINIT_HUAWEISCSI),
+ U3G_DEV(HUAWEI, ME909U, U3GINIT_HUAWEISCSI2),
U3G_DEV(HUAWEI, MOBILE, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E1752, U3GINIT_HUAWEISCSI),
U3G_DEV(HUAWEI, E1820, U3GINIT_HUAWEISCSI),
+ U3G_DEV(HUAWEI, K3772, U3GINIT_HUAWEI),
+ U3G_DEV(HUAWEI, K3772_INIT, U3GINIT_HUAWEISCSI2),
U3G_DEV(HUAWEI, K3765, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, K3765_INIT, U3GINIT_HUAWEISCSI),
U3G_DEV(HUAWEI, K3770, U3GINIT_HUAWEI),
@@ -343,8 +345,10 @@
U3G_DEV(NOVATEL, EU870D, 0),
U3G_DEV(NOVATEL, MC760, 0),
U3G_DEV(NOVATEL, MC547, 0),
+ U3G_DEV(NOVATEL, MC679, 0),
U3G_DEV(NOVATEL, MC950D, 0),
U3G_DEV(NOVATEL, MIFI2200, U3GINIT_SCSIEJECT),
+ U3G_DEV(NOVATEL, MIFI2200V, U3GINIT_SCSIEJECT),
U3G_DEV(NOVATEL, U720, 0),
U3G_DEV(NOVATEL, U727, 0),
U3G_DEV(NOVATEL, U727_2, 0),
@@ -387,6 +391,7 @@
U3G_DEV(OPTION, GTMAXHSUPA, 0),
U3G_DEV(OPTION, GTMAXHSUPAE, 0),
U3G_DEV(OPTION, VODAFONEMC3G, 0),
+ U3G_DEV(OPTION, GTM661W, 0),
U3G_DEV(QISDA, H20_1, 0),
U3G_DEV(QISDA, H20_2, 0),
U3G_DEV(QISDA, H21_1, 0),
@@ -395,10 +400,15 @@
U3G_DEV(QUALCOMM2, AC8700, 0),
U3G_DEV(QUALCOMM2, MF330, 0),
U3G_DEV(QUALCOMM2, SIM5218, 0),
+ U3G_DEV(QUALCOMM2, WM620, 0),
U3G_DEV(QUALCOMM2, VW110L, U3GINIT_SCSIEJECT),
U3G_DEV(QUALCOMM2, GOBI2000_QDL, 0),
U3G_DEV(QUALCOMM2, GOBI2000, 0),
+ U3G_DEV(QUALCOMM2, VT80N, 0),
+ U3G_DEV(QUALCOMM3, VFAST2, 0),
U3G_DEV(QUALCOMMINC, AC2726, 0),
+ U3G_DEV(QUALCOMMINC, AC682_INIT, U3GINIT_SCSIEJECT),
+ U3G_DEV(QUALCOMMINC, AC682, 0),
U3G_DEV(QUALCOMMINC, AC8700, 0),
U3G_DEV(QUALCOMMINC, AC8710, 0),
U3G_DEV(QUALCOMMINC, CDMA_MSM, U3GINIT_SCSIEJECT),
@@ -466,10 +476,15 @@
U3G_DEV(QUALCOMMINC, SURFSTICK, 0),
U3G_DEV(QUALCOMMINC, E2002, 0),
U3G_DEV(QUALCOMMINC, E2003, 0),
- U3G_DEV(QUALCOMMINC, K3772_Z, U3GINIT_SCSIEJECT),
+ U3G_DEV(QUALCOMMINC, K3772_Z, 0),
+ U3G_DEV(QUALCOMMINC, K3772_Z_INIT, U3GINIT_SCSIEJECT),
+ U3G_DEV(QUALCOMMINC, MF195E, 0),
+ U3G_DEV(QUALCOMMINC, MF195E_INIT, U3GINIT_SCSIEJECT),
U3G_DEV(QUALCOMMINC, MF626, 0),
U3G_DEV(QUALCOMMINC, MF628, 0),
U3G_DEV(QUALCOMMINC, MF633R, 0),
+ /* the following is a RNDIS device, no modem features */
+ U3G_DEV(QUALCOMMINC, ZTE_MF730M, U3GINIT_SCSIEJECT),
U3G_DEV(QUANTA, GKE, 0),
U3G_DEV(QUANTA, GLE, 0),
U3G_DEV(QUANTA, GLX, 0),
@@ -479,6 +494,7 @@
U3G_DEV(SIERRA, AC595U, 0),
U3G_DEV(SIERRA, AC313U, 0),
U3G_DEV(SIERRA, AC597E, 0),
+ U3G_DEV(SIERRA, AC875, 0),
U3G_DEV(SIERRA, AC875E, 0),
U3G_DEV(SIERRA, AC875U, 0),
U3G_DEV(SIERRA, AC875U_2, 0),
@@ -493,7 +509,6 @@
U3G_DEV(SIERRA, AC885U, 0),
U3G_DEV(SIERRA, AIRCARD580, 0),
U3G_DEV(SIERRA, AIRCARD595, 0),
- U3G_DEV(SIERRA, AIRCARD875, 0),
U3G_DEV(SIERRA, C22, 0),
U3G_DEV(SIERRA, C597, 0),
U3G_DEV(SIERRA, C888, 0),
@@ -508,6 +523,7 @@
U3G_DEV(SIERRA, MC5727, 0),
U3G_DEV(SIERRA, MC5727_2, 0),
U3G_DEV(SIERRA, MC5728, 0),
+ U3G_DEV(SIERRA, MC7430, 0),
U3G_DEV(SIERRA, MC8700, 0),
U3G_DEV(SIERRA, MC8755, 0),
U3G_DEV(SIERRA, MC8755_2, 0),
@@ -558,6 +574,7 @@
U3G_DEV(TOSHIBA, G450, 0),
U3G_DEV(TOSHIBA, HSDPA, 0),
U3G_DEV(YISO, C893, 0),
+ U3G_DEV(WETELECOM, WM_D200, 0),
/* Autoinstallers */
U3G_DEV(NOVATEL, ZEROCD, U3GINIT_SCSIEJECT),
U3G_DEV(OPTION, GTICON322, U3GINIT_REZERO),
@@ -610,7 +627,7 @@
static const uint8_t setup[][24] = {
{ 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x41, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02 },
@@ -622,7 +639,7 @@
{ 0x41, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 },
{ 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
- { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
{ 0x41, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -632,7 +649,7 @@
{ 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
{ 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
{ 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
};
@@ -666,7 +683,7 @@
DPRINTFN(0, "too small buffer\n");
continue;
}
- err = usbd_do_request(udev, NULL, &req,
+ err = usbd_do_request(udev, NULL, &req,
__DECONST(uint8_t *, &setup[n][8]));
}
if (err) {
@@ -725,6 +742,8 @@
method = U3GINIT_WAIT;
else if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEISCSI))
method = U3GINIT_HUAWEISCSI;
+ else if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEISCSI2))
+ method = U3GINIT_HUAWEISCSI2;
else if (usb_test_quirk(uaa, UQ_MSC_EJECT_TCT))
method = U3GINIT_TCT;
else if (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa) == 0)
@@ -745,6 +764,9 @@
case U3GINIT_HUAWEISCSI:
error = usb_msc_eject(udev, 0, MSC_EJECT_HUAWEI);
break;
+ case U3GINIT_HUAWEISCSI2:
+ error = usb_msc_eject(udev, 0, MSC_EJECT_HUAWEI2);
+ break;
case U3GINIT_SCSIEJECT:
error = usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT);
break;
@@ -836,7 +858,7 @@
}
/* copy in USB config */
- for (n = 0; n != U3G_N_TRANSFER; n++)
+ for (n = 0; n != U3G_N_TRANSFER; n++)
u3g_config_tmp[n] = u3g_config[n];
device_set_usb_desc(dev);
@@ -887,7 +909,7 @@
sc->sc_iface[nports] = id->bInterfaceNumber;
if (bootverbose && sc->sc_xfer[nports][U3G_INTR]) {
- device_printf(dev, "port %d supports modem control",
+ device_printf(dev, "port %d supports modem control\n",
nports);
}
@@ -1009,14 +1031,22 @@
struct ucom_softc *ucom = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
uint32_t actlen;
+ uint32_t frame;
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
tr_setup:
- pc = usbd_xfer_get_frame(xfer, 0);
- if (ucom_get_data(ucom, pc, 0, U3G_BSIZE, &actlen)) {
- usbd_xfer_set_frame_len(xfer, 0, actlen);
+ for (frame = 0; frame != U3G_TXFRAMES; frame++) {
+ usbd_xfer_set_frame_offset(xfer, frame * U3G_TXSIZE, frame);
+
+ pc = usbd_xfer_get_frame(xfer, frame);
+ if (ucom_get_data(ucom, pc, 0, U3G_TXSIZE, &actlen) == 0)
+ break;
+ usbd_xfer_set_frame_len(xfer, frame, actlen);
+ }
+ if (frame != 0) {
+ usbd_xfer_set_frames(xfer, frame);
usbd_transfer_submit(xfer);
}
break;
Modified: stable/0.8/sys/dev/usb/serial/uark.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uark.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uark.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/serial/uark.c 240659 2012-09-18 16:28:49Z hselasky $
*/
/*
Modified: stable/0.8/sys/dev/usb/serial/ubsa.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ubsa.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ubsa.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ubsa.c 263688 2014-03-24 13:50:11Z emaste $");
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -41,13 +41,6 @@
* 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
Modified: stable/0.8/sys/dev/usb/serial/ubser.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ubser.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ubser.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -48,13 +48,6 @@
* 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
@@ -70,7 +63,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ubser.c 263688 2014-03-24 13:50:11Z emaste $");
/*
* BWCT serial adapter driver
Modified: stable/0.8/sys/dev/usb/serial/uchcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uchcom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uchcom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -41,13 +41,6 @@
* 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
@@ -63,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uchcom.c 263688 2014-03-24 13:50:11Z emaste $");
/*
* Driver for WinChipHead CH341/340, the worst USB-serial chip in the
Modified: stable/0.8/sys/dev/usb/serial/ucycom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ucycom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ucycom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ucycom.c 240659 2012-09-18 16:28:49Z hselasky $");
/*-
* Copyright (c) 2004 Dag-Erling Co\xEFdan Sm\xF8rgrav
Modified: stable/0.8/sys/dev/usb/serial/ufoma.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ufoma.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ufoma.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ufoma.c 263688 2014-03-24 13:50:11Z emaste $");
#define UFOMA_HANDSFREE
/*-
* Copyright (c) 2005, Takanori Watanabe
@@ -46,13 +46,6 @@
* 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
Modified: stable/0.8/sys/dev/usb/serial/uftdi.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uftdi.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uftdi.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uftdi.c 283194 2015-05-21 07:50:56Z hselasky $");
/*
* NOTE: all function names beginning like "uftdi_cfg_" can only
@@ -38,7 +38,14 @@
*/
/*
- * FTDI FT2232x, FT8U100AX and FT8U232AM serial adapter driver
+ * FTDI FT232x, FT2232x, FT4232x, FT8U100AX and FT8U232xM serial adapters.
+ *
+ * Note that we specifically do not do a reset or otherwise alter the state of
+ * the chip during attach, detach, open, and close, because it could be
+ * pre-initialized (via an attached serial eeprom) to power-on into a mode such
+ * as bitbang in which the pins are being driven to a specific state which we
+ * must not perturb. The device gets reset at power-on, and doesn't need to be
+ * reset again after that to function, except as directed by ioctl() calls.
*/
#include <sys/stdint.h>
@@ -63,6 +70,8 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_ioctl.h>
#include "usbdevs.h"
#define USB_DEBUG_VAR uftdi_debug
@@ -71,20 +80,46 @@
#include <dev/usb/serial/usb_serial.h>
#include <dev/usb/serial/uftdi_reg.h>
+#include <dev/usb/uftdiio.h>
+static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
+
#ifdef USB_DEBUG
static int uftdi_debug = 0;
-
-static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
&uftdi_debug, 0, "Debug level");
#endif
#define UFTDI_CONFIG_INDEX 0
-#define UFTDI_IFACE_INDEX_JTAG 0
-#define UFTDI_OBUFSIZE 64 /* bytes, cannot be increased due to
- * do size encoding */
+/*
+ * IO buffer sizes and FTDI device procotol sizes.
+ *
+ * Note that the output packet size in the following defines is not the usb
+ * protocol packet size based on bus speed, it is the size dictated by the FTDI
+ * device itself, and is used only on older chips.
+ *
+ * We allocate buffers bigger than the hardware's packet size, and process
+ * multiple packets within each buffer. This allows the controller to make
+ * optimal use of the usb bus by conducting multiple transfers with the device
+ * during a single bus timeslice to fill or drain the chip's fifos.
+ *
+ * The output data on newer chips has no packet header, and we are able to pack
+ * any number of output bytes into a buffer. On some older chips, each output
+ * packet contains a 1-byte header and up to 63 bytes of payload. The size is
+ * encoded in 6 bits of the header, hence the 64-byte limit on packet size. We
+ * loop to fill the buffer with many of these header+payload packets.
+ *
+ * The input data on all chips consists of packets which contain a 2-byte header
+ * followed by data payload. The total size of the packet is wMaxPacketSize
+ * which can change based on the bus speed (e.g., 64 for full speed, 512 for
+ * high speed). We loop to extract the headers and payloads from the packets
+ * packed into an input buffer.
+ */
+#define UFTDI_IBUFSIZE 2048
+#define UFTDI_IHDRSIZE 2
+#define UFTDI_OBUFSIZE 2048
+#define UFTDI_OPKTSIZE 64
enum {
UFTDI_BULK_DT_WR,
@@ -92,6 +127,21 @@
UFTDI_N_TRANSFER,
};
+enum {
+ DEVT_SIO,
+ DEVT_232A,
+ DEVT_232B,
+ DEVT_2232D, /* Includes 2232C */
+ DEVT_232R,
+ DEVT_2232H,
+ DEVT_4232H,
+ DEVT_232H,
+ DEVT_230X,
+};
+
+#define DEVF_BAUDBITS_HINDEX 0x01 /* Baud bits in high byte of index. */
+#define DEVF_BAUDCLK_12M 0X02 /* Base baud clock is 12MHz. */
+
struct uftdi_softc {
struct ucom_super_softc sc_super_ucom;
struct ucom_softc sc_ucom;
@@ -104,9 +154,10 @@
uint32_t sc_unit;
uint16_t sc_last_lcr;
+ uint16_t sc_bcdDevice;
- uint8_t sc_type;
- uint8_t sc_iface_index;
+ uint8_t sc_devtype;
+ uint8_t sc_devflags;
uint8_t sc_hdrlen;
uint8_t sc_msr;
uint8_t sc_lsr;
@@ -113,7 +164,8 @@
};
struct uftdi_param_config {
- uint16_t rate;
+ uint16_t baud_lobits;
+ uint16_t baud_hibits;
uint16_t lcr;
uint8_t v_start;
uint8_t v_stop;
@@ -132,20 +184,29 @@
static void uftdi_free(struct ucom_softc *);
static void uftdi_cfg_open(struct ucom_softc *);
+static void uftdi_cfg_close(struct ucom_softc *);
static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t);
static void uftdi_cfg_set_break(struct ucom_softc *, uint8_t);
-static int uftdi_set_parm_soft(struct termios *,
- struct uftdi_param_config *, uint8_t);
+static int uftdi_set_parm_soft(struct ucom_softc *, struct termios *,
+ struct uftdi_param_config *);
static int uftdi_pre_param(struct ucom_softc *, struct termios *);
static void uftdi_cfg_param(struct ucom_softc *, struct termios *);
static void uftdi_cfg_get_status(struct ucom_softc *, uint8_t *,
uint8_t *);
+static int uftdi_reset(struct ucom_softc *, int);
+static int uftdi_set_bitmode(struct ucom_softc *, uint8_t, uint8_t);
+static int uftdi_get_bitmode(struct ucom_softc *, uint8_t *);
+static int uftdi_set_latency(struct ucom_softc *, int);
+static int uftdi_get_latency(struct ucom_softc *, int *);
+static int uftdi_set_event_char(struct ucom_softc *, int);
+static int uftdi_set_error_char(struct ucom_softc *, int);
+static int uftdi_ioctl(struct ucom_softc *, uint32_t, caddr_t, int,
+ struct thread *);
static void uftdi_start_read(struct ucom_softc *);
static void uftdi_stop_read(struct ucom_softc *);
static void uftdi_start_write(struct ucom_softc *);
static void uftdi_stop_write(struct ucom_softc *);
-static uint8_t uftdi_8u232am_getrate(uint32_t, uint16_t *);
static void uftdi_poll(struct ucom_softc *ucom);
static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = {
@@ -163,7 +224,7 @@
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .bufsize = 0, /* use wMaxPacketSize */
+ .bufsize = UFTDI_IBUFSIZE,
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.callback = &uftdi_read_callback,
},
@@ -176,7 +237,9 @@
.ucom_cfg_set_break = &uftdi_cfg_set_break,
.ucom_cfg_param = &uftdi_cfg_param,
.ucom_cfg_open = &uftdi_cfg_open,
+ .ucom_cfg_close = &uftdi_cfg_close,
.ucom_pre_param = &uftdi_pre_param,
+ .ucom_ioctl = &uftdi_ioctl,
.ucom_start_read = &uftdi_start_read,
.ucom_stop_read = &uftdi_stop_read,
.ucom_start_write = &uftdi_start_write,
@@ -209,641 +272,779 @@
static const STRUCT_USB_HOST_ID uftdi_devs[] = {
#define UFTDI_DEV(v, p, i) \
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
- UFTDI_DEV(ACTON, SPECTRAPRO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ALTI2, N3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ANALOGDEVICES, GNICE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(ANALOGDEVICES, GNICEPLUS, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(ATMEL, STK541, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(BAYER, CONTOUR_CABLE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, 232USB9M, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, 485USB9F_2W, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, 485USB9F_4W, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, 485USBTB_2W, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, 485USBTB_4W, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, TTL3USB9M, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, TTL5USB9M, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USO9ML2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USO9ML2DR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USO9ML2DR_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USOPTL4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USOPTL4DR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USOPTL4DR2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USOTL4, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(BBELECTRONICS, USPTL4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, USTL4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(CONTEC, COM1USBH, UFTDI_TYPE_AUTO),
- UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(ELEKTOR, FT323R, UFTDI_TYPE_AUTO),
- UFTDI_DEV(EVOLUTION, ER1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(EVOLUTION, HYBRID, UFTDI_TYPE_AUTO),
- UFTDI_DEV(EVOLUTION, RCM4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FALCOM, SAMBA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FALCOM, TWIST, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, 232H, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, 232RL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, 4N_GALAXY_DE_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, 4N_GALAXY_DE_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, 8U232AM_ALT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ACCESSO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ACG_HFDUAL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ACTIVE_ROBOTS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ACTZWAVE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, AMC232, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ARTEMIS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ASK_RDR400, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ATIK_ATK16, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ATIK_ATK16C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ATIK_ATK16HR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ATIK_ATK16HRC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ATIK_ATK16IC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, BCS_SE923, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, XDS100V2, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CANDAPTER, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CANUSB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSICDU20_0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSICDU40_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSICDU64_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSLOAD_N_GO_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSMACHX_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CCSPRIME8_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CFA_631, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CFA_632, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CFA_633, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CFA_634, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CFA_635, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CHAMSYS_24_MASTER_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_MAXI_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_MEDIA_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_MIDI_TIMECODE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_MINI_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_PC_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_USB_DMX, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CHAMSYS_WING, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, COM4SM, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CONVERTER_7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, CTI_USB_MINI_485, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, CTI_USB_NANO_485, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, DMX4ALL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, DOMINTELL_DGQG, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, DOMINTELL_DUSB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, DOTEC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ECLO_COM_1WIRE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ECO_PRO_CDS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, EISCOU, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, ELSTER_UNICOM, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_ALC8500, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_CLI7000, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_CSI8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_EC3000, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_EM1000DL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_EM1010PC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_FEM, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_FHZ1000PC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_FHZ1300PC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_FM3RX, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_FS20SIG, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_HS485, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_KL100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_MSM1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_PCD200, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_PCK100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_PPS7330, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_RFP500, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_T1100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_TFD128, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_TFM100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_TWS550, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UAD8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UDA7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UDF77, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UIO88, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_ULA200, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UM100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UMS100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UO100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UR100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_USI2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_USR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_UTP8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS300PC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS444PC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS500, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS550, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS777, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, ELV_WS888, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, EMCU2D, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, EMCU2H, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, FUTURE_0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, FUTURE_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, FUTURE_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GAMMASCOUT, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, GENERIC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E808, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E809, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E80F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E88D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E88E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, GUDEADS_E88F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, HD_RADIO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, HO720, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, HO730, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, HO820, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, HO870, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_APP70, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_PCMCIA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_PEDO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_PICPRO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_PK1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_PROD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_RS232MON, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IBS_US485, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IPLUS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IPLUS2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, IRTRANS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, KBS, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, KTLINK, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, LENZ_LIUSB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, LK202, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, LK204, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, LM3S_DEVEL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, LM3S_EVAL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, MASTERDEVEL2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MAXSTREAM, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, MHAM_DB9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_IC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_KW, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_RS232, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_Y6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_Y8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_Y9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MHAM_YS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MICRO_CHAMELEON, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MTXORB_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MTXORB_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, MX2_3, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, MX4_5, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, NXTCAM, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OCEANIC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OOCDLINK, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, OPENDCC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OPENDCC_GATEWAY, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OPENDCC_GBM, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OPENDCC_SNIFFER, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, OPENDCC_THROTTLE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, PCDJ_DAC2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, PCMSFU, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, PERLE_ULTRAPORT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, PHI_FISCO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, PIEGROUP, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, PROPOX_JTAGCABLEII, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, R2000KU_TRUE_RNG, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, R2X0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, RELAIS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, REU_TINY, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, RMP200, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, RM_CANVIEW, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, RRCIRKITS_LOCOBUFFER, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCIENCESCOPE_HS_LOGBOOK, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCIENCESCOPE_LOGBOOKML, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCIENCESCOPE_LS_LOGBOOK, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SCS_DEVICE_7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SDMUSBQSS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SEMC_DSS20, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SERIAL_2232D, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SERIAL_232RL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SERIAL_4232H, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SERIAL_8U100AX, UFTDI_TYPE_SIO),
- UFTDI_DEV(FTDI, SERIAL_8U232AM, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SERIAL_8U232AM4, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, SIGNALYZER_SH2, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, SIGNALYZER_SH4, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, SIGNALYZER_SLITE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, SIGNALYZER_ST, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, SPECIAL_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SPECIAL_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SPECIAL_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SPROG_II, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SR_RADIO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, SUUNTO_SPORTS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13M, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13S, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13U, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, TAVIR_STK500, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TERATRONIK_D2XX, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TERATRONIK_VCP, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, THORLABS, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TNC_X, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TTUSB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, TURTELIZER2, UFTDI_TYPE_8U232AM | UFTDI_FLAG_JTAG),
- UFTDI_DEV(FTDI, UOPTBR, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, USBSERIAL, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, USBX_707, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, USB_UIRT, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(FTDI, USINT_CAT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, USINT_RS232, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, USINT_WKEY, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, VARDAAN, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, VNHCPCUSB_D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, WESTREX_MODEL_777, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, WESTREX_MODEL_8900F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, XF_547, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, XF_640, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, XF_642, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, XM_RADIO, UFTDI_TYPE_AUTO),
- UFTDI_DEV(FTDI, YEI_SERVOCENTER31, UFTDI_TYPE_AUTO),
- UFTDI_DEV(GNOTOMETRICS, USB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, SP1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, OPC_U_UC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2C1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2C2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2KVR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2KVT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2VR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP2VT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP4KVR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(ICOM, RP4KVT, UFTDI_TYPE_AUTO),
- UFTDI_DEV(IDTECH, IDT1221U, UFTDI_TYPE_AUTO),
- UFTDI_DEV(INTERBIOMETRICS, IOBOARD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(INTERBIOMETRICS, MINI_IOBOARD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(INTREPIDCS, NEOVI, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(INTREPIDCS, VALUECAN, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(IONICS, PLUGCOMPUTER, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(JETI, SPC1201, UFTDI_TYPE_AUTO),
- UFTDI_DEV(KOBIL, CONV_B1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(KOBIL, CONV_KAAN, UFTDI_TYPE_AUTO),
- UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MARVELL, SHEEVAPLUG, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0103, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0104, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0105, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0106, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0107, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0108, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0109, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0110, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0111, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0112, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0113, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0114, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0115, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0116, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0117, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0118, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0119, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0120, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0121, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0122, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0123, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0124, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0125, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0126, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0128, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0129, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0130, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0131, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0132, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0133, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0134, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0135, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0136, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0137, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0138, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0139, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0140, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0141, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0142, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0143, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0144, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0145, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0146, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0147, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0148, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0149, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0150, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0151, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0152, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0159, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0160, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0161, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0162, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0163, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0164, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0165, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0166, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0167, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0168, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0169, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0170, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0171, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0172, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0173, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0174, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0175, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0176, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0177, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0178, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0179, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0180, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0181, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0182, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0183, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0184, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0185, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0186, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0187, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0188, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0189, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0190, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0191, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0192, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0193, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0194, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0195, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0196, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0197, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0198, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0199, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019A, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019D, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019E, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019F, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01ED, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F0, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F9, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FA, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FD, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FF, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MATRIXORBITAL, MOUA, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(MELCO, PCOPRS1, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(METAGEEK, TELLSTICK, UFTDI_TYPE_AUTO),
- UFTDI_DEV(MOBILITY, USB_SERIAL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(OLIMEX, ARM_USB_OCD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(OLIMEX, ARM_USB_OCD_H, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(OPTO, CRD7734, UFTDI_TYPE_AUTO),
- UFTDI_DEV(OPTO, CRD7734_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, AD4USB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, AP485, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, AP485_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, DRAK5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, DRAK6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, GMSR, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, GMUX, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, IRAMP, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, LEC, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, MU, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO10X1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO2X16, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO2X2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO30X3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO3X32, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO4X4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO60X3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, QUIDO8X8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB232, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB422, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB422_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB485, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB485C, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB485S, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SB485_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, SIMUKEY, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, TMU, UFTDI_TYPE_AUTO),
- UFTDI_DEV(PAPOUCH, UPSUSB, UFTDI_TYPE_AUTO),
- UFTDI_DEV(POSIFLEX, PP7000, UFTDI_TYPE_AUTO),
- UFTDI_DEV(QIHARDWARE, JTAGSERIAL, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
- UFTDI_DEV(RATOC, REXUSB60F, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(RTSYSTEMS, CT29B, UFTDI_TYPE_AUTO),
- UFTDI_DEV(RTSYSTEMS, SERIAL_VX7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2101, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2102, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2103, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2104, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2106, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2201_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2201_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2202_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2202_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2203_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2203_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2401_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2401_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2401_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2401_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2402_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2402_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2402_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2402_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2403_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2403_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2403_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2403_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2801_8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2802_8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_1, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_2, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_3, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_4, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_5, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_6, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_7, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SEALEVEL, 2803_8, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SIIG2, DK201, UFTDI_TYPE_AUTO),
- UFTDI_DEV(SIIG2, US2308, UFTDI_TYPE_8U232AM),
- UFTDI_DEV(TESTO, USB_INTERFACE, UFTDI_TYPE_AUTO),
- UFTDI_DEV(TML, USB_SERIAL, UFTDI_TYPE_AUTO),
- UFTDI_DEV(TTI, QL355P, UFTDI_TYPE_AUTO),
- UFTDI_DEV(UNKNOWN4, NF_RIC, UFTDI_TYPE_AUTO),
+ UFTDI_DEV(ACTON, SPECTRAPRO, 0),
+ UFTDI_DEV(ALTI2, N3, 0),
+ UFTDI_DEV(ANALOGDEVICES, GNICE, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(ANALOGDEVICES, GNICEPLUS, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(ATMEL, STK541, 0),
+ UFTDI_DEV(BAYER, CONTOUR_CABLE, 0),
+ UFTDI_DEV(BBELECTRONICS, 232USB9M, 0),
+ UFTDI_DEV(BBELECTRONICS, 485USB9F_2W, 0),
+ UFTDI_DEV(BBELECTRONICS, 485USB9F_4W, 0),
+ UFTDI_DEV(BBELECTRONICS, 485USBTB_2W, 0),
+ UFTDI_DEV(BBELECTRONICS, 485USBTB_4W, 0),
+ UFTDI_DEV(BBELECTRONICS, TTL3USB9M, 0),
+ UFTDI_DEV(BBELECTRONICS, TTL5USB9M, 0),
+ UFTDI_DEV(BBELECTRONICS, USO9ML2, 0),
+ UFTDI_DEV(BBELECTRONICS, USO9ML2DR, 0),
+ UFTDI_DEV(BBELECTRONICS, USO9ML2DR_2, 0),
+ UFTDI_DEV(BBELECTRONICS, USOPTL4, 0),
+ UFTDI_DEV(BBELECTRONICS, USOPTL4DR, 0),
+ UFTDI_DEV(BBELECTRONICS, USOPTL4DR2, 0),
+ UFTDI_DEV(BBELECTRONICS, USOTL4, 0),
+ UFTDI_DEV(BBELECTRONICS, USPTL4, 0),
+ UFTDI_DEV(BBELECTRONICS, USTL4, 0),
+ UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, 0),
+ UFTDI_DEV(CONTEC, COM1USBH, 0),
+ UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, 0),
+ UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, 0),
+ UFTDI_DEV(DRESDENELEKTRONIK, DE_RFNODE, 0),
+ UFTDI_DEV(DRESDENELEKTRONIK, LEVELSHIFTERSTICKLOWCOST, 0),
+ UFTDI_DEV(ELEKTOR, FT323R, 0),
+ UFTDI_DEV(EVOLUTION, ER1, 0),
+ UFTDI_DEV(EVOLUTION, HYBRID, 0),
+ UFTDI_DEV(EVOLUTION, RCM4, 0),
+ UFTDI_DEV(FALCOM, SAMBA, 0),
+ UFTDI_DEV(FALCOM, TWIST, 0),
+ UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, 232EX, 0),
+ UFTDI_DEV(FTDI, 232H, 0),
+ UFTDI_DEV(FTDI, 232RL, 0),
+ UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, 0),
+ UFTDI_DEV(FTDI, 4N_GALAXY_DE_2, 0),
+ UFTDI_DEV(FTDI, 4N_GALAXY_DE_3, 0),
+ UFTDI_DEV(FTDI, 8U232AM_ALT, 0),
+ UFTDI_DEV(FTDI, ACCESSO, 0),
+ UFTDI_DEV(FTDI, ACG_HFDUAL, 0),
+ UFTDI_DEV(FTDI, ACTIVE_ROBOTS, 0),
+ UFTDI_DEV(FTDI, ACTZWAVE, 0),
+ UFTDI_DEV(FTDI, AMC232, 0),
+ UFTDI_DEV(FTDI, ARTEMIS, 0),
+ UFTDI_DEV(FTDI, ASK_RDR400, 0),
+ UFTDI_DEV(FTDI, ATIK_ATK16, 0),
+ UFTDI_DEV(FTDI, ATIK_ATK16C, 0),
+ UFTDI_DEV(FTDI, ATIK_ATK16HR, 0),
+ UFTDI_DEV(FTDI, ATIK_ATK16HRC, 0),
+ UFTDI_DEV(FTDI, ATIK_ATK16IC, 0),
+ UFTDI_DEV(FTDI, BCS_SE923, 0),
+ UFTDI_DEV(FTDI, CANDAPTER, 0),
+ UFTDI_DEV(FTDI, CANUSB, 0),
+ UFTDI_DEV(FTDI, CCSICDU20_0, 0),
+ UFTDI_DEV(FTDI, CCSICDU40_1, 0),
+ UFTDI_DEV(FTDI, CCSICDU64_4, 0),
+ UFTDI_DEV(FTDI, CCSLOAD_N_GO_3, 0),
+ UFTDI_DEV(FTDI, CCSMACHX_2, 0),
+ UFTDI_DEV(FTDI, CCSPRIME8_5, 0),
+ UFTDI_DEV(FTDI, CFA_631, 0),
+ UFTDI_DEV(FTDI, CFA_632, 0),
+ UFTDI_DEV(FTDI, CFA_633, 0),
+ UFTDI_DEV(FTDI, CFA_634, 0),
+ UFTDI_DEV(FTDI, CFA_635, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_24_MASTER_WING, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_MAXI_WING, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_MEDIA_WING, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_MIDI_TIMECODE, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_MINI_WING, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_PC_WING, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_USB_DMX, 0),
+ UFTDI_DEV(FTDI, CHAMSYS_WING, 0),
+ UFTDI_DEV(FTDI, COM4SM, 0),
+ UFTDI_DEV(FTDI, CONVERTER_0, 0),
+ UFTDI_DEV(FTDI, CONVERTER_1, 0),
+ UFTDI_DEV(FTDI, CONVERTER_2, 0),
+ UFTDI_DEV(FTDI, CONVERTER_3, 0),
+ UFTDI_DEV(FTDI, CONVERTER_4, 0),
+ UFTDI_DEV(FTDI, CONVERTER_5, 0),
+ UFTDI_DEV(FTDI, CONVERTER_6, 0),
+ UFTDI_DEV(FTDI, CONVERTER_7, 0),
+ UFTDI_DEV(FTDI, CTI_USB_MINI_485, 0),
+ UFTDI_DEV(FTDI, CTI_USB_NANO_485, 0),
+ UFTDI_DEV(FTDI, DMX4ALL, 0),
+ UFTDI_DEV(FTDI, DOMINTELL_DGQG, 0),
+ UFTDI_DEV(FTDI, DOMINTELL_DUSB, 0),
+ UFTDI_DEV(FTDI, DOTEC, 0),
+ UFTDI_DEV(FTDI, ECLO_COM_1WIRE, 0),
+ UFTDI_DEV(FTDI, ECO_PRO_CDS, 0),
+ UFTDI_DEV(FTDI, EISCOU, 0),
+ UFTDI_DEV(FTDI, ELSTER_UNICOM, 0),
+ UFTDI_DEV(FTDI, ELV_ALC8500, 0),
+ UFTDI_DEV(FTDI, ELV_CLI7000, 0),
+ UFTDI_DEV(FTDI, ELV_CSI8, 0),
+ UFTDI_DEV(FTDI, ELV_EC3000, 0),
+ UFTDI_DEV(FTDI, ELV_EM1000DL, 0),
+ UFTDI_DEV(FTDI, ELV_EM1010PC, 0),
+ UFTDI_DEV(FTDI, ELV_FEM, 0),
+ UFTDI_DEV(FTDI, ELV_FHZ1000PC, 0),
+ UFTDI_DEV(FTDI, ELV_FHZ1300PC, 0),
+ UFTDI_DEV(FTDI, ELV_FM3RX, 0),
+ UFTDI_DEV(FTDI, ELV_FS20SIG, 0),
+ UFTDI_DEV(FTDI, ELV_HS485, 0),
+ UFTDI_DEV(FTDI, ELV_KL100, 0),
+ UFTDI_DEV(FTDI, ELV_MSM1, 0),
+ UFTDI_DEV(FTDI, ELV_PCD200, 0),
+ UFTDI_DEV(FTDI, ELV_PCK100, 0),
+ UFTDI_DEV(FTDI, ELV_PPS7330, 0),
+ UFTDI_DEV(FTDI, ELV_RFP500, 0),
+ UFTDI_DEV(FTDI, ELV_T1100, 0),
+ UFTDI_DEV(FTDI, ELV_TFD128, 0),
+ UFTDI_DEV(FTDI, ELV_TFM100, 0),
+ UFTDI_DEV(FTDI, ELV_TWS550, 0),
+ UFTDI_DEV(FTDI, ELV_UAD8, 0),
+ UFTDI_DEV(FTDI, ELV_UDA7, 0),
+ UFTDI_DEV(FTDI, ELV_UDF77, 0),
+ UFTDI_DEV(FTDI, ELV_UIO88, 0),
+ UFTDI_DEV(FTDI, ELV_ULA200, 0),
+ UFTDI_DEV(FTDI, ELV_UM100, 0),
+ UFTDI_DEV(FTDI, ELV_UMS100, 0),
+ UFTDI_DEV(FTDI, ELV_UO100, 0),
+ UFTDI_DEV(FTDI, ELV_UR100, 0),
+ UFTDI_DEV(FTDI, ELV_USI2, 0),
+ UFTDI_DEV(FTDI, ELV_USR, 0),
+ UFTDI_DEV(FTDI, ELV_UTP8, 0),
+ UFTDI_DEV(FTDI, ELV_WS300PC, 0),
+ UFTDI_DEV(FTDI, ELV_WS444PC, 0),
+ UFTDI_DEV(FTDI, ELV_WS500, 0),
+ UFTDI_DEV(FTDI, ELV_WS550, 0),
+ UFTDI_DEV(FTDI, ELV_WS777, 0),
+ UFTDI_DEV(FTDI, ELV_WS888, 0),
+ UFTDI_DEV(FTDI, EMCU2D, 0),
+ UFTDI_DEV(FTDI, EMCU2H, 0),
+ UFTDI_DEV(FTDI, FUTURE_0, 0),
+ UFTDI_DEV(FTDI, FUTURE_1, 0),
+ UFTDI_DEV(FTDI, FUTURE_2, 0),
+ UFTDI_DEV(FTDI, GAMMASCOUT, 0),
+ UFTDI_DEV(FTDI, GENERIC, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E808, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E809, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80A, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80B, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80C, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80D, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80E, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E80F, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E88D, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E88E, 0),
+ UFTDI_DEV(FTDI, GUDEADS_E88F, 0),
+ UFTDI_DEV(FTDI, HD_RADIO, 0),
+ UFTDI_DEV(FTDI, HO720, 0),
+ UFTDI_DEV(FTDI, HO730, 0),
+ UFTDI_DEV(FTDI, HO820, 0),
+ UFTDI_DEV(FTDI, HO870, 0),
+ UFTDI_DEV(FTDI, IBS_APP70, 0),
+ UFTDI_DEV(FTDI, IBS_PCMCIA, 0),
+ UFTDI_DEV(FTDI, IBS_PEDO, 0),
+ UFTDI_DEV(FTDI, IBS_PICPRO, 0),
+ UFTDI_DEV(FTDI, IBS_PK1, 0),
+ UFTDI_DEV(FTDI, IBS_PROD, 0),
+ UFTDI_DEV(FTDI, IBS_RS232MON, 0),
+ UFTDI_DEV(FTDI, IBS_US485, 0),
+ UFTDI_DEV(FTDI, IPLUS, 0),
+ UFTDI_DEV(FTDI, IPLUS2, 0),
+ UFTDI_DEV(FTDI, IRTRANS, 0),
+ UFTDI_DEV(FTDI, KBS, 0),
+ UFTDI_DEV(FTDI, KTLINK, 0),
+ UFTDI_DEV(FTDI, LENZ_LIUSB, 0),
+ UFTDI_DEV(FTDI, LK202, 0),
+ UFTDI_DEV(FTDI, LK204, 0),
+ UFTDI_DEV(FTDI, LM3S_DEVEL_BOARD, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, LM3S_EVAL_BOARD, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, LM3S_ICDI_B_BOARD, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, MASTERDEVEL2, 0),
+ UFTDI_DEV(FTDI, MAXSTREAM, 0),
+ UFTDI_DEV(FTDI, MHAM_DB9, 0),
+ UFTDI_DEV(FTDI, MHAM_IC, 0),
+ UFTDI_DEV(FTDI, MHAM_KW, 0),
+ UFTDI_DEV(FTDI, MHAM_RS232, 0),
+ UFTDI_DEV(FTDI, MHAM_Y6, 0),
+ UFTDI_DEV(FTDI, MHAM_Y8, 0),
+ UFTDI_DEV(FTDI, MHAM_Y9, 0),
+ UFTDI_DEV(FTDI, MHAM_YS, 0),
+ UFTDI_DEV(FTDI, MICRO_CHAMELEON, 0),
+ UFTDI_DEV(FTDI, MTXORB_5, 0),
+ UFTDI_DEV(FTDI, MTXORB_6, 0),
+ UFTDI_DEV(FTDI, MX2_3, 0),
+ UFTDI_DEV(FTDI, MX4_5, 0),
+ UFTDI_DEV(FTDI, NXTCAM, 0),
+ UFTDI_DEV(FTDI, OCEANIC, 0),
+ UFTDI_DEV(FTDI, OOCDLINK, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, OPENDCC, 0),
+ UFTDI_DEV(FTDI, OPENDCC_GATEWAY, 0),
+ UFTDI_DEV(FTDI, OPENDCC_GBM, 0),
+ UFTDI_DEV(FTDI, OPENDCC_SNIFFER, 0),
+ UFTDI_DEV(FTDI, OPENDCC_THROTTLE, 0),
+ UFTDI_DEV(FTDI, PCDJ_DAC2, 0),
+ UFTDI_DEV(FTDI, PCMSFU, 0),
+ UFTDI_DEV(FTDI, PERLE_ULTRAPORT, 0),
+ UFTDI_DEV(FTDI, PHI_FISCO, 0),
+ UFTDI_DEV(FTDI, PIEGROUP, 0),
+ UFTDI_DEV(FTDI, PROPOX_JTAGCABLEII, 0),
+ UFTDI_DEV(FTDI, R2000KU_TRUE_RNG, 0),
+ UFTDI_DEV(FTDI, R2X0, 0),
+ UFTDI_DEV(FTDI, RELAIS, 0),
+ UFTDI_DEV(FTDI, REU_TINY, 0),
+ UFTDI_DEV(FTDI, RMP200, 0),
+ UFTDI_DEV(FTDI, RM_CANVIEW, 0),
+ UFTDI_DEV(FTDI, RRCIRKITS_LOCOBUFFER, 0),
+ UFTDI_DEV(FTDI, SCIENCESCOPE_HS_LOGBOOK, 0),
+ UFTDI_DEV(FTDI, SCIENCESCOPE_LOGBOOKML, 0),
+ UFTDI_DEV(FTDI, SCIENCESCOPE_LS_LOGBOOK, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_0, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_1, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_2, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_3, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_4, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_5, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_6, 0),
+ UFTDI_DEV(FTDI, SCS_DEVICE_7, 0),
+ UFTDI_DEV(FTDI, SCX8_USB_PHOENIX, 0),
+ UFTDI_DEV(FTDI, SDMUSBQSS, 0),
+ UFTDI_DEV(FTDI, SEMC_DSS20, 0),
+ UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_JTAG_CHECK_STRING),
+ UFTDI_DEV(FTDI, SERIAL_2232D, 0),
+ UFTDI_DEV(FTDI, SERIAL_232RL, 0),
+ UFTDI_DEV(FTDI, SERIAL_4232H, 0),
+ UFTDI_DEV(FTDI, SERIAL_8U100AX, 0),
+ UFTDI_DEV(FTDI, SERIAL_8U232AM, 0),
+ UFTDI_DEV(FTDI, SERIAL_8U232AM4, 0),
+ UFTDI_DEV(FTDI, SIGNALYZER_SH2, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, SIGNALYZER_SH4, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, SIGNALYZER_SLITE, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, SIGNALYZER_ST, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, SPECIAL_1, 0),
+ UFTDI_DEV(FTDI, SPECIAL_3, 0),
+ UFTDI_DEV(FTDI, SPECIAL_4, 0),
+ UFTDI_DEV(FTDI, SPROG_II, 0),
+ UFTDI_DEV(FTDI, SR_RADIO, 0),
+ UFTDI_DEV(FTDI, SUUNTO_SPORTS, 0),
+ UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13M, 0),
+ UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13S, 0),
+ UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13U, 0),
+ UFTDI_DEV(FTDI, TAVIR_STK500, 0),
+ UFTDI_DEV(FTDI, TERATRONIK_D2XX, 0),
+ UFTDI_DEV(FTDI, TERATRONIK_VCP, 0),
+ UFTDI_DEV(FTDI, THORLABS, 0),
+ UFTDI_DEV(FTDI, TNC_X, 0),
+ UFTDI_DEV(FTDI, TTUSB, 0),
+ UFTDI_DEV(FTDI, TURTELIZER2, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, UOPTBR, 0),
+ UFTDI_DEV(FTDI, USBSERIAL, 0),
+ UFTDI_DEV(FTDI, USBX_707, 0),
+ UFTDI_DEV(FTDI, USB_UIRT, 0),
+ UFTDI_DEV(FTDI, USINT_CAT, 0),
+ UFTDI_DEV(FTDI, USINT_RS232, 0),
+ UFTDI_DEV(FTDI, USINT_WKEY, 0),
+ UFTDI_DEV(FTDI, VARDAAN, 0),
+ UFTDI_DEV(FTDI, VNHCPCUSB_D, 0),
+ UFTDI_DEV(FTDI, WESTREX_MODEL_777, 0),
+ UFTDI_DEV(FTDI, WESTREX_MODEL_8900F, 0),
+ UFTDI_DEV(FTDI, XDS100V2, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, XDS100V3, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(FTDI, XF_547, 0),
+ UFTDI_DEV(FTDI, XF_640, 0),
+ UFTDI_DEV(FTDI, XF_642, 0),
+ UFTDI_DEV(FTDI, XM_RADIO, 0),
+ UFTDI_DEV(FTDI, YEI_SERVOCENTER31, 0),
+ UFTDI_DEV(GNOTOMETRICS, USB, 0),
+ UFTDI_DEV(ICOM, SP1, 0),
+ UFTDI_DEV(ICOM, OPC_U_UC, 0),
+ UFTDI_DEV(ICOM, RP2C1, 0),
+ UFTDI_DEV(ICOM, RP2C2, 0),
+ UFTDI_DEV(ICOM, RP2D, 0),
+ UFTDI_DEV(ICOM, RP2KVR, 0),
+ UFTDI_DEV(ICOM, RP2KVT, 0),
+ UFTDI_DEV(ICOM, RP2VR, 0),
+ UFTDI_DEV(ICOM, RP2VT, 0),
+ UFTDI_DEV(ICOM, RP4KVR, 0),
+ UFTDI_DEV(ICOM, RP4KVT, 0),
+ UFTDI_DEV(IDTECH, IDT1221U, 0),
+ UFTDI_DEV(INTERBIOMETRICS, IOBOARD, 0),
+ UFTDI_DEV(INTERBIOMETRICS, MINI_IOBOARD, 0),
+ UFTDI_DEV(INTREPIDCS, NEOVI, 0),
+ UFTDI_DEV(INTREPIDCS, VALUECAN, 0),
+ UFTDI_DEV(IONICS, PLUGCOMPUTER, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(JETI, SPC1201, 0),
+ UFTDI_DEV(KOBIL, CONV_B1, 0),
+ UFTDI_DEV(KOBIL, CONV_KAAN, 0),
+ UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, 0),
+ UFTDI_DEV(MARVELL, SHEEVAPLUG, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0103, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0104, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0105, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0106, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0107, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0108, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0109, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0110, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0111, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0112, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0113, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0114, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0115, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0116, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0117, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0118, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0119, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0120, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0121, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0122, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0123, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0124, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0125, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0126, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0128, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0129, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0130, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0131, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0132, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0133, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0134, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0135, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0136, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0137, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0138, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0139, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0140, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0141, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0142, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0143, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0144, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0145, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0146, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0147, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0148, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0149, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0150, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0151, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0152, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0159, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0160, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0161, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0162, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0163, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0164, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0165, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0166, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0167, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0168, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0169, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0170, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0171, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0172, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0173, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0174, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0175, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0176, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0177, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0178, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0179, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0180, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0181, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0182, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0183, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0184, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0185, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0186, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0187, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0188, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0189, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0190, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0191, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0192, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0193, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0194, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0195, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0196, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0197, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0198, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0199, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019A, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019B, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019C, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019D, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019E, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019F, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AD, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AF, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BD, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BF, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CD, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CF, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DD, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DF, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01ED, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EF, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F0, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F1, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F2, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F3, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F4, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F5, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F6, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F7, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F8, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F9, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FA, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FB, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FC, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FD, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FE, 0),
+ UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FF, 0),
+ UFTDI_DEV(MATRIXORBITAL, MOUA, 0),
+ UFTDI_DEV(MELCO, PCOPRS1, 0),
+ UFTDI_DEV(METAGEEK, TELLSTICK, 0),
+ UFTDI_DEV(MOBILITY, USB_SERIAL, 0),
+ UFTDI_DEV(OLIMEX, ARM_USB_OCD, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(OLIMEX, ARM_USB_OCD_H, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(OPTO, CRD7734, 0),
+ UFTDI_DEV(OPTO, CRD7734_1, 0),
+ UFTDI_DEV(PAPOUCH, AD4USB, 0),
+ UFTDI_DEV(PAPOUCH, AP485, 0),
+ UFTDI_DEV(PAPOUCH, AP485_2, 0),
+ UFTDI_DEV(PAPOUCH, DRAK5, 0),
+ UFTDI_DEV(PAPOUCH, DRAK6, 0),
+ UFTDI_DEV(PAPOUCH, GMSR, 0),
+ UFTDI_DEV(PAPOUCH, GMUX, 0),
+ UFTDI_DEV(PAPOUCH, IRAMP, 0),
+ UFTDI_DEV(PAPOUCH, LEC, 0),
+ UFTDI_DEV(PAPOUCH, MU, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO10X1, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO2X16, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO2X2, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO30X3, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO3X32, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO4X4, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO60X3, 0),
+ UFTDI_DEV(PAPOUCH, QUIDO8X8, 0),
+ UFTDI_DEV(PAPOUCH, SB232, 0),
+ UFTDI_DEV(PAPOUCH, SB422, 0),
+ UFTDI_DEV(PAPOUCH, SB422_2, 0),
+ UFTDI_DEV(PAPOUCH, SB485, 0),
+ UFTDI_DEV(PAPOUCH, SB485C, 0),
+ UFTDI_DEV(PAPOUCH, SB485S, 0),
+ UFTDI_DEV(PAPOUCH, SB485_2, 0),
+ UFTDI_DEV(PAPOUCH, SIMUKEY, 0),
+ UFTDI_DEV(PAPOUCH, TMU, 0),
+ UFTDI_DEV(PAPOUCH, UPSUSB, 0),
+ UFTDI_DEV(POSIFLEX, PP7000, 0),
+ UFTDI_DEV(QIHARDWARE, JTAGSERIAL, UFTDI_JTAG_IFACE(0)),
+ UFTDI_DEV(RATOC, REXUSB60F, 0),
+ UFTDI_DEV(RTSYSTEMS, CT29B, 0),
+ UFTDI_DEV(RTSYSTEMS, SERIAL_VX7, 0),
+ UFTDI_DEV(SEALEVEL, 2101, 0),
+ UFTDI_DEV(SEALEVEL, 2102, 0),
+ UFTDI_DEV(SEALEVEL, 2103, 0),
+ UFTDI_DEV(SEALEVEL, 2104, 0),
+ UFTDI_DEV(SEALEVEL, 2106, 0),
+ UFTDI_DEV(SEALEVEL, 2201_1, 0),
+ UFTDI_DEV(SEALEVEL, 2201_2, 0),
+ UFTDI_DEV(SEALEVEL, 2202_1, 0),
+ UFTDI_DEV(SEALEVEL, 2202_2, 0),
+ UFTDI_DEV(SEALEVEL, 2203_1, 0),
+ UFTDI_DEV(SEALEVEL, 2203_2, 0),
+ UFTDI_DEV(SEALEVEL, 2401_1, 0),
+ UFTDI_DEV(SEALEVEL, 2401_2, 0),
+ UFTDI_DEV(SEALEVEL, 2401_3, 0),
+ UFTDI_DEV(SEALEVEL, 2401_4, 0),
+ UFTDI_DEV(SEALEVEL, 2402_1, 0),
+ UFTDI_DEV(SEALEVEL, 2402_2, 0),
+ UFTDI_DEV(SEALEVEL, 2402_3, 0),
+ UFTDI_DEV(SEALEVEL, 2402_4, 0),
+ UFTDI_DEV(SEALEVEL, 2403_1, 0),
+ UFTDI_DEV(SEALEVEL, 2403_2, 0),
+ UFTDI_DEV(SEALEVEL, 2403_3, 0),
+ UFTDI_DEV(SEALEVEL, 2403_4, 0),
+ UFTDI_DEV(SEALEVEL, 2801_1, 0),
+ UFTDI_DEV(SEALEVEL, 2801_2, 0),
+ UFTDI_DEV(SEALEVEL, 2801_3, 0),
+ UFTDI_DEV(SEALEVEL, 2801_4, 0),
+ UFTDI_DEV(SEALEVEL, 2801_5, 0),
+ UFTDI_DEV(SEALEVEL, 2801_6, 0),
+ UFTDI_DEV(SEALEVEL, 2801_7, 0),
+ UFTDI_DEV(SEALEVEL, 2801_8, 0),
+ UFTDI_DEV(SEALEVEL, 2802_1, 0),
+ UFTDI_DEV(SEALEVEL, 2802_2, 0),
+ UFTDI_DEV(SEALEVEL, 2802_3, 0),
+ UFTDI_DEV(SEALEVEL, 2802_4, 0),
+ UFTDI_DEV(SEALEVEL, 2802_5, 0),
+ UFTDI_DEV(SEALEVEL, 2802_6, 0),
+ UFTDI_DEV(SEALEVEL, 2802_7, 0),
+ UFTDI_DEV(SEALEVEL, 2802_8, 0),
+ UFTDI_DEV(SEALEVEL, 2803_1, 0),
+ UFTDI_DEV(SEALEVEL, 2803_2, 0),
+ UFTDI_DEV(SEALEVEL, 2803_3, 0),
+ UFTDI_DEV(SEALEVEL, 2803_4, 0),
+ UFTDI_DEV(SEALEVEL, 2803_5, 0),
+ UFTDI_DEV(SEALEVEL, 2803_6, 0),
+ UFTDI_DEV(SEALEVEL, 2803_7, 0),
+ UFTDI_DEV(SEALEVEL, 2803_8, 0),
+ UFTDI_DEV(SIIG2, DK201, 0),
+ UFTDI_DEV(SIIG2, US2308, 0),
+ UFTDI_DEV(TESTO, USB_INTERFACE, 0),
+ UFTDI_DEV(TML, USB_SERIAL, 0),
+ UFTDI_DEV(TTI, QL355P, 0),
+ UFTDI_DEV(UNKNOWN4, NF_RIC, 0),
#undef UFTDI_DEV
};
+/*
+ * Jtag product name strings table. Some products have one or more interfaces
+ * dedicated to jtag or gpio, but use a product ID that's the same as other
+ * products which don't. They are marked with a flag in the table above, and
+ * the following string table is checked for flagged products. The string check
+ * is done with strstr(); in effect there is an implicit wildcard at the
+ * beginning and end of each product name string in table.
+ */
+static const struct jtag_by_name {
+ const char * product_name;
+ uint32_t jtag_interfaces;
+} jtag_products_by_name[] = {
+ /* TI Beaglebone and TI XDS100Vn jtag product line. */
+ {"XDS100V", UFTDI_JTAG_IFACE(0)},
+};
+
+/*
+ * Set up a sysctl and tunable to en/disable the feature of skipping the
+ * creation of tty devices for jtag interfaces. Enabled by default.
+ */
+static int skip_jtag_interfaces = 1;
+TUNABLE_INT("hw.usb.uftdi.skip_jtag_interfaces", &skip_jtag_interfaces);
+SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, skip_jtag_interfaces, CTLFLAG_RWTUN,
+ &skip_jtag_interfaces, 1, "Skip creating tty devices for jtag interfaces");
+
+static boolean_t
+is_jtag_interface(struct usb_attach_arg *uaa, const struct usb_device_id *id)
+{
+ int i, iface_bit;
+ const char * product_name;
+ const struct jtag_by_name *jbn;
+
+ /* We only allocate 8 flag bits for jtag interface flags. */
+ if (uaa->info.bIfaceIndex >= UFTDI_JTAG_IFACES_MAX)
+ return (0);
+ iface_bit = UFTDI_JTAG_IFACE(uaa->info.bIfaceIndex);
+
+ /*
+ * If requested, search the name strings table and use the interface
+ * bits from that table when the product name string matches, else use
+ * the jtag interface bits from the main ID table.
+ */
+ if ((id->driver_info & UFTDI_JTAG_MASK) == UFTDI_JTAG_CHECK_STRING) {
+ product_name = usb_get_product(uaa->device);
+ for (i = 0; i < nitems(jtag_products_by_name); i++) {
+ jbn = &jtag_products_by_name[i];
+ if (strstr(product_name, jbn->product_name) != NULL &&
+ (jbn->jtag_interfaces & iface_bit) != 0)
+ return (1);
+ }
+ } else if ((id->driver_info & iface_bit) != 0)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Set up softc fields whose value depends on the device type.
+ *
+ * Note that the 2232C and 2232D devices are the same for our purposes. In the
+ * silicon the difference is that the D series has CPU FIFO mode and C doesn't.
+ * I haven't found any way of determining the C/D difference from info provided
+ * by the chip other than trying to set CPU FIFO mode and having it work or not.
+ *
+ * Due to a hardware bug, a 232B chip without an eeprom reports itself as a
+ * 232A, but if the serial number is also zero we know it's really a 232B.
+ */
+static void
+uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa)
+{
+ struct usb_device_descriptor *dd;
+
+ sc->sc_bcdDevice = uaa->info.bcdDevice;
+
+ switch (uaa->info.bcdDevice) {
+ case 0x200:
+ dd = usbd_get_device_descriptor(sc->sc_udev);
+ if (dd->iSerialNumber == 0) {
+ sc->sc_devtype = DEVT_232B;
+ } else {
+ sc->sc_devtype = DEVT_232A;
+ }
+ sc->sc_ucom.sc_portno = 0;
+ break;
+ case 0x400:
+ sc->sc_devtype = DEVT_232B;
+ sc->sc_ucom.sc_portno = 0;
+ break;
+ case 0x500:
+ sc->sc_devtype = DEVT_2232D;
+ sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
+ sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+ break;
+ case 0x600:
+ sc->sc_devtype = DEVT_232R;
+ sc->sc_ucom.sc_portno = 0;
+ break;
+ case 0x700:
+ sc->sc_devtype = DEVT_2232H;
+ sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+ sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+ break;
+ case 0x800:
+ sc->sc_devtype = DEVT_4232H;
+ sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+ sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+ break;
+ case 0x900:
+ sc->sc_devtype = DEVT_232H;
+ sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+ sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+ break;
+ case 0x1000:
+ sc->sc_devtype = DEVT_230X;
+ sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
+ sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+ break;
+ default:
+ if (uaa->info.bcdDevice < 0x200) {
+ sc->sc_devtype = DEVT_SIO;
+ sc->sc_hdrlen = 1;
+ } else {
+ sc->sc_devtype = DEVT_232R;
+ device_printf(sc->sc_dev, "Warning: unknown FTDI "
+ "device type, bcdDevice=0x%04x, assuming 232R\n",
+ uaa->info.bcdDevice);
+ }
+ sc->sc_ucom.sc_portno = 0;
+ break;
+ }
+}
+
static int
uftdi_probe(device_t dev)
{
@@ -865,10 +1066,12 @@
&uaa->info);
if (id == NULL)
return (ENXIO);
- if ((id->driver_info & UFTDI_FLAG_JTAG) != 0 &&
- uaa->info.bIfaceIndex == UFTDI_IFACE_INDEX_JTAG) {
- printf("%s: skipping JTAG interface at %u.%u\n",
- device_get_name(dev), usbd_get_bus_index(uaa->device),
+ if (skip_jtag_interfaces && is_jtag_interface(uaa, id)) {
+ printf("%s: skipping JTAG interface #%d for '%s' at %u.%u\n",
+ device_get_name(dev),
+ uaa->info.bIfaceIndex,
+ usb_get_product(uaa->device),
+ usbd_get_bus_index(uaa->device),
usbd_get_device_index(uaa->device));
return (ENXIO);
}
@@ -883,6 +1086,8 @@
struct uftdi_softc *sc = device_get_softc(dev);
int error;
+ DPRINTF("\n");
+
sc->sc_udev = uaa->device;
sc->sc_dev = dev;
sc->sc_unit = device_get_unit(dev);
@@ -891,34 +1096,11 @@
mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
ucom_ref(&sc->sc_super_ucom);
- DPRINTF("\n");
- sc->sc_iface_index = uaa->info.bIfaceIndex;
- sc->sc_type = USB_GET_DRIVER_INFO(uaa) & UFTDI_TYPE_MASK;
+ uftdi_devtype_setup(sc, uaa);
- switch (sc->sc_type) {
- case UFTDI_TYPE_AUTO:
- /* simplified type check */
- if (uaa->info.bcdDevice >= 0x0200 ||
- usbd_get_iface(uaa->device, 1) != NULL) {
- sc->sc_type = UFTDI_TYPE_8U232AM;
- sc->sc_hdrlen = 0;
- } else {
- sc->sc_type = UFTDI_TYPE_SIO;
- sc->sc_hdrlen = 1;
- }
- break;
- case UFTDI_TYPE_SIO:
- sc->sc_hdrlen = 1;
- break;
- case UFTDI_TYPE_8U232AM:
- default:
- sc->sc_hdrlen = 0;
- break;
- }
-
error = usbd_transfer_setup(uaa->device,
- &sc->sc_iface_index, sc->sc_xfer, uftdi_config,
+ &uaa->info.bIfaceIndex, sc->sc_xfer, uftdi_config,
UFTDI_N_TRANSFER, sc, &sc->sc_mtx);
if (error) {
@@ -926,8 +1108,6 @@
"transfers failed\n");
goto detach;
}
- sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
-
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_WR]);
@@ -990,37 +1170,25 @@
static void
uftdi_cfg_open(struct ucom_softc *ucom)
{
- struct uftdi_softc *sc = ucom->sc_parent;
- uint16_t wIndex = ucom->sc_portno;
- struct usb_device_request req;
+ /*
+ * This do-nothing open routine exists for the sole purpose of this
+ * DPRINTF() so that you can see the point at which open gets called
+ * when debugging is enabled.
+ */
DPRINTF("");
+}
- /* perform a full reset on the device */
+static void
+uftdi_cfg_close(struct ucom_softc *ucom)
+{
- req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
- req.bRequest = FTDI_SIO_RESET;
- USETW(req.wValue, FTDI_SIO_RESET_SIO);
- USETW(req.wIndex, wIndex);
- USETW(req.wLength, 0);
- ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
- &req, NULL, 0, 1000);
-
- /* 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, wIndex);
- USETW(req.wLength, 0);
- ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
- &req, NULL, 0, 1000);
-
/*
- * NOTE: with the new UCOM layer there will always be a
- * "uftdi_cfg_param()" call after "open()", so there is no need for
- * "open()" to configure anything
+ * This do-nothing close routine exists for the sole purpose of this
+ * DPRINTF() so that you can see the point at which close gets called
+ * when debugging is enabled.
*/
+ DPRINTF("");
}
static void
@@ -1028,35 +1196,53 @@
{
struct uftdi_softc *sc = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
- uint32_t actlen;
+ uint32_t pktlen;
+ uint32_t buflen;
uint8_t buf[1];
switch (USB_GET_STATE(xfer)) {
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ }
+ /* FALLTHROUGH */
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
-tr_setup:
+ /*
+ * If output packets don't require headers (the common case) we
+ * can just load the buffer up with payload bytes all at once.
+ * Otherwise, loop to format packets into the buffer while there
+ * is data available, and room for a packet header and at least
+ * one byte of payload.
+ *
+ * NOTE: The FTDI chip doesn't accept zero length
+ * packets. This cannot happen because the "pktlen"
+ * will always be non-zero when "ucom_get_data()"
+ * returns non-zero which we check below.
+ */
pc = usbd_xfer_get_frame(xfer, 0);
- if (ucom_get_data(&sc->sc_ucom, pc,
- sc->sc_hdrlen, UFTDI_OBUFSIZE - sc->sc_hdrlen,
- &actlen)) {
-
- if (sc->sc_hdrlen > 0) {
- buf[0] =
- FTDI_OUT_TAG(actlen, sc->sc_ucom.sc_portno);
- usbd_copy_in(pc, 0, buf, 1);
+ if (sc->sc_hdrlen == 0) {
+ if (ucom_get_data(&sc->sc_ucom, pc, 0, UFTDI_OBUFSIZE,
+ &buflen) == 0)
+ break;
+ } else {
+ buflen = 0;
+ while (buflen < UFTDI_OBUFSIZE - sc->sc_hdrlen - 1 &&
+ ucom_get_data(&sc->sc_ucom, pc, buflen +
+ sc->sc_hdrlen, UFTDI_OPKTSIZE - sc->sc_hdrlen,
+ &pktlen) != 0) {
+ buf[0] = FTDI_OUT_TAG(pktlen,
+ sc->sc_ucom.sc_portno);
+ usbd_copy_in(pc, buflen, buf, 1);
+ buflen += pktlen + sc->sc_hdrlen;
}
- usbd_xfer_set_frame_len(xfer, 0, actlen + sc->sc_hdrlen);
+ }
+ if (buflen != 0) {
+ usbd_xfer_set_frame_len(xfer, 0, buflen);
usbd_transfer_submit(xfer);
}
- return;
-
- default: /* Error */
- if (error != USB_ERR_CANCELLED) {
- /* try to clear stall first */
- usbd_xfer_set_stall(xfer);
- goto tr_setup;
- }
- return;
+ break;
}
}
@@ -1069,23 +1255,47 @@
uint8_t ftdi_msr;
uint8_t msr;
uint8_t lsr;
- int actlen;
+ int buflen;
+ int pktlen;
+ int pktmax;
+ int offset;
- usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+ usbd_xfer_status(xfer, &buflen, NULL, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
- if (actlen < 2) {
+ if (buflen < UFTDI_IHDRSIZE)
goto tr_setup;
+ pc = usbd_xfer_get_frame(xfer, 0);
+ pktmax = xfer->max_packet_size - UFTDI_IHDRSIZE;
+ lsr = 0;
+ msr = 0;
+ offset = 0;
+ /*
+ * Extract packet headers and payload bytes from the buffer.
+ * Feed payload bytes to ucom/tty layer; OR-accumulate header
+ * status bits which are transient and could toggle with each
+ * packet. After processing all packets in the buffer, process
+ * the accumulated transient MSR and LSR values along with the
+ * non-transient bits from the last packet header.
+ */
+ while (buflen >= UFTDI_IHDRSIZE) {
+ usbd_copy_out(pc, offset, buf, UFTDI_IHDRSIZE);
+ offset += UFTDI_IHDRSIZE;
+ buflen -= UFTDI_IHDRSIZE;
+ lsr |= FTDI_GET_LSR(buf);
+ if (FTDI_GET_MSR(buf) & FTDI_SIO_RI_MASK)
+ msr |= SER_RI;
+ pktlen = min(buflen, pktmax);
+ if (pktlen != 0) {
+ ucom_put_data(&sc->sc_ucom, pc, offset,
+ pktlen);
+ offset += pktlen;
+ buflen -= pktlen;
+ }
}
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_out(pc, 0, buf, 2);
-
ftdi_msr = FTDI_GET_MSR(buf);
- lsr = FTDI_GET_LSR(buf);
- msr = 0;
if (ftdi_msr & FTDI_SIO_CTS_MASK)
msr |= SER_CTS;
if (ftdi_msr & FTDI_SIO_DSR_MASK)
@@ -1106,11 +1316,7 @@
ucom_status_change(&sc->sc_ucom);
}
- actlen -= 2;
-
- if (actlen > 0) {
- ucom_put_data(&sc->sc_ucom, pc, 2, actlen);
- }
+ /* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
@@ -1190,58 +1396,162 @@
&req, NULL, 0, 1000);
}
+/*
+ * Return true if the given speed is within operational tolerance of the target
+ * speed. FTDI recommends that the hardware speed be within 3% of nominal.
+ */
+static inline boolean_t
+uftdi_baud_within_tolerance(uint64_t speed, uint64_t target)
+{
+ return ((speed >= (target * 100) / 103) &&
+ (speed <= (target * 100) / 97));
+}
+
static int
-uftdi_set_parm_soft(struct termios *t,
- struct uftdi_param_config *cfg, uint8_t type)
+uftdi_sio_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
+ struct uftdi_param_config *cfg)
{
+ u_int i;
+ const speed_t sio_speeds[] = {
+ 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
+ };
- memset(cfg, 0, sizeof(*cfg));
-
- switch (type) {
- case UFTDI_TYPE_SIO:
- switch (t->c_ospeed) {
- case 300:
- cfg->rate = ftdi_sio_b300;
- break;
- case 600:
- cfg->rate = ftdi_sio_b600;
- break;
- case 1200:
- cfg->rate = ftdi_sio_b1200;
- break;
- case 2400:
- cfg->rate = ftdi_sio_b2400;
- break;
- case 4800:
- cfg->rate = ftdi_sio_b4800;
- break;
- case 9600:
- cfg->rate = ftdi_sio_b9600;
- break;
- case 19200:
- cfg->rate = ftdi_sio_b19200;
- break;
- case 38400:
- cfg->rate = ftdi_sio_b38400;
- break;
- case 57600:
- cfg->rate = ftdi_sio_b57600;
- break;
- case 115200:
- cfg->rate = ftdi_sio_b115200;
- break;
- default:
- return (EINVAL);
+ /*
+ * The original SIO chips were limited to a small choice of speeds
+ * listed in an internal table of speeds chosen by an index value.
+ */
+ for (i = 0; i < nitems(sio_speeds); ++i) {
+ if (speed == sio_speeds[i]) {
+ cfg->baud_lobits = i;
+ cfg->baud_hibits = 0;
+ return (0);
}
- break;
+ }
+ return (ERANGE);
+}
- case UFTDI_TYPE_8U232AM:
- if (uftdi_8u232am_getrate(t->c_ospeed, &cfg->rate)) {
- return (EINVAL);
- }
- break;
+static int
+uftdi_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
+ struct uftdi_param_config *cfg)
+{
+ static const uint8_t encoded_fraction[8] = {0, 3, 2, 4, 1, 5, 6, 7};
+ static const uint8_t roundoff_232a[16] = {
+ 0, 1, 0, 1, 0, -1, 2, 1,
+ 0, -1, -2, -3, 4, 3, 2, 1,
+ };
+ uint32_t clk, divisor, fastclk_flag, frac, hwspeed;
+
+ /*
+ * If this chip has the fast clock capability and the speed is within
+ * range, use the 12MHz clock, otherwise the standard clock is 3MHz.
+ */
+ if ((sc->sc_devflags & DEVF_BAUDCLK_12M) && speed >= 1200) {
+ clk = 12000000;
+ fastclk_flag = (1 << 17);
+ } else {
+ clk = 3000000;
+ fastclk_flag = 0;
}
+ /*
+ * Make sure the requested speed is reachable with the available clock
+ * and a 14-bit divisor.
+ */
+ if (speed < (clk >> 14) || speed > clk)
+ return (ERANGE);
+
+ /*
+ * Calculate the divisor, initially yielding a fixed point number with a
+ * 4-bit (1/16ths) fraction, then round it to the nearest fraction the
+ * hardware can handle. When the integral part of the divisor is
+ * greater than one, the fractional part is in 1/8ths of the base clock.
+ * The FT8U232AM chips can handle only 0.125, 0.250, and 0.5 fractions.
+ * Later chips can handle all 1/8th fractions.
+ *
+ * If the integral part of the divisor is 1, a special rule applies: the
+ * fractional part can only be .0 or .5 (this is a limitation of the
+ * hardware). We handle this by truncating the fraction rather than
+ * rounding, because this only applies to the two fastest speeds the
+ * chip can achieve and rounding doesn't matter, either you've asked for
+ * that exact speed or you've asked for something the chip can't do.
+ *
+ * For the FT8U232AM chips, use a roundoff table to adjust the result
+ * to the nearest 1/8th fraction that is supported by the hardware,
+ * leaving a fixed-point number with a 3-bit fraction which exactly
+ * represents the math the hardware divider will do. For later-series
+ * chips that support all 8 fractional divisors, just round 16ths to
+ * 8ths by adding 1 and dividing by 2.
+ */
+ divisor = (clk << 4) / speed;
+ if ((divisor & 0xf) == 1)
+ divisor &= 0xfffffff8;
+ else if (sc->sc_devtype == DEVT_232A)
+ divisor += roundoff_232a[divisor & 0x0f];
+ else
+ divisor += 1; /* Rounds odd 16ths up to next 8th. */
+ divisor >>= 1;
+
+ /*
+ * Ensure the resulting hardware speed will be within operational
+ * tolerance (within 3% of nominal).
+ */
+ hwspeed = (clk << 3) / divisor;
+ if (!uftdi_baud_within_tolerance(hwspeed, speed))
+ return (ERANGE);
+
+ /*
+ * Re-pack the divisor into hardware format. The lower 14-bits hold the
+ * integral part, while the upper bits specify the fraction by indexing
+ * a table of fractions within the hardware which is laid out as:
+ * {0.0, 0.5, 0.25, 0.125, 0.325, 0.625, 0.725, 0.875}
+ * The A-series chips only have the first four table entries; the
+ * roundoff table logic above ensures that the fractional part for those
+ * chips will be one of the first four values.
+ *
+ * When the divisor is 1 a special encoding applies: 1.0 is encoded as
+ * 0.0, and 1.5 is encoded as 1.0. The rounding logic above has already
+ * ensured that the fraction is either .0 or .5 if the integral is 1.
+ */
+ frac = divisor & 0x07;
+ divisor >>= 3;
+ if (divisor == 1) {
+ if (frac == 0)
+ divisor = 0; /* 1.0 becomes 0.0 */
+ else
+ frac = 0; /* 1.5 becomes 1.0 */
+ }
+ divisor |= (encoded_fraction[frac] << 14) | fastclk_flag;
+
+ cfg->baud_lobits = (uint16_t)divisor;
+ cfg->baud_hibits = (uint16_t)(divisor >> 16);
+
+ /*
+ * If this chip requires the baud bits to be in the high byte of the
+ * index word, move the bits up to that location.
+ */
+ if (sc->sc_devflags & DEVF_BAUDBITS_HINDEX) {
+ cfg->baud_hibits <<= 8;
+ }
+
+ return (0);
+}
+
+static int
+uftdi_set_parm_soft(struct ucom_softc *ucom, struct termios *t,
+ struct uftdi_param_config *cfg)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ int err;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ if (sc->sc_devtype == DEVT_SIO)
+ err = uftdi_sio_encode_baudrate(sc, t->c_ospeed, cfg);
+ else
+ err = uftdi_encode_baudrate(sc, t->c_ospeed, cfg);
+ if (err != 0)
+ return (err);
+
if (t->c_cflag & CSTOPB)
cfg->lcr = FTDI_SIO_SET_DATA_STOP_BITS_2;
else
@@ -1291,12 +1601,11 @@
static int
uftdi_pre_param(struct ucom_softc *ucom, struct termios *t)
{
- struct uftdi_softc *sc = ucom->sc_parent;
struct uftdi_param_config cfg;
DPRINTF("\n");
- return (uftdi_set_parm_soft(t, &cfg, sc->sc_type));
+ return (uftdi_set_parm_soft(ucom, t, &cfg));
}
static void
@@ -1307,7 +1616,7 @@
struct uftdi_param_config cfg;
struct usb_device_request req;
- if (uftdi_set_parm_soft(t, &cfg, sc->sc_type)) {
+ if (uftdi_set_parm_soft(ucom, t, &cfg)) {
/* should not happen */
return;
}
@@ -1317,8 +1626,8 @@
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_BAUD_RATE;
- USETW(req.wValue, cfg.rate);
- USETW(req.wIndex, wIndex);
+ USETW(req.wValue, cfg.baud_lobits);
+ USETW(req.wIndex, cfg.baud_hibits | wIndex);
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
@@ -1352,6 +1661,187 @@
*lsr = sc->sc_lsr;
}
+static int
+uftdi_reset(struct ucom_softc *ucom, int reset_type)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_RESET;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 0);
+ USETW(req.wValue, reset_type);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_set_bitmode(struct ucom_softc *ucom, uint8_t bitmode, uint8_t iomask)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_SET_BITMODE;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 0);
+
+ if (bitmode == UFTDI_BITMODE_NONE)
+ USETW2(req.wValue, 0, 0);
+ else
+ USETW2(req.wValue, (1 << bitmode), iomask);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *iomask)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_GET_BITMODE;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 1);
+ USETW(req.wValue, 0);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, iomask));
+}
+
+static int
+uftdi_set_latency(struct ucom_softc *ucom, int latency)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+
+ if (latency < 0 || latency > 255)
+ return (USB_ERR_INVAL);
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_SET_LATENCY;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 0);
+ USETW2(req.wValue, 0, latency);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_get_latency(struct ucom_softc *ucom, int *latency)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ usb_error_t err;
+ uint8_t buf;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_GET_LATENCY;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 1);
+ USETW(req.wValue, 0);
+
+ err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &buf);
+ *latency = buf;
+
+ return (err);
+}
+
+static int
+uftdi_set_event_char(struct ucom_softc *ucom, int echar)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ uint8_t enable;
+
+ enable = (echar == -1) ? 0 : 1;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_SET_EVENT_CHAR;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 0);
+ USETW2(req.wValue, enable, echar & 0xff);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_set_error_char(struct ucom_softc *ucom, int echar)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ uint8_t enable;
+
+ enable = (echar == -1) ? 0 : 1;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_SET_ERROR_CHAR;
+
+ USETW(req.wIndex, sc->sc_ucom.sc_portno);
+ USETW(req.wLength, 0);
+ USETW2(req.wValue, enable, echar & 0xff);
+
+ return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
+ int flag, struct thread *td)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ int err;
+ struct uftdi_bitmode * mode;
+
+ DPRINTF("portno: %d cmd: %#x\n", ucom->sc_portno, cmd);
+
+ switch (cmd) {
+ case UFTDIIOC_RESET_IO:
+ case UFTDIIOC_RESET_RX:
+ case UFTDIIOC_RESET_TX:
+ err = uftdi_reset(ucom,
+ cmd == UFTDIIOC_RESET_IO ? FTDI_SIO_RESET_SIO :
+ (cmd == UFTDIIOC_RESET_RX ? FTDI_SIO_RESET_PURGE_RX :
+ FTDI_SIO_RESET_PURGE_TX));
+ break;
+ case UFTDIIOC_SET_BITMODE:
+ mode = (struct uftdi_bitmode *)data;
+ err = uftdi_set_bitmode(ucom, mode->mode, mode->iomask);
+ break;
+ case UFTDIIOC_GET_BITMODE:
+ mode = (struct uftdi_bitmode *)data;
+ err = uftdi_get_bitmode(ucom, &mode->iomask);
+ break;
+ case UFTDIIOC_SET_LATENCY:
+ err = uftdi_set_latency(ucom, *((int *)data));
+ break;
+ case UFTDIIOC_GET_LATENCY:
+ err = uftdi_get_latency(ucom, (int *)data);
+ break;
+ case UFTDIIOC_SET_ERROR_CHAR:
+ err = uftdi_set_error_char(ucom, *(int *)data);
+ break;
+ case UFTDIIOC_SET_EVENT_CHAR:
+ err = uftdi_set_event_char(ucom, *(int *)data);
+ break;
+ case UFTDIIOC_GET_HWREV:
+ *(int *)data = sc->sc_bcdDevice;
+ err = 0;
+ break;
+ default:
+ return (ENOIOCTL);
+ }
+ if (err != USB_ERR_NORMAL_COMPLETION)
+ return (EIO);
+ return (0);
+}
+
static void
uftdi_start_read(struct ucom_softc *ucom)
{
@@ -1384,75 +1874,6 @@
usbd_transfer_stop(sc->sc_xfer[UFTDI_BULK_DT_WR]);
}
-/*------------------------------------------------------------------------*
- * uftdi_8u232am_getrate
- *
- * Return values:
- * 0: Success
- * Else: Failure
- *------------------------------------------------------------------------*/
-static uint8_t
-uftdi_8u232am_getrate(uint32_t speed, uint16_t *rate)
-{
- /* Table of the nearest even powers-of-2 for values 0..15. */
- static const uint8_t roundoff[16] = {
- 0, 2, 2, 4, 4, 4, 8, 8,
- 8, 8, 8, 8, 16, 16, 16, 16,
- };
- uint32_t d;
- uint32_t freq;
- uint16_t result;
-
- if ((speed < 178) || (speed > ((3000000 * 100) / 97)))
- return (1); /* prevent numerical overflow */
-
- /* 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 < ((FTDI_8U232AM_FREQ * 1600ULL) / 103)) ||
- (freq > ((FTDI_8U232AM_FREQ * 1600ULL) / 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 void
uftdi_poll(struct ucom_softc *ucom)
{
Modified: stable/0.8/sys/dev/usb/serial/uftdi_reg.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/uftdi_reg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uftdi_reg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/uftdi_reg.h 273888 2014-10-31 08:00:22Z hselasky $ */
/*
* Definitions for the FTDI USB Single Port Serial Converter -
@@ -28,6 +28,10 @@
* reg */
#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
+#define FTDI_SIO_SET_LATENCY 9 /* Set the latency timer */
+#define FTDI_SIO_GET_LATENCY 10 /* Read the latency timer */
+#define FTDI_SIO_SET_BITMODE 11 /* Set the bit bang I/O mode */
+#define FTDI_SIO_GET_BITMODE 12 /* Read pin states in bit bang mode */
/* Port Identifier Table */
#define FTDI_PIT_DEFAULT 0 /* SIOA */
@@ -36,12 +40,10 @@
#define FTDI_PIT_PARALLEL 3 /* Parallel */
/* Values for driver_info */
-#define UFTDI_TYPE_MASK 0x000000ff
-#define UFTDI_TYPE_SIO 0x00000001
-#define UFTDI_TYPE_8U232AM 0x00000002
-#define UFTDI_TYPE_AUTO (UFTDI_TYPE_SIO | UFTDI_TYPE_8U232AM)
-#define UFTDI_FLAG_MASK 0x0000ff00
-#define UFTDI_FLAG_JTAG 0x00000100
+#define UFTDI_JTAG_IFACE(i) (1 << i) /* Flag interface as jtag */
+#define UFTDI_JTAG_IFACES_MAX 8 /* Allow up to 8 jtag intfs */
+#define UFTDI_JTAG_CHECK_STRING 0xff /* Check product names table */
+#define UFTDI_JTAG_MASK 0xff
/*
* BmRequestType: 0100 0000B
@@ -75,31 +77,13 @@
/*
* BmRequestType: 0100 0000B
* bRequest: FTDI_SIO_SET_BAUDRATE
- * wValue: BaudRate value - see below
- * wIndex: Port
+ * wValue: BaudRate low bits
+ * wIndex: Port and BaudRate high bits
* 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
Modified: stable/0.8/sys/dev/usb/serial/ugensa.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ugensa.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ugensa.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/ugensa.c 240659 2012-09-18 16:28:49Z hselasky $ */
/* $NetBSD: ugensa.c,v 1.9.2.1 2007/03/24 14:55:50 yamt Exp $ */
/*
Modified: stable/0.8/sys/dev/usb/serial/uipaq.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uipaq.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uipaq.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uipaq.c 240659 2012-09-18 16:28:49Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
Modified: stable/0.8/sys/dev/usb/serial/ulpt.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ulpt.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ulpt.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ulpt.c 248085 2013-03-09 02:36:32Z marius $");
/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */
Modified: stable/0.8/sys/dev/usb/serial/umcs.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umcs.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umcs.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -38,7 +38,7 @@
*
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umcs.c 269721 2014-08-08 14:56:04Z joerg $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -121,8 +121,6 @@
uint8_t sc_lcr; /* local line control register */
uint8_t sc_mcr; /* local modem control register */
- uint8_t sc_lsr; /* local line status register */
- uint8_t sc_msr; /* local modem status register */
};
struct umcs7840_softc {
@@ -535,12 +533,7 @@
if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_control, data))
return;
- /* Read LSR & MSR */
- if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
- return;
- if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
- return;
- DPRINTF("Port %d has been opened, LSR=%02x MSR=%02x\n", pn, sc->sc_ports[pn].sc_lsr, sc->sc_ports[pn].sc_msr);
+ DPRINTF("Port %d has been opened\n", pn);
}
static void
@@ -748,9 +741,17 @@
umcs7840_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
{
struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+ uint8_t hw_lsr = 0; /* local line status register */
+ uint8_t hw_msr = 0; /* local modem status register */
- *lsr = sc->sc_ports[ucom->sc_portno].sc_lsr;
- *msr = sc->sc_ports[ucom->sc_portno].sc_msr;
+ /* Read LSR & MSR */
+ umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &hw_lsr);
+ umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &hw_msr);
+
+ *lsr = hw_lsr;
+ *msr = hw_msr;
+
DPRINTF("Port %d status: LSR=%02x MSR=%02x\n", ucom->sc_portno, *lsr, *msr);
}
@@ -781,21 +782,11 @@
case MCS7840_UART_ISR_RXERR:
case MCS7840_UART_ISR_RXHASDATA:
case MCS7840_UART_ISR_RXTIMEOUT:
- /* Read new LSR */
- if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
- break; /* Inner switch */
+ case MCS7840_UART_ISR_MSCHANGE:
ucom_status_change(&sc->sc_ucom[subunit]);
- /* Inner switch */
break;
- case MCS7840_UART_ISR_TXEMPTY:
+ default:
/* Do nothing */
- break; /* Inner switch */
- case MCS7840_UART_ISR_MSCHANGE:
- /* Read new MSR */
- if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
- break; /* Inner switch */
- DPRINTF("Port %d: new MSR %02x\n", pn, sc->sc_ports[pn].sc_msr);
- ucom_status_change(&sc->sc_ucom[subunit]);
break;
}
}
@@ -1092,7 +1083,10 @@
for (i = 0; i < umcs7840_baudrate_divisors_len - 1 &&
!(rate > umcs7840_baudrate_divisors[i] && rate <= umcs7840_baudrate_divisors[i + 1]); ++i);
- *divisor = umcs7840_baudrate_divisors[i + 1] / rate;
+ if (rate == 0)
+ *divisor = 1; /* XXX */
+ else
+ *divisor = umcs7840_baudrate_divisors[i + 1] / rate;
/* 0x00 .. 0x70 */
*clk = i << MCS7840_DEV_SPx_CLOCK_SHIFT;
return (0);
Modified: stable/0.8/sys/dev/usb/serial/umcs.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/umcs.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umcs.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/umcs.h 222696 2011-06-04 20:40:24Z hselasky $ */
/*-
* Copyright (c) 2010 Lev Serebryakov <lev at FreeBSD.org>.
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/serial/umct.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umct.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umct.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umct.c 240659 2012-09-18 16:28:49Z hselasky $");
/*-
* Copyright (c) 2003 Scott Long
Modified: stable/0.8/sys/dev/usb/serial/umodem.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umodem.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umodem.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umodem.c 277410 2015-01-20 05:14:07Z hselasky $");
/*-
* Copyright (c) 2003, M. Warner Losh <imp at FreeBSD.org>.
@@ -45,13 +45,6 @@
* 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
@@ -105,6 +98,7 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usb_cdc.h>
#include "usbdevs.h"
+#include "usb_if.h"
#include <dev/usb/usb_ioctl.h>
@@ -123,13 +117,16 @@
&umodem_debug, 0, "Debug level");
#endif
-static const STRUCT_USB_HOST_ID umodem_devs[] = {
+static const STRUCT_USB_DUAL_ID umodem_dual_devs[] = {
/* Generic Modem class match */
{USB_IFACE_CLASS(UICLASS_CDC),
USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
USB_IFACE_PROTOCOL(UIPROTO_CDC_AT)},
+};
+
+static const STRUCT_USB_HOST_ID umodem_host_devs[] = {
/* Huawei Modem class match */
- {USB_IFACE_CLASS(UICLASS_CDC),
+ {USB_VENDOR(USB_VENDOR_HUAWEI),USB_IFACE_CLASS(UICLASS_CDC),
USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
USB_IFACE_PROTOCOL(0xFF)},
/* Kyocera AH-K3001V */
@@ -149,6 +146,7 @@
enum {
UMODEM_BULK_WR,
UMODEM_BULK_RD,
+ UMODEM_INTR_WR,
UMODEM_INTR_RD,
UMODEM_N_TRANSFER,
};
@@ -173,14 +171,19 @@
uint8_t sc_cm_over_data;
uint8_t sc_cm_cap; /* CM capabilities */
uint8_t sc_acm_cap; /* ACM capabilities */
+ uint8_t sc_line_coding[32]; /* used in USB device mode */
+ uint8_t sc_abstract_state[32]; /* used in USB device mode */
};
static device_probe_t umodem_probe;
static device_attach_t umodem_attach;
static device_detach_t umodem_detach;
+static usb_handle_request_t umodem_handle_request;
+
static void umodem_free_softc(struct umodem_softc *);
-static usb_callback_t umodem_intr_callback;
+static usb_callback_t umodem_intr_read_callback;
+static usb_callback_t umodem_intr_write_callback;
static usb_callback_t umodem_write_callback;
static usb_callback_t umodem_read_callback;
@@ -211,31 +214,45 @@
[UMODEM_BULK_WR] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
+ .direction = UE_DIR_TX,
.if_index = 0,
.bufsize = UMODEM_BUF_SIZE,
.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
.callback = &umodem_write_callback,
+ .usb_mode = USB_MODE_DUAL,
},
[UMODEM_BULK_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
+ .direction = UE_DIR_RX,
.if_index = 0,
.bufsize = UMODEM_BUF_SIZE,
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.callback = &umodem_read_callback,
+ .usb_mode = USB_MODE_DUAL,
},
+ [UMODEM_INTR_WR] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_TX,
+ .if_index = 1,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umodem_intr_write_callback,
+ .usb_mode = USB_MODE_DEVICE,
+ },
+
[UMODEM_INTR_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
+ .direction = UE_DIR_RX,
.if_index = 1,
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
.bufsize = 0, /* use wMaxPacketSize */
- .callback = &umodem_intr_callback,
+ .callback = &umodem_intr_read_callback,
+ .usb_mode = USB_MODE_HOST,
},
};
@@ -256,6 +273,10 @@
};
static device_method_t umodem_methods[] = {
+ /* USB interface */
+ DEVMETHOD(usb_handle_request, umodem_handle_request),
+
+ /* Device interface */
DEVMETHOD(device_probe, umodem_probe),
DEVMETHOD(device_attach, umodem_attach),
DEVMETHOD(device_detach, umodem_detach),
@@ -283,13 +304,14 @@
DPRINTFN(11, "\n");
- if (uaa->usb_mode != USB_MODE_HOST)
- return (ENXIO);
-
- error = usbd_lookup_id_by_uaa(umodem_devs, sizeof(umodem_devs), uaa);
- if (error)
- return (error);
-
+ error = usbd_lookup_id_by_uaa(umodem_host_devs,
+ sizeof(umodem_host_devs), uaa);
+ if (error) {
+ error = usbd_lookup_id_by_uaa(umodem_dual_devs,
+ sizeof(umodem_dual_devs), uaa);
+ if (error)
+ return (error);
+ }
return (BUS_PROBE_GENERIC);
}
@@ -404,18 +426,22 @@
umodem_config, UMODEM_N_TRANSFER,
sc, &sc->sc_mtx);
if (error) {
+ device_printf(dev, "Can't setup transfer\n");
goto detach;
}
- /* clear stall at first run */
- mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
- mtx_unlock(&sc->sc_mtx);
+ /* clear stall at first run, if USB host mode */
+ if (uaa->usb_mode == USB_MODE_HOST) {
+ mtx_lock(&sc->sc_mtx);
+ usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
+ usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
+ mtx_unlock(&sc->sc_mtx);
+ }
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
&umodem_callback, &sc->sc_mtx);
if (error) {
+ device_printf(dev, "Can't attach com\n");
goto detach;
}
ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
@@ -486,6 +512,7 @@
{
struct umodem_softc *sc = ucom->sc_parent;
+ usbd_transfer_start(sc->sc_xfer[UMODEM_INTR_WR]);
usbd_transfer_start(sc->sc_xfer[UMODEM_BULK_WR]);
}
@@ -494,6 +521,7 @@
{
struct umodem_softc *sc = ucom->sc_parent;
+ usbd_transfer_stop(sc->sc_xfer[UMODEM_INTR_WR]);
usbd_transfer_stop(sc->sc_xfer[UMODEM_BULK_WR]);
}
@@ -688,8 +716,35 @@
}
static void
-umodem_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+umodem_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
+ int actlen;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+
+ DPRINTF("Transferred %d bytes\n", actlen);
+
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ break;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* start clear stall */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ break;
+ }
+}
+
+static void
+umodem_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
struct usb_cdc_notification pkt;
struct umodem_softc *sc = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
@@ -910,3 +965,56 @@
struct umodem_softc *sc = ucom->sc_parent;
usbd_transfer_poll(sc->sc_xfer, UMODEM_N_TRANSFER);
}
+
+static int
+umodem_handle_request(device_t dev,
+ const void *preq, void **pptr, uint16_t *plen,
+ uint16_t offset, uint8_t *pstate)
+{
+ struct umodem_softc *sc = device_get_softc(dev);
+ const struct usb_device_request *req = preq;
+ uint8_t is_complete = *pstate;
+
+ DPRINTF("sc=%p\n", sc);
+
+ if (!is_complete) {
+ if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+ (req->bRequest == UCDC_SET_LINE_CODING) &&
+ (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+ (req->wIndex[1] == 0x00) &&
+ (req->wValue[0] == 0x00) &&
+ (req->wValue[1] == 0x00)) {
+ if (offset == 0) {
+ *plen = sizeof(sc->sc_line_coding);
+ *pptr = &sc->sc_line_coding;
+ } else {
+ *plen = 0;
+ }
+ return (0);
+ } else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+ (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+ (req->wIndex[1] == 0x00) &&
+ (req->bRequest == UCDC_SET_COMM_FEATURE)) {
+ if (offset == 0) {
+ *plen = sizeof(sc->sc_abstract_state);
+ *pptr = &sc->sc_abstract_state;
+ } else {
+ *plen = 0;
+ }
+ return (0);
+ } else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+ (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+ (req->wIndex[1] == 0x00) &&
+ (req->bRequest == UCDC_SET_CONTROL_LINE_STATE)) {
+ *plen = 0;
+ return (0);
+ } else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+ (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+ (req->wIndex[1] == 0x00) &&
+ (req->bRequest == UCDC_SEND_BREAK)) {
+ *plen = 0;
+ return (0);
+ }
+ }
+ return (ENXIO); /* use builtin handler */
+}
Modified: stable/0.8/sys/dev/usb/serial/umoscom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umoscom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umoscom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/umoscom.c 248085 2013-03-09 02:36:32Z marius $ */
/* $OpenBSD: umoscom.c,v 1.2 2006/10/26 06:02:43 jsg Exp $ */
/*
Modified: stable/0.8/sys/dev/usb/serial/uplcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uplcom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uplcom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
/* $NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uplcom.c 305557 2016-09-07 19:21:52Z dim $");
/*-
* Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -44,13 +44,6 @@
* 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
@@ -173,7 +166,7 @@
/* prototypes */
static usb_error_t uplcom_reset(struct uplcom_softc *, struct usb_device *);
-static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t,
+static usb_error_t uplcom_pl2303_do(struct usb_device *, uint8_t, uint8_t,
uint16_t, uint16_t, uint16_t);
static int uplcom_pl2303_init(struct usb_device *, uint8_t);
static void uplcom_free(struct ucom_softc *);
@@ -520,7 +513,7 @@
}
static usb_error_t
-uplcom_pl2303_do(struct usb_device *udev, int8_t req_type, uint8_t request,
+uplcom_pl2303_do(struct usb_device *udev, uint8_t req_type, uint8_t request,
uint16_t value, uint16_t index, uint16_t length)
{
struct usb_device_request req;
Modified: stable/0.8/sys/dev/usb/serial/usb_serial.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/usb_serial.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/usb_serial.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/usb_serial.c 268208 2014-07-03 08:07:37Z hselasky $");
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -46,13 +46,6 @@
* 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
@@ -210,7 +203,7 @@
mtx_destroy(&ucom_mtx);
}
-SYSUNINIT(ucom_uninit, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL);
+SYSUNINIT(ucom_uninit, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_uninit, NULL);
/*
* Mark a unit number (the X in cuaUX) as in use.
@@ -965,7 +958,7 @@
sc->sc_pls_set = 0;
sc->sc_pls_clr = 0;
- /* ensure that we don't loose any levels */
+ /* ensure that we don't lose any levels */
if (notch_bits & UCOM_LS_DTR)
sc->sc_callback->ucom_cfg_set_dtr(sc,
(prev_value & UCOM_LS_DTR) ? 1 : 0);
Modified: stable/0.8/sys/dev/usb/serial/usb_serial.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/usb_serial.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/usb_serial.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/usb_serial.h 268208 2014-07-03 08:07:37Z hselasky $ */
/*-
* Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -43,13 +43,6 @@
* 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
@@ -146,7 +139,7 @@
struct ucom_softc {
/*
- * NOTE: To avoid loosing level change information we use two
+ * NOTE: To avoid losing level change information we use two
* tasks instead of one for all commands.
*
* Level changes are transitions like:
@@ -202,7 +195,7 @@
#define UCOM_MTX_LOCK(sc) mtx_lock((sc)->sc_mtx)
#define UCOM_MTX_UNLOCK(sc) mtx_unlock((sc)->sc_mtx)
#define UCOM_UNLOAD_DRAIN(x) \
-SYSUNINIT(var, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_drain_all, 0)
+SYSUNINIT(var, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_drain_all, 0)
#define ucom_cfg_do_request(udev,com,req,ptr,flags,timo) \
usbd_do_request_proc(udev,&(com)->sc_super->sc_tq,req,ptr,flags,NULL,timo)
Modified: stable/0.8/sys/dev/usb/serial/uslcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uslcom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uslcom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uslcom.c 263166 2014-03-14 10:18:53Z hselasky $");
/*
* Copyright (c) 2006 Jonathan Gray <jsg at openbsd.org>
@@ -242,15 +242,37 @@
USLCOM_DEV(JABLOTRON, PC60B),
USLCOM_DEV(KAMSTRUP, OPTICALEYE),
USLCOM_DEV(KAMSTRUP, MBUS_250D),
+ USLCOM_DEV(LAKESHORE, 121),
+ USLCOM_DEV(LAKESHORE, 218A),
+ USLCOM_DEV(LAKESHORE, 219),
+ USLCOM_DEV(LAKESHORE, 233),
+ USLCOM_DEV(LAKESHORE, 235),
+ USLCOM_DEV(LAKESHORE, 335),
+ USLCOM_DEV(LAKESHORE, 336),
+ USLCOM_DEV(LAKESHORE, 350),
+ USLCOM_DEV(LAKESHORE, 371),
+ USLCOM_DEV(LAKESHORE, 411),
+ USLCOM_DEV(LAKESHORE, 425),
+ USLCOM_DEV(LAKESHORE, 455A),
+ USLCOM_DEV(LAKESHORE, 465),
+ USLCOM_DEV(LAKESHORE, 475A),
+ USLCOM_DEV(LAKESHORE, 625A),
+ USLCOM_DEV(LAKESHORE, 642A),
+ USLCOM_DEV(LAKESHORE, 648),
+ USLCOM_DEV(LAKESHORE, 737),
+ USLCOM_DEV(LAKESHORE, 776),
USLCOM_DEV(LINKINSTRUMENTS, MSO19),
USLCOM_DEV(LINKINSTRUMENTS, MSO28),
USLCOM_DEV(LINKINSTRUMENTS, MSO28_2),
USLCOM_DEV(MEI, CASHFLOW_SC),
USLCOM_DEV(MEI, S2000),
+ USLCOM_DEV(NETGEAR, M4100),
USLCOM_DEV(OWEN, AC4),
+ USLCOM_DEV(OWL, CM_160),
USLCOM_DEV(PHILIPS, ACE1001),
USLCOM_DEV(PLX, CA42),
USLCOM_DEV(RENESAS, RX610),
+ USLCOM_DEV(SEL, C662),
USLCOM_DEV(SILABS, AC_SERV_CAN),
USLCOM_DEV(SILABS, AC_SERV_CIS),
USLCOM_DEV(SILABS, AC_SERV_IBUS),
@@ -283,6 +305,7 @@
USLCOM_DEV(SILABS, HELICOM),
USLCOM_DEV(SILABS, IMS_USB_RS422),
USLCOM_DEV(SILABS, INFINITY_MIC),
+ USLCOM_DEV(SILABS, INGENI_ZIGBEE),
USLCOM_DEV(SILABS, INSYS_MODEM),
USLCOM_DEV(SILABS, IRZ_SG10),
USLCOM_DEV(SILABS, KYOCERA_GPS),
@@ -290,6 +313,7 @@
USLCOM_DEV(SILABS, LIPOWSKY_JTAG),
USLCOM_DEV(SILABS, LIPOWSKY_LIN),
USLCOM_DEV(SILABS, MC35PU),
+ USLCOM_DEV(SILABS, MMB_ZIGBEE),
USLCOM_DEV(SILABS, MJS_TOSLINK),
USLCOM_DEV(SILABS, MSD_DASHHAWK),
USLCOM_DEV(SILABS, MULTIPLEX_RC),
@@ -306,6 +330,7 @@
USLCOM_DEV(SILABS, USBPULSE100),
USLCOM_DEV(SILABS, USBSCOPE50),
USLCOM_DEV(SILABS, USBWAVE12),
+ USLCOM_DEV(SILABS, V_PREON32),
USLCOM_DEV(SILABS, VSTABI),
USLCOM_DEV(SILABS, WAVIT),
USLCOM_DEV(SILABS, WMRBATT),
@@ -320,6 +345,7 @@
USLCOM_DEV(VAISALA, CABLE),
USLCOM_DEV(WAGO, SERVICECABLE),
USLCOM_DEV(WAVESENSE, JAZZ),
+ USLCOM_DEV(WESTMOUNTAIN, RIGBLASTER_ADVANTAGE),
USLCOM_DEV(WIENERPLEINBAUS, PL512),
USLCOM_DEV(WIENERPLEINBAUS, RCM),
USLCOM_DEV(WIENERPLEINBAUS, MPOD),
Modified: stable/0.8/sys/dev/usb/serial/uvisor.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uvisor.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uvisor.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/uvisor.c 248085 2013-03-09 02:36:32Z marius $ */
/* Also already merged from NetBSD:
* $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
Modified: stable/0.8/sys/dev/usb/serial/uvscom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uvscom.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uvscom.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
/* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uvscom.c 248085 2013-03-09 02:36:32Z marius $");
/*-
* Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
Modified: stable/0.8/sys/dev/usb/storage/rio500_usb.h
===================================================================
--- stable/0.8/sys/dev/usb/storage/rio500_usb.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/rio500_usb.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -20,7 +20,7 @@
---------------------------------------------------------------------- */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/storage/rio500_usb.h 196219 2009-08-14 20:03:53Z jhb $ */
#include <sys/ioccom.h>
#ifndef USB_VENDOR_DIAMOND
Modified: stable/0.8/sys/dev/usb/storage/umass.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/umass.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/umass.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/storage/umass.c 255663 2013-09-18 06:38:40Z hselasky $");
/*-
* Copyright (c) 1999 MAEKAWA Masahide <bishop at rr.iij4u.or.jp>,
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/storage/umass.c 255663 2013-09-18 06:38:40Z hselasky $
* $NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $
*/
@@ -1320,10 +1320,12 @@
}
sc->cbw.bCDBLength = sc->sc_transfer.cmd_len;
+ /* copy SCSI command data */
memcpy(sc->cbw.CBWCDB, sc->sc_transfer.cmd_data,
sc->sc_transfer.cmd_len);
- memset(sc->sc_transfer.cmd_data +
+ /* clear remaining command area */
+ memset(sc->cbw.CBWCDB +
sc->sc_transfer.cmd_len, 0,
sizeof(sc->cbw.CBWCDB) -
sc->sc_transfer.cmd_len);
Modified: stable/0.8/sys/dev/usb/storage/urio.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/urio.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/urio.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/storage/urio.c 248085 2013-03-09 02:36:32Z marius $");
/*
Modified: stable/0.8/sys/dev/usb/storage/ustorage_fs.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/ustorage_fs.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/ustorage_fs.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/storage/ustorage_fs.c 260575 2014-01-12 21:21:19Z hselasky $ */
/*-
* Copyright (C) 2003-2005 Alan Stern
* Copyright (C) 2008 Hans Petter Selasky
@@ -74,7 +74,7 @@
/* Define some limits */
#ifndef USTORAGE_FS_BULK_SIZE
-#define USTORAGE_FS_BULK_SIZE (1UL << 17) /* bytes */
+#define USTORAGE_FS_BULK_SIZE (1U << 17) /* bytes */
#endif
#ifndef USTORAGE_FS_MAX_LUN
@@ -85,8 +85,6 @@
#define USTORAGE_QDATA_MAX 40 /* bytes */
#endif
-#define sc_cmd_data sc_cbw.CBWCDB
-
/*
* The SCSI ID string must be exactly 28 characters long
* exluding the terminating zero.
@@ -176,8 +174,9 @@
struct ustorage_fs_softc {
- ustorage_fs_bbb_cbw_t sc_cbw; /* Command Wrapper Block */
- ustorage_fs_bbb_csw_t sc_csw; /* Command Status Block */
+ ustorage_fs_bbb_cbw_t *sc_cbw; /* Command Wrapper Block */
+ ustorage_fs_bbb_csw_t *sc_csw; /* Command Status Block */
+ void *sc_dma_ptr; /* Main data buffer */
struct mtx sc_mtx;
@@ -275,7 +274,6 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
- .flags = {.ext_buffer = 1,},
.callback = &ustorage_fs_t_bbb_command_callback,
.usb_mode = USB_MODE_DEVICE,
},
@@ -295,7 +293,7 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = USTORAGE_FS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
.callback = &ustorage_fs_t_bbb_data_read_callback,
.usb_mode = USB_MODE_DEVICE,
},
@@ -315,7 +313,7 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(ustorage_fs_bbb_csw_t),
- .flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
+ .flags = {.short_xfer_ok = 1},
.callback = &ustorage_fs_t_bbb_status_callback,
.usb_mode = USB_MODE_DEVICE,
},
@@ -409,6 +407,14 @@
"transfers, %s\n", usbd_errstr(err));
goto detach;
}
+
+ sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+ USTORAGE_FS_T_BBB_COMMAND], 0);
+ sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+ USTORAGE_FS_T_BBB_STATUS], 0);
+ sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+ USTORAGE_FS_T_BBB_DATA_READ], 0);
+
/* start Mass Storage State Machine */
mtx_lock(&sc->sc_mtx);
@@ -518,7 +524,7 @@
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
- tag = UGETDW(sc->sc_cbw.dCBWSignature);
+ tag = UGETDW(sc->sc_cbw->dCBWSignature);
if (tag != CBWSIGNATURE) {
/* do nothing */
@@ -525,29 +531,29 @@
DPRINTF("invalid signature 0x%08x\n", tag);
break;
}
- tag = UGETDW(sc->sc_cbw.dCBWTag);
+ tag = UGETDW(sc->sc_cbw->dCBWTag);
/* echo back tag */
- USETDW(sc->sc_csw.dCSWTag, tag);
+ USETDW(sc->sc_csw->dCSWTag, tag);
/* reset status */
- sc->sc_csw.bCSWStatus = 0;
+ sc->sc_csw->bCSWStatus = 0;
/* reset data offset, data length and data remainder */
sc->sc_transfer.offset = 0;
sc->sc_transfer.data_rem =
- UGETDW(sc->sc_cbw.dCBWDataTransferLength);
+ UGETDW(sc->sc_cbw->dCBWDataTransferLength);
/* reset data flags */
sc->sc_transfer.data_short = 0;
/* extract LUN */
- sc->sc_transfer.lun = sc->sc_cbw.bCBWLUN;
+ sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
if (sc->sc_transfer.data_rem == 0) {
sc->sc_transfer.cbw_dir = DIR_NONE;
} else {
- if (sc->sc_cbw.bCBWFlags & CBWFLAGS_IN) {
+ if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
sc->sc_transfer.cbw_dir = DIR_WRITE;
} else {
sc->sc_transfer.cbw_dir = DIR_READ;
@@ -554,8 +560,8 @@
}
}
- sc->sc_transfer.cmd_len = sc->sc_cbw.bCDBLength;
- if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw.CBWCDB)) ||
+ sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
+ if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
(sc->sc_transfer.cmd_len == 0)) {
/* just halt - this is invalid */
DPRINTF("invalid command length %d bytes\n",
@@ -597,9 +603,8 @@
usbd_xfer_set_stall(xfer);
DPRINTF("stall pipe\n");
}
-
- usbd_xfer_set_frame_data(xfer, 0, &sc->sc_cbw,
- sizeof(sc->sc_cbw));
+ usbd_xfer_set_frame_len(xfer, 0,
+ sizeof(ustorage_fs_bbb_cbw_t));
usbd_transfer_submit(xfer);
break;
@@ -616,9 +621,9 @@
goto tr_setup;
}
if (err) {
- if (sc->sc_csw.bCSWStatus == 0) {
+ if (sc->sc_csw->bCSWStatus == 0) {
/* set some default error code */
- sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+ sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
}
if (sc->sc_transfer.cbw_dir == DIR_READ) {
/* dump all data */
@@ -699,6 +704,9 @@
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
+ /* XXX copy data from DMA buffer */
+ memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
+
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.offset += actlen;
@@ -721,8 +729,7 @@
usbd_xfer_set_stall(xfer);
}
- usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
- max_bulk);
+ usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
usbd_transfer_submit(xfer);
break;
@@ -778,8 +785,10 @@
usbd_xfer_set_stall(xfer);
}
- usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
- max_bulk);
+ /* XXX copy data to DMA buffer */
+ memcpy(sc->sc_dma_ptr, sc->sc_transfer.data_ptr, max_bulk);
+
+ usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
usbd_transfer_submit(xfer);
break;
@@ -813,16 +822,15 @@
case USB_ST_SETUP:
tr_setup:
- USETDW(sc->sc_csw.dCSWSignature, CSWSIGNATURE);
- USETDW(sc->sc_csw.dCSWDataResidue, sc->sc_transfer.data_rem);
+ USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
+ USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
if (sc->sc_transfer.data_error) {
sc->sc_transfer.data_error = 0;
usbd_xfer_set_stall(xfer);
}
-
- usbd_xfer_set_frame_data(xfer, 0, &sc->sc_csw,
- sizeof(sc->sc_csw));
+ usbd_xfer_set_frame_len(xfer, 0,
+ sizeof(ustorage_fs_bbb_csw_t));
usbd_transfer_submit(xfer);
break;
@@ -934,17 +942,17 @@
/*
* Get the starting Logical Block Address
*/
- lba = get_be32(&sc->sc_cmd_data[2]);
+ lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the cache)
* but we don't implement it.
*/
- if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
+ if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- vlen = get_be16(&sc->sc_cmd_data[7]);
+ vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
if (vlen == 0) {
goto done;
}
@@ -1092,8 +1100,8 @@
{
uint8_t *buf = sc->sc_transfer.data_ptr;
struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
- uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
- uint8_t pmi = sc->sc_cmd_data[8];
+ uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
+ uint8_t pmi = sc->sc_cbw->CBWCDB[8];
/* Check the PMI and LBA fields */
if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
@@ -1126,7 +1134,7 @@
uint8_t *buf0;
uint16_t len;
uint16_t limit;
- uint8_t mscmnd = sc->sc_cmd_data[0];
+ uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
uint8_t pc;
uint8_t page_code;
uint8_t changeable_values;
@@ -1134,13 +1142,13 @@
buf0 = buf;
- if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
+ if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
/* Mask away DBD */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- pc = sc->sc_cmd_data[2] >> 6;
- page_code = sc->sc_cmd_data[2] & 0x3f;
+ pc = sc->sc_cbw->CBWCDB[2] >> 6;
+ page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
if (pc == 3) {
currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return (1);
@@ -1237,9 +1245,9 @@
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
- immed = sc->sc_cmd_data[1] & 0x01;
- loej = sc->sc_cmd_data[4] & 0x02;
- start = sc->sc_cmd_data[4] & 0x01;
+ immed = sc->sc_cbw->CBWCDB[1] & 0x01;
+ loej = sc->sc_cbw->CBWCDB[4] & 0x02;
+ start = sc->sc_cbw->CBWCDB[4] & 0x01;
if (immed || loej || start) {
/* compile fix */
@@ -1264,8 +1272,8 @@
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
- prevent = sc->sc_cmd_data[4] & 0x01;
- if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
+ prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
+ if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
/* Mask away Prevent */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
@@ -1369,11 +1377,11 @@
* Get the starting Logical Block Address and check that it's not
* too big
*/
- if (sc->sc_cmd_data[0] == SC_READ_6) {
- lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
- get_be16(&sc->sc_cmd_data[2]);
+ if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
+ lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+ get_be16(&sc->sc_cbw->CBWCDB[2]);
} else {
- lba = get_be32(&sc->sc_cmd_data[2]);
+ lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
@@ -1380,7 +1388,7 @@
* cache) and FUA (Force Unit Access = don't read from the
* cache), but we don't implement them.
*/
- if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+ if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
@@ -1427,11 +1435,11 @@
* Get the starting Logical Block Address and check that it's not
* too big.
*/
- if (sc->sc_cmd_data[0] == SC_WRITE_6)
- lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
- get_be16(&sc->sc_cmd_data[2]);
+ if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
+ lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+ get_be16(&sc->sc_cbw->CBWCDB[2]);
else {
- lba = get_be32(&sc->sc_cmd_data[2]);
+ lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
@@ -1439,11 +1447,11 @@
* medium). We don't implement DPO; we implement FUA by
* performing synchronous output.
*/
- if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+ if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- if (sc->sc_cmd_data[1] & 0x08) {
+ if (sc->sc_cbw->CBWCDB[1] & 0x08) {
/* FUA */
/* XXX set SYNC flag here */
}
@@ -1483,7 +1491,7 @@
* there must be something wrong about this SCSI
* command
*/
- sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+ sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
return (1);
}
/* compute the minimum length */
@@ -1519,7 +1527,7 @@
uint16_t mask, uint8_t needs_medium)
{
struct ustorage_fs_lun *currlun;
- uint8_t lun = (sc->sc_cmd_data[1] >> 5);
+ uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
uint8_t i;
/* Verify the length of the command itself */
@@ -1526,11 +1534,11 @@
if (min_cmd_size > sc->sc_transfer.cmd_len) {
DPRINTF("%u > %u\n",
min_cmd_size, sc->sc_transfer.cmd_len);
- sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+ sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
return (1);
}
/* Mask away the LUN */
- sc->sc_cmd_data[1] &= 0x1f;
+ sc->sc_cbw->CBWCDB[1] &= 0x1f;
/* Check if LUN is correct */
if (lun != sc->sc_transfer.lun) {
@@ -1540,7 +1548,7 @@
if (sc->sc_transfer.lun <= sc->sc_last_lun) {
sc->sc_transfer.currlun = currlun =
sc->sc_lun + sc->sc_transfer.lun;
- if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
+ if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
currlun->sense_data = SS_NO_SENSE;
currlun->sense_data_info = 0;
currlun->info_valid = 0;
@@ -1551,8 +1559,8 @@
* else must fail!
*/
if ((currlun->unit_attention_data != SS_NO_SENSE) &&
- (sc->sc_cmd_data[0] != SC_INQUIRY) &&
- (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+ (sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+ (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
currlun->sense_data = currlun->unit_attention_data;
currlun->unit_attention_data = SS_NO_SENSE;
return (1);
@@ -1564,8 +1572,8 @@
* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not.
*/
- if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
- (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+ if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+ (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
return (1);
}
}
@@ -1575,7 +1583,7 @@
* non-zero.
*/
for (i = 0; i != min_cmd_size; i++) {
- if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
+ if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
if (currlun) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
}
@@ -1613,12 +1621,12 @@
sc->sc_transfer.data_ptr = sc->sc_qdata;
DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
- sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
+ sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
- switch (sc->sc_cmd_data[0]) {
+ switch (sc->sc_cbw->CBWCDB[0]) {
case SC_INQUIRY:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+ error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@@ -1633,7 +1641,7 @@
case SC_MODE_SELECT_6:
sc->sc_transfer.cmd_dir = DIR_READ;
- error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+ error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@@ -1649,7 +1657,7 @@
case SC_MODE_SELECT_10:
sc->sc_transfer.cmd_dir = DIR_READ;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_cmd_data[7]), -1U);
+ get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@@ -1664,7 +1672,7 @@
case SC_MODE_SENSE_6:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+ error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@@ -1680,7 +1688,7 @@
case SC_MODE_SENSE_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_cmd_data[7]), -1U);
+ get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@@ -1708,7 +1716,7 @@
break;
case SC_READ_6:
- i = sc->sc_cmd_data[4];
+ i = sc->sc_cbw->CBWCDB[4];
sc->sc_transfer.cmd_dir = DIR_WRITE;
temp = ((i == 0) ? 256UL : i);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1726,7 +1734,7 @@
case SC_READ_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- temp = get_be16(&sc->sc_cmd_data[7]);
+ temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
@@ -1742,10 +1750,10 @@
case SC_READ_12:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- temp = get_be32(&sc->sc_cmd_data[6]);
+ temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
if (temp >= (1UL << (32 - 9))) {
/* numerical overflow */
- sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+ sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
error = 1;
break;
}
@@ -1776,7 +1784,7 @@
case SC_READ_FORMAT_CAPACITIES:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_cmd_data[7]), -1U);
+ get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
if (error) {
break;
}
@@ -1791,7 +1799,7 @@
case SC_REQUEST_SENSE:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+ error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
if (error) {
break;
}
@@ -1860,7 +1868,7 @@
break;
case SC_WRITE_6:
- i = sc->sc_cmd_data[4];
+ i = sc->sc_cbw->CBWCDB[4];
sc->sc_transfer.cmd_dir = DIR_READ;
temp = ((i == 0) ? 256UL : i);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1878,7 +1886,7 @@
case SC_WRITE_10:
sc->sc_transfer.cmd_dir = DIR_READ;
- temp = get_be16(&sc->sc_cmd_data[7]);
+ temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
@@ -1894,10 +1902,10 @@
case SC_WRITE_12:
sc->sc_transfer.cmd_dir = DIR_READ;
- temp = get_be32(&sc->sc_cmd_data[6]);
+ temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
if (temp > (mask9 >> 9)) {
/* numerical overflow */
- sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+ sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
error = 1;
break;
}
Modified: stable/0.8/sys/dev/usb/template/usb_template.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/template/usb_template.c 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
*
@@ -1240,7 +1240,7 @@
return (0);
/* Protect scratch area */
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
uts = udev->scratch.temp_setup;
@@ -1319,7 +1319,7 @@
if (error)
usb_temp_unsetup(udev);
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
return (error);
}
Modified: stable/0.8/sys/dev/usb/template/usb_template.h
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/template/usb_template.h 223467 2011-06-23 07:54:03Z hselasky $ */
/*-
* Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
* All rights reserved.
Modified: stable/0.8/sys/dev/usb/template/usb_template_audio.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_audio.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_audio.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_audio.c 223472 2011-06-23 10:35:45Z hselasky $");
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
Modified: stable/0.8/sys/dev/usb/template/usb_template_cdce.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_cdce.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_cdce.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_cdce.c 223467 2011-06-23 07:54:03Z hselasky $");
/*-
* Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
Modified: stable/0.8/sys/dev/usb/template/usb_template_kbd.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_kbd.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_kbd.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_kbd.c 229103 2011-12-31 14:37:51Z hselasky $");
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
Modified: stable/0.8/sys/dev/usb/template/usb_template_modem.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_modem.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_modem.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_modem.c 229103 2011-12-31 14:37:51Z hselasky $");
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
Modified: stable/0.8/sys/dev/usb/template/usb_template_mouse.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_mouse.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_mouse.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_mouse.c 229103 2011-12-31 14:37:51Z hselasky $");
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
Modified: stable/0.8/sys/dev/usb/template/usb_template_msc.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_msc.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_msc.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_msc.c 223467 2011-06-23 07:54:03Z hselasky $");
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
Modified: stable/0.8/sys/dev/usb/template/usb_template_mtp.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_mtp.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_mtp.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_mtp.c 223467 2011-06-23 07:54:03Z hselasky $");
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
Modified: stable/0.8/sys/dev/usb/ufm_ioctl.h
===================================================================
--- stable/0.8/sys/dev/usb/ufm_ioctl.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/ufm_ioctl.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -28,7 +28,7 @@
* its contributors.
*/
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/ufm_ioctl.h 196219 2009-08-14 20:03:53Z jhb $ */
#include <sys/ioccom.h>
Added: stable/0.8/sys/dev/usb/uftdiio.h
===================================================================
--- stable/0.8/sys/dev/usb/uftdiio.h (rev 0)
+++ stable/0.8/sys/dev/usb/uftdiio.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,75 @@
+/*-
+ * Copyright 2008-2012 - Symmetricom, 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.
+ *
+ * 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: stable/9/sys/dev/usb/uftdiio.h 265050 2014-04-28 13:28:10Z ian $
+ */
+
+/*
+ * FTDI USB serial converter chip ioctl commands.
+ */
+
+#ifndef _USB_UFTDIIO_H_
+#define _USB_UFTDIIO_H_
+
+#include <sys/ioccom.h>
+
+enum uftdi_bitmodes
+{
+ UFTDI_BITMODE_ASYNC = 0,
+ UFTDI_BITMODE_MPSSE = 1,
+ UFTDI_BITMODE_SYNC = 2,
+ UFTDI_BITMODE_CPU_EMUL = 3,
+ UFTDI_BITMODE_FAST_SERIAL = 4,
+ UFTDI_BITMODE_CBUS = 5,
+ UFTDI_BITMODE_NONE = 0xff,
+};
+
+/*
+ * For UFTDIIOC_SET_BITMODE:
+ * mode = One of the uftdi_bitmodes enum values.
+ * iomask = Mask of bits enabled for bitbang output.
+ *
+ * For UFTDIIOC_GET_BITMODE:
+ * mode = Unused.
+ * iomask = Returned snapshot of bitbang pin states at time of call.
+ */
+struct uftdi_bitmode
+{
+ uint8_t mode;
+ uint8_t iomask;
+};
+
+#define UFTDIIOC_RESET_IO _IO('c', 0) /* Reset config, flush fifos.*/
+#define UFTDIIOC_RESET_RX _IO('c', 1) /* Flush input fifo. */
+#define UFTDIIOC_RESET_TX _IO('c', 2) /* Flush output fifo. */
+#define UFTDIIOC_SET_BITMODE _IOW('c', 3, struct uftdi_bitmode)
+#define UFTDIIOC_GET_BITMODE _IOR('c', 4, struct uftdi_bitmode)
+#define UFTDIIOC_SET_ERROR_CHAR _IOW('c', 5, int) /* -1 to disable */
+#define UFTDIIOC_SET_EVENT_CHAR _IOW('c', 6, int) /* -1 to disable */
+#define UFTDIIOC_SET_LATENCY _IOW('c', 7, int) /* 1-255 ms */
+#define UFTDIIOC_GET_LATENCY _IOR('c', 8, int)
+#define UFTDIIOC_GET_HWREV _IOR('c', 9, int)
+
+#endif
Property changes on: stable/0.8/sys/dev/usb/uftdiio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/usb.h
===================================================================
--- stable/0.8/sys/dev/usb/usb.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb.h 282510 2015-05-05 20:00:20Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -493,8 +493,11 @@
#define UICLASS_WIRELESS 0xe0
#define UISUBCLASS_RF 0x01
#define UIPROTO_BLUETOOTH 0x01
+#define UIPROTO_RNDIS 0x03
#define UICLASS_IAD 0xEF /* Interface Association Descriptor */
+#define UISUBCLASS_SYNC 0x01
+#define UIPROTO_ACTIVESYNC 0x01
#define UICLASS_APPL_SPEC 0xfe
#define UISUBCLASS_FIRMWARE_DOWNLOAD 1
@@ -533,6 +536,11 @@
#define UE_ISO_ADAPT 0x08
#define UE_ISO_SYNC 0x0c
#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE)
+#define UE_ISO_USAGE 0x30
+#define UE_ISO_USAGE_DATA 0x00
+#define UE_ISO_USAGE_FEEDBACK 0x10
+#define UE_ISO_USAGE_IMPLICT_FB 0x20
+#define UE_GET_ISO_USAGE(a) ((a) & UE_ISO_USAGE)
uWord wMaxPacketSize;
#define UE_ZERO_MPS 0xFFFF /* for internal use only */
uByte bInterval;
Modified: stable/0.8/sys/dev/usb/usb_bus.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_bus.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_bus.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_bus.h 278291 2015-02-05 21:37:59Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -27,6 +27,8 @@
#ifndef _USB_BUS_H_
#define _USB_BUS_H_
+struct usb_fs_privdata;
+
/*
* The following structure defines the USB explore message sent to the USB
* explore process.
@@ -71,7 +73,12 @@
struct usb_bus_msg attach_msg[2];
struct usb_bus_msg suspend_msg[2];
struct usb_bus_msg resume_msg[2];
+ struct usb_bus_msg reset_msg[2];
struct usb_bus_msg shutdown_msg[2];
+#if USB_HAVE_UGEN
+ struct usb_bus_msg cleanup_msg[2];
+ LIST_HEAD(,usb_fs_privdata) pd_cleanup_list;
+#endif
/*
* This mutex protects the USB hardware:
*/
@@ -103,6 +110,7 @@
uint8_t devices_max; /* maximum number of USB devices */
uint8_t do_probe; /* set if USB should be re-probed */
uint8_t no_explore; /* don't explore USB ports */
+ uint8_t dma_bits; /* number of DMA address lines */
};
#endif /* _USB_BUS_H_ */
Modified: stable/0.8/sys/dev/usb/usb_busdma.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_busdma.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_busdma.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_busdma.c 291251 2015-11-24 12:19:20Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -130,6 +130,35 @@
}
/*------------------------------------------------------------------------*
+ * usb_pc_buffer_is_aligned - verify alignment
+ *
+ * This function is used to check if a page cache buffer is properly
+ * aligned to reduce the use of bounce buffers in PIO mode.
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_buffer_is_aligned(struct usb_page_cache *pc, usb_frlength_t offset,
+ usb_frlength_t len, usb_frlength_t mask)
+{
+ struct usb_page_search buf_res;
+
+ while (len != 0) {
+
+ usbd_get_page(pc, offset, &buf_res);
+
+ if (buf_res.length > len)
+ buf_res.length = len;
+ if (USB_P2U(buf_res.buffer) & mask)
+ return (0);
+ if (buf_res.length & mask)
+ return (0);
+
+ offset += buf_res.length;
+ len -= buf_res.length;
+ }
+ return (1);
+}
+
+/*------------------------------------------------------------------------*
* usbd_copy_in - copy directly to DMA-able memory
*------------------------------------------------------------------------*/
void
@@ -211,9 +240,7 @@
struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
{
struct usb_m_copy_in_arg arg = {cache, dst_offset};
- int error;
-
- error = m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
+ (void) m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
}
#endif
@@ -358,8 +385,7 @@
if (bus_dma_tag_create
( /* parent */ udt->tag_parent->tag,
/* alignment */ align,
- /* boundary */ (align == 1) ?
- USB_PAGE_SIZE : 0,
+ /* boundary */ 0,
/* lowaddr */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
/* highaddr */ BUS_SPACE_MAXADDR,
/* filter */ NULL,
@@ -418,6 +444,7 @@
struct usb_page_cache *pc;
struct usb_page *pg;
usb_size_t rem;
+ bus_size_t off;
uint8_t owned;
pc = arg;
@@ -433,16 +460,21 @@
if (error) {
goto done;
}
+
+ off = 0;
pg = pc->page_start;
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
- nseg--;
#ifdef USB_DEBUG
- if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
+ if (nseg > 1 &&
+ ((segs->ds_addr + segs->ds_len) & (USB_PAGE_SIZE - 1)) !=
+ ((segs + 1)->ds_addr & (USB_PAGE_SIZE - 1))) {
/*
- * This check verifies that the physical address is correct:
+ * This check verifies there is no page offset hole
+ * between the first and second segment. See the
+ * BUS_DMA_KEEP_PG_OFFSET flag.
*/
DPRINTFN(0, "Page offset was not preserved\n");
error = 1;
@@ -449,11 +481,19 @@
goto done;
}
#endif
- while (nseg > 0) {
- nseg--;
- segs++;
+ while (pc->ismultiseg) {
+ off += USB_PAGE_SIZE;
+ if (off >= (segs->ds_len + rem)) {
+ /* page crossing */
+ nseg--;
+ segs++;
+ off = 0;
+ rem = 0;
+ if (nseg == 0)
+ break;
+ }
pg++;
- pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
+ pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
}
done:
Modified: stable/0.8/sys/dev/usb/usb_busdma.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_busdma.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_busdma.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_busdma.h 291063 2015-11-19 09:54:28Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -60,7 +60,7 @@
*/
struct usb_page {
#if USB_HAVE_BUSDMA
- bus_size_t physaddr;
+ bus_addr_t physaddr;
void *buffer; /* non Kernel Virtual Address */
#endif
};
@@ -73,7 +73,7 @@
struct usb_page_search {
void *buffer;
#if USB_HAVE_BUSDMA
- bus_size_t physaddr;
+ bus_addr_t physaddr;
#endif
usb_size_t length;
};
@@ -157,5 +157,8 @@
void usb_pc_cpu_invalidate(struct usb_page_cache *pc);
void usb_pc_dmamap_destroy(struct usb_page_cache *pc);
void usb_pc_free_mem(struct usb_page_cache *pc);
+uint8_t usb_pc_buffer_is_aligned(struct usb_page_cache *pc,
+ usb_frlength_t offset, usb_frlength_t len,
+ usb_frlength_t mask);
#endif /* _USB_BUSDMA_H_ */
Modified: stable/0.8/sys/dev/usb/usb_cdc.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_cdc.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_cdc.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $NetBSD: usbcdc.h,v 1.9 2004/10/23 13:24:24 augustss Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_cdc.h 213809 2010-10-13 22:04:55Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
Modified: stable/0.8/sys/dev/usb/usb_compat_linux.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_compat_linux.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_compat_linux.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_compat_linux.c 254555 2013-08-20 07:28:24Z hselasky $ */
/*-
* Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved.
* Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
@@ -45,7 +45,6 @@
#include <sys/priv.h>
#include <dev/usb/usb.h>
-#include <dev/usb/usb_ioctl.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
Modified: stable/0.8/sys/dev/usb/usb_compat_linux.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_compat_linux.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_compat_linux.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_compat_linux.h 198776 2009-11-01 21:48:18Z thompsa $ */
/*-
* Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved.
* Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
Modified: stable/0.8/sys/dev/usb/usb_controller.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_controller.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_controller.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_controller.h 259602 2013-12-19 07:12:40Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -186,6 +186,7 @@
uint8_t usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, usb_bus_mem_cb_t *cb);
void usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
uint16_t usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr);
+void usb_bus_reset_async_locked(struct usb_bus *bus);
#if USB_HAVE_TT_SUPPORT
uint8_t usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time);
#endif
Modified: stable/0.8/sys/dev/usb/usb_core.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_core.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_core.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_core.c 217265 2011-01-11 13:59:06Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_core.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_core.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_core.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_core.h 278508 2015-02-10 13:18:48Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -97,6 +97,7 @@
* sent */
uint8_t control_act:1; /* set if control transfer is active */
uint8_t control_stall:1; /* set if control transfer should be stalled */
+ uint8_t control_did_data:1; /* set if control DATA has been transferred */
uint8_t short_frames_ok:1; /* filtered version */
uint8_t short_xfer_ok:1; /* filtered version */
@@ -113,6 +114,8 @@
uint8_t can_cancel_immed:1; /* set if USB transfer can be
* cancelled immediately */
uint8_t doing_callback:1; /* set if executing the callback */
+ uint8_t maxp_was_clamped:1; /* set if the max packet size
+ * was outside its allowed range */
};
/*
Modified: stable/0.8/sys/dev/usb/usb_debug.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_debug.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_debug.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_debug.c 242775 2012-11-08 16:13:51Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_debug.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_debug.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_debug.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_debug.h 242775 2012-11-08 16:13:51Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_dev.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_dev.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dev.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dev.c 301254 2016-06-03 08:56:54Z hselasky $ */
/*-
* Copyright (c) 2006-2008 Hans Petter Selasky. All rights reserved.
*
@@ -105,7 +105,7 @@
static int usb_fifo_uiomove(struct usb_fifo *, void *, int,
struct uio *);
static void usb_fifo_check_methods(struct usb_fifo_methods *);
-static struct usb_fifo *usb_fifo_alloc(void);
+static struct usb_fifo *usb_fifo_alloc(struct mtx *);
static struct usb_endpoint *usb_dev_get_ep(struct usb_device *, uint8_t,
uint8_t);
static void usb_loc_fill(struct usb_fs_privdata *,
@@ -120,6 +120,7 @@
static d_read_t usb_read;
static d_write_t usb_write;
static d_poll_t usb_poll;
+static d_kqfilter_t usb_kqfilter;
static d_ioctl_t usb_static_ioctl;
@@ -137,7 +138,8 @@
.d_flags = D_TRACKCLOSE,
.d_read = usb_read,
.d_write = usb_write,
- .d_poll = usb_poll
+ .d_poll = usb_poll,
+ .d_kqfilter = usb_kqfilter,
};
static struct cdev* usb_dev = NULL;
@@ -203,12 +205,18 @@
DPRINTFN(2, "no device at %u\n", cpd->dev_index);
goto error;
}
- if (cpd->udev->refcount == USB_DEV_REF_MAX) {
- DPRINTFN(2, "no dev ref\n");
+ if (cpd->udev->state == USB_STATE_DETACHED &&
+ (need_uref != 2)) {
+ DPRINTFN(2, "device is detached\n");
goto error;
}
if (need_uref) {
DPRINTFN(2, "ref udev - needed\n");
+
+ if (cpd->udev->refcount == USB_DEV_REF_MAX) {
+ DPRINTFN(2, "no dev ref\n");
+ goto error;
+ }
cpd->udev->refcount++;
mtx_unlock(&usb_ref_lock);
@@ -217,7 +225,7 @@
* We need to grab the enumeration SX-lock before
* grabbing the FIFO refs to avoid deadlock at detach!
*/
- crd->do_unlock = usbd_enum_lock(cpd->udev);
+ crd->do_unlock = usbd_enum_lock_sig(cpd->udev);
mtx_lock(&usb_ref_lock);
@@ -225,6 +233,12 @@
* Set "is_uref" after grabbing the default SX lock
*/
crd->is_uref = 1;
+
+ /* check for signal */
+ if (crd->do_unlock > 1) {
+ crd->do_unlock = 0;
+ goto error;
+ }
}
/* check if we are doing an open */
@@ -282,12 +296,15 @@
usbd_enum_unlock(cpd->udev);
if (crd->is_uref) {
- if (--(cpd->udev->refcount) == 0) {
- cv_signal(&cpd->udev->ref_cv);
- }
+ if (--(cpd->udev->refcount) == 0)
+ cv_broadcast(&cpd->udev->ref_cv);
}
mtx_unlock(&usb_ref_lock);
DPRINTFN(2, "fail\n");
+
+ /* clear all refs */
+ memset(crd, 0, sizeof(*crd));
+
return (USB_ERR_INVAL);
}
@@ -350,24 +367,25 @@
crd->is_write = 0;
}
if (crd->is_uref) {
- if (--(cpd->udev->refcount) == 0) {
- cv_signal(&cpd->udev->ref_cv);
- }
crd->is_uref = 0;
+ if (--(cpd->udev->refcount) == 0)
+ cv_broadcast(&cpd->udev->ref_cv);
}
mtx_unlock(&usb_ref_lock);
}
static struct usb_fifo *
-usb_fifo_alloc(void)
+usb_fifo_alloc(struct mtx *mtx)
{
struct usb_fifo *f;
f = malloc(sizeof(*f), M_USBDEV, M_WAITOK | M_ZERO);
- if (f) {
+ if (f != NULL) {
cv_init(&f->cv_io, "FIFO-IO");
cv_init(&f->cv_drain, "FIFO-DRAIN");
+ f->priv_mtx = mtx;
f->refcount = 1;
+ knlist_init_mtx(&f->selinfo.si_note, mtx);
}
return (f);
}
@@ -491,7 +509,7 @@
DPRINTFN(5, "dev_get_endpoint returned NULL\n");
return (EINVAL);
}
- f = usb_fifo_alloc();
+ f = usb_fifo_alloc(&udev->device_mtx);
if (f == NULL) {
DPRINTFN(5, "could not alloc tx fifo\n");
return (ENOMEM);
@@ -499,7 +517,6 @@
/* update some fields */
f->fifo_index = n + USB_FIFO_TX;
f->dev_ep_index = e;
- f->priv_mtx = &udev->device_mtx;
f->priv_sc0 = ep;
f->methods = &usb_ugen_methods;
f->iface_index = ep->iface_index;
@@ -518,7 +535,7 @@
DPRINTFN(5, "dev_get_endpoint returned NULL\n");
return (EINVAL);
}
- f = usb_fifo_alloc();
+ f = usb_fifo_alloc(&udev->device_mtx);
if (f == NULL) {
DPRINTFN(5, "could not alloc rx fifo\n");
return (ENOMEM);
@@ -526,7 +543,6 @@
/* update some fields */
f->fifo_index = n + USB_FIFO_RX;
f->dev_ep_index = e;
- f->priv_mtx = &udev->device_mtx;
f->priv_sc0 = ep;
f->methods = &usb_ugen_methods;
f->iface_index = ep->iface_index;
@@ -579,12 +595,12 @@
/* decrease refcount */
f->refcount--;
- /* prevent any write flush */
- f->flag_iserror = 1;
/* need to wait until all callers have exited */
while (f->refcount != 0) {
mtx_unlock(&usb_ref_lock); /* avoid LOR */
mtx_lock(f->priv_mtx);
+ /* prevent write flush, if any */
+ f->flag_iserror = 1;
/* get I/O thread out of any sleep state */
if (f->flag_sleeping) {
f->flag_sleeping = 0;
@@ -593,6 +609,13 @@
mtx_unlock(f->priv_mtx);
mtx_lock(&usb_ref_lock);
+ /*
+ * Check if the "f->refcount" variable reached zero
+ * during the unlocked time before entering wait:
+ */
+ if (f->refcount == 0)
+ break;
+
/* wait for sync */
cv_wait(&f->cv_drain, &usb_ref_lock);
}
@@ -604,6 +627,10 @@
cv_destroy(&f->cv_io);
cv_destroy(&f->cv_drain);
+ knlist_clear(&f->selinfo.si_note, 0);
+ seldrain(&f->selinfo);
+ knlist_destroy(&f->selinfo.si_note);
+
free(f, M_USBDEV);
}
@@ -758,8 +785,13 @@
mtx_lock(f->priv_mtx);
/* clear current cdev private data pointer */
+ mtx_lock(&usb_ref_lock);
f->curr_cpd = NULL;
+ mtx_unlock(&usb_ref_lock);
+ /* check if we are watched by kevent */
+ KNOTE_LOCKED(&f->selinfo.si_note, 0);
+
/* check if we are selected */
if (f->flag_isselect) {
selwakeup(&f->selinfo);
@@ -801,7 +833,8 @@
(!f->flag_iserror)) {
/* wait until all data has been written */
f->flag_sleeping = 1;
- err = cv_wait_sig(&f->cv_io, f->priv_mtx);
+ err = cv_timedwait_sig(&f->cv_io, f->priv_mtx,
+ USB_MS_TO_TICKS(USB_DEFAULT_TIMEOUT));
if (err) {
DPRINTF("signal received\n");
break;
@@ -911,23 +944,12 @@
DPRINTFN(2, "cpd=%p\n", cpd);
- err = usb_ref_device(cpd, &refs, 0);
- if (err)
+ err = usb_ref_device(cpd, &refs,
+ 2 /* uref and allow detached state */);
+ if (err) {
+ DPRINTFN(2, "Cannot grab USB reference when "
+ "closing USB file handle\n");
goto done;
-
- /*
- * If this function is not called directly from the root HUB
- * thread, there is usually a need to lock the enumeration
- * lock. Check this.
- */
- if (!usbd_enum_is_locked(cpd->udev)) {
-
- DPRINTFN(2, "Locking enumeration\n");
-
- /* reference device */
- err = usb_usb_ref_device(cpd, &refs);
- if (err)
- goto done;
}
if (cpd->fflags & FREAD) {
usb_fifo_close(refs.rxfifo, cpd->fflags);
@@ -1079,8 +1101,8 @@
goto done;
if (usb_usb_ref_device(cpd, &refs)) {
- err = ENXIO;
- goto done;
+ /* we lost the reference */
+ return (ENXIO);
}
err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
@@ -1095,15 +1117,19 @@
/* Wait for re-enumeration, if any */
- while (f->udev->re_enumerate_wait != 0) {
+ while (f->udev->re_enumerate_wait != USB_RE_ENUM_DONE) {
usb_unref_device(cpd, &refs);
usb_pause_mtx(NULL, hz / 128);
- if (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
- err = ENXIO;
- goto done;
+ while (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
+ if (usb_ref_device(cpd, &refs, 0)) {
+ /* device no longer exists */
+ return (ENXIO);
+ }
+ usb_unref_device(cpd, &refs);
+ usb_pause_mtx(NULL, hz / 128);
}
}
@@ -1112,8 +1138,164 @@
return (err);
}
+static void
+usb_filter_detach(struct knote *kn)
+{
+ struct usb_fifo *f = kn->kn_hook;
+ knlist_remove(&f->selinfo.si_note, kn, 0);
+}
+
+static int
+usb_filter_write(struct knote *kn, long hint)
+{
+ struct usb_cdev_privdata* cpd;
+ struct usb_fifo *f;
+ struct usb_mbuf *m;
+
+ DPRINTFN(2, "\n");
+
+ f = kn->kn_hook;
+
+ mtx_assert(f->priv_mtx, MA_OWNED);
+
+ cpd = f->curr_cpd;
+ if (cpd == NULL) {
+ m = (void *)1;
+ } else if (f->fs_ep_max == 0) {
+ if (f->flag_iserror) {
+ /* we got an error */
+ m = (void *)1;
+ } else {
+ if (f->queue_data == NULL) {
+ /*
+ * start write transfer, if not
+ * already started
+ */
+ (f->methods->f_start_write) (f);
+ }
+ /* check if any packets are available */
+ USB_IF_POLL(&f->free_q, m);
+ }
+ } else {
+ if (f->flag_iscomplete) {
+ m = (void *)1;
+ } else {
+ m = NULL;
+ }
+ }
+ return (m ? 1 : 0);
+}
+
+static int
+usb_filter_read(struct knote *kn, long hint)
+{
+ struct usb_cdev_privdata* cpd;
+ struct usb_fifo *f;
+ struct usb_mbuf *m;
+
+ DPRINTFN(2, "\n");
+
+ f = kn->kn_hook;
+
+ mtx_assert(f->priv_mtx, MA_OWNED);
+
+ cpd = f->curr_cpd;
+ if (cpd == NULL) {
+ m = (void *)1;
+ } else if (f->fs_ep_max == 0) {
+ if (f->flag_iserror) {
+ /* we have an error */
+ m = (void *)1;
+ } else {
+ if (f->queue_data == NULL) {
+ /*
+ * start read transfer, if not
+ * already started
+ */
+ (f->methods->f_start_read) (f);
+ }
+ /* check if any packets are available */
+ USB_IF_POLL(&f->used_q, m);
+
+ /* start reading data, if any */
+ if (m == NULL)
+ (f->methods->f_start_read) (f);
+ }
+ } else {
+ if (f->flag_iscomplete) {
+ m = (void *)1;
+ } else {
+ m = NULL;
+ }
+ }
+ return (m ? 1 : 0);
+}
+
+static struct filterops usb_filtops_write = {
+ .f_isfd = 1,
+ .f_detach = usb_filter_detach,
+ .f_event = usb_filter_write,
+};
+
+static struct filterops usb_filtops_read = {
+ .f_isfd = 1,
+ .f_detach = usb_filter_detach,
+ .f_event = usb_filter_read,
+};
+
+
/* ARGSUSED */
static int
+usb_kqfilter(struct cdev* dev, struct knote *kn)
+{
+ struct usb_cdev_refdata refs;
+ struct usb_cdev_privdata* cpd;
+ struct usb_fifo *f;
+ int fflags;
+ int err = EINVAL;
+
+ DPRINTFN(2, "\n");
+
+ if (devfs_get_cdevpriv((void **)&cpd) != 0 ||
+ usb_ref_device(cpd, &refs, 0) != 0)
+ return (ENXIO);
+
+ fflags = cpd->fflags;
+
+ /* Figure out who needs service */
+ switch (kn->kn_filter) {
+ case EVFILT_WRITE:
+ if (fflags & FWRITE) {
+ f = refs.txfifo;
+ kn->kn_fop = &usb_filtops_write;
+ err = 0;
+ }
+ break;
+ case EVFILT_READ:
+ if (fflags & FREAD) {
+ f = refs.rxfifo;
+ kn->kn_fop = &usb_filtops_read;
+ err = 0;
+ }
+ break;
+ default:
+ err = EOPNOTSUPP;
+ break;
+ }
+
+ if (err == 0) {
+ kn->kn_hook = f;
+ mtx_lock(f->priv_mtx);
+ knlist_add(&f->selinfo.si_note, kn, 1);
+ mtx_unlock(f->priv_mtx);
+ }
+
+ usb_unref_device(cpd, &refs);
+ return (err);
+}
+
+/* ARGSUSED */
+static int
usb_poll(struct cdev* dev, int events, struct thread* td)
{
struct usb_cdev_refdata refs;
@@ -1179,7 +1361,7 @@
if (!refs.is_usbfs) {
if (f->flag_iserror) {
- /* we have and error */
+ /* we have an error */
m = (void *)1;
} else {
if (f->queue_data == NULL) {
@@ -1236,9 +1418,9 @@
return (err);
err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
- if (err) {
+ if (err)
return (ENXIO);
- }
+
fflags = cpd->fflags;
f = refs.rxfifo;
@@ -1362,9 +1544,9 @@
return (err);
err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
- if (err) {
+ if (err)
return (ENXIO);
- }
+
fflags = cpd->fflags;
f = refs.txfifo;
@@ -1576,6 +1758,8 @@
{
usb_fifo_signal(f);
+ KNOTE_LOCKED(&f->selinfo.si_note, 0);
+
if (f->flag_isselect) {
selwakeup(&f->selinfo);
f->flag_isselect = 0;
@@ -1691,8 +1875,8 @@
break;
}
- f_tx = usb_fifo_alloc();
- f_rx = usb_fifo_alloc();
+ f_tx = usb_fifo_alloc(priv_mtx);
+ f_rx = usb_fifo_alloc(priv_mtx);
if ((f_tx == NULL) || (f_rx == NULL)) {
usb_fifo_free(f_tx);
@@ -1703,7 +1887,6 @@
f_tx->fifo_index = n + USB_FIFO_TX;
f_tx->dev_ep_index = -1;
- f_tx->priv_mtx = priv_mtx;
f_tx->priv_sc0 = priv_sc;
f_tx->methods = pm;
f_tx->iface_index = iface_index;
@@ -1711,7 +1894,6 @@
f_rx->fifo_index = n + USB_FIFO_RX;
f_rx->dev_ep_index = -1;
- f_rx->priv_mtx = priv_mtx;
f_rx->priv_sc0 = priv_sc;
f_rx->methods = pm;
f_rx->iface_index = iface_index;
Modified: stable/0.8/sys/dev/usb/usb_dev.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_dev.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dev.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dev.h 247090 2013-02-21 07:48:07Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_device.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_device.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_device.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_device.c 310283 2016-12-19 18:32:26Z trasz $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -94,7 +94,7 @@
struct usb_attach_arg *);
static void usb_suspend_resume_sub(struct usb_device *, device_t,
uint8_t);
-static void usbd_clear_stall_proc(struct usb_proc_msg *_pm);
+static usb_proc_callback_t usbd_clear_stall_proc;
static usb_error_t usb_config_parse(struct usb_device *, uint8_t, uint8_t);
static void usbd_set_device_strings(struct usb_device *);
#if USB_HAVE_DEVCTL
@@ -431,6 +431,33 @@
}
/*------------------------------------------------------------------------*
+ * usb_wait_pending_refs
+ *
+ * This function will wait for any USB references to go away before
+ * returning. This function is used before freeing a USB device.
+ *------------------------------------------------------------------------*/
+static void
+usb_wait_pending_refs(struct usb_device *udev)
+{
+#if USB_HAVE_UGEN
+ DPRINTF("Refcount = %d\n", (int)udev->refcount);
+
+ mtx_lock(&usb_ref_lock);
+ udev->refcount--;
+ while (1) {
+ /* wait for any pending references to go away */
+ if (udev->refcount == 0) {
+ /* prevent further refs being taken, if any */
+ udev->refcount = USB_DEV_REF_MAX;
+ break;
+ }
+ cv_wait(&udev->ref_cv, &usb_ref_lock);
+ }
+ mtx_unlock(&usb_ref_lock);
+#endif
+}
+
+/*------------------------------------------------------------------------*
* usb_unconfigure
*
* This function will free all USB interfaces and USB endpoints belonging
@@ -779,9 +806,6 @@
/* find maximum number of endpoints */
if (ep_max < temp)
ep_max = temp;
-
- /* optimalisation */
- id = (struct usb_interface_descriptor *)ed;
}
}
@@ -1035,10 +1059,12 @@
*/
*ppdev = NULL;
- device_printf(dev, "at %s, port %d, addr %d "
- "(disconnected)\n",
- device_get_nameunit(udev->parent_dev),
- udev->port_no, udev->address);
+ if (!rebooting) {
+ device_printf(dev, "at %s, port %d, addr %d "
+ "(disconnected)\n",
+ device_get_nameunit(udev->parent_dev),
+ udev->port_no, udev->address);
+ }
if (device_is_attached(dev)) {
if (udev->flags.peer_suspended) {
@@ -1047,10 +1073,8 @@
device_printf(dev, "Resume failed\n");
}
}
- if (device_detach(dev)) {
- goto error;
- }
}
+ /* detach and delete child */
if (device_delete_child(udev->parent_dev, dev)) {
goto error;
}
@@ -1287,6 +1311,12 @@
*/
if (iface_index == USB_IFACE_INDEX_ANY) {
+ if (usb_test_quirk(&uaa, UQ_MSC_DYMO_EJECT) != 0 &&
+ usb_dymo_eject(udev, 0) == 0) {
+ /* success, mark the udev as disappearing */
+ uaa.dev_state = UAA_DEV_EJECTING;
+ }
+
EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa);
if (uaa.dev_state != UAA_DEV_READY) {
@@ -1444,7 +1474,7 @@
static void
usbd_clear_stall_proc(struct usb_proc_msg *_pm)
{
- struct usb_clear_stall_msg *pm = (void *)_pm;
+ struct usb_udev_msg *pm = (void *)_pm;
struct usb_device *udev = pm->udev;
/* Change lock */
@@ -1523,6 +1553,7 @@
/* initialise our SX-lock */
sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
+ sx_init_flags(&udev->ctrl_sx, "USB control transfer SX lock", SX_DUPOK);
cv_init(&udev->ctrlreq_cv, "WCTRL");
cv_init(&udev->ref_cv, "UGONE");
@@ -1673,10 +1704,14 @@
err = usbd_setup_device_desc(udev, NULL);
if (err != 0) {
- /* XXX try to re-enumerate the device */
+ /* try to enumerate two more times */
err = usbd_req_re_enumerate(udev, NULL);
- if (err)
- goto done;
+ if (err != 0) {
+ err = usbd_req_re_enumerate(udev, NULL);
+ if (err != 0) {
+ goto done;
+ }
+ }
}
/*
@@ -1704,11 +1739,13 @@
*/
/* Protect scratch area */
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
scratch_ptr = udev->scratch.data;
- if (udev->ddesc.iManufacturer ||
+ if (udev->flags.no_strings) {
+ err = USB_ERR_INVAL;
+ } else if (udev->ddesc.iManufacturer ||
udev->ddesc.iProduct ||
udev->ddesc.iSerialNumber) {
/* read out the language ID string */
@@ -1753,7 +1790,7 @@
}
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
@@ -1867,8 +1904,8 @@
udev->ugen_symlink = usb_alloc_symlink(udev->ugen_name);
/* Announce device */
- printf("%s: <%s> at %s\n", udev->ugen_name,
- usb_get_manufacturer(udev),
+ printf("%s: <%s %s> at %s\n", udev->ugen_name,
+ usb_get_manufacturer(udev), usb_get_product(udev),
device_get_nameunit(udev->bus->bdev));
#endif
@@ -1925,14 +1962,46 @@
}
void
+usb_destroy_dev_sync(struct usb_fs_privdata *pd)
+{
+ DPRINTFN(1, "Destroying device at ugen%d.%d\n",
+ pd->bus_index, pd->dev_index);
+
+ /*
+ * Destroy character device synchronously. After this
+ * all system calls are returned. Can block.
+ */
+ destroy_dev(pd->cdev);
+
+ free(pd, M_USBDEV);
+}
+
+void
usb_destroy_dev(struct usb_fs_privdata *pd)
{
+ struct usb_bus *bus;
+
if (pd == NULL)
return;
- destroy_dev(pd->cdev);
+ mtx_lock(&usb_ref_lock);
+ bus = devclass_get_softc(usb_devclass_ptr, pd->bus_index);
+ mtx_unlock(&usb_ref_lock);
- free(pd, M_USBDEV);
+ if (bus == NULL) {
+ usb_destroy_dev_sync(pd);
+ return;
+ }
+
+ /* make sure we can re-use the device name */
+ delist_dev(pd->cdev);
+
+ USB_BUS_LOCK(bus);
+ LIST_INSERT_HEAD(&bus->pd_cleanup_list, pd, pd_next);
+ /* get cleanup going */
+ usb_proc_msignal(&bus->explore_proc,
+ &bus->cleanup_msg[0], &bus->cleanup_msg[1]);
+ USB_BUS_UNLOCK(bus);
}
static void
@@ -2032,6 +2101,8 @@
DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no);
bus = udev->bus;
+
+ /* set DETACHED state to prevent any further references */
usb_set_device_state(udev, USB_STATE_DETACHED);
#if USB_HAVE_DEVCTL
@@ -2039,8 +2110,11 @@
#endif
#if USB_HAVE_UGEN
- printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
- usb_get_manufacturer(udev), device_get_nameunit(bus->bdev));
+ if (!rebooting) {
+ printf("%s: <%s %s> at %s (disconnected)\n", udev->ugen_name,
+ usb_get_manufacturer(udev), usb_get_product(udev),
+ device_get_nameunit(bus->bdev));
+ }
/* Destroy UGEN symlink, if any */
if (udev->ugen_symlink) {
@@ -2047,24 +2121,7 @@
usb_free_symlink(udev->ugen_symlink);
udev->ugen_symlink = NULL;
}
-#endif
- /*
- * Unregister our device first which will prevent any further
- * references:
- */
- usb_bus_port_set_device(bus, udev->parent_hub ?
- udev->parent_hub->hub->ports + udev->port_index : NULL,
- NULL, USB_ROOT_HUB_ADDR);
-#if USB_HAVE_UGEN
- /* wait for all pending references to go away: */
- mtx_lock(&usb_ref_lock);
- udev->refcount--;
- while (udev->refcount != 0) {
- cv_wait(&udev->ref_cv, &usb_ref_lock);
- }
- mtx_unlock(&usb_ref_lock);
-
usb_destroy_dev(udev->ctrl_dev);
#endif
@@ -2076,6 +2133,11 @@
/* the following will get the device unconfigured in software */
usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_EP0);
+ /* final device unregister after all character devices are closed */
+ usb_bus_port_set_device(bus, udev->parent_hub ?
+ udev->parent_hub->hub->ports + udev->port_index : NULL,
+ NULL, USB_ROOT_HUB_ADDR);
+
/* unsetup any leftover default USB transfers */
usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
@@ -2091,8 +2153,12 @@
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
+ /* wait for all references to go away */
+ usb_wait_pending_refs(udev);
+
sx_destroy(&udev->enum_sx);
sx_destroy(&udev->sr_sx);
+ sx_destroy(&udev->ctrl_sx);
cv_destroy(&udev->ctrlreq_cv);
cv_destroy(&udev->ref_cv);
@@ -2256,7 +2322,7 @@
uint8_t do_unlock;
/* Protect scratch area */
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
temp_ptr = (char *)udev->scratch.data;
temp_size = sizeof(udev->scratch.data);
@@ -2316,7 +2382,7 @@
}
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
}
/*
@@ -2609,8 +2675,14 @@
DPRINTF("udev %p state %s -> %s\n", udev,
usb_statestr(udev->state), usb_statestr(state));
+
+#if USB_HAVE_UGEN
+ mtx_lock(&usb_ref_lock);
+#endif
udev->state = state;
-
+#if USB_HAVE_UGEN
+ mtx_unlock(&usb_ref_lock);
+#endif
if (udev->bus->methods->device_state_change != NULL)
(udev->bus->methods->device_state_change) (udev);
}
@@ -2632,7 +2704,7 @@
/*
* The following function locks enumerating the given USB device. If
* the lock is already grabbed this function returns zero. Else a
- * non-zero value is returned.
+ * a value of one is returned.
*/
uint8_t
usbd_enum_lock(struct usb_device *udev)
@@ -2651,6 +2723,27 @@
return (1);
}
+#if USB_HAVE_UGEN
+/*
+ * This function is the same like usbd_enum_lock() except a value of
+ * 255 is returned when a signal is pending:
+ */
+uint8_t
+usbd_enum_lock_sig(struct usb_device *udev)
+{
+ if (sx_xlocked(&udev->enum_sx))
+ return (0);
+ if (sx_xlock_sig(&udev->enum_sx))
+ return (255);
+ if (sx_xlock_sig(&udev->sr_sx)) {
+ sx_xunlock(&udev->enum_sx);
+ return (255);
+ }
+ mtx_lock(&Giant);
+ return (1);
+}
+#endif
+
/* The following function unlocks enumerating the given USB device. */
void
@@ -2696,6 +2789,40 @@
}
/*
+ * The following function is used to serialize access to USB control
+ * transfers and the USB scratch area. If the lock is already grabbed
+ * this function returns zero. Else a value of one is returned.
+ */
+uint8_t
+usbd_ctrl_lock(struct usb_device *udev)
+{
+ if (sx_xlocked(&udev->ctrl_sx))
+ return (0);
+ sx_xlock(&udev->ctrl_sx);
+
+ /*
+ * We need to allow suspend and resume at this point, else the
+ * control transfer will timeout if the device is suspended!
+ */
+ if (usbd_enum_is_locked(udev))
+ usbd_sr_unlock(udev);
+ return (1);
+}
+
+void
+usbd_ctrl_unlock(struct usb_device *udev)
+{
+ sx_xunlock(&udev->ctrl_sx);
+
+ /*
+ * Restore the suspend and resume lock after we have unlocked
+ * the USB control transfer lock to avoid LOR:
+ */
+ if (usbd_enum_is_locked(udev))
+ usbd_sr_lock(udev);
+}
+
+/*
* The following function is used to set the per-interface specific
* plug and play information. The string referred to by the pnpinfo
* argument can safely be freed after calling this function. The
Modified: stable/0.8/sys/dev/usb/usb_device.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_device.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_device.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_device.h 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -53,7 +53,7 @@
#define USB_UNCFG_FLAG_NONE 0x00
#define USB_UNCFG_FLAG_FREE_EP0 0x02 /* endpoint zero is freed */
-struct usb_clear_stall_msg {
+struct usb_udev_msg {
struct usb_proc_msg hdr;
struct usb_device *udev;
};
@@ -162,7 +162,7 @@
/*
* The scratch area for USB devices. Access to this structure is
- * protected by the enumeration SX lock.
+ * protected by the control SX lock.
*/
union usb_device_scratch {
struct usb_hw_ep_scratch hw_ep_scratch[1];
@@ -179,10 +179,11 @@
* these structures for every USB device.
*/
struct usb_device {
- struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall
- * messages */
+ /* generic clear stall message */
+ struct usb_udev_msg cs_msg[2];
struct sx enum_sx;
struct sx sr_sx;
+ struct sx ctrl_sx;
struct mtx device_mtx;
struct cv ctrlreq_cv;
struct cv ref_cv;
@@ -220,6 +221,7 @@
uint8_t address; /* device addess */
uint8_t device_index; /* device index in "bus->devices" */
uint8_t controller_slot_id; /* controller specific value */
+ uint8_t next_config_index; /* used by USB_RE_ENUM_SET_CONFIG */
uint8_t curr_config_index; /* current configuration index */
uint8_t curr_config_no; /* current configuration number */
uint8_t depth; /* distance from root HUB */
@@ -230,6 +232,10 @@
uint8_t driver_added_refcount; /* our driver added generation count */
uint8_t power_mode; /* see USB_POWER_XXX */
uint8_t re_enumerate_wait; /* set if re-enum. is in progress */
+#define USB_RE_ENUM_DONE 0
+#define USB_RE_ENUM_START 1
+#define USB_RE_ENUM_PWR_OFF 2
+#define USB_RE_ENUM_SET_CONFIG 3
uint8_t ifaces_max; /* number of interfaces present */
uint8_t endpoints_max; /* number of endpoints present */
@@ -276,6 +282,7 @@
struct usb_fs_privdata *usb_make_dev(struct usb_device *, const char *,
int, int, int, uid_t, gid_t, int);
void usb_destroy_dev(struct usb_fs_privdata *);
+void usb_destroy_dev_sync(struct usb_fs_privdata *);
#endif
usb_error_t usb_probe_and_attach(struct usb_device *udev,
uint8_t iface_index);
@@ -296,9 +303,20 @@
enum usb_dev_state usb_get_device_state(struct usb_device *);
uint8_t usbd_enum_lock(struct usb_device *);
+#if USB_HAVE_UGEN
+uint8_t usbd_enum_lock_sig(struct usb_device *);
+#endif
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
void usbd_sr_unlock(struct usb_device *);
+uint8_t usbd_ctrl_lock(struct usb_device *);
+void usbd_ctrl_unlock(struct usb_device *);
uint8_t usbd_enum_is_locked(struct usb_device *);
+#if USB_HAVE_TT_SUPPORT
+void uhub_tt_buffer_reset_async_locked(struct usb_device *, struct usb_endpoint *);
+#endif
+
+uint8_t uhub_count_active_host_ports(struct usb_device *, enum usb_dev_speed);
+
#endif /* _USB_DEVICE_H_ */
Modified: stable/0.8/sys/dev/usb/usb_dynamic.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_dynamic.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dynamic.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dynamic.c 273889 2014-10-31 08:06:21Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -64,7 +64,7 @@
usb_temp_unsetup_t *usb_temp_unsetup_p = &usb_temp_unsetup_w;
usb_test_quirk_t *usb_test_quirk_p = &usb_test_quirk_w;
usb_quirk_ioctl_t *usb_quirk_ioctl_p = &usb_quirk_ioctl_w;
-devclass_t usb_devclass_ptr = NULL;
+devclass_t usb_devclass_ptr;
static usb_error_t
usb_temp_setup_by_index_w(struct usb_device *udev, uint16_t index)
Modified: stable/0.8/sys/dev/usb/usb_dynamic.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_dynamic.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dynamic.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dynamic.h 225469 2011-09-10 15:55:36Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_endian.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_endian.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_endian.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_endian.h 196219 2009-08-14 20:03:53Z jhb $ */
/*
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_error.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_error.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_error.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_error.c 217265 2011-01-11 13:59:06Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_freebsd.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_freebsd.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_freebsd.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_freebsd.h 277363 2015-01-19 07:03:40Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -43,6 +43,9 @@
#define USB_HAVE_MSCTEST 1
#define USB_HAVE_PF 1
+/* define zero ticks callout value */
+#define USB_CALLOUT_ZERO_TICKS 1
+
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
@@ -68,7 +71,7 @@
#define USB_EP0_BUFSIZE 1024 /* bytes */
#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
-#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
+#define USB_MAX_AUTO_QUIRK 8 /* maximum number of dynamic quirks */
typedef uint32_t usb_timeout_t; /* milliseconds */
typedef uint32_t usb_frlength_t; /* bytes */
Modified: stable/0.8/sys/dev/usb/usb_generic.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_generic.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_generic.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_generic.c 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -610,10 +610,7 @@
/* not possible in device side mode */
return (ENOTTY);
}
- if (f->udev->curr_config_index == index) {
- /* no change needed */
- return (0);
- }
+
/* make sure all FIFO's are gone */
/* else there can be a deadlock */
if (ugen_fs_uninit(f)) {
@@ -620,14 +617,10 @@
/* ignore any errors */
DPRINTFN(6, "no FIFOs\n");
}
- /* change setting - will free generic FIFOs, if any */
- if (usbd_set_config_index(f->udev, index)) {
+
+ if (usbd_start_set_config(f->udev, index) != 0)
return (EIO);
- }
- /* probe and attach */
- if (usb_probe_and_attach(f->udev, USB_IFACE_INDEX_ANY)) {
- return (EIO);
- }
+
return (0);
}
@@ -713,10 +706,6 @@
return (error);
}
-/*
- * This function is called having the enumeration SX locked which
- * protects the scratch area used.
- */
static int
ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
{
@@ -723,7 +712,11 @@
void *ptr;
uint16_t size;
int error;
+ uint8_t do_unlock;
+ /* Protect scratch area */
+ do_unlock = usbd_ctrl_lock(f->udev);
+
ptr = f->udev->scratch.data;
size = sizeof(f->udev->scratch.data);
@@ -743,6 +736,9 @@
error = copyout(ptr, ugd->ugd_data, size);
}
+ if (do_unlock)
+ usbd_ctrl_unlock(f->udev);
+
return (error);
}
@@ -961,11 +957,6 @@
DPRINTFN(6, "device mode\n");
return (ENOTTY);
}
- if (udev->parent_hub == NULL) {
- /* the root HUB cannot be re-enumerated */
- DPRINTFN(6, "cannot reset root HUB\n");
- return (EINVAL);
- }
/* make sure all FIFO's are gone */
/* else there can be a deadlock */
if (ugen_fs_uninit(f)) {
@@ -1749,16 +1740,11 @@
switch (mode) {
case USB_POWER_MODE_OFF:
- /* get the device unconfigured */
- err = ugen_set_config(f, USB_UNCONFIG_INDEX);
- if (err) {
- DPRINTFN(0, "Could not unconfigure "
- "device (ignored)\n");
+ if (udev->flags.usb_mode == USB_MODE_HOST &&
+ udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+ udev->re_enumerate_wait = USB_RE_ENUM_PWR_OFF;
}
-
- /* clear port enable */
- err = usbd_req_clear_port_feature(udev->parent_hub,
- NULL, udev->port_no, UHF_PORT_ENABLE);
+ /* set power mode will wake up the explore thread */
break;
case USB_POWER_MODE_ON:
@@ -1806,9 +1792,9 @@
/* if we are powered off we need to re-enumerate first */
if (old_mode == USB_POWER_MODE_OFF) {
- if (udev->flags.usb_mode == USB_MODE_HOST) {
- if (udev->re_enumerate_wait == 0)
- udev->re_enumerate_wait = 1;
+ if (udev->flags.usb_mode == USB_MODE_HOST &&
+ udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+ udev->re_enumerate_wait = USB_RE_ENUM_START;
}
/* set power mode will wake up the explore thread */
}
@@ -1831,6 +1817,45 @@
}
static int
+ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp)
+{
+ struct usb_device *udev = f->udev;
+ struct usb_device *next;
+ unsigned int nlevel = 0;
+
+ if (udev == NULL)
+ goto error;
+
+ dpp->udp_bus = device_get_unit(udev->bus->bdev);
+ dpp->udp_index = udev->device_index;
+
+ /* count port levels */
+ next = udev;
+ while (next->parent_hub != NULL) {
+ nlevel++;
+ next = next->parent_hub;
+ }
+
+ /* check if too many levels */
+ if (nlevel > USB_DEVICE_PORT_PATH_MAX)
+ goto error;
+
+ /* store total level of ports */
+ dpp->udp_port_level = nlevel;
+
+ /* store port index array */
+ next = udev;
+ while (next->parent_hub != NULL) {
+ dpp->udp_port_no[--nlevel] = next->port_no;
+ next = next->parent_hub;
+ }
+ return (0); /* success */
+
+error:
+ return (EINVAL); /* failure */
+}
+
+static int
ugen_get_power_usage(struct usb_fifo *f)
{
struct usb_device *udev = f->udev;
@@ -2031,6 +2056,7 @@
struct usb_device_stats *stat;
struct usb_fs_init *pinit;
struct usb_fs_uninit *puninit;
+ struct usb_device_port_path *dpp;
uint32_t *ptime;
void *addr;
int *pint;
@@ -2203,6 +2229,10 @@
*u.pint = ugen_get_power_mode(f);
break;
+ case USB_GET_DEV_PORT_PATH:
+ error = ugen_get_port_path(f, u.dpp);
+ break;
+
case USB_GET_POWER_USAGE:
*u.pint = ugen_get_power_usage(f);
break;
Modified: stable/0.8/sys/dev/usb/usb_generic.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_generic.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_generic.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_generic.h 196219 2009-08-14 20:03:53Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_handle_request.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_handle_request.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_handle_request.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_handle_request.c 247090 2013-02-21 07:48:07Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_hid.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_hid.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hid.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -2,7 +2,7 @@
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/usb_hid.c 296445 2016-03-07 09:39:35Z hselasky $");
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -353,7 +353,8 @@
/* range check usage count */
if (c->loc.count > 255) {
DPRINTFN(0, "Number of "
- "items truncated to 255\n");
+ "items(%u) truncated to 255\n",
+ (unsigned)(c->loc.count));
s->ncount = 255;
} else
s->ncount = c->loc.count;
Modified: stable/0.8/sys/dev/usb/usb_hub.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_hub.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hub.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_hub.c 279637 2015-03-05 09:35:15Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -50,7 +50,6 @@
#include <sys/priv.h>
#include <dev/usb/usb.h>
-#include <dev/usb/usb_ioctl.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -71,7 +70,13 @@
#include <dev/usb/usb_bus.h>
#define UHUB_INTR_INTERVAL 250 /* ms */
-#define UHUB_N_TRANSFER 1
+enum {
+ UHUB_INTR_TRANSFER,
+#if USB_HAVE_TT_SUPPORT
+ UHUB_RESET_TT_TRANSFER,
+#endif
+ UHUB_N_TRANSFER,
+};
#ifdef USB_DEBUG
static int uhub_debug = 0;
@@ -124,6 +129,9 @@
static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
static usb_callback_t uhub_intr_callback;
+#if USB_HAVE_TT_SUPPORT
+static usb_callback_t uhub_reset_tt_callback;
+#endif
static void usb_dev_resume_peer(struct usb_device *udev);
static void usb_dev_suspend_peer(struct usb_device *udev);
@@ -131,7 +139,7 @@
static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
- [0] = {
+ [UHUB_INTR_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_ANY,
@@ -141,6 +149,17 @@
.callback = &uhub_intr_callback,
.interval = UHUB_INTR_INTERVAL,
},
+#if USB_HAVE_TT_SUPPORT
+ [UHUB_RESET_TT_TRANSFER] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = UE_DIR_ANY,
+ .bufsize = sizeof(struct usb_device_request),
+ .callback = &uhub_reset_tt_callback,
+ .timeout = 1000, /* 1 second */
+ .usb_mode = USB_MODE_HOST,
+ },
+#endif
};
/*
@@ -210,6 +229,279 @@
}
/*------------------------------------------------------------------------*
+ * uhub_reset_tt_proc
+ *
+ * This function starts the TT reset USB request
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
+static void
+uhub_reset_tt_proc(struct usb_proc_msg *_pm)
+{
+ struct usb_udev_msg *pm = (void *)_pm;
+ struct usb_device *udev = pm->udev;
+ struct usb_hub *hub;
+ struct uhub_softc *sc;
+
+ hub = udev->hub;
+ if (hub == NULL)
+ return;
+ sc = hub->hubsoftc;
+ if (sc == NULL)
+ return;
+
+ /* Change lock */
+ USB_BUS_UNLOCK(udev->bus);
+ mtx_lock(&sc->sc_mtx);
+ /* Start transfer */
+ usbd_transfer_start(sc->sc_xfer[UHUB_RESET_TT_TRANSFER]);
+ /* Change lock */
+ mtx_unlock(&sc->sc_mtx);
+ USB_BUS_LOCK(udev->bus);
+}
+#endif
+
+/*------------------------------------------------------------------------*
+ * uhub_tt_buffer_reset_async_locked
+ *
+ * This function queues a TT reset for the given USB device and endpoint.
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
+void
+uhub_tt_buffer_reset_async_locked(struct usb_device *child, struct usb_endpoint *ep)
+{
+ struct usb_device_request req;
+ struct usb_device *udev;
+ struct usb_hub *hub;
+ struct usb_port *up;
+ uint16_t wValue;
+ uint8_t port;
+
+ if (child == NULL || ep == NULL)
+ return;
+
+ udev = child->parent_hs_hub;
+ port = child->hs_port_no;
+
+ if (udev == NULL)
+ return;
+
+ hub = udev->hub;
+ if ((hub == NULL) ||
+ (udev->speed != USB_SPEED_HIGH) ||
+ (child->speed != USB_SPEED_LOW &&
+ child->speed != USB_SPEED_FULL) ||
+ (child->flags.usb_mode != USB_MODE_HOST) ||
+ (port == 0) || (ep->edesc == NULL)) {
+ /* not applicable */
+ return;
+ }
+
+ USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
+
+ up = hub->ports + port - 1;
+
+ if (udev->ddesc.bDeviceClass == UDCLASS_HUB &&
+ udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBSTT)
+ port = 1;
+
+ /* if we already received a clear buffer request, reset the whole TT */
+ if (up->req_reset_tt.bRequest != 0) {
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_RESET_TT;
+ USETW(req.wValue, 0);
+ req.wIndex[0] = port;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+ } else {
+ wValue = (ep->edesc->bEndpointAddress & 0xF) |
+ ((child->address & 0x7F) << 4) |
+ ((ep->edesc->bEndpointAddress & 0x80) << 8) |
+ ((ep->edesc->bmAttributes & 3) << 12);
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_CLEAR_TT_BUFFER;
+ USETW(req.wValue, wValue);
+ req.wIndex[0] = port;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+ }
+ up->req_reset_tt = req;
+ /* get reset transfer started */
+ usb_proc_msignal(&udev->bus->non_giant_callback_proc,
+ &hub->tt_msg[0], &hub->tt_msg[1]);
+}
+#endif
+
+#if USB_HAVE_TT_SUPPORT
+static void
+uhub_reset_tt_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct uhub_softc *sc;
+ struct usb_device *udev;
+ struct usb_port *up;
+ uint8_t x;
+
+ DPRINTF("TT buffer reset\n");
+
+ sc = usbd_xfer_softc(xfer);
+ udev = sc->sc_udev;
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ case USB_ST_SETUP:
+tr_setup:
+ USB_BUS_LOCK(udev->bus);
+ /* find first port which needs a TT reset */
+ for (x = 0; x != udev->hub->nports; x++) {
+ up = udev->hub->ports + x;
+
+ if (up->req_reset_tt.bRequest == 0)
+ continue;
+
+ /* copy in the transfer */
+ usbd_copy_in(xfer->frbuffers, 0, &up->req_reset_tt,
+ sizeof(up->req_reset_tt));
+ /* reset buffer */
+ memset(&up->req_reset_tt, 0, sizeof(up->req_reset_tt));
+
+ /* set length */
+ usbd_xfer_set_frame_len(xfer, 0, sizeof(up->req_reset_tt));
+ xfer->nframes = 1;
+ USB_BUS_UNLOCK(udev->bus);
+
+ usbd_transfer_submit(xfer);
+ return;
+ }
+ USB_BUS_UNLOCK(udev->bus);
+ break;
+
+ default:
+ if (error == USB_ERR_CANCELLED)
+ break;
+
+ DPRINTF("TT buffer reset failed (%s)\n", usbd_errstr(error));
+ goto tr_setup;
+ }
+}
+#endif
+
+/*------------------------------------------------------------------------*
+ * uhub_count_active_host_ports
+ *
+ * This function counts the number of active ports at the given speed.
+ *------------------------------------------------------------------------*/
+uint8_t
+uhub_count_active_host_ports(struct usb_device *udev, enum usb_dev_speed speed)
+{
+ struct uhub_softc *sc;
+ struct usb_device *child;
+ struct usb_hub *hub;
+ struct usb_port *up;
+ uint8_t retval = 0;
+ uint8_t x;
+
+ if (udev == NULL)
+ goto done;
+ hub = udev->hub;
+ if (hub == NULL)
+ goto done;
+ sc = hub->hubsoftc;
+ if (sc == NULL)
+ goto done;
+
+ for (x = 0; x != hub->nports; x++) {
+ up = hub->ports + x;
+ child = usb_bus_port_get_device(udev->bus, up);
+ if (child != NULL &&
+ child->flags.usb_mode == USB_MODE_HOST &&
+ child->speed == speed)
+ retval++;
+ }
+done:
+ return (retval);
+}
+
+void
+uhub_explore_handle_re_enumerate(struct usb_device *child)
+{
+ uint8_t do_unlock;
+ usb_error_t err;
+
+ /* check if device should be re-enumerated */
+ if (child->flags.usb_mode != USB_MODE_HOST)
+ return;
+
+ do_unlock = usbd_enum_lock(child);
+ switch (child->re_enumerate_wait) {
+ case USB_RE_ENUM_START:
+ err = usbd_set_config_index(child,
+ USB_UNCONFIG_INDEX);
+ if (err != 0) {
+ DPRINTF("Unconfigure failed: %s: Ignored.\n",
+ usbd_errstr(err));
+ }
+ if (child->parent_hub == NULL) {
+ /* the root HUB cannot be re-enumerated */
+ DPRINTFN(6, "cannot reset root HUB\n");
+ err = 0;
+ } else {
+ err = usbd_req_re_enumerate(child, NULL);
+ }
+ if (err == 0)
+ err = usbd_set_config_index(child, 0);
+ if (err == 0) {
+ err = usb_probe_and_attach(child,
+ USB_IFACE_INDEX_ANY);
+ }
+ child->re_enumerate_wait = USB_RE_ENUM_DONE;
+ break;
+
+ case USB_RE_ENUM_PWR_OFF:
+ /* get the device unconfigured */
+ err = usbd_set_config_index(child,
+ USB_UNCONFIG_INDEX);
+ if (err) {
+ DPRINTFN(0, "Could not unconfigure "
+ "device (ignored)\n");
+ }
+ if (child->parent_hub == NULL) {
+ /* the root HUB cannot be re-enumerated */
+ DPRINTFN(6, "cannot set port feature\n");
+ err = 0;
+ } else {
+ /* clear port enable */
+ err = usbd_req_clear_port_feature(child->parent_hub,
+ NULL, child->port_no, UHF_PORT_ENABLE);
+ if (err) {
+ DPRINTFN(0, "Could not disable port "
+ "(ignored)\n");
+ }
+ }
+ child->re_enumerate_wait = USB_RE_ENUM_DONE;
+ break;
+
+ case USB_RE_ENUM_SET_CONFIG:
+ err = usbd_set_config_index(child,
+ child->next_config_index);
+ if (err != 0) {
+ DPRINTF("Configure failed: %s: Ignored.\n",
+ usbd_errstr(err));
+ } else {
+ err = usb_probe_and_attach(child,
+ USB_IFACE_INDEX_ANY);
+ }
+ child->re_enumerate_wait = USB_RE_ENUM_DONE;
+ break;
+
+ default:
+ child->re_enumerate_wait = USB_RE_ENUM_DONE;
+ break;
+ }
+ if (do_unlock)
+ usbd_enum_unlock(child);
+}
+
+/*------------------------------------------------------------------------*
* uhub_explore_sub - subroutine
*
* Return values:
@@ -237,34 +529,8 @@
goto done;
}
- /* check if device should be re-enumerated */
+ uhub_explore_handle_re_enumerate(child);
- if (child->flags.usb_mode == USB_MODE_HOST) {
- uint8_t do_unlock;
-
- do_unlock = usbd_enum_lock(child);
- if (child->re_enumerate_wait) {
- err = usbd_set_config_index(child,
- USB_UNCONFIG_INDEX);
- if (err != 0) {
- DPRINTF("Unconfigure failed: "
- "%s: Ignored.\n",
- usbd_errstr(err));
- }
- err = usbd_req_re_enumerate(child, NULL);
- if (err == 0)
- err = usbd_set_config_index(child, 0);
- if (err == 0) {
- err = usb_probe_and_attach(child,
- USB_IFACE_INDEX_ANY);
- }
- child->re_enumerate_wait = 0;
- err = 0;
- }
- if (do_unlock)
- usbd_enum_unlock(child);
- }
-
/* check if probe and attach should be done */
if (child->driver_added_refcount != refcount) {
@@ -335,7 +601,6 @@
DPRINTF("reattaching port %d\n", portno);
- err = 0;
timeout = 0;
udev = sc->sc_udev;
child = usb_bus_port_get_device(udev->bus,
@@ -520,7 +785,10 @@
*
* NOTE: This part is currently FreeBSD specific.
*/
- if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
+ if (udev->parent_hub != NULL) {
+ /* inherit mode from the parent HUB */
+ mode = udev->parent_hub->flags.usb_mode;
+ } else if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
mode = USB_MODE_DEVICE;
else
mode = USB_MODE_HOST;
@@ -1077,7 +1345,12 @@
hub->explore = &uhub_explore;
hub->nports = nports;
hub->hubudev = udev;
-
+#if USB_HAVE_TT_SUPPORT
+ hub->tt_msg[0].hdr.pm_callback = &uhub_reset_tt_proc;
+ hub->tt_msg[0].udev = udev;
+ hub->tt_msg[1].hdr.pm_callback = &uhub_reset_tt_proc;
+ hub->tt_msg[1].udev = udev;
+#endif
/* if self powered hub, give ports maximum current */
if (udev->flags.self_powered) {
hub->portpower = USB_MAX_POWER;
@@ -1179,11 +1452,9 @@
/* Start the interrupt endpoint, if any */
- if (sc->sc_xfer[0] != NULL) {
- mtx_lock(&sc->sc_mtx);
- usbd_transfer_start(sc->sc_xfer[0]);
- mtx_unlock(&sc->sc_mtx);
- }
+ mtx_lock(&sc->sc_mtx);
+ usbd_transfer_start(sc->sc_xfer[UHUB_INTR_TRANSFER]);
+ mtx_unlock(&sc->sc_mtx);
/* Enable automatic power save on all USB HUBs */
@@ -1213,6 +1484,7 @@
{
struct uhub_softc *sc = device_get_softc(dev);
struct usb_hub *hub = sc->sc_udev->hub;
+ struct usb_bus *bus = sc->sc_udev->bus;
struct usb_device *child;
uint8_t x;
@@ -1225,7 +1497,7 @@
/* Detach all ports */
for (x = 0; x != hub->nports; x++) {
- child = usb_bus_port_get_device(sc->sc_udev->bus, hub->ports + x);
+ child = usb_bus_port_get_device(bus, hub->ports + x);
if (child == NULL) {
continue;
@@ -1237,6 +1509,13 @@
usb_free_device(child, 0);
}
+#if USB_HAVE_TT_SUPPORT
+ /* Make sure our TT messages are not queued anywhere */
+ USB_BUS_LOCK(bus);
+ usb_proc_mwait(&bus->non_giant_callback_proc,
+ &hub->tt_msg[0], &hub->tt_msg[1]);
+ USB_BUS_UNLOCK(bus);
+#endif
free(hub, M_USBDEV);
sc->sc_udev->hub = NULL;
@@ -1332,10 +1611,11 @@
}
goto done;
}
- snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u",
+ snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u"
+ " ugen=%s",
(res.udev->parent_hub != NULL) ? res.udev->parent_hub->device_index : 0,
res.portno, device_get_unit(res.udev->bus->bdev),
- res.udev->device_index, res.iface_index);
+ res.udev->device_index, res.iface_index, res.udev->ugen_name);
done:
mtx_unlock(&Giant);
@@ -1377,7 +1657,7 @@
"release=0x%04x "
"mode=%s "
"intclass=0x%02x intsubclass=0x%02x "
- "intprotocol=0x%02x " "%s%s",
+ "intprotocol=0x%02x" "%s%s",
UGETW(res.udev->ddesc.idVendor),
UGETW(res.udev->ddesc.idProduct),
res.udev->ddesc.bDeviceClass,
@@ -2068,9 +2348,10 @@
static uint8_t
usb_peer_should_wakeup(struct usb_device *udev)
{
- return ((udev->power_mode == USB_POWER_MODE_ON) ||
+ return (((udev->power_mode == USB_POWER_MODE_ON) &&
+ (udev->flags.usb_mode == USB_MODE_HOST)) ||
(udev->driver_added_refcount != udev->bus->driver_added_refcount) ||
- (udev->re_enumerate_wait != 0) ||
+ (udev->re_enumerate_wait != USB_RE_ENUM_DONE) ||
(udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
(udev->pwr_save.write_refs != 0) ||
((udev->pwr_save.read_refs != 0) &&
@@ -2486,6 +2767,8 @@
#if USB_HAVE_POWERD
usb_bus_power_update(udev->bus);
+#else
+ usb_needs_explore(udev->bus, 0 /* no probe */ );
#endif
}
@@ -2524,8 +2807,36 @@
void
usbd_start_re_enumerate(struct usb_device *udev)
{
- if (udev->re_enumerate_wait == 0) {
- udev->re_enumerate_wait = 1;
+ if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+ udev->re_enumerate_wait = USB_RE_ENUM_START;
usb_needs_explore(udev->bus, 0);
}
}
+
+/*-----------------------------------------------------------------------*
+ * usbd_start_set_config
+ *
+ * This function starts setting a USB configuration. This function
+ * does not need to be called BUS-locked. This function does not wait
+ * until the set USB configuratino is completed.
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_start_set_config(struct usb_device *udev, uint8_t index)
+{
+ if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+ if (udev->curr_config_index == index) {
+ /* no change needed */
+ return (0);
+ }
+ udev->next_config_index = index;
+ udev->re_enumerate_wait = USB_RE_ENUM_SET_CONFIG;
+ usb_needs_explore(udev->bus, 0);
+ return (0);
+ } else if (udev->re_enumerate_wait == USB_RE_ENUM_SET_CONFIG) {
+ if (udev->next_config_index == index) {
+ /* no change needed */
+ return (0);
+ }
+ }
+ return (USB_ERR_PENDING_REQUESTS);
+}
Modified: stable/0.8/sys/dev/usb/usb_hub.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_hub.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hub.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_hub.h 267350 2014-06-11 06:45:52Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -35,6 +35,9 @@
#define USB_RESTART_MAX 5
uint8_t device_index; /* zero means not valid */
enum usb_hc_mode usb_mode; /* host or device mode */
+#if USB_HAVE_TT_SUPPORT
+ struct usb_device_request req_reset_tt __aligned(4);
+#endif
};
/*
@@ -44,6 +47,9 @@
struct usb_device *hubudev; /* the HUB device */
usb_error_t (*explore) (struct usb_device *hub);
void *hubsoftc;
+#if USB_HAVE_TT_SUPPORT
+ struct usb_udev_msg tt_msg[2];
+#endif
usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
uint16_t portpower; /* mA per USB port */
uint8_t isoc_last_time;
@@ -65,5 +71,6 @@
void usb_bus_powerd(struct usb_bus *bus);
void uhub_root_intr(struct usb_bus *, const uint8_t *, uint8_t);
usb_error_t uhub_query_info(struct usb_device *, uint8_t *, uint8_t *);
+void uhub_explore_handle_re_enumerate(struct usb_device *);
#endif /* _USB_HUB_H_ */
Modified: stable/0.8/sys/dev/usb/usb_if.m
===================================================================
--- stable/0.8/sys/dev/usb/usb_if.m 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_if.m 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
-# $MidnightBSD$
+# $FreeBSD: stable/9/sys/dev/usb/usb_if.m 229096 2011-12-31 14:22:02Z hselasky $
#
# USB interface description
Modified: stable/0.8/sys/dev/usb/usb_ioctl.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_ioctl.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_ioctl.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_ioctl.h 254566 2013-08-20 14:19:00Z emaste $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -30,6 +30,7 @@
#define _USB_IOCTL_H_
#include <sys/ioccom.h>
+#include <sys/cdefs.h>
/* Building "kdump" depends on these includes */
@@ -41,6 +42,16 @@
#define USB_GENERIC_NAME "ugen"
#define USB_TEMPLATE_SYSCTL "hw.usb.template" /* integer type */
+/*
+ * Align IOCTL structures to hide differences when running 32-bit
+ * programs under 64-bit kernels:
+ */
+#ifdef COMPAT_32BIT
+#define USB_IOCTL_STRUCT_ALIGN(n) __aligned(n)
+#else
+#define USB_IOCTL_STRUCT_ALIGN(n)
+#endif
+
/* Definition of valid template sysctl values */
enum {
@@ -62,7 +73,7 @@
#endif
uint32_t urd_startentry;
uint32_t urd_maxlen;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
struct usb_ctl_request {
#ifdef COMPAT_32BIT
@@ -74,12 +85,12 @@
uint16_t ucr_actlen; /* actual length transferred */
uint8_t ucr_addr; /* zero - currently not used */
struct usb_device_request ucr_request;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
struct usb_alt_interface {
uint8_t uai_interface_index;
uint8_t uai_alt_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_gen_descriptor {
#ifdef COMPAT_32BIT
@@ -98,7 +109,7 @@
uint8_t ugd_endpt_index;
uint8_t ugd_report_type;
uint8_t reserved[8];
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
struct usb_device_info {
uint16_t udi_productNo;
@@ -127,24 +138,33 @@
char udi_vendor[128];
char udi_serial[64];
char udi_release[8];
-};
+} USB_IOCTL_STRUCT_ALIGN(2);
+#define USB_DEVICE_PORT_PATH_MAX 32
+
+struct usb_device_port_path {
+ uint8_t udp_bus; /* which bus we are on */
+ uint8_t udp_index; /* which device index */
+ uint8_t udp_port_level; /* how many levels: 0, 1, 2 ... */
+ uint8_t udp_port_no[USB_DEVICE_PORT_PATH_MAX];
+} USB_IOCTL_STRUCT_ALIGN(1);
+
struct usb_device_stats {
uint32_t uds_requests_ok[4]; /* Indexed by transfer type UE_XXX */
uint32_t uds_requests_fail[4]; /* Indexed by transfer type UE_XXX */
-};
+} USB_IOCTL_STRUCT_ALIGN(4);
struct usb_fs_start {
uint8_t ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_fs_stop {
uint8_t ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_fs_complete {
uint8_t ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
/* This structure is used for all endpoint types */
struct usb_fs_endpoint {
@@ -177,7 +197,7 @@
/* timeout value for no timeout */
#define USB_FS_TIMEOUT_NONE 0
int status; /* see USB_ERR_XXX */
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
struct usb_fs_init {
/* userland pointer to endpoints structure */
@@ -188,11 +208,11 @@
#endif
/* maximum number of endpoints */
uint8_t ep_index_max;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
struct usb_fs_uninit {
uint8_t dummy; /* zero */
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_fs_open {
#define USB_FS_MAX_BUFSIZE (1 << 18)
@@ -204,15 +224,20 @@
uint8_t dev_index; /* currently unused */
uint8_t ep_index;
uint8_t ep_no; /* bEndpointNumber */
-};
+} USB_IOCTL_STRUCT_ALIGN(4);
+struct usb_fs_open_stream {
+ struct usb_fs_open fs_open;
+ uint16_t stream_id; /* stream ID */
+} USB_IOCTL_STRUCT_ALIGN(4);
+
struct usb_fs_close {
uint8_t ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_fs_clear_stall_sync {
uint8_t ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
struct usb_gen_quirk {
uint16_t index; /* Quirk Index */
@@ -222,11 +247,11 @@
uint16_t bcdDeviceHigh; /* High Device Revision */
uint16_t reserved[2];
/*
- * String version of quirk including terminating zero. See UQ_XXX in
- * "usb_quirk.h".
+ * String version of quirk including terminating zero. See
+ * UQ_XXX in "usb_quirk.h".
*/
char quirkname[64 - 14];
-};
+} USB_IOCTL_STRUCT_ALIGN(2);
/* USB controller */
#define USB_REQUEST _IOWR('U', 1, struct usb_ctl_request)
@@ -270,7 +295,8 @@
#define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int)
#define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t)
#define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir)
-/* 128 - 134 unused */
+/* 128 - 133 unused */
+#define USB_GET_DEV_PORT_PATH _IOR ('U', 134, struct usb_device_port_path)
#define USB_GET_POWER_USAGE _IOR ('U', 135, int)
#define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int)
#define USB_SET_TX_TIMEOUT _IOW ('U', 137, int)
Modified: stable/0.8/sys/dev/usb/usb_lookup.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_lookup.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_lookup.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_lookup.c 223538 2011-06-25 15:51:44Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_mbuf.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_mbuf.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_mbuf.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_mbuf.c 217265 2011-01-11 13:59:06Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_mbuf.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_mbuf.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_mbuf.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_mbuf.h 196219 2009-08-14 20:03:53Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_msctest.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_msctest.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_msctest.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_msctest.c 283174 2015-05-21 06:53:55Z hselasky $ */
/*-
* Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
*
@@ -83,7 +83,7 @@
DIR_NONE,
};
-#define SCSI_MAX_LEN 0x100
+#define SCSI_MAX_LEN MAX(0x100, BULK_SIZE)
#define SCSI_INQ_LEN 0x24
#define SCSI_SENSE_LEN 0xFF
@@ -98,6 +98,9 @@
static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_huawei_eject2[] = { 0x11, 0x06, 0x20, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
@@ -105,6 +108,8 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_prevent_removal[] = { 0x1e, 0, 0, 0, 1, 0 };
+static uint8_t scsi_allow_removal[] = { 0x1e, 0, 0, 0, 0, 0 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -139,8 +144,8 @@
struct bbb_transfer {
struct mtx mtx;
struct cv cv;
- struct bbb_cbw cbw;
- struct bbb_csw csw;
+ struct bbb_cbw *cbw;
+ struct bbb_csw *csw;
struct usb_xfer *xfer[ST_MAX];
@@ -150,6 +155,7 @@
usb_size_t data_rem; /* bytes */
usb_timeout_t data_timeout; /* ms */
usb_frlength_t actlen; /* bytes */
+ usb_frlength_t buffer_size; /* bytes */
uint8_t cmd_len; /* bytes */
uint8_t dir;
@@ -158,7 +164,7 @@
uint8_t status_try;
int error;
- uint8_t buffer[SCSI_MAX_LEN] __aligned(4);
+ uint8_t *buffer;
};
static usb_callback_t bbb_command_callback;
@@ -167,6 +173,7 @@
static usb_callback_t bbb_data_write_callback;
static usb_callback_t bbb_data_wr_cs_callback;
static usb_callback_t bbb_status_callback;
+static usb_callback_t bbb_raw_write_callback;
static void bbb_done(struct bbb_transfer *, int);
static void bbb_transfer_start(struct bbb_transfer *, uint8_t);
@@ -174,7 +181,7 @@
uint8_t);
static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
void *, size_t, void *, size_t, usb_timeout_t);
-static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
+static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t, uint8_t);
static void bbb_detach(struct bbb_transfer *);
static const struct usb_config bbb_config[ST_MAX] = {
@@ -184,7 +191,6 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(struct bbb_cbw),
- .flags = {.ext_buffer = 1,},
.callback = &bbb_command_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -193,8 +199,8 @@
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .bufsize = BULK_SIZE,
- .flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .bufsize = SCSI_MAX_LEN,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_data_read_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -212,7 +218,7 @@
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .bufsize = BULK_SIZE,
+ .bufsize = SCSI_MAX_LEN,
.flags = {.ext_buffer = 1,.proxy_buffer = 1,},
.callback = &bbb_data_write_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
@@ -232,16 +238,28 @@
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(struct bbb_csw),
- .flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
+ .flags = {.short_xfer_ok = 1,},
.callback = &bbb_status_callback,
.timeout = 1 * USB_MS_HZ, /* 1 second */
},
};
+static const struct usb_config bbb_raw_config[1] = {
+
+ [0] = {
+ .type = UE_BULK_INTR,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_OUT,
+ .bufsize = SCSI_MAX_LEN,
+ .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
+ .callback = &bbb_raw_write_callback,
+ .timeout = 1 * USB_MS_HZ, /* 1 second */
+ },
+};
+
static void
bbb_done(struct bbb_transfer *sc, int error)
{
-
sc->error = error;
sc->state = ST_COMMAND;
sc->status_try = 1;
@@ -290,18 +308,19 @@
case USB_ST_SETUP:
sc->status_try = 0;
- tag = UGETDW(sc->cbw.dCBWTag) + 1;
- USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
- USETDW(sc->cbw.dCBWTag, tag);
- USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
- sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
- sc->cbw.bCBWLUN = sc->lun;
- sc->cbw.bCDBLength = sc->cmd_len;
- if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) {
- sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB);
+ tag = UGETDW(sc->cbw->dCBWTag) + 1;
+ USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
+ USETDW(sc->cbw->dCBWTag, tag);
+ USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
+ sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
+ sc->cbw->bCBWLUN = sc->lun;
+ sc->cbw->bCDBLength = sc->cmd_len;
+ if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
+ sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
DPRINTFN(0, "Truncating long command\n");
}
- usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw));
+ usbd_xfer_set_frame_len(xfer, 0,
+ sizeof(struct bbb_cbw));
usbd_transfer_submit(xfer);
break;
@@ -388,7 +407,7 @@
if (sc->data_rem == 0) {
bbb_transfer_start(sc, ST_STATUS);
- return;
+ break;
}
if (max_bulk > sc->data_rem) {
max_bulk = sc->data_rem;
@@ -396,7 +415,7 @@
usbd_xfer_set_timeout(xfer, sc->data_timeout);
usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
usbd_transfer_submit(xfer);
- return;
+ break;
default: /* Error */
if (error == USB_ERR_CANCELLED) {
@@ -404,8 +423,7 @@
} else {
bbb_transfer_start(sc, ST_DATA_WR_CS);
}
- return;
-
+ break;
}
}
@@ -430,9 +448,9 @@
/* very simple status check */
- if (actlen < (int)sizeof(sc->csw)) {
+ if (actlen < (int)sizeof(struct bbb_csw)) {
bbb_done(sc, USB_ERR_SHORT_XFER);
- } else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
+ } else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
bbb_done(sc, 0); /* success */
} else {
bbb_done(sc, ERR_CSW_FAILED); /* error */
@@ -440,7 +458,8 @@
break;
case USB_ST_SETUP:
- usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw));
+ usbd_xfer_set_frame_len(xfer, 0,
+ sizeof(struct bbb_csw));
usbd_transfer_submit(xfer);
break;
@@ -458,6 +477,47 @@
}
}
+static void
+bbb_raw_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct bbb_transfer *sc = usbd_xfer_softc(xfer);
+ usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
+ int actlen, sumlen;
+
+ usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ sc->data_rem -= actlen;
+ sc->data_ptr += actlen;
+ sc->actlen += actlen;
+
+ if (actlen < sumlen) {
+ /* short transfer */
+ sc->data_rem = 0;
+ }
+ case USB_ST_SETUP:
+ DPRINTF("max_bulk=%d, data_rem=%d\n",
+ max_bulk, sc->data_rem);
+
+ if (sc->data_rem == 0) {
+ bbb_done(sc, 0);
+ break;
+ }
+ if (max_bulk > sc->data_rem) {
+ max_bulk = sc->data_rem;
+ }
+ usbd_xfer_set_timeout(xfer, sc->data_timeout);
+ usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
+ usbd_transfer_submit(xfer);
+ break;
+
+ default: /* Error */
+ bbb_done(sc, error);
+ break;
+ }
+}
+
/*------------------------------------------------------------------------*
* bbb_command_start - execute a SCSI command synchronously
*
@@ -477,10 +537,11 @@
sc->data_rem = data_len;
sc->data_timeout = (data_timeout + USB_MS_HZ);
sc->actlen = 0;
+ sc->error = 0;
sc->cmd_len = cmd_len;
- memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
- memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
- DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
+ memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
+ memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
+ DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
mtx_lock(&sc->mtx);
usbd_transfer_start(sc->xfer[sc->state]);
@@ -492,13 +553,45 @@
return (sc->error);
}
+/*------------------------------------------------------------------------*
+ * bbb_raw_write - write a raw BULK message synchronously
+ *
+ * Return values
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+static int
+bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len,
+ usb_timeout_t data_timeout)
+{
+ sc->data_ptr = __DECONST(void *, data_ptr);
+ sc->data_len = data_len;
+ sc->data_rem = data_len;
+ sc->data_timeout = (data_timeout + USB_MS_HZ);
+ sc->actlen = 0;
+ sc->error = 0;
+
+ DPRINTFN(1, "BULK DATA = %*D\n", (int)data_len,
+ (const char *)data_ptr, ":");
+
+ mtx_lock(&sc->mtx);
+ usbd_transfer_start(sc->xfer[0]);
+ while (usbd_transfer_pending(sc->xfer[0]))
+ cv_wait(&sc->cv, &sc->mtx);
+ mtx_unlock(&sc->mtx);
+ return (sc->error);
+}
+
static struct bbb_transfer *
-bbb_attach(struct usb_device *udev, uint8_t iface_index)
+bbb_attach(struct usb_device *udev, uint8_t iface_index,
+ uint8_t bInterfaceClass)
{
struct usb_interface *iface;
struct usb_interface_descriptor *id;
+ const struct usb_config *pconfig;
struct bbb_transfer *sc;
usb_error_t err;
+ int nconfig;
uint8_t do_unlock;
/* Prevent re-enumeration */
@@ -518,22 +611,39 @@
return (NULL);
id = iface->idesc;
- if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+ if (id == NULL || id->bInterfaceClass != bInterfaceClass)
return (NULL);
- switch (id->bInterfaceSubClass) {
- case UISUBCLASS_SCSI:
- case UISUBCLASS_UFI:
- case UISUBCLASS_SFF8020I:
- case UISUBCLASS_SFF8070I:
+ switch (id->bInterfaceClass) {
+ case UICLASS_MASS:
+ switch (id->bInterfaceSubClass) {
+ case UISUBCLASS_SCSI:
+ case UISUBCLASS_UFI:
+ case UISUBCLASS_SFF8020I:
+ case UISUBCLASS_SFF8070I:
+ break;
+ default:
+ return (NULL);
+ }
+ switch (id->bInterfaceProtocol) {
+ case UIPROTO_MASS_BBB_OLD:
+ case UIPROTO_MASS_BBB:
+ break;
+ default:
+ return (NULL);
+ }
+ pconfig = bbb_config;
+ nconfig = ST_MAX;
break;
- default:
- return (NULL);
- }
-
- switch (id->bInterfaceProtocol) {
- case UIPROTO_MASS_BBB_OLD:
- case UIPROTO_MASS_BBB:
+ case UICLASS_HID:
+ switch (id->bInterfaceSubClass) {
+ case 0:
+ break;
+ default:
+ return (NULL);
+ }
+ pconfig = bbb_raw_config;
+ nconfig = 1;
break;
default:
return (NULL);
@@ -543,12 +653,27 @@
mtx_init(&sc->mtx, "USB autoinstall", NULL, MTX_DEF);
cv_init(&sc->cv, "WBBB");
- err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config,
- ST_MAX, sc, &sc->mtx);
+ err = usbd_transfer_setup(udev, &iface_index, sc->xfer, pconfig,
+ nconfig, sc, &sc->mtx);
if (err) {
bbb_detach(sc);
return (NULL);
}
+ switch (id->bInterfaceClass) {
+ case UICLASS_MASS:
+ /* store pointer to DMA buffers */
+ sc->buffer = usbd_xfer_get_frame_buffer(
+ sc->xfer[ST_DATA_RD], 0);
+ sc->buffer_size =
+ usbd_xfer_max_len(sc->xfer[ST_DATA_RD]);
+ sc->cbw = usbd_xfer_get_frame_buffer(
+ sc->xfer[ST_COMMAND], 0);
+ sc->csw = usbd_xfer_get_frame_buffer(
+ sc->xfer[ST_STATUS], 0);
+ break;
+ default:
+ break;
+ }
return (sc);
}
@@ -577,7 +702,7 @@
uint8_t sid_type;
int err;
- sc = bbb_attach(udev, iface_index);
+ sc = bbb_attach(udev, iface_index, UICLASS_MASS);
if (sc == NULL)
return (0);
@@ -633,7 +758,7 @@
uint8_t sid_type;
int err;
- sc = bbb_attach(udev, iface_index);
+ sc = bbb_attach(udev, iface_index, UICLASS_MASS);
if (sc == NULL)
return (0);
@@ -677,10 +802,28 @@
USB_MS_HZ);
if (err != 0) {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ DPRINTF("Test unit ready failed\n");
+ }
+ err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
+ &scsi_prevent_removal, sizeof(scsi_prevent_removal),
+ USB_MS_HZ);
+
+ if (err == 0) {
+ err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
+ &scsi_allow_removal, sizeof(scsi_allow_removal),
+ USB_MS_HZ);
+ }
+
+ if (err != 0) {
if (err != ERR_CSW_FAILED)
goto error;
+ DPRINTF("Device doesn't handle prevent and allow removal\n");
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
}
+
timeout = 1;
retry_sync_cache:
@@ -696,7 +839,6 @@
DPRINTF("Device doesn't handle synchronize cache\n");
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
-
} else {
/*
@@ -770,6 +912,7 @@
DPRINTF("Device did not respond, enabling all quirks\n");
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
/* Need to re-enumerate the device */
@@ -784,11 +927,10 @@
struct bbb_transfer *sc;
usb_error_t err;
- sc = bbb_attach(udev, iface_index);
+ sc = bbb_attach(udev, iface_index, UICLASS_MASS);
if (sc == NULL)
return (USB_ERR_INVAL);
- err = 0;
switch (method) {
case MSC_EJECT_STOPUNIT:
err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
@@ -819,21 +961,44 @@
&scsi_huawei_eject, sizeof(scsi_huawei_eject),
USB_MS_HZ);
break;
+ case MSC_EJECT_HUAWEI2:
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_huawei_eject2, sizeof(scsi_huawei_eject2),
+ USB_MS_HZ);
+ break;
case MSC_EJECT_TCT:
/*
* TCTMobile needs DIR_IN flag. To get it, we
* supply a dummy data with the command.
*/
- err = bbb_command_start(sc, DIR_IN, 0, &sc->buffer,
- sizeof(sc->buffer), &scsi_tct_eject,
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ sc->buffer_size, &scsi_tct_eject,
sizeof(scsi_tct_eject), USB_MS_HZ);
break;
default:
- printf("usb_msc_eject: unknown eject method (%d)\n", method);
- break;
+ DPRINTF("Unknown eject method (%d)\n", method);
+ bbb_detach(sc);
+ return (USB_ERR_INVAL);
}
+
DPRINTF("Eject CD command status: %s\n", usbd_errstr(err));
bbb_detach(sc);
return (0);
}
+
+usb_error_t
+usb_dymo_eject(struct usb_device *udev, uint8_t iface_index)
+{
+ static const uint8_t data[3] = { 0x1b, 0x5a, 0x01 };
+ struct bbb_transfer *sc;
+ usb_error_t err;
+
+ sc = bbb_attach(udev, iface_index, UICLASS_HID);
+ if (sc == NULL)
+ return (USB_ERR_INVAL);
+ err = bbb_raw_write(sc, data, sizeof(data), USB_MS_HZ);
+ bbb_detach(sc);
+ return (err);
+}
+
Modified: stable/0.8/sys/dev/usb/usb_msctest.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_msctest.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_msctest.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_msctest.h 283174 2015-05-21 06:53:55Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -33,6 +33,7 @@
MSC_EJECT_ZTESTOR,
MSC_EJECT_CMOTECH,
MSC_EJECT_HUAWEI,
+ MSC_EJECT_HUAWEI2,
MSC_EJECT_TCT,
};
@@ -42,5 +43,7 @@
uint8_t iface_index, int method);
usb_error_t usb_msc_auto_quirk(struct usb_device *udev,
uint8_t iface_index);
+usb_error_t usb_dymo_eject(struct usb_device *udev,
+ uint8_t iface_index);
#endif /* _USB_MSCTEST_H_ */
Modified: stable/0.8/sys/dev/usb/usb_parse.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_parse.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_parse.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_parse.c 217265 2011-01-11 13:59:06Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_pci.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_pci.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pci.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_pci.h 196219 2009-08-14 20:03:53Z jhb $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_pf.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_pf.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pf.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/usb_pf.c 287273 2015-08-29 06:17:39Z hselasky $");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
@@ -103,6 +103,10 @@
{
struct ifnet *ifp = ubus->ifp;
+ USB_BUS_LOCK(ubus);
+ ubus->ifp = NULL;
+ USB_BUS_UNLOCK(ubus);
+
if (ifp != NULL) {
bpfdetach(ifp);
if_down(ifp);
@@ -109,7 +113,6 @@
if_detach(ifp);
if_free(ifp);
}
- ubus->ifp = NULL;
}
static uint32_t
@@ -261,7 +264,7 @@
/* sanity checks */
if (usb_no_pf != 0)
return;
- if (bus->ifp == NULL)
+ if (bus->ifp == NULL || bus->ifp->if_bpf == NULL)
return;
if (!bpf_peers_present(bus->ifp->if_bpf))
return;
Modified: stable/0.8/sys/dev/usb/usb_pf.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_pf.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pf.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usb_pf.h 220301 2011-04-03 20:03:45Z hselasky $
*/
#ifndef _DEV_USB_PF_H
Modified: stable/0.8/sys/dev/usb/usb_process.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_process.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_process.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_process.c 273889 2014-10-31 08:06:21Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -24,8 +24,6 @@
* SUCH DAMAGE.
*/
-#define USB_DEBUG_VAR usb_proc_debug
-
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -49,6 +47,8 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usb_process.h>
+
+#define USB_DEBUG_VAR usb_proc_debug
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_util.h>
@@ -493,3 +493,15 @@
cv_signal(&up->up_cv);
}
}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_is_called_from
+ *
+ * This function will return non-zero if called from inside the USB
+ * process passed as first argument. Else this function returns zero.
+ *------------------------------------------------------------------------*/
+int
+usb_proc_is_called_from(struct usb_process *up)
+{
+ return (up->up_curtd == curthread);
+}
Modified: stable/0.8/sys/dev/usb/usb_process.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_process.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_process.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_process.h 263800 2014-03-27 07:03:50Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -79,6 +79,7 @@
void usb_proc_free(struct usb_process *up);
void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
void usb_proc_rewakeup(struct usb_process *up);
+int usb_proc_is_called_from(struct usb_process *up);
void usb_proc_explore_mwait(struct usb_device *, void *, void *);
void *usb_proc_explore_msignal(struct usb_device *, void *, void *);
Modified: stable/0.8/sys/dev/usb/usb_request.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_request.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_request.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_request.c 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -48,7 +48,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usb_ioctl.h>
#include <dev/usb/usbhid.h>
#define USB_DEBUG_VAR usb_debug
@@ -72,6 +71,11 @@
SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
&usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
+static int usb_full_ddesc;
+
+SYSCTL_INT(_hw_usb, OID_AUTO, full_ddesc, CTLFLAG_RW,
+ &usb_full_ddesc, 0, "USB always read complete device descriptor, if set");
+
#ifdef USB_DEBUG
#ifdef USB_REQ_DEBUG
/* The following structures are used in connection to fault injection. */
@@ -449,17 +453,10 @@
}
/*
- * Grab the USB device enumeration SX-lock serialization is
- * achieved when multiple threads are involved:
+ * Serialize access to this function:
*/
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
- /*
- * We need to allow suspend and resume at this point, else the
- * control transfer will timeout if the device is suspended!
- */
- usbd_sr_unlock(udev);
-
hr_func = usbd_get_hr_func(udev);
if (hr_func != NULL) {
@@ -702,14 +699,23 @@
USB_XFER_UNLOCK(xfer);
done:
- usbd_sr_lock(udev);
-
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);
+ switch (err) {
+ case USB_ERR_NORMAL_COMPLETION:
+ case USB_ERR_SHORT_XFER:
+ case USB_ERR_STALLED:
+ case USB_ERR_CANCELLED:
+ break;
+ default:
+ DPRINTF("I/O error - waiting a bit for TT cleanup\n");
+ usb_pause_mtx(mtx, hz / 16);
+ break;
+ }
return ((usb_error_t)err);
}
@@ -789,8 +795,6 @@
/* check for errors */
if (err)
goto done;
-#ifdef USB_DEBUG
-#endif
n = 0;
while (1) {
/* wait for the device to recover from reset */
@@ -997,7 +1001,7 @@
USETW(req.wLength, min_len);
err = usbd_do_request_flags(udev, mtx, &req,
- desc, 0, NULL, 1000);
+ desc, 0, NULL, 500 /* ms */);
if (err) {
if (!retries) {
@@ -1882,32 +1886,41 @@
*/
switch (udev->speed) {
case USB_SPEED_FULL:
- case USB_SPEED_LOW:
+ if (usb_full_ddesc != 0) {
+ /* get full device descriptor */
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+ if (err == 0)
+ break;
+ }
+
+ /* get partial device descriptor, some devices crash on this */
err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
- if (err != 0) {
- DPRINTFN(0, "getting device descriptor "
- "at addr %d failed, %s\n", udev->address,
- usbd_errstr(err));
- return (err);
- }
+ if (err != 0)
+ break;
+
+ /* get the full device descriptor */
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
break;
+
default:
DPRINTF("Minimum MaxPacketSize is large enough "
- "to hold the complete device descriptor\n");
+ "to hold the complete device descriptor or "
+ "only once MaxPacketSize choice\n");
+
+ /* get the full device descriptor */
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+ /* try one more time, if error */
+ if (err != 0)
+ err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
break;
}
- /* get the full device descriptor */
- err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-
- /* try one more time, if error */
- if (err)
- err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-
- if (err) {
- DPRINTF("addr=%d, getting full desc failed\n",
- udev->address);
+ if (err != 0) {
+ DPRINTFN(0, "getting device descriptor "
+ "at addr %d failed, %s\n", udev->address,
+ usbd_errstr(err));
return (err);
}
@@ -1952,6 +1965,7 @@
return (USB_ERR_INVAL);
}
retry:
+#if USB_HAVE_TT_SUPPORT
/*
* Try to reset the High Speed parent HUB of a LOW- or FULL-
* speed device, if any.
@@ -1959,8 +1973,17 @@
if (udev->parent_hs_hub != NULL &&
udev->speed != USB_SPEED_HIGH) {
DPRINTF("Trying to reset parent High Speed TT.\n");
- err = usbd_req_reset_tt(udev->parent_hs_hub, NULL,
- udev->hs_port_no);
+ if (udev->parent_hs_hub == parent_hub &&
+ (uhub_count_active_host_ports(parent_hub, USB_SPEED_LOW) +
+ uhub_count_active_host_ports(parent_hub, USB_SPEED_FULL)) == 1) {
+ /* we can reset the whole TT */
+ err = usbd_req_reset_tt(parent_hub, NULL,
+ udev->hs_port_no);
+ } else {
+ /* only reset a particular device and endpoint */
+ err = usbd_req_clear_tt_buffer(udev->parent_hs_hub, NULL,
+ udev->hs_port_no, old_addr, UE_CONTROL, 0);
+ }
if (err) {
DPRINTF("Resetting parent High "
"Speed TT failed (%s).\n",
@@ -1967,7 +1990,7 @@
usbd_errstr(err));
}
}
-
+#endif
/* Try to warm reset first */
if (parent_hub->speed == USB_SPEED_SUPER)
usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);
Modified: stable/0.8/sys/dev/usb/usb_request.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_request.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_request.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_request.h 236898 2012-06-11 17:27:53Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_transfer.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_transfer.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_transfer.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_transfer.c 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -322,6 +322,7 @@
usb_frcount_t n_frlengths;
usb_frcount_t n_frbuffers;
usb_frcount_t x;
+ uint16_t maxp_old;
uint8_t type;
uint8_t zmps;
@@ -407,6 +408,11 @@
if (xfer->max_packet_count > parm->hc_max_packet_count) {
xfer->max_packet_count = parm->hc_max_packet_count;
}
+
+ /* store max packet size value before filtering */
+
+ maxp_old = xfer->max_packet_size;
+
/* filter "wMaxPacketSize" according to HC capabilities */
if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
@@ -439,6 +445,13 @@
}
}
+ /*
+ * Check if the max packet size was outside its allowed range
+ * and clamped to a valid value:
+ */
+ if (maxp_old != xfer->max_packet_size)
+ xfer->flags_int.maxp_was_clamped = 1;
+
/* compute "max_frame_size" */
usbd_update_max_frame_size(xfer);
@@ -859,7 +872,7 @@
return (error);
/* Protect scratch area */
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
refcount = 0;
info = NULL;
@@ -902,7 +915,8 @@
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(&info->dma_parent_tag,
parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
- xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max);
+ xfer_mtx, &usb_bdma_done_event, udev->bus->dma_bits,
+ parm->dma_tag_max);
#endif
info->bus = udev->bus;
@@ -1157,7 +1171,7 @@
error = parm->err;
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
return (error);
}
@@ -1331,6 +1345,29 @@
}
/*------------------------------------------------------------------------*
+ * usbd_control_transfer_did_data
+ *
+ * This function returns non-zero if a control endpoint has
+ * transferred the first DATA packet after the SETUP packet.
+ * Else it returns zero.
+ *------------------------------------------------------------------------*/
+static uint8_t
+usbd_control_transfer_did_data(struct usb_xfer *xfer)
+{
+ struct usb_device_request req;
+
+ /* SETUP packet is not yet sent */
+ if (xfer->flags_int.control_hdr != 0)
+ return (0);
+
+ /* copy out the USB request header */
+ usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
+
+ /* compare remainder to the initial value */
+ return (xfer->flags_int.control_rem != UGETW(req.wLength));
+}
+
+/*------------------------------------------------------------------------*
* usbd_setup_ctrl_transfer
*
* This function handles initialisation of control transfers. Control
@@ -1435,6 +1472,11 @@
len = (xfer->sumlen - sizeof(struct usb_device_request));
}
+ /* update did data flag */
+
+ xfer->flags_int.control_did_data =
+ usbd_control_transfer_did_data(xfer);
+
/* check if there is a length mismatch */
if (len > xfer->flags_int.control_rem) {
@@ -2250,8 +2292,11 @@
}
#if USB_HAVE_PF
- if (xfer->usb_state != USB_ST_SETUP)
+ if (xfer->usb_state != USB_ST_SETUP) {
+ USB_BUS_LOCK(info->bus);
usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
+ USB_BUS_UNLOCK(info->bus);
+ }
#endif
/* call processing routine */
(xfer->callback) (xfer, xfer->error);
@@ -2366,8 +2411,10 @@
void
usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
{
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
+ struct usb_xfer_root *info = xfer->xroot;
+ USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
+
DPRINTF("err=%s\n", usbd_errstr(error));
/*
@@ -2380,10 +2427,10 @@
xfer->flags_int.control_act = 0;
return;
}
- /* only set transfer error if not already set */
- if (!xfer->error) {
+ /* only set transfer error, if not already set */
+ if (xfer->error == USB_ERR_NORMAL_COMPLETION)
xfer->error = error;
- }
+
/* stop any callouts */
usb_callout_stop(&xfer->timeout_handle);
@@ -2395,7 +2442,7 @@
usbd_transfer_dequeue(xfer);
#if USB_HAVE_BUSDMA
- if (mtx_owned(xfer->xroot->xfer_mtx)) {
+ if (mtx_owned(info->xfer_mtx)) {
struct usb_xfer_queue *pq;
/*
@@ -2402,7 +2449,7 @@
* If the private USB lock is not locked, then we assume
* that the BUS-DMA load stage has been passed:
*/
- pq = &xfer->xroot->dma_q;
+ pq = &info->dma_q;
if (pq->curr == xfer) {
/* start the next BUS-DMA load, if any */
@@ -2412,10 +2459,10 @@
#endif
/* keep some statistics */
if (xfer->error) {
- xfer->xroot->bus->stats_err.uds_requests
+ info->bus->stats_err.uds_requests
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
} else {
- xfer->xroot->bus->stats_ok.uds_requests
+ info->bus->stats_ok.uds_requests
[xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
}
@@ -2655,7 +2702,7 @@
/* defer delay */
usb_callout_reset(&xfer->timeout_handle,
- USB_MS_TO_TICKS(ms), cb, xfer);
+ USB_MS_TO_TICKS(ms) + USB_CALLOUT_ZERO_TICKS, cb, xfer);
}
/*------------------------------------------------------------------------*
@@ -2781,6 +2828,22 @@
/* end of control transfer, if any */
xfer->flags_int.control_act = 0;
+#if USB_HAVE_TT_SUPPORT
+ switch (xfer->error) {
+ case USB_ERR_NORMAL_COMPLETION:
+ case USB_ERR_SHORT_XFER:
+ case USB_ERR_STALLED:
+ case USB_ERR_CANCELLED:
+ /* nothing to do */
+ break;
+ default:
+ /* try to reset the TT, if any */
+ USB_BUS_LOCK(bus);
+ uhub_tt_buffer_reset_async_locked(xfer->xroot->udev, xfer->endpoint);
+ USB_BUS_UNLOCK(bus);
+ break;
+ }
+#endif
/* check if we should block the execution queue */
if ((xfer->error != USB_ERR_CANCELLED) &&
(xfer->flags.pipe_bof)) {
@@ -3347,3 +3410,13 @@
{
return (xfer->isoc_time_complete);
}
+
+/*
+ * The following function returns non-zero if the max packet size
+ * field was clamped to a valid value. Else it returns zero.
+ */
+uint8_t
+usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
+{
+ return (xfer->flags_int.maxp_was_clamped);
+}
Modified: stable/0.8/sys/dev/usb/usb_transfer.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_transfer.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_transfer.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_transfer.h 213435 2010-10-04 23:18:05Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usb_util.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_util.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_util.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_util.c 305735 2016-09-12 10:20:44Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -94,7 +94,7 @@
}
/* Protect scratch area */
- do_unlock = usbd_enum_lock(udev);
+ do_unlock = usbd_ctrl_lock(udev);
temp_p = (char *)udev->scratch.data;
@@ -111,7 +111,7 @@
}
if (do_unlock)
- usbd_enum_unlock(udev);
+ usbd_ctrl_unlock(udev);
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,
Modified: stable/0.8/sys/dev/usb/usb_util.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_util.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_util.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_util.h 229118 2011-12-31 15:31:34Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
Modified: stable/0.8/sys/dev/usb/usbdevs
===================================================================
--- stable/0.8/sys/dev/usb/usbdevs 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdevs 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-$MidnightBSD$
+$FreeBSD: stable/9/sys/dev/usb/usbdevs 315250 2017-03-14 15:25:49Z hselasky $
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
/*-
@@ -525,7 +525,7 @@
vendor CANYON 0x0c10 Canyon
vendor ICOM 0x0c26 Icom Inc.
vendor GNOTOMETRICS 0x0c33 GN Otometrics
-vendor CHICONY2 0x0c45 Chicony
+vendor CHICONY2 0x0c45 Chicony / Microdia / Sonix Technology Co., Ltd.
vendor REINERSCT 0x0c4b Reiner-SCT
vendor SEALEVEL 0x0c52 Sealevel System
vendor JETI 0x0c6c Jeti
@@ -687,6 +687,7 @@
vendor SWEEX2 0x177f Sweex
vendor METAGEEK 0x1781 MetaGeek
vendor KAMSTRUP 0x17a8 Kamstrup A/S
+vendor DISPLAYLINK 0x17e9 DisplayLink
vendor LENOVO 0x17ef Lenovo
vendor WAVESENSE 0x17f4 WaveSense
vendor VAISALA 0x1843 Vaisala
@@ -775,6 +776,7 @@
vendor NETGEAR4 0x9846 Netgear
vendor MARVELL 0x9e88 Marvell Technology Group Ltd.
vendor 3COM3 0xa727 3Com
+vendor CACE 0xcace CACE Technologies
vendor EVOLUTION 0xdeee Evolution Robotics products
vendor DATAAPEX 0xdaae DataApex
vendor HP2 0xf003 Hewlett Packard
@@ -862,6 +864,7 @@
product ACCTON RT3070_5 0xd522 RT3070
product ACCTON RTL8192SU 0xc512 RTL8192SU
product ACCTON ZD1211B 0xe501 ZD1211B
+product ACCTON WN7512 0xf522 WN7512
/* Aceeca products */
product ACEECA MEZ1000 0x0001 MEZ1000 RDA
@@ -1128,6 +1131,10 @@
product APPLE WELLSPRING8_ANSI 0x0290 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING8_ISO 0x0291 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING8_JIS 0x0292 Apple Internal Keyboard/Trackpad
+/* MacbookPro12,1 */
+product APPLE WELLSPRING9_ANSI 0x0272 Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_ISO 0x0273 Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_JIS 0x0274 Apple Internal Keyboard/Trackpad
product APPLE MOUSE 0x0301 Mouse M4848
product APPLE OPTMOUSE 0x0302 Optical mouse
product APPLE MIGHTYMOUSE 0x0304 Mighty Mouse
@@ -1222,6 +1229,11 @@
product ATHEROS2 AR5523_2_NF 0x0004 AR5523 (no firmware)
product ATHEROS2 AR5523_3 0x0005 AR5523
product ATHEROS2 AR5523_3_NF 0x0006 AR5523 (no firmware)
+product ATHEROS2 TG121N 0x1001 TG121N
+product ATHEROS2 WN821NV2 0x1002 WN821NV2
+product ATHEROS2 3CRUSBN275 0x1010 3CRUSBN275
+product ATHEROS2 WN612 0x1011 WN612
+product ATHEROS2 AR9170 0x9170 AR9170
/* Atmel Comp. products */
product ATMEL STK541 0x2109 Zigbee Controller
@@ -1237,6 +1249,9 @@
/* Avision products */
product AVISION 1200U 0x0268 1200U scanner
+/* AVM products */
+product AVM FRITZWLAN 0x8401 FRITZ!WLAN N
+
/* Axesstel products */
product AXESSTEL DATAMODEM 0x1000 Data Modem
@@ -1339,6 +1354,9 @@
product BTC BTC6100 0x5550 6100C Keyboard
product BTC BTC7932 0x6782 Keyboard with mouse port
+/* CACE Technologies products */
+product CACE AIRPCAPNX 0x0300 AirPcap NX
+
/* Canon, Inc. products */
product CANON N656U 0x2206 CanoScan N656U
product CANON N1220U 0x2207 CanoScan N1220U
@@ -1407,6 +1425,7 @@
product CISCOLINKSYS WUSB54GR 0x0023 WUSB54GR
product CISCOLINKSYS WUSBF54G 0x0024 WUSBF54G
product CISCOLINKSYS AE1000 0x002f AE1000
+product CISCOLINKSYS USB3GIGV1 0x0041 USB3GIGV1 USB Ethernet Adapter
product CISCOLINKSYS2 RT3070 0x4001 RT3070
product CISCOLINKSYS3 RT3070 0x0101 RT3070
@@ -1419,6 +1438,9 @@
product CLIPSAL C5000CT2 0x0305 C5000CT2 C-Bus Touch Screen
product CLIPSAL L51xx 0x0401 L51xx C-Bus Dimmer
+/* C-Media products */
+product CMEDIA CM6206 0x0102 CM106 compatible sound device
+
/* CMOTECH products */
product CMOTECH CNU510 0x5141 CDMA Technologies USB modem
product CMOTECH CNU550 0x5543 CDMA 2000 1xRTT/1xEVDO USB modem
@@ -1490,6 +1512,7 @@
/* Corsair products */
product CORSAIR K60 0x0a60 Corsair Vengeance K60 keyboard
product CORSAIR K70 0x1b09 Corsair Vengeance K70 keyboard
+product CORSAIR STRAFE 0x1b15 Cossair STRAFE Gaming keyboard
/* Creative products */
product CREATIVE NOMAD_II 0x1002 Nomad II MP3 player
@@ -1598,6 +1621,7 @@
product DLINK DSB650TX4 0x200c 10/100 Ethernet
product DLINK DWL120E 0x3200 DWL-120 rev E
product DLINK DWA125D1 0x330f DWA-125 rev D1
+product DLINK DWA123D1 0x3310 DWA-123 rev D1
product DLINK DWL122 0x3700 DWL-122
product DLINK DWLG120 0x3701 DWL-G120
product DLINK DWL120F 0x3702 DWL-120 rev F
@@ -1637,8 +1661,10 @@
product DLINK2 RTL8192SU_1 0x3300 RTL8192SU
product DLINK2 RTL8192SU_2 0x3302 RTL8192SU
product DLINK2 DWA131A1 0x3303 DWA-131 A1
+product DLINK2 DWA160A2 0x3a09 DWA-160 A2
product DLINK2 DWA120 0x3a0c DWA-120
product DLINK2 DWA120_NF 0x3a0d DWA-120 (no firmware)
+product DLINK2 DWA130D1 0x3a0f DWA-130 D1
product DLINK2 DWLG122C1 0x3c03 DWL-G122 c1
product DLINK2 WUA1340 0x3c04 WUA-1340
product DLINK2 DWA111 0x3c06 DWA-111
@@ -1649,6 +1675,7 @@
product DLINK2 RT3070_1 0x3c0d RT3070
product DLINK2 RT3070_2 0x3c0e RT3070
product DLINK2 RT3070_3 0x3c0f RT3070
+product DLINK2 DWA160A1 0x3c10 DWA-160 A1
product DLINK2 RT2870_2 0x3c11 RT2870
product DLINK2 DWA130 0x3c13 DWA-130
product DLINK2 RT3070_4 0x3c15 RT3070
@@ -1655,6 +1682,28 @@
product DLINK2 RT3070_5 0x3c16 RT3070
product DLINK3 DWM652 0x3e04 DWM-652
+/* DisplayLink products */
+product DISPLAYLINK LCD4300U 0x01ba LCD-4300U
+product DISPLAYLINK LCD8000U 0x01bb LCD-8000U
+product DISPLAYLINK LD220 0x0100 Samsung LD220
+product DISPLAYLINK GUC2020 0x0059 IOGEAR DVI GUC2020
+product DISPLAYLINK VCUD60 0x0136 Rextron DVI
+product DISPLAYLINK CONV 0x0138 StarTech CONV-USB2DVI
+product DISPLAYLINK DLDVI 0x0141 DisplayLink DVI
+product DISPLAYLINK VGA10 0x015a CMP-USBVGA10
+product DISPLAYLINK WSDVI 0x0198 WS Tech DVI
+product DISPLAYLINK EC008 0x019b EasyCAP008 DVI
+product DISPLAYLINK HPDOCK 0x01d4 HP USB Docking
+product DISPLAYLINK NL571 0x01d7 HP USB DVI
+product DISPLAYLINK M01061 0x01e2 Lenovo DVI
+product DISPLAYLINK SWDVI 0x024c SUNWEIT DVI
+product DISPLAYLINK NBDOCK 0x0215 VideoHome NBdock1920
+product DISPLAYLINK LUM70 0x02a9 Lilliput UM-70
+product DISPLAYLINK UM7X0 0x401a nanovision MiMo
+product DISPLAYLINK LT1421 0x03e0 Lenovo ThinkVision LT1421
+product DISPLAYLINK POLARIS2 0x0117 Polaris2 USB dock
+product DISPLAYLINK PLUGABLE 0x0377 Plugable docking station
+
/* DMI products */
product DMI CFSM_RW 0xa109 CF/SM Reader/Writer
product DMI DISK 0x2bcf Generic Disk
@@ -1715,6 +1764,7 @@
product ELECOM LDUSBTX0 0x200c LD-USB/TX
product ELECOM LDUSBTX1 0x4002 LD-USB/TX
product ELECOM LDUSBLTX 0x4005 LD-USBL/TX
+product ELECOM WDC150SU2M 0x4008 WDC-150SU2M
product ELECOM LDUSBTX2 0x400b LD-USB/TX
product ELECOM LDUSB20 0x4010 LD-USB20
product ELECOM UCSGT 0x5003 UC-SGT
@@ -2220,6 +2270,9 @@
product HITACHI DVDCAM_DZ_MV100A 0x0004 DVD-CAM DZ-MV100A Camcorder
product HITACHI DVDCAM_USB 0x001e DVDCAM USB HS Interface
+/* Holtek products */
+product HOLTEK F85 0xa030 Holtek USB gaming keyboard
+
/* HP products */
product HP 895C 0x0004 DeskJet 895C
product HP 4100C 0x0101 Scanjet 4100C
@@ -2364,6 +2417,7 @@
product HUAWEI K4505_INIT 0x1521 K4505 Initial
product HUAWEI K3772_INIT 0x1526 K3772 Initial
product HUAWEI E3272_INIT 0x155b LTE modem initial
+product HUAWEI ME909U 0x1573 LTE modem
product HUAWEI R215_INIT 0x1582 LTE modem initial
product HUAWEI R215 0x1588 LTE modem
product HUAWEI ETS2055 0x1803 CDMA modem
@@ -2442,6 +2496,7 @@
product IODATA USBWNB11A 0x0919 USB WN-B11
product IODATA USBWNB11 0x0922 USB Airport WN-B11
product IODATA ETGUS2 0x0930 ETG-US2
+product IODATA WNGDNUS2 0x093f WN-GDN/US2
product IODATA RT3072_1 0x0944 RT3072
product IODATA RT3072_2 0x0945 RT3072
product IODATA RT3072_3 0x0947 RT3072
@@ -2607,6 +2662,7 @@
product LEADTEK 9531 0x2101 9531 GPS
/* Lenovo products */
+product LENOVO GIGALAN 0x304b USB 3.0 Ethernet
product LENOVO ETHERNET 0x7203 USB 2.0 Ethernet
/* Lexar products */
@@ -2673,6 +2729,7 @@
product LOGITECH RK53 0xc501 Cordless mouse
product LOGITECH RB6 0xc503 Cordless keyboard
product LOGITECH MX700 0xc506 Cordless optical mouse
+product LOGITECH UNIFYING 0xc52b Logitech Unifying Receiver
product LOGITECH QUICKCAMPRO2 0xd001 QuickCam Pro
/* Logitec Corp. products */
@@ -2996,11 +3053,12 @@
product MELCO WLRUCGAOSS 0x0119 WLR-UC-G-AOSS
product MELCO WLIUCAG300N 0x012e WLI-UC-AG300N
product MELCO WLIUCG 0x0137 WLI-UC-G
-product MELCO RT2870_1 0x0148 RT2870
+product MELCO WLIUCG300HP 0x0148 WLI-UC-G300HP
product MELCO RT2870_2 0x0150 RT2870
product MELCO WLIUCGN 0x015d WLI-UC-GN
product MELCO WLIUCG301N 0x016f WLI-UC-G301N
product MELCO WLIUCGNM 0x01a2 WLI-UC-GNM
+product MELCO WLIUCG300HPV1 0x01a8 WLI-UC-G300HP-V1
product MELCO WLIUCGNM2 0x01ee WLI-UC-GNM2
/* Merlin products */
@@ -3023,6 +3081,11 @@
product MEI CASHFLOW_SC 0x1100 Cashflow-SC Cash Acceptor
product MEI S2000 0x1101 Series 2000 Combo Acceptor
+/* Microdia / Sonix Techonology Co., Ltd. products */
+product CHICONY2 YUREX 0x1010 YUREX
+product CHICONY2 CAM_1 0x62c0 CAM_1
+product CHICONY2 TEMPER 0x7401 TEMPer sensor
+
/* Micro Star International products */
product MSI BT_DONGLE 0x1967 Bluetooth USB dongle
product MSI RT3070_1 0x3820 RT3070
@@ -3175,6 +3238,7 @@
/* NEC products */
product NEC HUB_0050 0x0050 USB 2.0 7-Port Hub
product NEC HUB_005A 0x005a USB 2.0 4-Port Hub
+product NEC WL300NUG 0x0249 WL300NU-G
product NEC HUB 0x55aa hub
product NEC HUB_B 0x55ab hub
@@ -3202,12 +3266,17 @@
product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
product NETGEAR FA120 0x1040 USB 2.0 Ethernet
product NETGEAR M4100 0x1100 M4100/M5300/M7100 series switch
-product NETGEAR WG111V2_2 0x4240 PrismGT USB 2.0 WLAN
+product NETGEAR WG111V1_2 0x4240 PrismGT USB 2.0 WLAN
product NETGEAR WG111V3 0x4260 WG111v3
product NETGEAR WG111U 0x4300 WG111U
product NETGEAR WG111U_NF 0x4301 WG111U (no firmware)
product NETGEAR WG111V2 0x6a00 WG111V2
+product NETGEAR WN111V2 0x9001 WN111V2
+product NETGEAR WNDA3100 0x9010 WNDA3100
+product NETGEAR WNDA4100 0x9012 WNDA4100
+product NETGEAR WNDA3200 0x9018 WNDA3200
product NETGEAR RTL8192CU 0x9021 RTL8192CU
+product NETGEAR WNA1000 0x9040 WNA1000
product NETGEAR WNA1000M 0x9041 WNA1000M
product NETGEAR2 MA101 0x4100 MA101
product NETGEAR2 MA101B 0x4102 MA101 Rev B
@@ -3471,6 +3540,7 @@
product PLANEX2 RTL8188CUS 0x1201 RTL8188CUS
product PLANEX2 GW_US11S 0x3220 GW-US11S WLAN
product PLANEX2 GW_US54GXS 0x5303 GW-US54GXS WLAN
+product PLANEX2 GW_US300 0x5304 GW-US300
product PLANEX2 RTL8188CU_1 0xab2a RTL8188CU
product PLANEX2 RTL8188CU_2 0xed17 RTL8188CU
product PLANEX2 RTL8188CU_3 0x4902 RTL8188CU
@@ -3651,6 +3721,7 @@
product QUALCOMMINC E0078 0x0078 3G modem
product QUALCOMMINC E0082 0x0082 3G modem
product QUALCOMMINC E0086 0x0086 3G modem
+product QUALCOMMINC MF112 0x0103 3G modem
product QUALCOMMINC SURFSTICK 0x0117 1&1 Surf Stick
product QUALCOMMINC K3772_Z_INIT 0x1179 K3772-Z Initial
product QUALCOMMINC K3772_Z 0x1181 K3772-Z
@@ -3734,6 +3805,7 @@
product REALTEK RTL8188CU_2 0x817b RTL8188CU
product REALTEK RTL8187 0x8187 RTL8187 Wireless Adapter
product REALTEK RTL8187B_0 0x8189 RTL8187B Wireless Adapter
+product REALTEK RTL8188CU_3 0x8191 RTL8188CU
product REALTEK RTL8196EU 0x8196 RTL8196EU
product REALTEK RTL8187B_1 0x8197 RTL8187B Wireless Adapter
product REALTEK RTL8187B_2 0x8198 RTL8187B Wireless Adapter
@@ -4007,7 +4079,9 @@
product SIERRA E6892 0x6892 E6892
product SIERRA E6893 0x6893 E6893
product SIERRA MC8700 0x68A3 MC8700
-product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA
+product SIERRA MC7354 0x68C0 MC7354
+product SIERRA MC7355 0x9041 MC7355
+product SIERRA MC7430 0x9071 Sierra Wireless MC7430 Qualcomm Snapdragon X7 LTE-A
product SIERRA AC313U 0x68aa Sierra Wireless AirCard 313U
product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer
@@ -4386,6 +4460,7 @@
/* TRENDnet products */
product TRENDNET RTL8192CU 0x624d RTL8192CU
+product TRENDNET TEW646UBH 0x646b TEW-646UBH
product TRENDNET RTL8188CU 0x648b RTL8188CU
/* Tripp-Lite products */
@@ -4539,8 +4614,10 @@
product WINMAXGROUP FLASH64MC 0x6660 USB Flash Disk 64M-C
/* Wistron NeWeb products */
+product WISTRONNEWEB WNC0600 0x0326 WNC-0600USB
product WISTRONNEWEB UR045G 0x0427 PrismGT USB 2.0 WLAN
product WISTRONNEWEB UR055G 0x0711 UR055G
+product WISTRONNEWEB O8494 0x0804 ORiNOCO 802.11n
product WISTRONNEWEB AR5523_1 0x0826 AR5523
product WISTRONNEWEB AR5523_1_NF 0x0827 AR5523 (no firmware)
product WISTRONNEWEB AR5523_2 0x082a AR5523
@@ -4589,7 +4666,9 @@
product ZCOM XM142 0x0015 XM-142
product ZCOM ZD1211B 0x001a ZD1211B
product ZCOM RT2870_1 0x0022 RT2870
+product ZCOM UB81 0x0023 UB81
product ZCOM RT2870_2 0x0025 RT2870
+product ZCOM UB82 0x0026 UB82
/* Zinwell products */
product ZINWELL RT2570 0x0260 RT2570
@@ -4608,6 +4687,7 @@
/* Zydas Technology Corporation products */
product ZYDAS ZD1211 0x1211 ZD1211 WLAN abg
product ZYDAS ZD1211B 0x1215 ZD1211B
+product ZYDAS ZD1221 0x1221 ZD1221
/* ZyXEL Communication Co. products */
product ZYXEL OMNI56K 0x1500 Omni 56K Plus
@@ -4619,6 +4699,8 @@
product ZYXEL G220V2 0x340f G-220 v2
product ZYXEL G202 0x3410 G-202
product ZYXEL RT2870_1 0x3416 RT2870
+product ZYXEL NWD271N 0x3417 NWD-271N
+product ZYXEL NWD211AN 0x3418 NWD-211AN
product ZYXEL RT2870_2 0x341a RT2870
product ZYXEL RT3070 0x341e NWD2105
product ZYXEL RTL8192CU 0x341f RTL8192CU
Modified: stable/0.8/sys/dev/usb/usbdi.h
===================================================================
--- stable/0.8/sys/dev/usb/usbdi.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdi.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usbdi.h 267350 2014-06-11 06:45:52Z hselasky $
*/
#ifndef _USB_USBDI_H_
#define _USB_USBDI_H_
@@ -549,6 +549,7 @@
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
void usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
+uint8_t usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer);
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
const void *ptr, usb_frlength_t len);
@@ -565,6 +566,8 @@
void usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
usb_frlength_t len);
void usbd_start_re_enumerate(struct usb_device *udev);
+usb_error_t
+ usbd_start_set_config(struct usb_device *, uint8_t);
int usb_fifo_attach(struct usb_device *udev, void *priv_sc,
struct mtx *priv_mtx, struct usb_fifo_methods *pm,
Modified: stable/0.8/sys/dev/usb/usbdi_util.h
===================================================================
--- stable/0.8/sys/dev/usb/usbdi_util.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdi_util.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usbdi_util.h 213435 2010-10-04 23:18:05Z hselasky $
*/
#ifndef _USB_USBDI_UTIL_H_
#define _USB_USBDI_UTIL_H_
Modified: stable/0.8/sys/dev/usb/usbhid.h
===================================================================
--- stable/0.8/sys/dev/usb/usbhid.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbhid.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usbhid.h 245733 2013-01-21 07:28:46Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
Modified: stable/0.8/sys/dev/usb/wlan/if_rum.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rum.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rum.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_rum.c 269267 2014-07-29 22:00:54Z hselasky $ */
/*-
* Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini at free.fr>
@@ -19,7 +19,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_rum.c 269267 2014-07-29 22:00:54Z hselasky $");
/*-
* Ralink Technology RT2501USB/RT2601USB chipset driver
@@ -543,6 +543,11 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
+ /* Prevent further ioctls */
+ RUM_LOCK(sc);
+ sc->sc_detached = 1;
+ RUM_UNLOCK(sc);
+
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
@@ -557,7 +562,6 @@
if_free(ifp);
}
mtx_destroy(&sc->sc_mtx);
-
return (0);
}
@@ -600,9 +604,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(rvp, M_80211_VAP);
+ return (NULL);
+ }
+
/* override state transition machine */
rvp->newstate = vap->iv_newstate;
vap->iv_newstate = rum_newstate;
@@ -1025,6 +1034,8 @@
desc->plcp_length_hi = plcp_length >> 6;
desc->plcp_length_lo = plcp_length & 0x3f;
} else {
+ if (rate == 0)
+ rate = 2; /* avoid division by zero */
plcp_length = (16 * len + rate - 1) / rate;
if (rate == 22) {
remainder = (16 * len) % 22;
@@ -1127,7 +1138,7 @@
dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
/* tell hardware to add timestamp for probe responses */
if ((wh->i_fc[0] &
@@ -1271,7 +1282,7 @@
dur = ieee80211_ack_duration(ic->ic_rt, rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
}
rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
@@ -1322,8 +1333,15 @@
struct rum_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ int error;
+ int startall = 0;
+ RUM_LOCK(sc);
+ error = sc->sc_detached ? ENXIO : 0;
+ RUM_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
RUM_LOCK(sc);
@@ -2366,8 +2384,7 @@
DEVMETHOD(device_probe, rum_match),
DEVMETHOD(device_attach, rum_attach),
DEVMETHOD(device_detach, rum_detach),
-
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t rum_driver = {
Modified: stable/0.8/sys/dev/usb/wlan/if_rumfw.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumfw.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumfw.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_rumfw.h 196219 2009-08-14 20:03:53Z jhb $ */
/*-
* Copyright (c) 2005-2006, Ralink Technology, Corp.
Modified: stable/0.8/sys/dev/usb/wlan/if_rumreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_rumreg.h 196970 2009-09-08 13:19:05Z phk $ */
/*-
* Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
Modified: stable/0.8/sys/dev/usb/wlan/if_rumvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_rumvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
/*-
* Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
@@ -29,7 +29,7 @@
int8_t wr_antsignal;
int8_t wr_antnoise;
uint8_t wr_antenna;
-};
+} __packed __aligned(8);
#define RT2573_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -47,7 +47,7 @@
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-};
+} __packed __aligned(8);
#define RT2573_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -106,6 +106,7 @@
uint32_t rf_regs[4];
uint8_t txpow[44];
uint8_t sc_bssid[6];
+ uint8_t sc_detached;
struct {
uint8_t val;
Modified: stable/0.8/sys/dev/usb/wlan/if_run.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_run.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_run.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -2,6 +2,7 @@
* Copyright (c) 2008,2010 Damien Bergamini <damien.bergamini at free.fr>
* ported to FreeBSD by Akinori Furukoshi <moonlightakkiy at yahoo.ca>
* USB Consulting, Hans Petter Selasky <hselasky at freebsd.org>
+ * Copyright (c) 2013-2014 Kevin Lo
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,10 +18,10 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_run.c 294903 2016-01-27 07:34:23Z delphij $");
/*-
- * Ralink Technology RT2700U/RT2800U/RT3000U chipset driver.
+ * Ralink Technology RT2700U/RT2800U/RT3000U/RT3900E chipset driver.
* http://www.ralinktech.com/
*/
@@ -68,16 +69,15 @@
#include <dev/usb/usbdi.h>
#include "usbdevs.h"
-#define USB_DEBUG_VAR run_debug
+#define USB_DEBUG_VAR run_debug
#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_msctest.h>
#include <dev/usb/wlan/if_runreg.h>
#include <dev/usb/wlan/if_runvar.h>
-#define N(_a) ((int)(sizeof((_a)) / sizeof((_a)[0])))
-
#ifdef USB_DEBUG
-#define RUN_DEBUG
+#define RUN_DEBUG
#endif
#ifdef RUN_DEBUG
@@ -87,7 +87,7 @@
"run debug level");
#endif
-#define IEEE80211_HAS_ADDR4(wh) \
+#define IEEE80211_HAS_ADDR4(wh) \
(((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
/*
@@ -94,10 +94,13 @@
* Because of LOR in run_key_delete(), use atomic instead.
* '& RUN_CMDQ_MASQ' is to loop cmdq[].
*/
-#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
+#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
static const STRUCT_USB_HOST_ID run_devs[] = {
-#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+#define RUN_DEV_EJECT(v,p) \
+ { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RUN_EJECT) }
+#define RUN_EJECT 1
RUN_DEV(ABOCOM, RT2770),
RUN_DEV(ABOCOM, RT2870),
RUN_DEV(ABOCOM, RT3070),
@@ -136,6 +139,7 @@
RUN_DEV(ASUS, RT2870_5),
RUN_DEV(ASUS, USBN13),
RUN_DEV(ASUS, RT3070_1),
+ RUN_DEV(ASUS, USBN66),
RUN_DEV(ASUS, USB_N53),
RUN_DEV(ASUS2, USBN11),
RUN_DEV(AZUREWAVE, RT2870_1),
@@ -143,10 +147,12 @@
RUN_DEV(AZUREWAVE, RT3070_1),
RUN_DEV(AZUREWAVE, RT3070_2),
RUN_DEV(AZUREWAVE, RT3070_3),
+ RUN_DEV(BELKIN, F9L1103),
RUN_DEV(BELKIN, F5D8053V3),
RUN_DEV(BELKIN, F5D8055),
RUN_DEV(BELKIN, F5D8055V2),
RUN_DEV(BELKIN, F6D4050V1),
+ RUN_DEV(BELKIN, F6D4050V2),
RUN_DEV(BELKIN, RT2870_1),
RUN_DEV(BELKIN, RT2870_2),
RUN_DEV(CISCOLINKSYS, AE1000),
@@ -171,6 +177,10 @@
RUN_DEV(CYBERTAN, RT2870),
RUN_DEV(DLINK, RT2870),
RUN_DEV(DLINK, RT3072),
+ RUN_DEV(DLINK, DWA127),
+ RUN_DEV(DLINK, DWA140B3),
+ RUN_DEV(DLINK, DWA160B2),
+ RUN_DEV(DLINK, DWA162),
RUN_DEV(DLINK2, DWA130),
RUN_DEV(DLINK2, RT2870_1),
RUN_DEV(DLINK2, RT2870_2),
@@ -183,6 +193,7 @@
RUN_DEV(DLINK2, RT3072_1),
RUN_DEV(EDIMAX, EW7717),
RUN_DEV(EDIMAX, EW7718),
+ RUN_DEV(EDIMAX, EW7733UND),
RUN_DEV(EDIMAX, RT2870_1),
RUN_DEV(ENCORE, RT3070_1),
RUN_DEV(ENCORE, RT3070_2),
@@ -212,7 +223,7 @@
RUN_DEV(LOGITEC, LANW300NU2),
RUN_DEV(LOGITEC, LANW150NU2),
RUN_DEV(LOGITEC, LANW300NU2S),
- RUN_DEV(MELCO, RT2870_1),
+ RUN_DEV(MELCO, WLIUCG300HP),
RUN_DEV(MELCO, RT2870_2),
RUN_DEV(MELCO, WLIUCAG300N),
RUN_DEV(MELCO, WLIUCG300N),
@@ -219,6 +230,7 @@
RUN_DEV(MELCO, WLIUCG301N),
RUN_DEV(MELCO, WLIUCGN),
RUN_DEV(MELCO, WLIUCGNM),
+ RUN_DEV(MELCO, WLIUCG300HPV1),
RUN_DEV(MELCO, WLIUCGNM2),
RUN_DEV(MOTOROLA4, RT2770),
RUN_DEV(MOTOROLA4, RT3070),
@@ -233,6 +245,7 @@
RUN_DEV(MSI, RT3070_9),
RUN_DEV(MSI, RT3070_10),
RUN_DEV(MSI, RT3070_11),
+ RUN_DEV(NETGEAR, WNDA4100),
RUN_DEV(OVISLINK, RT3072),
RUN_DEV(PARA, RT3070),
RUN_DEV(PEGATRON, RT2870),
@@ -254,6 +267,9 @@
RUN_DEV(RALINK, RT3072),
RUN_DEV(RALINK, RT3370),
RUN_DEV(RALINK, RT3572),
+ RUN_DEV(RALINK, RT3573),
+ RUN_DEV(RALINK, RT5370),
+ RUN_DEV(RALINK, RT5572),
RUN_DEV(RALINK, RT8070),
RUN_DEV(SAMSUNG, WIS09ABGN),
RUN_DEV(SAMSUNG2, RT2870_1),
@@ -301,6 +317,10 @@
RUN_DEV(ZINWELL, RT3072_2),
RUN_DEV(ZYXEL, RT2870_1),
RUN_DEV(ZYXEL, RT2870_2),
+ RUN_DEV(ZYXEL, RT3070),
+ RUN_DEV_EJECT(ZYXEL, NWD2705),
+ RUN_DEV_EJECT(RALINK, RT_STOR),
+#undef RUN_DEV_EJECT
#undef RUN_DEV
};
@@ -316,8 +336,11 @@
static usb_callback_t run_bulk_tx_callback4;
static usb_callback_t run_bulk_tx_callback5;
+static void run_autoinst(void *, struct usb_device *,
+ struct usb_attach_arg *);
+static int run_driver_loaded(struct module *, int, void *);
static void run_bulk_tx_callbackN(struct usb_xfer *xfer,
- usb_error_t error, unsigned int index);
+ usb_error_t error, u_int index);
static struct ieee80211vap *run_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
const uint8_t [IEEE80211_ADDR_LEN],
@@ -339,15 +362,18 @@
static int run_write_region_1(struct run_softc *, uint16_t,
const uint8_t *, int);
static int run_set_region_4(struct run_softc *, uint16_t, uint32_t, int);
+static int run_efuse_read(struct run_softc *, uint16_t, uint16_t *, int);
static int run_efuse_read_2(struct run_softc *, uint16_t, uint16_t *);
static int run_eeprom_read_2(struct run_softc *, uint16_t, uint16_t *);
-static int run_rt2870_rf_write(struct run_softc *, uint8_t, uint32_t);
+static int run_rt2870_rf_write(struct run_softc *, uint32_t);
static int run_rt3070_rf_read(struct run_softc *, uint8_t, uint8_t *);
static int run_rt3070_rf_write(struct run_softc *, uint8_t, uint8_t);
static int run_bbp_read(struct run_softc *, uint8_t, uint8_t *);
static int run_bbp_write(struct run_softc *, uint8_t, uint8_t);
static int run_mcu_cmd(struct run_softc *, uint8_t, uint16_t);
-static const char *run_get_rf(int);
+static const char *run_get_rf(uint16_t);
+static void run_rt3593_get_txpower(struct run_softc *);
+static void run_get_txpower(struct run_softc *);
static int run_read_eeprom(struct run_softc *);
static struct ieee80211_node *run_node_alloc(struct ieee80211vap *,
const uint8_t mac[IEEE80211_ADDR_LEN]);
@@ -359,7 +385,7 @@
static void run_key_update_end(struct ieee80211vap *);
static void run_key_set_cb(void *);
static int run_key_set(struct ieee80211vap *, struct ieee80211_key *,
- const uint8_t mac[IEEE80211_ADDR_LEN]);
+ const uint8_t mac[IEEE80211_ADDR_LEN]);
static void run_key_delete_cb(void *);
static int run_key_delete(struct ieee80211vap *, struct ieee80211_key *);
static void run_ratectl_to(void *);
@@ -385,6 +411,7 @@
const struct ieee80211_bpf_params *);
static void run_start(struct ifnet *);
static int run_ioctl(struct ifnet *, u_long, caddr_t);
+static void run_iq_calib(struct run_softc *, u_int);
static void run_set_agc(struct run_softc *, uint8_t);
static void run_select_chan_group(struct run_softc *, int);
static void run_set_rx_antenna(struct run_softc *, int);
@@ -391,6 +418,9 @@
static void run_rt2870_set_chan(struct run_softc *, u_int);
static void run_rt3070_set_chan(struct run_softc *, u_int);
static void run_rt3572_set_chan(struct run_softc *, u_int);
+static void run_rt3593_set_chan(struct run_softc *, u_int);
+static void run_rt5390_set_chan(struct run_softc *, u_int);
+static void run_rt5592_set_chan(struct run_softc *, u_int);
static int run_set_chan(struct run_softc *, struct ieee80211_channel *);
static void run_set_channel(struct ieee80211com *);
static void run_scan_start(struct ieee80211com *);
@@ -414,17 +444,47 @@
static int8_t run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
static void run_update_promisc_locked(struct ifnet *);
static void run_update_promisc(struct ifnet *);
+static void run_rt5390_bbp_init(struct run_softc *);
static int run_bbp_init(struct run_softc *);
static int run_rt3070_rf_init(struct run_softc *);
+static void run_rt3593_rf_init(struct run_softc *);
+static void run_rt5390_rf_init(struct run_softc *);
static int run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t,
uint8_t *);
static void run_rt3070_rf_setup(struct run_softc *);
+static void run_rt3593_rf_setup(struct run_softc *);
+static void run_rt5390_rf_setup(struct run_softc *);
static int run_txrx_enable(struct run_softc *);
+static void run_adjust_freq_offset(struct run_softc *);
static void run_init(void *);
static void run_init_locked(struct run_softc *);
static void run_stop(void *);
-static void run_delay(struct run_softc *, unsigned int);
+static void run_delay(struct run_softc *, u_int);
+static eventhandler_tag run_etag;
+
+static const struct rt2860_rate {
+ uint8_t rate;
+ uint8_t mcs;
+ enum ieee80211_phytype phy;
+ uint8_t ctl_ridx;
+ uint16_t sp_ack_dur;
+ uint16_t lp_ack_dur;
+} rt2860_rates[] = {
+ { 2, 0, IEEE80211_T_DS, 0, 314, 314 },
+ { 4, 1, IEEE80211_T_DS, 1, 258, 162 },
+ { 11, 2, IEEE80211_T_DS, 2, 223, 127 },
+ { 22, 3, IEEE80211_T_DS, 3, 213, 117 },
+ { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 },
+ { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 },
+ { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 },
+ { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 },
+ { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 },
+ { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 },
+ { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 },
+ { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 }
+};
+
static const struct {
uint16_t reg;
uint32_t val;
@@ -437,8 +497,27 @@
uint8_t val;
} rt2860_def_bbp[] = {
RT2860_DEF_BBP
+},rt5390_def_bbp[] = {
+ RT5390_DEF_BBP
+},rt5592_def_bbp[] = {
+ RT5592_DEF_BBP
};
+/*
+ * Default values for BBP register R196 for RT5592.
+ */
+static const uint8_t rt5592_bbp_r196[] = {
+ 0xe0, 0x1f, 0x38, 0x32, 0x08, 0x28, 0x19, 0x0a, 0xff, 0x00,
+ 0x16, 0x10, 0x10, 0x0b, 0x36, 0x2c, 0x26, 0x24, 0x42, 0x36,
+ 0x30, 0x2d, 0x4c, 0x46, 0x3d, 0x40, 0x3e, 0x42, 0x3d, 0x40,
+ 0x3c, 0x34, 0x2c, 0x2f, 0x3c, 0x35, 0x2e, 0x2a, 0x49, 0x41,
+ 0x36, 0x31, 0x30, 0x30, 0x0e, 0x0d, 0x28, 0x21, 0x1c, 0x16,
+ 0x50, 0x4a, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7d, 0x14, 0x32, 0x2c, 0x36, 0x4c, 0x43, 0x2c,
+ 0x2e, 0x36, 0x30, 0x6e
+};
+
static const struct rfprog {
uint8_t chan;
uint32_t r1, r2, r3, r4;
@@ -452,6 +531,15 @@
RT3070_RF3052
};
+static const struct rt5592_freqs {
+ uint16_t n;
+ uint8_t k, m, r;
+} rt5592_freqs_20mhz[] = {
+ RT5592_RF5592_20MHZ
+},rt5592_freqs_40mhz[] = {
+ RT5592_RF5592_40MHZ
+};
+
static const struct {
uint8_t reg;
uint8_t val;
@@ -459,8 +547,29 @@
RT3070_DEF_RF
},rt3572_def_rf[] = {
RT3572_DEF_RF
+},rt3593_def_rf[] = {
+ RT3593_DEF_RF
+},rt5390_def_rf[] = {
+ RT5390_DEF_RF
+},rt5392_def_rf[] = {
+ RT5392_DEF_RF
+},rt5592_def_rf[] = {
+ RT5592_DEF_RF
+},rt5592_2ghz_def_rf[] = {
+ RT5592_2GHZ_DEF_RF
+},rt5592_5ghz_def_rf[] = {
+ RT5592_5GHZ_DEF_RF
};
+static const struct {
+ u_int firstchan;
+ u_int lastchan;
+ uint8_t reg;
+ uint8_t val;
+} rt5592_chan_5ghz[] = {
+ RT5592_CHAN_5GHZ
+};
+
static const struct usb_config run_config[RUN_N_XFER] = {
[RUN_BULK_TX_BE] = {
.type = UE_BULK,
@@ -532,7 +641,47 @@
}
};
+static void
+run_autoinst(void *arg, struct usb_device *udev,
+ struct usb_attach_arg *uaa)
+{
+ struct usb_interface *iface;
+ struct usb_interface_descriptor *id;
+
+ if (uaa->dev_state != UAA_DEV_READY)
+ return;
+
+ iface = usbd_get_iface(udev, 0);
+ if (iface == NULL)
+ return;
+ id = iface->idesc;
+ if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+ return;
+ if (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa))
+ return;
+
+ if (usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT) == 0)
+ uaa->dev_state = UAA_DEV_EJECTING;
+}
+
static int
+run_driver_loaded(struct module *mod, int what, void *arg)
+{
+ switch (what) {
+ case MOD_LOAD:
+ run_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
+ run_autoinst, NULL, EVENTHANDLER_PRI_ANY);
+ break;
+ case MOD_UNLOAD:
+ EVENTHANDLER_DEREGISTER(usb_dev_configured, run_etag);
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (0);
+}
+
+static int
run_match(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
@@ -555,12 +704,14 @@
struct ieee80211com *ic;
struct ifnet *ifp;
uint32_t ver;
- int i, ntries, error;
+ int ntries, error;
uint8_t iface_index, bands;
device_set_usb_desc(self);
sc->sc_udev = uaa->device;
sc->sc_dev = self;
+ if (USB_GET_DRIVER_INFO(uaa) != RUN_EJECT)
+ sc->sc_flags |= RUN_FLAG_FWLOAD_NEEDED;
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
@@ -652,27 +803,12 @@
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
setbit(&bands, IEEE80211_MODE_11G);
+ if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
+ sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
+ sc->rf_rev == RT5592_RF_5592)
+ setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- /*
- * Do this by own because h/w supports
- * more channels than ieee80211_init_channels()
- */
- if (sc->rf_rev == RT2860_RF_2750 ||
- sc->rf_rev == RT2860_RF_2850 ||
- sc->rf_rev == RT3070_RF_3052) {
- /* set supported .11a rates */
- for (i = 14; i < N(rt2860_rf2850); i++) {
- uint8_t chan = rt2860_rf2850[i].chan;
- ic->ic_channels[ic->ic_nchans].ic_freq =
- ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A);
- ic->ic_channels[ic->ic_nchans].ic_ieee = chan;
- ic->ic_channels[ic->ic_nchans].ic_flags = IEEE80211_CHAN_A;
- ic->ic_channels[ic->ic_nchans].ic_extieee = 0;
- ic->ic_nchans++;
- }
- }
-
ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_scan_start = run_scan_start;
@@ -697,7 +833,7 @@
TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc);
TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc);
- callout_init((struct callout *)&sc->ratectl_ch, 1);
+ usb_callout_init_mtx(&sc->ratectl_ch, &sc->sc_mtx, 0);
if (bootverbose)
ieee80211_announce(ic);
@@ -717,11 +853,14 @@
struct ieee80211com *ic;
int i;
+ RUN_LOCK(sc);
+ sc->sc_detached = 1;
+ RUN_UNLOCK(sc);
+
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER);
RUN_LOCK(sc);
-
sc->ratectl_run = RUN_RATECTL_OFF;
sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT;
@@ -798,8 +937,14 @@
if (rvp == NULL)
return (NULL);
vap = &rvp->vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ if (ieee80211_vap_setup(ic, vap, name, unit,
+ opmode, flags, bssid, mac) != 0) {
+ /* out of memory */
+ free(rvp, M_80211_VAP);
+ return (NULL);
+ }
+
vap->iv_key_update_begin = run_key_update_begin;
vap->iv_key_update_end = run_key_update_end;
vap->iv_update_beacon = run_update_beacon;
@@ -1004,17 +1149,18 @@
/* cheap sanity check */
temp = fw->data;
bytes = *temp;
- if (bytes != be64toh(0xffffff0210280210)) {
+ if (bytes != be64toh(0xffffff0210280210ULL)) {
device_printf(sc->sc_dev, "firmware checksum failed\n");
error = EINVAL;
goto fail;
}
- run_read(sc, RT2860_ASIC_VER_ID, &tmp);
/* write microcode image */
- run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
- run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
- run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+ if (sc->sc_flags & RUN_FLAG_FWLOAD_NEEDED) {
+ run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
+ run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
+ run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+ }
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = RT2870_RESET;
@@ -1029,15 +1175,16 @@
run_delay(sc, 10);
+ run_write(sc, RT2860_H2M_BBPAGENT, 0);
run_write(sc, RT2860_H2M_MAILBOX, 0);
+ run_write(sc, RT2860_H2M_INTSRC, 0);
if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0)
goto fail;
/* wait until microcontroller is ready */
for (ntries = 0; ntries < 1000; ntries++) {
- if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) {
+ if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0)
goto fail;
- }
if (tmp & RT2860_MCU_READY)
break;
run_delay(sc, 10);
@@ -1057,7 +1204,7 @@
return (error);
}
-int
+static int
run_reset(struct run_softc *sc)
{
usb_device_request_t req;
@@ -1159,13 +1306,32 @@
return (error);
#else
usb_device_request_t req;
+ int error = 0;
- req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
- req.bRequest = RT2870_WRITE_REGION_1;
- USETW(req.wValue, 0);
- USETW(req.wIndex, reg);
- USETW(req.wLength, len);
- return (run_do_request(sc, &req, buf));
+ /*
+ * NOTE: It appears the WRITE_REGION_1 command cannot be
+ * passed a huge amount of data, which will crash the
+ * firmware. Limit amount of data passed to 64-bytes at a
+ * time.
+ */
+ while (len > 0) {
+ int delta = 64;
+ if (delta > len)
+ delta = len;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RT2870_WRITE_REGION_1;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, delta);
+ error = run_do_request(sc, &req, __DECONST(uint8_t *, buf));
+ if (error != 0)
+ break;
+ reg += delta;
+ buf += delta;
+ len -= delta;
+ }
+ return (error);
#endif
}
@@ -1180,9 +1346,8 @@
return (error);
}
-/* Read 16-bit from eFUSE ROM (RT3070 only.) */
static int
-run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count)
{
uint32_t tmp;
uint16_t reg;
@@ -1191,7 +1356,8 @@
if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0)
return (error);
- addr *= 2;
+ if (count == 2)
+ addr *= 2;
/*-
* Read one 16-byte block into registers EFUSE_DATA[0-3]:
* DATA0: F E D C
@@ -1221,11 +1387,20 @@
if ((error = run_read(sc, reg, &tmp)) != 0)
return (error);
- *val = (addr & 2) ? tmp >> 16 : tmp & 0xffff;
+ tmp >>= (8 * (addr & 0x3));
+ *val = (addr & 1) ? tmp >> 16 : tmp & 0xffff;
+
return (0);
}
+/* Read 16-bit from eFUSE ROM for RT3xxx. */
static int
+run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+{
+ return (run_efuse_read(sc, addr, val, 2));
+}
+
+static int
run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
{
usb_device_request_t req;
@@ -1237,7 +1412,7 @@
req.bRequest = RT2870_EEPROM_READ;
USETW(req.wValue, 0);
USETW(req.wIndex, addr);
- USETW(req.wLength, sizeof tmp);
+ USETW(req.wLength, sizeof(tmp));
error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &tmp);
if (error == 0)
@@ -1255,7 +1430,7 @@
}
static int
-run_rt2870_rf_write(struct run_softc *sc, uint8_t reg, uint32_t val)
+run_rt2870_rf_write(struct run_softc *sc, uint32_t val)
{
uint32_t tmp;
int error, ntries;
@@ -1269,10 +1444,7 @@
if (ntries == 10)
return (ETIMEDOUT);
- /* RF registers are 24-bit on the RT2860 */
- tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT |
- (val & 0x3fffff) << 2 | (reg & 3);
- return (run_write(sc, RT2860_RF_CSR_CFG0, tmp));
+ return (run_write(sc, RT2860_RF_CSR_CFG0, val));
}
static int
@@ -1423,7 +1595,7 @@
}
static const char *
-run_get_rf(int rev)
+run_get_rf(uint16_t rev)
{
switch (rev) {
case RT2860_RF_2820: return "RT2820";
@@ -1435,11 +1607,134 @@
case RT3070_RF_3021: return "RT3021";
case RT3070_RF_3022: return "RT3022";
case RT3070_RF_3052: return "RT3052";
+ case RT3593_RF_3053: return "RT3053";
+ case RT5592_RF_5592: return "RT5592";
+ case RT5390_RF_5370: return "RT5370";
+ case RT5390_RF_5372: return "RT5372";
}
return ("unknown");
}
-int
+static void
+run_rt3593_get_txpower(struct run_softc *sc)
+{
+ uint16_t addr, val;
+ int i;
+
+ /* Read power settings for 2GHz channels. */
+ for (i = 0; i < 14; i += 2) {
+ addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 :
+ RT2860_EEPROM_PWR2GHZ_BASE1;
+ run_srom_read(sc, addr + i / 2, &val);
+ sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+ sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+ addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 :
+ RT2860_EEPROM_PWR2GHZ_BASE2;
+ run_srom_read(sc, addr + i / 2, &val);
+ sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+ sc->txpow2[i + 1] = (int8_t)(val >> 8);
+
+ if (sc->ntxchains == 3) {
+ run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2,
+ &val);
+ sc->txpow3[i + 0] = (int8_t)(val & 0xff);
+ sc->txpow3[i + 1] = (int8_t)(val >> 8);
+ }
+ }
+ /* Fix broken Tx power entries. */
+ for (i = 0; i < 14; i++) {
+ if (sc->txpow1[i] > 31)
+ sc->txpow1[i] = 5;
+ if (sc->txpow2[i] > 31)
+ sc->txpow2[i] = 5;
+ if (sc->ntxchains == 3) {
+ if (sc->txpow3[i] > 31)
+ sc->txpow3[i] = 5;
+ }
+ }
+ /* Read power settings for 5GHz channels. */
+ for (i = 0; i < 40; i += 2) {
+ run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+ sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+ sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+ run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+ sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+ sc->txpow2[i + 15] = (int8_t)(val >> 8);
+
+ if (sc->ntxchains == 3) {
+ run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2,
+ &val);
+ sc->txpow3[i + 14] = (int8_t)(val & 0xff);
+ sc->txpow3[i + 15] = (int8_t)(val >> 8);
+ }
+ }
+}
+
+static void
+run_get_txpower(struct run_softc *sc)
+{
+ uint16_t val;
+ int i;
+
+ /* Read power settings for 2GHz channels. */
+ for (i = 0; i < 14; i += 2) {
+ run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
+ sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+ sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+ if (sc->mac_ver != 0x5390) {
+ run_srom_read(sc,
+ RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
+ sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+ sc->txpow2[i + 1] = (int8_t)(val >> 8);
+ }
+ }
+ /* Fix broken Tx power entries. */
+ for (i = 0; i < 14; i++) {
+ if (sc->mac_ver >= 0x5390) {
+ if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
+ sc->txpow1[i] = 5;
+ } else {
+ if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
+ sc->txpow1[i] = 5;
+ }
+ if (sc->mac_ver > 0x5390) {
+ if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
+ sc->txpow2[i] = 5;
+ } else if (sc->mac_ver < 0x5390) {
+ if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
+ sc->txpow2[i] = 5;
+ }
+ DPRINTF("chan %d: power1=%d, power2=%d\n",
+ rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
+ }
+ /* Read power settings for 5GHz channels. */
+ for (i = 0; i < 40; i += 2) {
+ run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+ sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+ sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+ run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+ sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+ sc->txpow2[i + 15] = (int8_t)(val >> 8);
+ }
+ /* Fix broken Tx power entries. */
+ for (i = 0; i < 40; i++ ) {
+ if (sc->mac_ver != 0x5592) {
+ if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
+ sc->txpow1[14 + i] = 5;
+ if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
+ sc->txpow2[14 + i] = 5;
+ }
+ DPRINTF("chan %d: power1=%d, power2=%d\n",
+ rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
+ sc->txpow2[14 + i]);
+ }
+}
+
+static int
run_read_eeprom(struct run_softc *sc)
{
int8_t delta_2ghz, delta_5ghz;
@@ -1452,7 +1747,7 @@
if (sc->mac_ver >= 0x3070) {
run_read(sc, RT3070_EFUSE_CTRL, &tmp);
DPRINTF("EFUSE_CTRL=0x%08x\n", tmp);
- if (tmp & RT3070_SEL_EFUSE)
+ if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593)
sc->sc_srom_read = run_efuse_read_2;
}
@@ -1471,35 +1766,45 @@
sc->sc_bssid[4] = val & 0xff;
sc->sc_bssid[5] = val >> 8;
- /* read vender BBP settings */
- for (i = 0; i < 10; i++) {
- run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
- sc->bbp[i].val = val & 0xff;
- sc->bbp[i].reg = val >> 8;
- DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val);
- }
- if (sc->mac_ver >= 0x3071) {
- /* read vendor RF settings */
+ if (sc->mac_ver < 0x3593) {
+ /* read vender BBP settings */
for (i = 0; i < 10; i++) {
- run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
- sc->rf[i].val = val & 0xff;
- sc->rf[i].reg = val >> 8;
- DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
- sc->rf[i].val);
+ run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
+ sc->bbp[i].val = val & 0xff;
+ sc->bbp[i].reg = val >> 8;
+ DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg,
+ sc->bbp[i].val);
}
+ if (sc->mac_ver >= 0x3071) {
+ /* read vendor RF settings */
+ for (i = 0; i < 10; i++) {
+ run_srom_read(sc, RT3071_EEPROM_RF_BASE + i,
+ &val);
+ sc->rf[i].val = val & 0xff;
+ sc->rf[i].reg = val >> 8;
+ DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
+ sc->rf[i].val);
+ }
+ }
}
/* read RF frequency offset from EEPROM */
- run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+ RT3593_EEPROM_FREQ, &val);
sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+ RT3593_EEPROM_FREQ_LEDS, &val);
if (val >> 8 != 0xff) {
/* read LEDs operating mode */
sc->leds = val >> 8;
- run_srom_read(sc, RT2860_EEPROM_LED1, &sc->led[0]);
- run_srom_read(sc, RT2860_EEPROM_LED2, &sc->led[1]);
- run_srom_read(sc, RT2860_EEPROM_LED3, &sc->led[2]);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 :
+ RT3593_EEPROM_LED1, &sc->led[0]);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 :
+ RT3593_EEPROM_LED2, &sc->led[1]);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 :
+ RT3593_EEPROM_LED3, &sc->led[2]);
} else {
/* broken EEPROM, use default settings */
sc->leds = 0x01;
@@ -1511,8 +1816,14 @@
sc->leds, sc->led[0], sc->led[1], sc->led[2]);
/* read RF information */
- run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+ if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392)
+ run_srom_read(sc, 0x00, &val);
+ else
+ run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+
if (val == 0xffff) {
+ device_printf(sc->sc_dev,
+ "invalid EEPROM antenna info, using default\n");
DPRINTF("invalid EEPROM antenna info, using default\n");
if (sc->mac_ver == 0x3572) {
/* default to RF3052 2T2R */
@@ -1531,11 +1842,15 @@
sc->nrxchains = 2;
}
} else {
- sc->rf_rev = (val >> 8) & 0xf;
+ if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) {
+ sc->rf_rev = val;
+ run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+ } else
+ sc->rf_rev = (val >> 8) & 0xf;
sc->ntxchains = (val >> 4) & 0xf;
sc->nrxchains = val & 0xf;
}
- DPRINTF("EEPROM RF rev=0x%02x chains=%dT%dR\n",
+ DPRINTF("EEPROM RF rev=0x%04x chains=%dT%dR\n",
sc->rf_rev, sc->ntxchains, sc->nrxchains);
/* check if RF supports automatic Tx access gain control */
@@ -1553,46 +1868,12 @@
sc->rfswitch = val & 1;
}
- /* read power settings for 2GHz channels */
- for (i = 0; i < 14; i += 2) {
- run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
- sc->txpow1[i + 0] = (int8_t)(val & 0xff);
- sc->txpow1[i + 1] = (int8_t)(val >> 8);
+ /* Read Tx power settings. */
+ if (sc->mac_ver == 0x3593)
+ run_rt3593_get_txpower(sc);
+ else
+ run_get_txpower(sc);
- run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
- sc->txpow2[i + 0] = (int8_t)(val & 0xff);
- sc->txpow2[i + 1] = (int8_t)(val >> 8);
- }
- /* fix broken Tx power entries */
- for (i = 0; i < 14; i++) {
- if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
- sc->txpow1[i] = 5;
- if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
- sc->txpow2[i] = 5;
- DPRINTF("chan %d: power1=%d, power2=%d\n",
- rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
- }
- /* read power settings for 5GHz channels */
- for (i = 0; i < 40; i += 2) {
- run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
- sc->txpow1[i + 14] = (int8_t)(val & 0xff);
- sc->txpow1[i + 15] = (int8_t)(val >> 8);
-
- run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
- sc->txpow2[i + 14] = (int8_t)(val & 0xff);
- sc->txpow2[i + 15] = (int8_t)(val >> 8);
- }
- /* fix broken Tx power entries */
- for (i = 0; i < 40; i++) {
- if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
- sc->txpow1[14 + i] = 5;
- if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
- sc->txpow2[14 + i] = 5;
- DPRINTF("chan %d: power1=%d, power2=%d\n",
- rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
- sc->txpow2[14 + i]);
- }
-
/* read Tx power compensation for each Tx rate */
run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val);
delta_2ghz = delta_5ghz = 0;
@@ -1627,27 +1908,38 @@
sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]);
}
- /* read RSSI offsets and LNA gains from EEPROM */
- run_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ, &val);
+ /* Read RSSI offsets and LNA gains from EEPROM. */
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ :
+ RT3593_EEPROM_RSSI1_2GHZ, &val);
sc->rssi_2ghz[0] = val & 0xff; /* Ant A */
sc->rssi_2ghz[1] = val >> 8; /* Ant B */
- run_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ, &val);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ :
+ RT3593_EEPROM_RSSI2_2GHZ, &val);
if (sc->mac_ver >= 0x3070) {
- /*
- * On RT3070 chips (limited to 2 Rx chains), this ROM
- * field contains the Tx mixer gain for the 2GHz band.
- */
- if ((val & 0xff) != 0xff)
- sc->txmixgain_2ghz = val & 0x7;
+ if (sc->mac_ver == 0x3593) {
+ sc->txmixgain_2ghz = 0;
+ sc->rssi_2ghz[2] = val & 0xff; /* Ant C */
+ } else {
+ /*
+ * On RT3070 chips (limited to 2 Rx chains), this ROM
+ * field contains the Tx mixer gain for the 2GHz band.
+ */
+ if ((val & 0xff) != 0xff)
+ sc->txmixgain_2ghz = val & 0x7;
+ }
DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz);
} else
sc->rssi_2ghz[2] = val & 0xff; /* Ant C */
+ if (sc->mac_ver == 0x3593)
+ run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
sc->lna[2] = val >> 8; /* channel group 2 */
- run_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ, &val);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ :
+ RT3593_EEPROM_RSSI1_5GHZ, &val);
sc->rssi_5ghz[0] = val & 0xff; /* Ant A */
sc->rssi_5ghz[1] = val >> 8; /* Ant B */
- run_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ, &val);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ :
+ RT3593_EEPROM_RSSI2_5GHZ, &val);
if (sc->mac_ver == 0x3572) {
/*
* On RT3572 chips (limited to 2 Rx chains), this ROM
@@ -1658,9 +1950,14 @@
DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz);
} else
sc->rssi_5ghz[2] = val & 0xff; /* Ant C */
+ if (sc->mac_ver == 0x3593) {
+ sc->txmixgain_5ghz = 0;
+ run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
+ }
sc->lna[3] = val >> 8; /* channel group 3 */
- run_srom_read(sc, RT2860_EEPROM_LNA, &val);
+ run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA :
+ RT3593_EEPROM_LNA, &val);
sc->lna[0] = val & 0xff; /* channel group 0 */
sc->lna[1] = val >> 8; /* channel group 1 */
@@ -2213,9 +2510,7 @@
if (vap == NULL)
return;
- if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA)
- run_iter_func(sc, vap->iv_bss);
- else {
+ if (sc->rvp_cnt > 1 || vap->iv_opmode != IEEE80211_M_STA) {
/*
* run_reset_livelock() doesn't do anything with AMRR,
* but Ralink wants us to call it every 1 sec. So, we
@@ -2228,11 +2523,14 @@
/* just in case, there are some stats to drain */
run_drain_fifo(sc);
RUN_UNLOCK(sc);
- ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc);
}
+ ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc);
+
+ RUN_LOCK(sc);
if(sc->ratectl_run != RUN_RATECTL_OFF)
usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+ RUN_UNLOCK(sc);
}
static void
@@ -2308,6 +2606,11 @@
RUN_LOCK(sc);
+ /* Check for special case */
+ if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA &&
+ ni != vap->iv_bss)
+ goto fail;
+
if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_STA)) {
/* read statistic counters (clear on read) and update AMRR state */
@@ -2436,7 +2739,10 @@
rn->mgt_ridx = ridx;
DPRINTF("rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx);
- usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+ RUN_LOCK(sc);
+ if(sc->ratectl_run != RUN_RATECTL_OFF)
+ usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+ RUN_UNLOCK(sc);
}
/*
@@ -2467,12 +2773,17 @@
struct rt2870_rxd *rxd;
struct rt2860_rxwi *rxwi;
uint32_t flags;
- uint16_t len, phy;
+ uint16_t len, rxwisize;
uint8_t ant, rssi;
int8_t nf;
rxwi = mtod(m, struct rt2860_rxwi *);
len = le16toh(rxwi->len) & 0xfff;
+ rxwisize = sizeof(struct rt2860_rxwi);
+ if (sc->mac_ver == 0x5592)
+ rxwisize += sizeof(uint64_t);
+ else if (sc->mac_ver == 0x3593)
+ rxwisize += sizeof(uint32_t);
if (__predict_false(len > dmalen)) {
m_freem(m);
ifp->if_ierrors++;
@@ -2490,8 +2801,8 @@
return;
}
- m->m_data += sizeof(struct rt2860_rxwi);
- m->m_pkthdr.len = m->m_len -= sizeof(struct rt2860_rxwi);
+ m->m_data += rxwisize;
+ m->m_pkthdr.len = m->m_len -= rxwisize;
wh = mtod(m, struct ieee80211_frame *);
@@ -2511,7 +2822,8 @@
if (__predict_false(flags & RT2860_RX_MICERR)) {
/* report MIC failures to net80211 for TKIP */
if (ni != NULL)
- ieee80211_notify_michael_failure(ni->ni_vap, wh, rxwi->keyidx);
+ ieee80211_notify_michael_failure(ni->ni_vap, wh,
+ rxwi->keyidx);
m_freem(m);
ifp->if_ierrors++;
DPRINTF("MIC error. Someone is lying.\n");
@@ -2534,6 +2846,7 @@
if (__predict_false(ieee80211_radiotap_active(ic))) {
struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
+ uint16_t phy;
tap->wr_flags = 0;
tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
@@ -2578,8 +2891,15 @@
struct mbuf *m = NULL;
struct mbuf *m0;
uint32_t dmalen;
+ uint16_t rxwisize;
int xferlen;
+ rxwisize = sizeof(struct rt2860_rxwi);
+ if (sc->mac_ver == 0x5592)
+ rxwisize += sizeof(uint64_t);
+ else if (sc->mac_ver == 0x3593)
+ rxwisize += sizeof(uint32_t);
+
usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
@@ -2587,8 +2907,8 @@
DPRINTFN(15, "rx done, actlen=%d\n", xferlen);
- if (xferlen < (int)(sizeof(uint32_t) +
- sizeof(struct rt2860_rxwi) + sizeof(struct rt2870_rxd))) {
+ if (xferlen < (int)(sizeof(uint32_t) + rxwisize +
+ sizeof(struct rt2870_rxd))) {
DPRINTF("xfer too short %d\n", xferlen);
goto tr_setup;
}
@@ -2670,6 +2990,7 @@
m->m_data += 4;
m->m_pkthdr.len = m->m_len -= 4;
run_rx_frame(sc, m, dmalen);
+ m = NULL; /* don't free source buffer */
break;
}
@@ -2691,6 +3012,9 @@
m->m_pkthdr.len = m->m_len -= dmalen + 8;
}
+ /* make sure we free the source buffer, if any */
+ m_freem(m);
+
RUN_LOCK(sc);
}
@@ -2718,7 +3042,7 @@
}
static void
-run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, unsigned int index)
+run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
@@ -2758,8 +3082,10 @@
STAILQ_REMOVE_HEAD(&pq->tx_qh, next);
m = data->m;
+ size = (sc->mac_ver == 0x5592) ?
+ sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc);
if ((m->m_pkthdr.len +
- sizeof(data->desc) + 3 + 8) > RUN_MAX_TXSZ) {
+ size + 3 + 8) > RUN_MAX_TXSZ) {
DPRINTF("data overflow, %u bytes\n",
m->m_pkthdr.len);
@@ -2771,7 +3097,6 @@
}
pc = usbd_xfer_get_frame(xfer, 0);
- size = sizeof(data->desc);
usbd_copy_in(pc, 0, &data->desc, size);
usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len);
size += m->m_pkthdr.len;
@@ -2786,9 +3111,8 @@
vap = data->ni->ni_vap;
if (ieee80211_radiotap_active_vap(vap)) {
struct run_tx_radiotap_header *tap = &sc->sc_txtap;
- struct rt2860_txwi *txwi =
+ struct rt2860_txwi *txwi =
(struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd));
-
tap->wt_flags = 0;
tap->wt_rate = rt2860_rates[data->ridx].rate;
tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
@@ -2898,7 +3222,7 @@
struct ieee80211_frame *wh;
struct rt2870_txd *txd;
struct rt2860_txwi *txwi;
- uint16_t xferlen;
+ uint16_t xferlen, txwisize;
uint16_t mcs;
uint8_t ridx = data->ridx;
uint8_t pad;
@@ -2906,7 +3230,9 @@
/* get MCS code from rate index */
mcs = rt2860_rates[ridx].mcs;
- xferlen = sizeof(*txwi) + m->m_pkthdr.len;
+ txwisize = (sc->mac_ver == 0x5592) ?
+ sizeof(*txwi) + sizeof(uint32_t) : sizeof(*txwi);
+ xferlen = txwisize + m->m_pkthdr.len;
/* roundup to 32-bit alignment */
xferlen = (xferlen + 3) & ~3;
@@ -3032,7 +3358,7 @@
dur = rt2860_rates[ctl_ridx].sp_ack_dur;
else
dur = rt2860_rates[ctl_ridx].lp_ack_dur;
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
}
/* reserve slots for mgmt packets, just in case */
@@ -3049,12 +3375,12 @@
txd->flags = qflags;
txwi = (struct rt2860_txwi *)(txd + 1);
txwi->xflags = xflags;
- if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
txwi->wcid = 0;
- } else {
+ else
txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
1 : RUN_AID2WCID(ni->ni_associd);
- }
+
/* clear leftover garbage bits */
txwi->flags = 0;
txwi->txop = 0;
@@ -3112,9 +3438,9 @@
usbd_transfer_start(sc->sc_xfer[qid]);
- DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", m->m_pkthdr.len +
- (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
- rt2860_rates[ridx].rate, qid);
+ DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n",
+ m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) +
+ sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate, qid);
return (0);
}
@@ -3151,7 +3477,7 @@
dur = ieee80211_ack_duration(ic->ic_rt, rt2860_rates[ridx].rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
}
if (sc->sc_epq[0].tx_nfree == 0) {
@@ -3178,7 +3504,7 @@
run_set_tx_desc(sc, data);
DPRINTFN(10, "sending mgt frame len=%d rate=%d\n", m->m_pkthdr.len +
- (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
+ (int)(sizeof(struct rt2870_txd) + sizeof(struct rt2860_txwi)),
rt2860_rates[ridx].rate);
STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next);
@@ -3442,8 +3768,14 @@
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int startall = 0;
- int error = 0;
+ int error;
+ RUN_LOCK(sc);
+ error = sc->sc_detached ? ENXIO : 0;
+ RUN_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
RUN_LOCK(sc);
@@ -3478,6 +3810,107 @@
}
static void
+run_iq_calib(struct run_softc *sc, u_int chan)
+{
+ uint16_t val;
+
+ /* Tx0 IQ gain. */
+ run_bbp_write(sc, 158, 0x2c);
+ if (chan <= 14)
+ run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1);
+ else if (chan <= 64) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ,
+ &val, 1);
+ } else if (chan <= 138) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ,
+ &val, 1);
+ } else if (chan <= 165) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ,
+ &val, 1);
+ } else
+ val = 0;
+ run_bbp_write(sc, 159, val);
+
+ /* Tx0 IQ phase. */
+ run_bbp_write(sc, 158, 0x2d);
+ if (chan <= 14) {
+ run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ,
+ &val, 1);
+ } else if (chan <= 64) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ,
+ &val, 1);
+ } else if (chan <= 138) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ,
+ &val, 1);
+ } else if (chan <= 165) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ,
+ &val, 1);
+ } else
+ val = 0;
+ run_bbp_write(sc, 159, val);
+
+ /* Tx1 IQ gain. */
+ run_bbp_write(sc, 158, 0x4a);
+ if (chan <= 14) {
+ run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ,
+ &val, 1);
+ } else if (chan <= 64) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ,
+ &val, 1);
+ } else if (chan <= 138) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ,
+ &val, 1);
+ } else if (chan <= 165) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ,
+ &val, 1);
+ } else
+ val = 0;
+ run_bbp_write(sc, 159, val);
+
+ /* Tx1 IQ phase. */
+ run_bbp_write(sc, 158, 0x4b);
+ if (chan <= 14) {
+ run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ,
+ &val, 1);
+ } else if (chan <= 64) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ,
+ &val, 1);
+ } else if (chan <= 138) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ,
+ &val, 1);
+ } else if (chan <= 165) {
+ run_efuse_read(sc,
+ RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ,
+ &val, 1);
+ } else
+ val = 0;
+ run_bbp_write(sc, 159, val);
+
+ /* RF IQ compensation control. */
+ run_bbp_write(sc, 158, 0x04);
+ run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL,
+ &val, 1);
+ run_bbp_write(sc, 159, val);
+
+ /* RF IQ imbalance compensation control. */
+ run_bbp_write(sc, 158, 0x03);
+ run_efuse_read(sc,
+ RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1);
+ run_bbp_write(sc, 159, val);
+}
+
+static void
run_set_agc(struct run_softc *sc, uint8_t agc)
{
uint8_t bbp;
@@ -3502,21 +3935,73 @@
run_bbp_write(sc, 62, 0x37 - sc->lna[group]);
run_bbp_write(sc, 63, 0x37 - sc->lna[group]);
run_bbp_write(sc, 64, 0x37 - sc->lna[group]);
- run_bbp_write(sc, 86, 0x00);
+ if (sc->mac_ver < 0x3572)
+ run_bbp_write(sc, 86, 0x00);
+ if (sc->mac_ver == 0x3593) {
+ run_bbp_write(sc, 77, 0x98);
+ run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a);
+ }
+
if (group == 0) {
if (sc->ext_2ghz_lna) {
- run_bbp_write(sc, 82, 0x62);
- run_bbp_write(sc, 75, 0x46);
+ if (sc->mac_ver >= 0x5390)
+ run_bbp_write(sc, 75, 0x52);
+ else {
+ run_bbp_write(sc, 82, 0x62);
+ run_bbp_write(sc, 75, 0x46);
+ }
} else {
- run_bbp_write(sc, 82, 0x84);
- run_bbp_write(sc, 75, 0x50);
+ if (sc->mac_ver == 0x5592) {
+ run_bbp_write(sc, 79, 0x1c);
+ run_bbp_write(sc, 80, 0x0e);
+ run_bbp_write(sc, 81, 0x3a);
+ run_bbp_write(sc, 82, 0x62);
+
+ run_bbp_write(sc, 195, 0x80);
+ run_bbp_write(sc, 196, 0xe0);
+ run_bbp_write(sc, 195, 0x81);
+ run_bbp_write(sc, 196, 0x1f);
+ run_bbp_write(sc, 195, 0x82);
+ run_bbp_write(sc, 196, 0x38);
+ run_bbp_write(sc, 195, 0x83);
+ run_bbp_write(sc, 196, 0x32);
+ run_bbp_write(sc, 195, 0x85);
+ run_bbp_write(sc, 196, 0x28);
+ run_bbp_write(sc, 195, 0x86);
+ run_bbp_write(sc, 196, 0x19);
+ } else if (sc->mac_ver >= 0x5390)
+ run_bbp_write(sc, 75, 0x50);
+ else {
+ run_bbp_write(sc, 82,
+ (sc->mac_ver == 0x3593) ? 0x62 : 0x84);
+ run_bbp_write(sc, 75, 0x50);
+ }
}
} else {
- if (sc->mac_ver == 0x3572)
+ if (sc->mac_ver == 0x5592) {
+ run_bbp_write(sc, 79, 0x18);
+ run_bbp_write(sc, 80, 0x08);
+ run_bbp_write(sc, 81, 0x38);
+ run_bbp_write(sc, 82, 0x92);
+
+ run_bbp_write(sc, 195, 0x80);
+ run_bbp_write(sc, 196, 0xf0);
+ run_bbp_write(sc, 195, 0x81);
+ run_bbp_write(sc, 196, 0x1e);
+ run_bbp_write(sc, 195, 0x82);
+ run_bbp_write(sc, 196, 0x28);
+ run_bbp_write(sc, 195, 0x83);
+ run_bbp_write(sc, 196, 0x20);
+ run_bbp_write(sc, 195, 0x85);
+ run_bbp_write(sc, 196, 0x7f);
+ run_bbp_write(sc, 195, 0x86);
+ run_bbp_write(sc, 196, 0x7f);
+ } else if (sc->mac_ver == 0x3572)
run_bbp_write(sc, 82, 0x94);
else
- run_bbp_write(sc, 82, 0xf2);
+ run_bbp_write(sc, 82,
+ (sc->mac_ver == 0x3593) ? 0x82 : 0xf2);
if (sc->ext_5ghz_lna)
run_bbp_write(sc, 75, 0x46);
else
@@ -3530,6 +4015,8 @@
/* enable appropriate Power Amplifiers and Low Noise Amplifiers */
tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN;
+ if (sc->mac_ver == 0x3593)
+ tmp |= 1 << 29 | 1 << 28;
if (sc->nrxchains > 1)
tmp |= RT2860_LNA_PE1_EN;
if (group == 0) { /* 2GHz */
@@ -3536,6 +4023,10 @@
tmp |= RT2860_PA_PE_G0_EN;
if (sc->ntxchains > 1)
tmp |= RT2860_PA_PE_G1_EN;
+ if (sc->mac_ver == 0x3593) {
+ if (sc->ntxchains > 2)
+ tmp |= 1 << 25;
+ }
} else { /* 5GHz */
tmp |= RT2860_PA_PE_A0_EN;
if (sc->ntxchains > 1)
@@ -3548,6 +4039,20 @@
} else
run_write(sc, RT2860_TX_PIN_CFG, tmp);
+ if (sc->mac_ver == 0x5592) {
+ run_bbp_write(sc, 195, 0x8d);
+ run_bbp_write(sc, 196, 0x1a);
+ }
+
+ if (sc->mac_ver == 0x3593) {
+ run_read(sc, RT2860_GPIO_CTRL, &tmp);
+ tmp &= ~0x01010000;
+ if (group == 0)
+ tmp |= 0x00010000;
+ tmp = (tmp & ~0x00009090) | 0x00000090;
+ run_write(sc, RT2860_GPIO_CTRL, tmp);
+ }
+
/* set initial AGC value */
if (group == 0) { /* 2GHz band */
if (sc->mac_ver >= 0x3070)
@@ -3555,7 +4060,9 @@
else
agc = 0x2e + sc->lna[0];
} else { /* 5GHz band */
- if (sc->mac_ver == 0x3572)
+ if (sc->mac_ver == 0x5592)
+ agc = 0x24 + sc->lna[group] * 2;
+ else if (sc->mac_ver == 0x3572 || sc->mac_ver == 0x3593)
agc = 0x22 + (sc->lna[group] * 5) / 3;
else
agc = 0x32 + (sc->lna[group] * 5) / 3;
@@ -3564,7 +4071,7 @@
}
static void
-run_rt2870_set_chan(struct run_softc *sc, uint32_t chan)
+run_rt2870_set_chan(struct run_softc *sc, u_int chan)
{
const struct rfprog *rfprog = rt2860_rf2850;
uint32_t r2, r3, r4;
@@ -3576,58 +4083,71 @@
r2 = rfprog[i].r2;
if (sc->ntxchains == 1)
- r2 |= 1 << 12; /* 1T: disable Tx chain 2 */
+ r2 |= 1 << 14; /* 1T: disable Tx chain 2 */
if (sc->nrxchains == 1)
- r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */
+ r2 |= 1 << 17 | 1 << 6; /* 1R: disable Rx chains 2 & 3 */
else if (sc->nrxchains == 2)
- r2 |= 1 << 4; /* 2R: disable Rx chain 3 */
+ r2 |= 1 << 6; /* 2R: disable Rx chain 3 */
/* use Tx power values from EEPROM */
txpow1 = sc->txpow1[i];
txpow2 = sc->txpow2[i];
+
+ /* Initialize RF R3 and R4. */
+ r3 = rfprog[i].r3 & 0xffffc1ff;
+ r4 = (rfprog[i].r4 & ~(0x001f87c0)) | (sc->freq << 15);
if (chan > 14) {
- if (txpow1 >= 0)
- txpow1 = txpow1 << 1 | 1;
- else
- txpow1 = (7 + txpow1) << 1;
- if (txpow2 >= 0)
- txpow2 = txpow2 << 1 | 1;
- else
- txpow2 = (7 + txpow2) << 1;
+ if (txpow1 >= 0) {
+ txpow1 = (txpow1 > 0xf) ? (0xf) : (txpow1);
+ r3 |= (txpow1 << 10) | (1 << 9);
+ } else {
+ txpow1 += 7;
+
+ /* txpow1 is not possible larger than 15. */
+ r3 |= (txpow1 << 10);
+ }
+ if (txpow2 >= 0) {
+ txpow2 = (txpow2 > 0xf) ? (0xf) : (txpow2);
+ r4 |= (txpow2 << 7) | (1 << 6);
+ } else {
+ txpow2 += 7;
+ r4 |= (txpow2 << 7);
+ }
+ } else {
+ /* Set Tx0 power. */
+ r3 |= (txpow1 << 9);
+
+ /* Set frequency offset and Tx1 power. */
+ r4 |= (txpow2 << 6);
}
- r3 = rfprog[i].r3 | txpow1 << 7;
- r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4;
- run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
- run_rt2870_rf_write(sc, RT2860_RF2, r2);
- run_rt2870_rf_write(sc, RT2860_RF3, r3);
- run_rt2870_rf_write(sc, RT2860_RF4, r4);
+ run_rt2870_rf_write(sc, rfprog[i].r1);
+ run_rt2870_rf_write(sc, r2);
+ run_rt2870_rf_write(sc, r3 & ~(1 << 2));
+ run_rt2870_rf_write(sc, r4);
run_delay(sc, 10);
- run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
- run_rt2870_rf_write(sc, RT2860_RF2, r2);
- run_rt2870_rf_write(sc, RT2860_RF3, r3 | 1);
- run_rt2870_rf_write(sc, RT2860_RF4, r4);
+ run_rt2870_rf_write(sc, rfprog[i].r1);
+ run_rt2870_rf_write(sc, r2);
+ run_rt2870_rf_write(sc, r3 | (1 << 2));
+ run_rt2870_rf_write(sc, r4);
run_delay(sc, 10);
- run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
- run_rt2870_rf_write(sc, RT2860_RF2, r2);
- run_rt2870_rf_write(sc, RT2860_RF3, r3);
- run_rt2870_rf_write(sc, RT2860_RF4, r4);
+ run_rt2870_rf_write(sc, rfprog[i].r1);
+ run_rt2870_rf_write(sc, r2);
+ run_rt2870_rf_write(sc, r3 & ~(1 << 2));
+ run_rt2870_rf_write(sc, r4);
}
static void
-run_rt3070_set_chan(struct run_softc *sc, uint32_t chan)
+run_rt3070_set_chan(struct run_softc *sc, u_int chan)
{
int8_t txpow1, txpow2;
uint8_t rf;
int i;
- /* RT3070 is 2GHz only */
- KASSERT(chan >= 1 && chan <= 14, ("wrong channel selected\n"));
-
/* find the settings for this channel (we know it exists) */
for (i = 0; rt2860_rf2850[i].chan != chan; i++);
@@ -3636,7 +4156,12 @@
txpow2 = sc->txpow2[i];
run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n);
- run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k);
+
+ /* RT3370/RT3390: RF R3 [7:4] is not reserved bits. */
+ run_rt3070_rf_read(sc, 3, &rf);
+ rf = (rf & ~0x0f) | rt3070_freqs[i].k;
+ run_rt3070_rf_write(sc, 3, rf);
+
run_rt3070_rf_read(sc, 6, &rf);
rf = (rf & ~0x03) | rt3070_freqs[i].r;
run_rt3070_rf_write(sc, 6, rf);
@@ -3832,18 +4357,436 @@
}
static void
+run_rt3593_set_chan(struct run_softc *sc, u_int chan)
+{
+ int8_t txpow1, txpow2, txpow3;
+ uint8_t h20mhz, rf;
+ int i;
+
+ /* find the settings for this channel (we know it exists) */
+ for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+ /* use Tx power values from EEPROM */
+ txpow1 = sc->txpow1[i];
+ txpow2 = sc->txpow2[i];
+ txpow3 = (sc->ntxchains == 3) ? sc->txpow3[i] : 0;
+
+ if (chan <= 14) {
+ run_bbp_write(sc, 25, sc->bbp25);
+ run_bbp_write(sc, 26, sc->bbp26);
+ } else {
+ /* Enable IQ phase correction. */
+ run_bbp_write(sc, 25, 0x09);
+ run_bbp_write(sc, 26, 0xff);
+ }
+
+ run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+ run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+ run_rt3070_rf_read(sc, 11, &rf);
+ rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+ run_rt3070_rf_write(sc, 11, rf);
+
+ /* Set pll_idoh. */
+ run_rt3070_rf_read(sc, 11, &rf);
+ rf &= ~0x4c;
+ rf |= (chan <= 14) ? 0x44 : 0x48;
+ run_rt3070_rf_write(sc, 11, rf);
+
+ if (chan <= 14)
+ rf = txpow1 & 0x1f;
+ else
+ rf = 0x40 | ((txpow1 & 0x18) << 1) | (txpow1 & 0x07);
+ run_rt3070_rf_write(sc, 53, rf);
+
+ if (chan <= 14)
+ rf = txpow2 & 0x1f;
+ else
+ rf = 0x40 | ((txpow2 & 0x18) << 1) | (txpow2 & 0x07);
+ run_rt3070_rf_write(sc, 55, rf);
+
+ if (chan <= 14)
+ rf = txpow3 & 0x1f;
+ else
+ rf = 0x40 | ((txpow3 & 0x18) << 1) | (txpow3 & 0x07);
+ run_rt3070_rf_write(sc, 54, rf);
+
+ rf = RT3070_RF_BLOCK | RT3070_PLL_PD;
+ if (sc->ntxchains == 3)
+ rf |= RT3070_TX0_PD | RT3070_TX1_PD | RT3070_TX2_PD;
+ else
+ rf |= RT3070_TX0_PD | RT3070_TX1_PD;
+ rf |= RT3070_RX0_PD | RT3070_RX1_PD | RT3070_RX2_PD;
+ run_rt3070_rf_write(sc, 1, rf);
+
+ run_adjust_freq_offset(sc);
+
+ run_rt3070_rf_write(sc, 31, (chan <= 14) ? 0xa0 : 0x80);
+
+ h20mhz = (sc->rf24_20mhz & 0x20) >> 5;
+ run_rt3070_rf_read(sc, 30, &rf);
+ rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
+ run_rt3070_rf_write(sc, 30, rf);
+
+ run_rt3070_rf_read(sc, 36, &rf);
+ if (chan <= 14)
+ rf |= 0x80;
+ else
+ rf &= ~0x80;
+ run_rt3070_rf_write(sc, 36, rf);
+
+ /* Set vcolo_bs. */
+ run_rt3070_rf_write(sc, 34, (chan <= 14) ? 0x3c : 0x20);
+ /* Set pfd_delay. */
+ run_rt3070_rf_write(sc, 12, (chan <= 14) ? 0x1a : 0x12);
+
+ /* Set vco bias current control. */
+ run_rt3070_rf_read(sc, 6, &rf);
+ rf &= ~0xc0;
+ if (chan <= 14)
+ rf |= 0x40;
+ else if (chan <= 128)
+ rf |= 0x80;
+ else
+ rf |= 0x40;
+ run_rt3070_rf_write(sc, 6, rf);
+
+ run_rt3070_rf_read(sc, 30, &rf);
+ rf = (rf & ~0x18) | 0x10;
+ run_rt3070_rf_write(sc, 30, rf);
+
+ run_rt3070_rf_write(sc, 10, (chan <= 14) ? 0xd3 : 0xd8);
+ run_rt3070_rf_write(sc, 13, (chan <= 14) ? 0x12 : 0x23);
+
+ run_rt3070_rf_read(sc, 51, &rf);
+ rf = (rf & ~0x03) | 0x01;
+ run_rt3070_rf_write(sc, 51, rf);
+ /* Set tx_mx1_cc. */
+ run_rt3070_rf_read(sc, 51, &rf);
+ rf &= ~0x1c;
+ rf |= (chan <= 14) ? 0x14 : 0x10;
+ run_rt3070_rf_write(sc, 51, rf);
+ /* Set tx_mx1_ic. */
+ run_rt3070_rf_read(sc, 51, &rf);
+ rf &= ~0xe0;
+ rf |= (chan <= 14) ? 0x60 : 0x40;
+ run_rt3070_rf_write(sc, 51, rf);
+ /* Set tx_lo1_ic. */
+ run_rt3070_rf_read(sc, 49, &rf);
+ rf &= ~0x1c;
+ rf |= (chan <= 14) ? 0x0c : 0x08;
+ run_rt3070_rf_write(sc, 49, rf);
+ /* Set tx_lo1_en. */
+ run_rt3070_rf_read(sc, 50, &rf);
+ run_rt3070_rf_write(sc, 50, rf & ~0x20);
+ /* Set drv_cc. */
+ run_rt3070_rf_read(sc, 57, &rf);
+ rf &= ~0xfc;
+ rf |= (chan <= 14) ? 0x6c : 0x3c;
+ run_rt3070_rf_write(sc, 57, rf);
+ /* Set rx_mix1_ic, rxa_lnactr, lna_vc, lna_inbias_en and lna_en. */
+ run_rt3070_rf_write(sc, 44, (chan <= 14) ? 0x93 : 0x9b);
+ /* Set drv_gnd_a, tx_vga_cc_a and tx_mx2_gain. */
+ run_rt3070_rf_write(sc, 52, (chan <= 14) ? 0x45 : 0x05);
+ /* Enable VCO calibration. */
+ run_rt3070_rf_read(sc, 3, &rf);
+ rf &= ~RT5390_VCOCAL;
+ rf |= (chan <= 14) ? RT5390_VCOCAL : 0xbe;
+ run_rt3070_rf_write(sc, 3, rf);
+
+ if (chan <= 14)
+ rf = 0x23;
+ else if (chan <= 64)
+ rf = 0x36;
+ else if (chan <= 128)
+ rf = 0x32;
+ else
+ rf = 0x30;
+ run_rt3070_rf_write(sc, 39, rf);
+ if (chan <= 14)
+ rf = 0xbb;
+ else if (chan <= 64)
+ rf = 0xeb;
+ else if (chan <= 128)
+ rf = 0xb3;
+ else
+ rf = 0x9b;
+ run_rt3070_rf_write(sc, 45, rf);
+
+ /* Set FEQ/AEQ control. */
+ run_bbp_write(sc, 105, 0x34);
+}
+
+static void
+run_rt5390_set_chan(struct run_softc *sc, u_int chan)
+{
+ int8_t txpow1, txpow2;
+ uint8_t rf;
+ int i;
+
+ /* find the settings for this channel (we know it exists) */
+ for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+ /* use Tx power values from EEPROM */
+ txpow1 = sc->txpow1[i];
+ txpow2 = sc->txpow2[i];
+
+ run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+ run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+ run_rt3070_rf_read(sc, 11, &rf);
+ rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+ run_rt3070_rf_write(sc, 11, rf);
+
+ run_rt3070_rf_read(sc, 49, &rf);
+ rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+ /* The valid range of the RF R49 is 0x00 to 0x27. */
+ if ((rf & 0x3f) > 0x27)
+ rf = (rf & ~0x3f) | 0x27;
+ run_rt3070_rf_write(sc, 49, rf);
+
+ if (sc->mac_ver == 0x5392) {
+ run_rt3070_rf_read(sc, 50, &rf);
+ rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+ /* The valid range of the RF R50 is 0x00 to 0x27. */
+ if ((rf & 0x3f) > 0x27)
+ rf = (rf & ~0x3f) | 0x27;
+ run_rt3070_rf_write(sc, 50, rf);
+ }
+
+ run_rt3070_rf_read(sc, 1, &rf);
+ rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD;
+ if (sc->mac_ver == 0x5392)
+ rf |= RT3070_RX1_PD | RT3070_TX1_PD;
+ run_rt3070_rf_write(sc, 1, rf);
+
+ if (sc->mac_ver != 0x5392) {
+ run_rt3070_rf_read(sc, 2, &rf);
+ rf |= 0x80;
+ run_rt3070_rf_write(sc, 2, rf);
+ run_delay(sc, 10);
+ rf &= 0x7f;
+ run_rt3070_rf_write(sc, 2, rf);
+ }
+
+ run_adjust_freq_offset(sc);
+
+ if (sc->mac_ver == 0x5392) {
+ /* Fix for RT5392C. */
+ if (sc->mac_rev >= 0x0223) {
+ if (chan <= 4)
+ rf = 0x0f;
+ else if (chan >= 5 && chan <= 7)
+ rf = 0x0e;
+ else
+ rf = 0x0d;
+ run_rt3070_rf_write(sc, 23, rf);
+
+ if (chan <= 4)
+ rf = 0x0c;
+ else if (chan == 5)
+ rf = 0x0b;
+ else if (chan >= 6 && chan <= 7)
+ rf = 0x0a;
+ else if (chan >= 8 && chan <= 10)
+ rf = 0x09;
+ else
+ rf = 0x08;
+ run_rt3070_rf_write(sc, 59, rf);
+ } else {
+ if (chan <= 11)
+ rf = 0x0f;
+ else
+ rf = 0x0b;
+ run_rt3070_rf_write(sc, 59, rf);
+ }
+ } else {
+ /* Fix for RT5390F. */
+ if (sc->mac_rev >= 0x0502) {
+ if (chan <= 11)
+ rf = 0x43;
+ else
+ rf = 0x23;
+ run_rt3070_rf_write(sc, 55, rf);
+
+ if (chan <= 11)
+ rf = 0x0f;
+ else if (chan == 12)
+ rf = 0x0d;
+ else
+ rf = 0x0b;
+ run_rt3070_rf_write(sc, 59, rf);
+ } else {
+ run_rt3070_rf_write(sc, 55, 0x44);
+ run_rt3070_rf_write(sc, 59, 0x8f);
+ }
+ }
+
+ /* Enable VCO calibration. */
+ run_rt3070_rf_read(sc, 3, &rf);
+ rf |= RT5390_VCOCAL;
+ run_rt3070_rf_write(sc, 3, rf);
+}
+
+static void
+run_rt5592_set_chan(struct run_softc *sc, u_int chan)
+{
+ const struct rt5592_freqs *freqs;
+ uint32_t tmp;
+ uint8_t reg, rf, txpow_bound;
+ int8_t txpow1, txpow2;
+ int i;
+
+ run_read(sc, RT5592_DEBUG_INDEX, &tmp);
+ freqs = (tmp & RT5592_SEL_XTAL) ?
+ rt5592_freqs_40mhz : rt5592_freqs_20mhz;
+
+ /* find the settings for this channel (we know it exists) */
+ for (i = 0; rt2860_rf2850[i].chan != chan; i++, freqs++);
+
+ /* use Tx power values from EEPROM */
+ txpow1 = sc->txpow1[i];
+ txpow2 = sc->txpow2[i];
+
+ run_read(sc, RT3070_LDO_CFG0, &tmp);
+ tmp &= ~0x1c000000;
+ if (chan > 14)
+ tmp |= 0x14000000;
+ run_write(sc, RT3070_LDO_CFG0, tmp);
+
+ /* N setting. */
+ run_rt3070_rf_write(sc, 8, freqs->n & 0xff);
+ run_rt3070_rf_read(sc, 9, &rf);
+ rf &= ~(1 << 4);
+ rf |= ((freqs->n & 0x0100) >> 8) << 4;
+ run_rt3070_rf_write(sc, 9, rf);
+
+ /* K setting. */
+ run_rt3070_rf_read(sc, 9, &rf);
+ rf &= ~0x0f;
+ rf |= (freqs->k & 0x0f);
+ run_rt3070_rf_write(sc, 9, rf);
+
+ /* Mode setting. */
+ run_rt3070_rf_read(sc, 11, &rf);
+ rf &= ~0x0c;
+ rf |= ((freqs->m - 0x8) & 0x3) << 2;
+ run_rt3070_rf_write(sc, 11, rf);
+ run_rt3070_rf_read(sc, 9, &rf);
+ rf &= ~(1 << 7);
+ rf |= (((freqs->m - 0x8) & 0x4) >> 2) << 7;
+ run_rt3070_rf_write(sc, 9, rf);
+
+ /* R setting. */
+ run_rt3070_rf_read(sc, 11, &rf);
+ rf &= ~0x03;
+ rf |= (freqs->r - 0x1);
+ run_rt3070_rf_write(sc, 11, rf);
+
+ if (chan <= 14) {
+ /* Initialize RF registers for 2GHZ. */
+ for (i = 0; i < nitems(rt5592_2ghz_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt5592_2ghz_def_rf[i].reg,
+ rt5592_2ghz_def_rf[i].val);
+ }
+
+ rf = (chan <= 10) ? 0x07 : 0x06;
+ run_rt3070_rf_write(sc, 23, rf);
+ run_rt3070_rf_write(sc, 59, rf);
+
+ run_rt3070_rf_write(sc, 55, 0x43);
+
+ /*
+ * RF R49/R50 Tx power ALC code.
+ * G-band bit<7:6>=1:0, bit<5:0> range from 0x0 ~ 0x27.
+ */
+ reg = 2;
+ txpow_bound = 0x27;
+ } else {
+ /* Initialize RF registers for 5GHZ. */
+ for (i = 0; i < nitems(rt5592_5ghz_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt5592_5ghz_def_rf[i].reg,
+ rt5592_5ghz_def_rf[i].val);
+ }
+ for (i = 0; i < nitems(rt5592_chan_5ghz); i++) {
+ if (chan >= rt5592_chan_5ghz[i].firstchan &&
+ chan <= rt5592_chan_5ghz[i].lastchan) {
+ run_rt3070_rf_write(sc, rt5592_chan_5ghz[i].reg,
+ rt5592_chan_5ghz[i].val);
+ }
+ }
+
+ /*
+ * RF R49/R50 Tx power ALC code.
+ * A-band bit<7:6>=1:1, bit<5:0> range from 0x0 ~ 0x2b.
+ */
+ reg = 3;
+ txpow_bound = 0x2b;
+ }
+
+ /* RF R49 ch0 Tx power ALC code. */
+ run_rt3070_rf_read(sc, 49, &rf);
+ rf &= ~0xc0;
+ rf |= (reg << 6);
+ rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+ if ((rf & 0x3f) > txpow_bound)
+ rf = (rf & ~0x3f) | txpow_bound;
+ run_rt3070_rf_write(sc, 49, rf);
+
+ /* RF R50 ch1 Tx power ALC code. */
+ run_rt3070_rf_read(sc, 50, &rf);
+ rf &= ~(1 << 7 | 1 << 6);
+ rf |= (reg << 6);
+ rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+ if ((rf & 0x3f) > txpow_bound)
+ rf = (rf & ~0x3f) | txpow_bound;
+ run_rt3070_rf_write(sc, 50, rf);
+
+ /* Enable RF_BLOCK, PLL_PD, RX0_PD, and TX0_PD. */
+ run_rt3070_rf_read(sc, 1, &rf);
+ rf |= (RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD);
+ if (sc->ntxchains > 1)
+ rf |= RT3070_TX1_PD;
+ if (sc->nrxchains > 1)
+ rf |= RT3070_RX1_PD;
+ run_rt3070_rf_write(sc, 1, rf);
+
+ run_rt3070_rf_write(sc, 6, 0xe4);
+
+ run_rt3070_rf_write(sc, 30, 0x10);
+ run_rt3070_rf_write(sc, 31, 0x80);
+ run_rt3070_rf_write(sc, 32, 0x80);
+
+ run_adjust_freq_offset(sc);
+
+ /* Enable VCO calibration. */
+ run_rt3070_rf_read(sc, 3, &rf);
+ rf |= RT5390_VCOCAL;
+ run_rt3070_rf_write(sc, 3, rf);
+}
+
+static void
run_set_rx_antenna(struct run_softc *sc, int aux)
{
uint32_t tmp;
+ uint8_t bbp152;
if (aux) {
- run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0);
- run_read(sc, RT2860_GPIO_CTRL, &tmp);
- run_write(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+ if (sc->rf_rev == RT5390_RF_5370) {
+ run_bbp_read(sc, 152, &bbp152);
+ run_bbp_write(sc, 152, bbp152 & ~0x80);
+ } else {
+ run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0);
+ run_read(sc, RT2860_GPIO_CTRL, &tmp);
+ run_write(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+ }
} else {
- run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 1);
- run_read(sc, RT2860_GPIO_CTRL, &tmp);
- run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+ if (sc->rf_rev == RT5390_RF_5370) {
+ run_bbp_read(sc, 152, &bbp152);
+ run_bbp_write(sc, 152, bbp152 | 0x80);
+ } else {
+ run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 1);
+ run_read(sc, RT2860_GPIO_CTRL, &tmp);
+ run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+ }
}
}
@@ -3851,13 +4794,19 @@
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
- uint32_t chan, group;
+ u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
if (chan == 0 || chan == IEEE80211_CHAN_ANY)
return (EINVAL);
- if (sc->mac_ver == 0x3572)
+ if (sc->mac_ver == 0x5592)
+ run_rt5592_set_chan(sc, chan);
+ else if (sc->mac_ver >= 0x5390)
+ run_rt5390_set_chan(sc, chan);
+ else if (sc->mac_ver == 0x3593)
+ run_rt3593_set_chan(sc, chan);
+ else if (sc->mac_ver == 0x3572)
run_rt3572_set_chan(sc, chan);
else if (sc->mac_ver >= 0x3070)
run_rt3070_set_chan(sc, chan);
@@ -3879,6 +4828,10 @@
run_delay(sc, 10);
+ /* Perform IQ calibration. */
+ if (sc->mac_ver >= 0x5392)
+ run_iq_calib(sc, chan);
+
return (0);
}
@@ -3960,6 +4913,12 @@
}
setbit(rvp->bo.bo_flags, item);
+ if (rvp->beacon_mbuf == NULL) {
+ rvp->beacon_mbuf = ieee80211_beacon_alloc(vap->iv_bss,
+ &rvp->bo);
+ if (rvp->beacon_mbuf == NULL)
+ return;
+ }
ieee80211_beacon_update(vap->iv_bss, &rvp->bo, rvp->beacon_mbuf, mcast);
i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -3980,6 +4939,7 @@
struct run_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_txwi txwi;
struct mbuf *m;
+ uint16_t txwisize;
uint8_t ridx;
if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC)
@@ -3999,25 +4959,26 @@
}
m = rvp->beacon_mbuf;
- memset(&txwi, 0, sizeof txwi);
+ memset(&txwi, 0, sizeof(txwi));
txwi.wcid = 0xff;
txwi.len = htole16(m->m_pkthdr.len);
+
/* send beacons at the lowest available rate */
ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
txwi.phy = htole16(rt2860_rates[ridx].mcs);
if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM)
- txwi.phy |= htole16(RT2860_PHY_OFDM);
+ txwi.phy |= htole16(RT2860_PHY_OFDM);
txwi.txop = RT2860_TX_TXOP_HT;
txwi.flags = RT2860_TX_TS;
txwi.xflags = RT2860_TX_NSEQ;
- run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id),
- (uint8_t *)&txwi, sizeof txwi);
- run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + sizeof txwi,
- mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1); /* roundup len */
-
- return;
+ txwisize = (sc->mac_ver == 0x5592) ?
+ sizeof(txwi) + sizeof(uint32_t) : sizeof(txwi);
+ run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id), (uint8_t *)&txwi,
+ txwisize);
+ run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + txwisize,
+ mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1);
}
static void
@@ -4137,7 +5098,8 @@
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
- DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id, ic->ic_opmode);
+ DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id,
+ ic->ic_opmode);
run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
tmp &= ~0x1fffff;
@@ -4173,8 +5135,8 @@
static void
run_enable_mrr(struct run_softc *sc)
{
-#define CCK(mcs) (mcs)
-#define OFDM(mcs) (1 << 3 | (mcs))
+#define CCK(mcs) (mcs)
+#define OFDM(mcs) (1 << 3 | (mcs))
run_write(sc, RT2860_LG_FBK_CFG0,
OFDM(6) << 28 | /* 54->48 */
OFDM(5) << 24 | /* 48->36 */
@@ -4293,7 +5255,7 @@
int delta;
if (IEEE80211_IS_CHAN_5GHZ(c)) {
- uint32_t chan = ieee80211_chan2ieee(ic, c);
+ u_int chan = ieee80211_chan2ieee(ic, c);
delta = sc->rssi_5ghz[rxchain];
/* determine channel group */
@@ -4309,6 +5271,64 @@
return (-12 - delta - rssi);
}
+static void
+run_rt5390_bbp_init(struct run_softc *sc)
+{
+ int i;
+ uint8_t bbp;
+
+ /* Apply maximum likelihood detection for 2 stream case. */
+ run_bbp_read(sc, 105, &bbp);
+ if (sc->nrxchains > 1)
+ run_bbp_write(sc, 105, bbp | RT5390_MLD);
+
+ /* Avoid data lost and CRC error. */
+ run_bbp_read(sc, 4, &bbp);
+ run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+ if (sc->mac_ver == 0x5592) {
+ for (i = 0; i < nitems(rt5592_def_bbp); i++) {
+ run_bbp_write(sc, rt5592_def_bbp[i].reg,
+ rt5592_def_bbp[i].val);
+ }
+ for (i = 0; i < nitems(rt5592_bbp_r196); i++) {
+ run_bbp_write(sc, 195, i + 0x80);
+ run_bbp_write(sc, 196, rt5592_bbp_r196[i]);
+ }
+ } else {
+ for (i = 0; i < nitems(rt5390_def_bbp); i++) {
+ run_bbp_write(sc, rt5390_def_bbp[i].reg,
+ rt5390_def_bbp[i].val);
+ }
+ }
+ if (sc->mac_ver == 0x5392) {
+ run_bbp_write(sc, 88, 0x90);
+ run_bbp_write(sc, 95, 0x9a);
+ run_bbp_write(sc, 98, 0x12);
+ run_bbp_write(sc, 106, 0x12);
+ run_bbp_write(sc, 134, 0xd0);
+ run_bbp_write(sc, 135, 0xf6);
+ run_bbp_write(sc, 148, 0x84);
+ }
+
+ run_bbp_read(sc, 152, &bbp);
+ run_bbp_write(sc, 152, bbp | 0x80);
+
+ /* Fix BBP254 for RT5592C. */
+ if (sc->mac_ver == 0x5592 && sc->mac_rev >= 0x0221) {
+ run_bbp_read(sc, 254, &bbp);
+ run_bbp_write(sc, 254, bbp | 0x80);
+ }
+
+ /* Disable hardware antenna diversity. */
+ if (sc->mac_ver == 0x5390)
+ run_bbp_write(sc, 154, 0);
+
+ /* Initialize Rx CCK/OFDM frequency offset report. */
+ run_bbp_write(sc, 142, 1);
+ run_bbp_write(sc, 143, 57);
+}
+
static int
run_bbp_init(struct run_softc *sc)
{
@@ -4326,16 +5346,29 @@
return (ETIMEDOUT);
/* initialize BBP registers to default values */
- for (i = 0; i < N(rt2860_def_bbp); i++) {
- run_bbp_write(sc, rt2860_def_bbp[i].reg,
- rt2860_def_bbp[i].val);
+ if (sc->mac_ver >= 0x5390)
+ run_rt5390_bbp_init(sc);
+ else {
+ for (i = 0; i < nitems(rt2860_def_bbp); i++) {
+ run_bbp_write(sc, rt2860_def_bbp[i].reg,
+ rt2860_def_bbp[i].val);
+ }
}
+ if (sc->mac_ver == 0x3593) {
+ run_bbp_write(sc, 79, 0x13);
+ run_bbp_write(sc, 80, 0x05);
+ run_bbp_write(sc, 81, 0x33);
+ run_bbp_write(sc, 86, 0x46);
+ run_bbp_write(sc, 137, 0x0f);
+ }
+
/* fix BBP84 for RT2860E */
if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101)
run_bbp_write(sc, 84, 0x19);
- if (sc->mac_ver >= 0x3070) {
+ if (sc->mac_ver >= 0x3070 && (sc->mac_ver != 0x3593 &&
+ sc->mac_ver != 0x5592)) {
run_bbp_write(sc, 79, 0x13);
run_bbp_write(sc, 80, 0x05);
run_bbp_write(sc, 81, 0x33);
@@ -4350,7 +5383,7 @@
run_rt3070_rf_init(struct run_softc *sc)
{
uint32_t tmp;
- uint8_t rf, target, bbp4;
+ uint8_t bbp4, mingain, rf, target;
int i;
run_rt3070_rf_read(sc, 30, &rf);
@@ -4361,19 +5394,23 @@
/* initialize RF registers to default value */
if (sc->mac_ver == 0x3572) {
- for (i = 0; i < N(rt3572_def_rf); i++) {
+ for (i = 0; i < nitems(rt3572_def_rf); i++) {
run_rt3070_rf_write(sc, rt3572_def_rf[i].reg,
rt3572_def_rf[i].val);
}
} else {
- for (i = 0; i < N(rt3070_def_rf); i++) {
+ for (i = 0; i < nitems(rt3070_def_rf); i++) {
run_rt3070_rf_write(sc, rt3070_def_rf[i].reg,
rt3070_def_rf[i].val);
}
}
- if (sc->mac_ver == 0x3070) {
- /* change voltage from 1.2V to 1.35V for RT3070 */
+ if (sc->mac_ver == 0x3070 && sc->mac_rev < 0x0201) {
+ /*
+ * Change voltage from 1.2V to 1.35V for RT3070.
+ * The DAC issue (RT3070_LDO_CFG0) has been fixed
+ * in RT3070(F).
+ */
run_read(sc, RT3070_LDO_CFG0, &tmp);
tmp = (tmp & ~0x0f000000) | 0x0d000000;
run_write(sc, RT3070_LDO_CFG0, tmp);
@@ -4423,7 +5460,7 @@
/* select 40MHz bandwidth */
run_bbp_read(sc, 4, &bbp4);
- run_bbp_write(sc, 4, (bbp4 & ~0x08) | 0x10);
+ run_bbp_write(sc, 4, (bbp4 & ~0x18) | 0x10);
run_rt3070_rf_read(sc, 31, &rf);
run_rt3070_rf_write(sc, 31, rf | 0x20);
@@ -4440,7 +5477,7 @@
/* save default BBP registers 25 and 26 values */
run_bbp_read(sc, 25, &sc->bbp25);
run_bbp_read(sc, 26, &sc->bbp26);
- } else if (sc->mac_rev < 0x0211)
+ } else if (sc->mac_rev < 0x0201 || sc->mac_rev < 0x0211)
run_rt3070_rf_write(sc, 27, 0x03);
run_read(sc, RT3070_OPT_14, &tmp);
@@ -4453,12 +5490,13 @@
(sc->mac_ver == 0x3071 && sc->mac_rev >= 0x0211)) &&
!sc->ext_2ghz_lna)
rf |= 0x20; /* fix for long range Rx issue */
- if (sc->txmixgain_2ghz >= 1)
+ mingain = (sc->mac_ver == 0x3070) ? 1 : 2;
+ if (sc->txmixgain_2ghz >= mingain)
rf = (rf & ~0x7) | sc->txmixgain_2ghz;
run_rt3070_rf_write(sc, 17, rf);
}
- if (sc->mac_rev == 0x3071) {
+ if (sc->mac_ver == 0x3071) {
run_rt3070_rf_read(sc, 1, &rf);
rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD);
rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD;
@@ -4485,6 +5523,119 @@
return (0);
}
+static void
+run_rt3593_rf_init(struct run_softc *sc)
+{
+ uint32_t tmp;
+ uint8_t rf;
+ int i;
+
+ /* Disable the GPIO bits 4 and 7 for LNA PE control. */
+ run_read(sc, RT3070_GPIO_SWITCH, &tmp);
+ tmp &= ~(1 << 4 | 1 << 7);
+ run_write(sc, RT3070_GPIO_SWITCH, tmp);
+
+ /* Initialize RF registers to default value. */
+ for (i = 0; i < nitems(rt3593_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt3593_def_rf[i].reg,
+ rt3593_def_rf[i].val);
+ }
+
+ /* Toggle RF R2 to initiate calibration. */
+ run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+
+ /* Initialize RF frequency offset. */
+ run_adjust_freq_offset(sc);
+
+ run_rt3070_rf_read(sc, 18, &rf);
+ run_rt3070_rf_write(sc, 18, rf | RT3593_AUTOTUNE_BYPASS);
+
+ /*
+ * Increase voltage from 1.2V to 1.35V, wait for 1 msec to
+ * decrease voltage back to 1.2V.
+ */
+ run_read(sc, RT3070_LDO_CFG0, &tmp);
+ tmp = (tmp & ~0x1f000000) | 0x0d000000;
+ run_write(sc, RT3070_LDO_CFG0, tmp);
+ run_delay(sc, 1);
+ tmp = (tmp & ~0x1f000000) | 0x01000000;
+ run_write(sc, RT3070_LDO_CFG0, tmp);
+
+ sc->rf24_20mhz = 0x1f;
+ sc->rf24_40mhz = 0x2f;
+
+ /* Save default BBP registers 25 and 26 values. */
+ run_bbp_read(sc, 25, &sc->bbp25);
+ run_bbp_read(sc, 26, &sc->bbp26);
+
+ run_read(sc, RT3070_OPT_14, &tmp);
+ run_write(sc, RT3070_OPT_14, tmp | 1);
+}
+
+static void
+run_rt5390_rf_init(struct run_softc *sc)
+{
+ uint32_t tmp;
+ uint8_t rf;
+ int i;
+
+ /* Toggle RF R2 to initiate calibration. */
+ if (sc->mac_ver == 0x5390) {
+ run_rt3070_rf_read(sc, 2, &rf);
+ run_rt3070_rf_write(sc, 2, rf | RT5390_RESCAL);
+ run_delay(sc, 10);
+ run_rt3070_rf_write(sc, 2, rf & ~RT5390_RESCAL);
+ } else {
+ run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+ run_delay(sc, 10);
+ }
+
+ /* Initialize RF registers to default value. */
+ if (sc->mac_ver == 0x5592) {
+ for (i = 0; i < nitems(rt5592_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt5592_def_rf[i].reg,
+ rt5592_def_rf[i].val);
+ }
+ /* Initialize RF frequency offset. */
+ run_adjust_freq_offset(sc);
+ } else if (sc->mac_ver == 0x5392) {
+ for (i = 0; i < nitems(rt5392_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt5392_def_rf[i].reg,
+ rt5392_def_rf[i].val);
+ }
+ if (sc->mac_rev >= 0x0223) {
+ run_rt3070_rf_write(sc, 23, 0x0f);
+ run_rt3070_rf_write(sc, 24, 0x3e);
+ run_rt3070_rf_write(sc, 51, 0x32);
+ run_rt3070_rf_write(sc, 53, 0x22);
+ run_rt3070_rf_write(sc, 56, 0xc1);
+ run_rt3070_rf_write(sc, 59, 0x0f);
+ }
+ } else {
+ for (i = 0; i < nitems(rt5390_def_rf); i++) {
+ run_rt3070_rf_write(sc, rt5390_def_rf[i].reg,
+ rt5390_def_rf[i].val);
+ }
+ if (sc->mac_rev >= 0x0502) {
+ run_rt3070_rf_write(sc, 6, 0xe0);
+ run_rt3070_rf_write(sc, 25, 0x80);
+ run_rt3070_rf_write(sc, 46, 0x73);
+ run_rt3070_rf_write(sc, 53, 0x00);
+ run_rt3070_rf_write(sc, 56, 0x42);
+ run_rt3070_rf_write(sc, 61, 0xd1);
+ }
+ }
+
+ sc->rf24_20mhz = 0x1f; /* default value */
+ sc->rf24_40mhz = (sc->mac_ver == 0x5592) ? 0 : 0x2f;
+
+ if (sc->mac_rev < 0x0211)
+ run_rt3070_rf_write(sc, 27, 0x3);
+
+ run_read(sc, RT3070_OPT_14, &tmp);
+ run_write(sc, RT3070_OPT_14, tmp | 1);
+}
+
static int
run_rt3070_filter_calib(struct run_softc *sc, uint8_t init, uint8_t target,
uint8_t *val)
@@ -4514,7 +5665,7 @@
break;
}
if (ntries == 100)
- return ETIMEDOUT;
+ return (ETIMEDOUT);
/* set power and frequency of stopband test tone */
run_bbp_write(sc, 24, 0x06);
@@ -4579,10 +5730,15 @@
run_rt3070_rf_write(sc, 16, rf);
} else if (sc->mac_ver == 0x3071) {
- /* enable DC filter */
- if (sc->mac_rev >= 0x0201)
+ if (sc->mac_rev >= 0x0211) {
+ /* enable DC filter */
run_bbp_write(sc, 103, 0xc0);
+ /* improve power consumption */
+ run_bbp_read(sc, 31, &bbp);
+ run_bbp_write(sc, 31, bbp & ~0x03);
+ }
+
run_bbp_read(sc, 138, &bbp);
if (sc->ntxchains == 1)
bbp |= 0x20; /* turn off DAC1 */
@@ -4590,12 +5746,6 @@
bbp &= ~0x02; /* turn off ADC1 */
run_bbp_write(sc, 138, bbp);
- if (sc->mac_rev >= 0x0211) {
- /* improve power consumption */
- run_bbp_read(sc, 31, &bbp);
- run_bbp_write(sc, 31, bbp & ~0x03);
- }
-
run_write(sc, RT2860_TX_SW_CFG1, 0);
if (sc->mac_rev < 0x0211) {
run_write(sc, RT2860_TX_SW_CFG2,
@@ -4613,7 +5763,7 @@
run_bbp_write(sc, 31, bbp & ~0x03);
}
- if (sc->mac_rev < 0x0211) {
+ if (sc->mac_rev < 0x0201) {
run_write(sc, RT2860_TX_SW_CFG1, 0);
run_write(sc, RT2860_TX_SW_CFG2, 0x2c);
} else
@@ -4630,6 +5780,123 @@
}
}
+static void
+run_rt3593_rf_setup(struct run_softc *sc)
+{
+ uint8_t bbp, rf;
+
+ if (sc->mac_rev >= 0x0211) {
+ /* Enable DC filter. */
+ run_bbp_write(sc, 103, 0xc0);
+ }
+ run_write(sc, RT2860_TX_SW_CFG1, 0);
+ if (sc->mac_rev < 0x0211) {
+ run_write(sc, RT2860_TX_SW_CFG2,
+ sc->patch_dac ? 0x2c : 0x0f);
+ } else
+ run_write(sc, RT2860_TX_SW_CFG2, 0);
+
+ run_rt3070_rf_read(sc, 50, &rf);
+ run_rt3070_rf_write(sc, 50, rf & ~RT3593_TX_LO2);
+
+ run_rt3070_rf_read(sc, 51, &rf);
+ rf = (rf & ~(RT3593_TX_LO1 | 0x0c)) |
+ ((sc->txmixgain_2ghz & 0x07) << 2);
+ run_rt3070_rf_write(sc, 51, rf);
+
+ run_rt3070_rf_read(sc, 38, &rf);
+ run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+
+ run_rt3070_rf_read(sc, 39, &rf);
+ run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+ run_rt3070_rf_read(sc, 1, &rf);
+ run_rt3070_rf_write(sc, 1, rf & ~(RT3070_RF_BLOCK | RT3070_PLL_PD));
+
+ run_rt3070_rf_read(sc, 30, &rf);
+ rf = (rf & ~0x18) | 0x10;
+ run_rt3070_rf_write(sc, 30, rf);
+
+ /* Apply maximum likelihood detection for 2 stream case. */
+ run_bbp_read(sc, 105, &bbp);
+ if (sc->nrxchains > 1)
+ run_bbp_write(sc, 105, bbp | RT5390_MLD);
+
+ /* Avoid data lost and CRC error. */
+ run_bbp_read(sc, 4, &bbp);
+ run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+ run_bbp_write(sc, 92, 0x02);
+ run_bbp_write(sc, 82, 0x82);
+ run_bbp_write(sc, 106, 0x05);
+ run_bbp_write(sc, 104, 0x92);
+ run_bbp_write(sc, 88, 0x90);
+ run_bbp_write(sc, 148, 0xc8);
+ run_bbp_write(sc, 47, 0x48);
+ run_bbp_write(sc, 120, 0x50);
+
+ run_bbp_write(sc, 163, 0x9d);
+
+ /* SNR mapping. */
+ run_bbp_write(sc, 142, 0x06);
+ run_bbp_write(sc, 143, 0xa0);
+ run_bbp_write(sc, 142, 0x07);
+ run_bbp_write(sc, 143, 0xa1);
+ run_bbp_write(sc, 142, 0x08);
+ run_bbp_write(sc, 143, 0xa2);
+
+ run_bbp_write(sc, 31, 0x08);
+ run_bbp_write(sc, 68, 0x0b);
+ run_bbp_write(sc, 105, 0x04);
+}
+
+static void
+run_rt5390_rf_setup(struct run_softc *sc)
+{
+ uint8_t bbp, rf;
+
+ if (sc->mac_rev >= 0x0211) {
+ /* Enable DC filter. */
+ run_bbp_write(sc, 103, 0xc0);
+
+ if (sc->mac_ver != 0x5592) {
+ /* Improve power consumption. */
+ run_bbp_read(sc, 31, &bbp);
+ run_bbp_write(sc, 31, bbp & ~0x03);
+ }
+ }
+
+ run_bbp_read(sc, 138, &bbp);
+ if (sc->ntxchains == 1)
+ bbp |= 0x20; /* turn off DAC1 */
+ if (sc->nrxchains == 1)
+ bbp &= ~0x02; /* turn off ADC1 */
+ run_bbp_write(sc, 138, bbp);
+
+ run_rt3070_rf_read(sc, 38, &rf);
+ run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+
+ run_rt3070_rf_read(sc, 39, &rf);
+ run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+ /* Avoid data lost and CRC error. */
+ run_bbp_read(sc, 4, &bbp);
+ run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+ run_rt3070_rf_read(sc, 30, &rf);
+ rf = (rf & ~0x18) | 0x10;
+ run_rt3070_rf_write(sc, 30, rf);
+
+ if (sc->mac_ver != 0x5592) {
+ run_write(sc, RT2860_TX_SW_CFG1, 0);
+ if (sc->mac_rev < 0x0211) {
+ run_write(sc, RT2860_TX_SW_CFG2,
+ sc->patch_dac ? 0x2c : 0x0f);
+ } else
+ run_write(sc, RT2860_TX_SW_CFG2, 0);
+ }
+}
+
static int
run_txrx_enable(struct run_softc *sc)
{
@@ -4640,13 +5907,13 @@
run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN);
for (ntries = 0; ntries < 200; ntries++) {
if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0)
- return error;
+ return (error);
if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
break;
run_delay(sc, 50);
}
if (ntries == 200)
- return ETIMEDOUT;
+ return (ETIMEDOUT);
run_delay(sc, 50);
@@ -4677,6 +5944,20 @@
}
static void
+run_adjust_freq_offset(struct run_softc *sc)
+{
+ uint8_t rf, tmp;
+
+ run_rt3070_rf_read(sc, 17, &rf);
+ tmp = rf;
+ rf = (rf & ~0x7f) | (sc->freq & 0x7f);
+ rf = MIN(rf, 0x5f);
+
+ if (tmp != rf)
+ run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf);
+}
+
+static void
run_init_locked(struct run_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
@@ -4749,13 +6030,29 @@
run_write(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]);
}
- for (i = 0; i < N(rt2870_def_mac); i++)
+ for (i = 0; i < nitems(rt2870_def_mac); i++)
run_write(sc, rt2870_def_mac[i].reg, rt2870_def_mac[i].val);
run_write(sc, RT2860_WMM_AIFSN_CFG, 0x00002273);
run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344);
run_write(sc, RT2860_WMM_CWMAX_CFG, 0x000034aa);
- if (sc->mac_ver >= 0x3070) {
+ if (sc->mac_ver >= 0x5390) {
+ run_write(sc, RT2860_TX_SW_CFG0,
+ 4 << RT2860_DLY_PAPE_EN_SHIFT | 4);
+ if (sc->mac_ver >= 0x5392) {
+ run_write(sc, RT2860_MAX_LEN_CFG, 0x00002fff);
+ if (sc->mac_ver == 0x5592) {
+ run_write(sc, RT2860_HT_FBK_CFG1, 0xedcba980);
+ run_write(sc, RT2860_TXOP_HLDR_ET, 0x00000082);
+ } else {
+ run_write(sc, RT2860_HT_FBK_CFG1, 0xedcb4980);
+ run_write(sc, RT2860_LG_FBK_CFG0, 0xedcba322);
+ }
+ }
+ } else if (sc->mac_ver == 0x3593) {
+ run_write(sc, RT2860_TX_SW_CFG0,
+ 4 << RT2860_DLY_PAPE_EN_SHIFT | 2);
+ } else if (sc->mac_ver >= 0x3070) {
/* set delay of PA_PE assertion to 1us (unit of 0.25us) */
run_write(sc, RT2860_TX_SW_CFG0,
4 << RT2860_DLY_PAPE_EN_SHIFT);
@@ -4812,14 +6109,16 @@
run_write(sc, RT2860_WMM_TXOP1_CFG, 48 << 16 | 96);
/* write vendor-specific BBP values (from EEPROM) */
- for (i = 0; i < 10; i++) {
- if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
- continue;
- run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+ if (sc->mac_ver < 0x3593) {
+ for (i = 0; i < 10; i++) {
+ if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
+ continue;
+ run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+ }
}
/* select Main antenna for 1T1R devices */
- if (sc->rf_rev == RT3070_RF_3020)
+ if (sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT5390_RF_5370)
run_set_rx_antenna(sc, 0);
/* send LEDs operating mode to microcontroller */
@@ -4827,7 +6126,11 @@
(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]);
(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]);
- if (sc->mac_ver >= 0x3070)
+ if (sc->mac_ver >= 0x5390)
+ run_rt5390_rf_init(sc);
+ else if (sc->mac_ver == 0x3593)
+ run_rt3593_rf_init(sc);
+ else if (sc->mac_ver >= 0x3070)
run_rt3070_rf_init(sc);
/* disable non-existing Rx chains */
@@ -4845,7 +6148,11 @@
bbp1 &= ~(1 << 3 | 1 << 4);
run_bbp_write(sc, 1, bbp1);
- if (sc->mac_ver >= 0x3070)
+ if (sc->mac_ver >= 0x5390)
+ run_rt5390_rf_setup(sc);
+ else if (sc->mac_ver == 0x3593)
+ run_rt3593_rf_setup(sc);
+ else if (sc->mac_ver >= 0x3070)
run_rt3070_rf_setup(sc);
/* select default channel */
@@ -4921,6 +6228,24 @@
sc->rx_m = NULL;
}
+ /* Disable Tx/Rx DMA. */
+ if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
+ return;
+ tmp &= ~(RT2860_RX_DMA_EN | RT2860_TX_DMA_EN);
+ run_write(sc, RT2860_WPDMA_GLO_CFG, tmp);
+
+ for (ntries = 0; ntries < 100; ntries++) {
+ if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
+ return;
+ if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
+ break;
+ run_delay(sc, 10);
+ }
+ if (ntries == 100) {
+ device_printf(sc->sc_dev, "timeout waiting for DMA engine\n");
+ return;
+ }
+
/* disable Tx/Rx */
run_read(sc, RT2860_MAC_SYS_CTRL, &tmp);
tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN);
@@ -4948,12 +6273,10 @@
for (i = 0; i != RUN_EP_QUEUES; i++)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
-
- return;
}
static void
-run_delay(struct run_softc *sc, unsigned int ms)
+run_delay(struct run_softc *sc, u_int ms)
{
usb_pause_mtx(mtx_owned(&sc->sc_mtx) ?
&sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms));
@@ -4964,8 +6287,7 @@
DEVMETHOD(device_probe, run_match),
DEVMETHOD(device_attach, run_attach),
DEVMETHOD(device_detach, run_detach),
-
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t run_driver = {
@@ -4976,7 +6298,7 @@
static devclass_t run_devclass;
-DRIVER_MODULE(run, uhub, run_driver, run_devclass, NULL, 0);
+DRIVER_MODULE(run, uhub, run_driver, run_devclass, run_driver_loaded, NULL);
MODULE_DEPEND(run, wlan, 1, 1, 1);
MODULE_DEPEND(run, usb, 1, 1, 1);
MODULE_DEPEND(run, firmware, 1, 1, 1);
Modified: stable/0.8/sys/dev/usb/wlan/if_runreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_runreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_runreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -16,715 +16,743 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/wlan/if_runreg.h 294903 2016-01-27 07:34:23Z delphij $
*/
#ifndef _IF_RUNREG_H_
#define _IF_RUNREG_H_
-/* PCI registers */
-#define RT2860_PCI_CFG 0x0000
-#define RT2860_PCI_EECTRL 0x0004
-#define RT2860_PCI_MCUCTRL 0x0008
-#define RT2860_PCI_SYSCTRL 0x000c
-#define RT2860_PCIE_JTAG 0x0010
+#define RT2860_CONFIG_NO 1
+#define RT2860_IFACE_INDEX 0
-#define RT2860_CONFIG_NO 1
-#define RT2860_IFACE_INDEX 0
+#define RT3070_OPT_14 0x0114
-#define RT3070_OPT_14 0x0114
-
/* SCH/DMA registers */
-#define RT2860_INT_STATUS 0x0200
-#define RT2860_INT_MASK 0x0204
-#define RT2860_WPDMA_GLO_CFG 0x0208
-#define RT2860_WPDMA_RST_IDX 0x020c
-#define RT2860_DELAY_INT_CFG 0x0210
-#define RT2860_WMM_AIFSN_CFG 0x0214
-#define RT2860_WMM_CWMIN_CFG 0x0218
-#define RT2860_WMM_CWMAX_CFG 0x021c
-#define RT2860_WMM_TXOP0_CFG 0x0220
-#define RT2860_WMM_TXOP1_CFG 0x0224
-#define RT2860_GPIO_CTRL 0x0228
-#define RT2860_MCU_CMD_REG 0x022c
-#define RT2860_TX_BASE_PTR(qid) (0x0230 + (qid) * 16)
-#define RT2860_TX_MAX_CNT(qid) (0x0234 + (qid) * 16)
-#define RT2860_TX_CTX_IDX(qid) (0x0238 + (qid) * 16)
-#define RT2860_TX_DTX_IDX(qid) (0x023c + (qid) * 16)
-#define RT2860_RX_BASE_PTR 0x0290
-#define RT2860_RX_MAX_CNT 0x0294
-#define RT2860_RX_CALC_IDX 0x0298
-#define RT2860_FS_DRX_IDX 0x029c
-#define RT2860_USB_DMA_CFG 0x02a0 /* RT2870 only */
-#define RT2860_US_CYC_CNT 0x02a4
+#define RT2860_INT_STATUS 0x0200
+#define RT2860_INT_MASK 0x0204
+#define RT2860_WPDMA_GLO_CFG 0x0208
+#define RT2860_WPDMA_RST_IDX 0x020c
+#define RT2860_DELAY_INT_CFG 0x0210
+#define RT2860_WMM_AIFSN_CFG 0x0214
+#define RT2860_WMM_CWMIN_CFG 0x0218
+#define RT2860_WMM_CWMAX_CFG 0x021c
+#define RT2860_WMM_TXOP0_CFG 0x0220
+#define RT2860_WMM_TXOP1_CFG 0x0224
+#define RT2860_GPIO_CTRL 0x0228
+#define RT2860_MCU_CMD_REG 0x022c
+#define RT2860_TX_BASE_PTR(qid) (0x0230 + (qid) * 16)
+#define RT2860_TX_MAX_CNT(qid) (0x0234 + (qid) * 16)
+#define RT2860_TX_CTX_IDX(qid) (0x0238 + (qid) * 16)
+#define RT2860_TX_DTX_IDX(qid) (0x023c + (qid) * 16)
+#define RT2860_RX_BASE_PTR 0x0290
+#define RT2860_RX_MAX_CNT 0x0294
+#define RT2860_RX_CALC_IDX 0x0298
+#define RT2860_FS_DRX_IDX 0x029c
+#define RT2860_USB_DMA_CFG 0x02a0 /* RT2870 only */
+#define RT2860_US_CYC_CNT 0x02a4
/* PBF registers */
-#define RT2860_SYS_CTRL 0x0400
-#define RT2860_HOST_CMD 0x0404
-#define RT2860_PBF_CFG 0x0408
-#define RT2860_MAX_PCNT 0x040c
-#define RT2860_BUF_CTRL 0x0410
-#define RT2860_MCU_INT_STA 0x0414
-#define RT2860_MCU_INT_ENA 0x0418
-#define RT2860_TXQ_IO(qid) (0x041c + (qid) * 4)
-#define RT2860_RX0Q_IO 0x0424
-#define RT2860_BCN_OFFSET0 0x042c
-#define RT2860_BCN_OFFSET1 0x0430
-#define RT2860_TXRXQ_STA 0x0434
-#define RT2860_TXRXQ_PCNT 0x0438
-#define RT2860_PBF_DBG 0x043c
-#define RT2860_CAP_CTRL 0x0440
+#define RT2860_SYS_CTRL 0x0400
+#define RT2860_HOST_CMD 0x0404
+#define RT2860_PBF_CFG 0x0408
+#define RT2860_MAX_PCNT 0x040c
+#define RT2860_BUF_CTRL 0x0410
+#define RT2860_MCU_INT_STA 0x0414
+#define RT2860_MCU_INT_ENA 0x0418
+#define RT2860_TXQ_IO(qid) (0x041c + (qid) * 4)
+#define RT2860_RX0Q_IO 0x0424
+#define RT2860_BCN_OFFSET0 0x042c
+#define RT2860_BCN_OFFSET1 0x0430
+#define RT2860_TXRXQ_STA 0x0434
+#define RT2860_TXRXQ_PCNT 0x0438
+#define RT2860_PBF_DBG 0x043c
+#define RT2860_CAP_CTRL 0x0440
/* RT3070 registers */
-#define RT3070_RF_CSR_CFG 0x0500
-#define RT3070_EFUSE_CTRL 0x0580
-#define RT3070_EFUSE_DATA0 0x0590
-#define RT3070_EFUSE_DATA1 0x0594
-#define RT3070_EFUSE_DATA2 0x0598
-#define RT3070_EFUSE_DATA3 0x059c
-#define RT3070_LDO_CFG0 0x05d4
-#define RT3070_GPIO_SWITCH 0x05dc
+#define RT3070_RF_CSR_CFG 0x0500
+#define RT3070_EFUSE_CTRL 0x0580
+#define RT3070_EFUSE_DATA0 0x0590
+#define RT3070_EFUSE_DATA1 0x0594
+#define RT3070_EFUSE_DATA2 0x0598
+#define RT3070_EFUSE_DATA3 0x059c
+#define RT3070_LDO_CFG0 0x05d4
+#define RT3070_GPIO_SWITCH 0x05dc
+/* RT5592 registers */
+#define RT5592_DEBUG_INDEX 0x05e8
+
/* MAC registers */
-#define RT2860_ASIC_VER_ID 0x1000
-#define RT2860_MAC_SYS_CTRL 0x1004
-#define RT2860_MAC_ADDR_DW0 0x1008
-#define RT2860_MAC_ADDR_DW1 0x100c
-#define RT2860_MAC_BSSID_DW0 0x1010
-#define RT2860_MAC_BSSID_DW1 0x1014
-#define RT2860_MAX_LEN_CFG 0x1018
-#define RT2860_BBP_CSR_CFG 0x101c
-#define RT2860_RF_CSR_CFG0 0x1020
-#define RT2860_RF_CSR_CFG1 0x1024
-#define RT2860_RF_CSR_CFG2 0x1028
-#define RT2860_LED_CFG 0x102c
+#define RT2860_ASIC_VER_ID 0x1000
+#define RT2860_MAC_SYS_CTRL 0x1004
+#define RT2860_MAC_ADDR_DW0 0x1008
+#define RT2860_MAC_ADDR_DW1 0x100c
+#define RT2860_MAC_BSSID_DW0 0x1010
+#define RT2860_MAC_BSSID_DW1 0x1014
+#define RT2860_MAX_LEN_CFG 0x1018
+#define RT2860_BBP_CSR_CFG 0x101c
+#define RT2860_RF_CSR_CFG0 0x1020
+#define RT2860_RF_CSR_CFG1 0x1024
+#define RT2860_RF_CSR_CFG2 0x1028
+#define RT2860_LED_CFG 0x102c
/* undocumented registers */
-#define RT2860_DEBUG 0x10f4
+#define RT2860_DEBUG 0x10f4
/* MAC Timing control registers */
-#define RT2860_XIFS_TIME_CFG 0x1100
-#define RT2860_BKOFF_SLOT_CFG 0x1104
-#define RT2860_NAV_TIME_CFG 0x1108
-#define RT2860_CH_TIME_CFG 0x110c
-#define RT2860_PBF_LIFE_TIMER 0x1110
-#define RT2860_BCN_TIME_CFG 0x1114
-#define RT2860_TBTT_SYNC_CFG 0x1118
-#define RT2860_TSF_TIMER_DW0 0x111c
-#define RT2860_TSF_TIMER_DW1 0x1120
-#define RT2860_TBTT_TIMER 0x1124
-#define RT2860_INT_TIMER_CFG 0x1128
-#define RT2860_INT_TIMER_EN 0x112c
-#define RT2860_CH_IDLE_TIME 0x1130
+#define RT2860_XIFS_TIME_CFG 0x1100
+#define RT2860_BKOFF_SLOT_CFG 0x1104
+#define RT2860_NAV_TIME_CFG 0x1108
+#define RT2860_CH_TIME_CFG 0x110c
+#define RT2860_PBF_LIFE_TIMER 0x1110
+#define RT2860_BCN_TIME_CFG 0x1114
+#define RT2860_TBTT_SYNC_CFG 0x1118
+#define RT2860_TSF_TIMER_DW0 0x111c
+#define RT2860_TSF_TIMER_DW1 0x1120
+#define RT2860_TBTT_TIMER 0x1124
+#define RT2860_INT_TIMER_CFG 0x1128
+#define RT2860_INT_TIMER_EN 0x112c
+#define RT2860_CH_IDLE_TIME 0x1130
/* MAC Power Save configuration registers */
-#define RT2860_MAC_STATUS_REG 0x1200
-#define RT2860_PWR_PIN_CFG 0x1204
-#define RT2860_AUTO_WAKEUP_CFG 0x1208
+#define RT2860_MAC_STATUS_REG 0x1200
+#define RT2860_PWR_PIN_CFG 0x1204
+#define RT2860_AUTO_WAKEUP_CFG 0x1208
/* MAC TX configuration registers */
-#define RT2860_EDCA_AC_CFG(aci) (0x1300 + (aci) * 4)
-#define RT2860_EDCA_TID_AC_MAP 0x1310
-#define RT2860_TX_PWR_CFG(ridx) (0x1314 + (ridx) * 4)
-#define RT2860_TX_PIN_CFG 0x1328
-#define RT2860_TX_BAND_CFG 0x132c
-#define RT2860_TX_SW_CFG0 0x1330
-#define RT2860_TX_SW_CFG1 0x1334
-#define RT2860_TX_SW_CFG2 0x1338
-#define RT2860_TXOP_THRES_CFG 0x133c
-#define RT2860_TXOP_CTRL_CFG 0x1340
-#define RT2860_TX_RTS_CFG 0x1344
-#define RT2860_TX_TIMEOUT_CFG 0x1348
-#define RT2860_TX_RTY_CFG 0x134c
-#define RT2860_TX_LINK_CFG 0x1350
-#define RT2860_HT_FBK_CFG0 0x1354
-#define RT2860_HT_FBK_CFG1 0x1358
-#define RT2860_LG_FBK_CFG0 0x135c
-#define RT2860_LG_FBK_CFG1 0x1360
-#define RT2860_CCK_PROT_CFG 0x1364
-#define RT2860_OFDM_PROT_CFG 0x1368
-#define RT2860_MM20_PROT_CFG 0x136c
-#define RT2860_MM40_PROT_CFG 0x1370
-#define RT2860_GF20_PROT_CFG 0x1374
-#define RT2860_GF40_PROT_CFG 0x1378
-#define RT2860_EXP_CTS_TIME 0x137c
-#define RT2860_EXP_ACK_TIME 0x1380
+#define RT2860_EDCA_AC_CFG(aci) (0x1300 + (aci) * 4)
+#define RT2860_EDCA_TID_AC_MAP 0x1310
+#define RT2860_TX_PWR_CFG(ridx) (0x1314 + (ridx) * 4)
+#define RT2860_TX_PIN_CFG 0x1328
+#define RT2860_TX_BAND_CFG 0x132c
+#define RT2860_TX_SW_CFG0 0x1330
+#define RT2860_TX_SW_CFG1 0x1334
+#define RT2860_TX_SW_CFG2 0x1338
+#define RT2860_TXOP_THRES_CFG 0x133c
+#define RT2860_TXOP_CTRL_CFG 0x1340
+#define RT2860_TX_RTS_CFG 0x1344
+#define RT2860_TX_TIMEOUT_CFG 0x1348
+#define RT2860_TX_RTY_CFG 0x134c
+#define RT2860_TX_LINK_CFG 0x1350
+#define RT2860_HT_FBK_CFG0 0x1354
+#define RT2860_HT_FBK_CFG1 0x1358
+#define RT2860_LG_FBK_CFG0 0x135c
+#define RT2860_LG_FBK_CFG1 0x1360
+#define RT2860_CCK_PROT_CFG 0x1364
+#define RT2860_OFDM_PROT_CFG 0x1368
+#define RT2860_MM20_PROT_CFG 0x136c
+#define RT2860_MM40_PROT_CFG 0x1370
+#define RT2860_GF20_PROT_CFG 0x1374
+#define RT2860_GF40_PROT_CFG 0x1378
+#define RT2860_EXP_CTS_TIME 0x137c
+#define RT2860_EXP_ACK_TIME 0x1380
/* MAC RX configuration registers */
-#define RT2860_RX_FILTR_CFG 0x1400
-#define RT2860_AUTO_RSP_CFG 0x1404
-#define RT2860_LEGACY_BASIC_RATE 0x1408
-#define RT2860_HT_BASIC_RATE 0x140c
-#define RT2860_HT_CTRL_CFG 0x1410
-#define RT2860_SIFS_COST_CFG 0x1414
-#define RT2860_RX_PARSER_CFG 0x1418
+#define RT2860_RX_FILTR_CFG 0x1400
+#define RT2860_AUTO_RSP_CFG 0x1404
+#define RT2860_LEGACY_BASIC_RATE 0x1408
+#define RT2860_HT_BASIC_RATE 0x140c
+#define RT2860_HT_CTRL_CFG 0x1410
+#define RT2860_SIFS_COST_CFG 0x1414
+#define RT2860_RX_PARSER_CFG 0x1418
/* MAC Security configuration registers */
-#define RT2860_TX_SEC_CNT0 0x1500
-#define RT2860_RX_SEC_CNT0 0x1504
-#define RT2860_CCMP_FC_MUTE 0x1508
+#define RT2860_TX_SEC_CNT0 0x1500
+#define RT2860_RX_SEC_CNT0 0x1504
+#define RT2860_CCMP_FC_MUTE 0x1508
/* MAC HCCA/PSMP configuration registers */
-#define RT2860_TXOP_HLDR_ADDR0 0x1600
-#define RT2860_TXOP_HLDR_ADDR1 0x1604
-#define RT2860_TXOP_HLDR_ET 0x1608
-#define RT2860_QOS_CFPOLL_RA_DW0 0x160c
-#define RT2860_QOS_CFPOLL_A1_DW1 0x1610
-#define RT2860_QOS_CFPOLL_QC 0x1614
+#define RT2860_TXOP_HLDR_ADDR0 0x1600
+#define RT2860_TXOP_HLDR_ADDR1 0x1604
+#define RT2860_TXOP_HLDR_ET 0x1608
+#define RT2860_QOS_CFPOLL_RA_DW0 0x160c
+#define RT2860_QOS_CFPOLL_A1_DW1 0x1610
+#define RT2860_QOS_CFPOLL_QC 0x1614
/* MAC Statistics Counters */
-#define RT2860_RX_STA_CNT0 0x1700
-#define RT2860_RX_STA_CNT1 0x1704
-#define RT2860_RX_STA_CNT2 0x1708
-#define RT2860_TX_STA_CNT0 0x170c
-#define RT2860_TX_STA_CNT1 0x1710
-#define RT2860_TX_STA_CNT2 0x1714
-#define RT2860_TX_STAT_FIFO 0x1718
+#define RT2860_RX_STA_CNT0 0x1700
+#define RT2860_RX_STA_CNT1 0x1704
+#define RT2860_RX_STA_CNT2 0x1708
+#define RT2860_TX_STA_CNT0 0x170c
+#define RT2860_TX_STA_CNT1 0x1710
+#define RT2860_TX_STA_CNT2 0x1714
+#define RT2860_TX_STAT_FIFO 0x1718
/* RX WCID search table */
-#define RT2860_WCID_ENTRY(wcid) (0x1800 + (wcid) * 8)
+#define RT2860_WCID_ENTRY(wcid) (0x1800 + (wcid) * 8)
-#define RT2860_FW_BASE 0x2000
-#define RT2870_FW_BASE 0x3000
+#define RT2860_FW_BASE 0x2000
+#define RT2870_FW_BASE 0x3000
/* Pair-wise key table */
-#define RT2860_PKEY(wcid) (0x4000 + (wcid) * 32)
+#define RT2860_PKEY(wcid) (0x4000 + (wcid) * 32)
/* IV/EIV table */
-#define RT2860_IVEIV(wcid) (0x6000 + (wcid) * 8)
+#define RT2860_IVEIV(wcid) (0x6000 + (wcid) * 8)
/* WCID attribute table */
-#define RT2860_WCID_ATTR(wcid) (0x6800 + (wcid) * 4)
+#define RT2860_WCID_ATTR(wcid) (0x6800 + (wcid) * 4)
/* Shared Key Table */
-#define RT2860_SKEY(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32)
+#define RT2860_SKEY(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32)
/* Shared Key Mode */
-#define RT2860_SKEY_MODE_0_7 0x7000
-#define RT2860_SKEY_MODE_8_15 0x7004
-#define RT2860_SKEY_MODE_16_23 0x7008
-#define RT2860_SKEY_MODE_24_31 0x700c
+#define RT2860_SKEY_MODE_0_7 0x7000
+#define RT2860_SKEY_MODE_8_15 0x7004
+#define RT2860_SKEY_MODE_16_23 0x7008
+#define RT2860_SKEY_MODE_24_31 0x700c
/* Shared Memory between MCU and host */
-#define RT2860_H2M_MAILBOX 0x7010
-#define RT2860_H2M_MAILBOX_CID 0x7014
-#define RT2860_H2M_MAILBOX_STATUS 0x701c
-#define RT2860_H2M_BBPAGENT 0x7028
-#define RT2860_BCN_BASE(vap) (0x7800 + (vap) * 512)
+#define RT2860_H2M_MAILBOX 0x7010
+#define RT2860_H2M_MAILBOX_CID 0x7014
+#define RT2860_H2M_MAILBOX_STATUS 0x701c
+#define RT2860_H2M_INTSRC 0x7024
+#define RT2860_H2M_BBPAGENT 0x7028
+#define RT2860_BCN_BASE(vap) (0x7800 + (vap) * 512)
/* possible flags for register RT2860_PCI_EECTRL */
-#define RT2860_C (1 << 0)
-#define RT2860_S (1 << 1)
-#define RT2860_D (1 << 2)
-#define RT2860_SHIFT_D 2
-#define RT2860_Q (1 << 3)
-#define RT2860_SHIFT_Q 3
+#define RT2860_C (1 << 0)
+#define RT2860_S (1 << 1)
+#define RT2860_D (1 << 2)
+#define RT2860_SHIFT_D 2
+#define RT2860_Q (1 << 3)
+#define RT2860_SHIFT_Q 3
/* possible flags for registers INT_STATUS/INT_MASK */
-#define RT2860_TX_COHERENT (1 << 17)
-#define RT2860_RX_COHERENT (1 << 16)
-#define RT2860_MAC_INT_4 (1 << 15)
-#define RT2860_MAC_INT_3 (1 << 14)
-#define RT2860_MAC_INT_2 (1 << 13)
-#define RT2860_MAC_INT_1 (1 << 12)
-#define RT2860_MAC_INT_0 (1 << 11)
-#define RT2860_TX_RX_COHERENT (1 << 10)
-#define RT2860_MCU_CMD_INT (1 << 9)
-#define RT2860_TX_DONE_INT5 (1 << 8)
-#define RT2860_TX_DONE_INT4 (1 << 7)
-#define RT2860_TX_DONE_INT3 (1 << 6)
-#define RT2860_TX_DONE_INT2 (1 << 5)
-#define RT2860_TX_DONE_INT1 (1 << 4)
-#define RT2860_TX_DONE_INT0 (1 << 3)
-#define RT2860_RX_DONE_INT (1 << 2)
-#define RT2860_TX_DLY_INT (1 << 1)
-#define RT2860_RX_DLY_INT (1 << 0)
+#define RT2860_TX_COHERENT (1 << 17)
+#define RT2860_RX_COHERENT (1 << 16)
+#define RT2860_MAC_INT_4 (1 << 15)
+#define RT2860_MAC_INT_3 (1 << 14)
+#define RT2860_MAC_INT_2 (1 << 13)
+#define RT2860_MAC_INT_1 (1 << 12)
+#define RT2860_MAC_INT_0 (1 << 11)
+#define RT2860_TX_RX_COHERENT (1 << 10)
+#define RT2860_MCU_CMD_INT (1 << 9)
+#define RT2860_TX_DONE_INT5 (1 << 8)
+#define RT2860_TX_DONE_INT4 (1 << 7)
+#define RT2860_TX_DONE_INT3 (1 << 6)
+#define RT2860_TX_DONE_INT2 (1 << 5)
+#define RT2860_TX_DONE_INT1 (1 << 4)
+#define RT2860_TX_DONE_INT0 (1 << 3)
+#define RT2860_RX_DONE_INT (1 << 2)
+#define RT2860_TX_DLY_INT (1 << 1)
+#define RT2860_RX_DLY_INT (1 << 0)
/* possible flags for register WPDMA_GLO_CFG */
-#define RT2860_HDR_SEG_LEN_SHIFT 8
-#define RT2860_BIG_ENDIAN (1 << 7)
-#define RT2860_TX_WB_DDONE (1 << 6)
-#define RT2860_WPDMA_BT_SIZE_SHIFT 4
-#define RT2860_WPDMA_BT_SIZE16 0
-#define RT2860_WPDMA_BT_SIZE32 1
-#define RT2860_WPDMA_BT_SIZE64 2
-#define RT2860_WPDMA_BT_SIZE128 3
-#define RT2860_RX_DMA_BUSY (1 << 3)
-#define RT2860_RX_DMA_EN (1 << 2)
-#define RT2860_TX_DMA_BUSY (1 << 1)
-#define RT2860_TX_DMA_EN (1 << 0)
+#define RT2860_HDR_SEG_LEN_SHIFT 8
+#define RT2860_BIG_ENDIAN (1 << 7)
+#define RT2860_TX_WB_DDONE (1 << 6)
+#define RT2860_WPDMA_BT_SIZE_SHIFT 4
+#define RT2860_WPDMA_BT_SIZE16 0
+#define RT2860_WPDMA_BT_SIZE32 1
+#define RT2860_WPDMA_BT_SIZE64 2
+#define RT2860_WPDMA_BT_SIZE128 3
+#define RT2860_RX_DMA_BUSY (1 << 3)
+#define RT2860_RX_DMA_EN (1 << 2)
+#define RT2860_TX_DMA_BUSY (1 << 1)
+#define RT2860_TX_DMA_EN (1 << 0)
/* possible flags for register DELAY_INT_CFG */
-#define RT2860_TXDLY_INT_EN (1 << 31)
-#define RT2860_TXMAX_PINT_SHIFT 24
-#define RT2860_TXMAX_PTIME_SHIFT 16
-#define RT2860_RXDLY_INT_EN (1 << 15)
-#define RT2860_RXMAX_PINT_SHIFT 8
-#define RT2860_RXMAX_PTIME_SHIFT 0
+#define RT2860_TXDLY_INT_EN (1U << 31)
+#define RT2860_TXMAX_PINT_SHIFT 24
+#define RT2860_TXMAX_PTIME_SHIFT 16
+#define RT2860_RXDLY_INT_EN (1 << 15)
+#define RT2860_RXMAX_PINT_SHIFT 8
+#define RT2860_RXMAX_PTIME_SHIFT 0
/* possible flags for register GPIO_CTRL */
-#define RT2860_GPIO_D_SHIFT 8
-#define RT2860_GPIO_O_SHIFT 0
+#define RT2860_GPIO_D_SHIFT 8
+#define RT2860_GPIO_O_SHIFT 0
/* possible flags for register USB_DMA_CFG */
-#define RT2860_USB_TX_BUSY (1 << 31)
-#define RT2860_USB_RX_BUSY (1 << 30)
-#define RT2860_USB_EPOUT_VLD_SHIFT 24
-#define RT2860_USB_TX_EN (1 << 23)
-#define RT2860_USB_RX_EN (1 << 22)
-#define RT2860_USB_RX_AGG_EN (1 << 21)
-#define RT2860_USB_TXOP_HALT (1 << 20)
-#define RT2860_USB_TX_CLEAR (1 << 19)
-#define RT2860_USB_PHY_WD_EN (1 << 16)
-#define RT2860_USB_PHY_MAN_RST (1 << 15)
-#define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */
-#define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */
+#define RT2860_USB_TX_BUSY (1U << 31)
+#define RT2860_USB_RX_BUSY (1 << 30)
+#define RT2860_USB_EPOUT_VLD_SHIFT 24
+#define RT2860_USB_TX_EN (1 << 23)
+#define RT2860_USB_RX_EN (1 << 22)
+#define RT2860_USB_RX_AGG_EN (1 << 21)
+#define RT2860_USB_TXOP_HALT (1 << 20)
+#define RT2860_USB_TX_CLEAR (1 << 19)
+#define RT2860_USB_PHY_WD_EN (1 << 16)
+#define RT2860_USB_PHY_MAN_RST (1 << 15)
+#define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */
+#define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */
/* possible flags for register US_CYC_CNT */
-#define RT2860_TEST_EN (1 << 24)
-#define RT2860_TEST_SEL_SHIFT 16
-#define RT2860_BT_MODE_EN (1 << 8)
-#define RT2860_US_CYC_CNT_SHIFT 0
+#define RT2860_TEST_EN (1 << 24)
+#define RT2860_TEST_SEL_SHIFT 16
+#define RT2860_BT_MODE_EN (1 << 8)
+#define RT2860_US_CYC_CNT_SHIFT 0
/* possible flags for register SYS_CTRL */
-#define RT2860_HST_PM_SEL (1 << 16)
-#define RT2860_CAP_MODE (1 << 14)
-#define RT2860_PME_OEN (1 << 13)
-#define RT2860_CLKSELECT (1 << 12)
-#define RT2860_PBF_CLK_EN (1 << 11)
-#define RT2860_MAC_CLK_EN (1 << 10)
-#define RT2860_DMA_CLK_EN (1 << 9)
-#define RT2860_MCU_READY (1 << 7)
-#define RT2860_ASY_RESET (1 << 4)
-#define RT2860_PBF_RESET (1 << 3)
-#define RT2860_MAC_RESET (1 << 2)
-#define RT2860_DMA_RESET (1 << 1)
-#define RT2860_MCU_RESET (1 << 0)
+#define RT2860_HST_PM_SEL (1 << 16)
+#define RT2860_CAP_MODE (1 << 14)
+#define RT2860_PME_OEN (1 << 13)
+#define RT2860_CLKSELECT (1 << 12)
+#define RT2860_PBF_CLK_EN (1 << 11)
+#define RT2860_MAC_CLK_EN (1 << 10)
+#define RT2860_DMA_CLK_EN (1 << 9)
+#define RT2860_MCU_READY (1 << 7)
+#define RT2860_ASY_RESET (1 << 4)
+#define RT2860_PBF_RESET (1 << 3)
+#define RT2860_MAC_RESET (1 << 2)
+#define RT2860_DMA_RESET (1 << 1)
+#define RT2860_MCU_RESET (1 << 0)
/* possible values for register HOST_CMD */
-#define RT2860_MCU_CMD_SLEEP 0x30
-#define RT2860_MCU_CMD_WAKEUP 0x31
-#define RT2860_MCU_CMD_LEDS 0x50
-#define RT2860_MCU_CMD_LED_RSSI 0x51
-#define RT2860_MCU_CMD_LED1 0x52
-#define RT2860_MCU_CMD_LED2 0x53
-#define RT2860_MCU_CMD_LED3 0x54
-#define RT2860_MCU_CMD_RFRESET 0x72
-#define RT2860_MCU_CMD_ANTSEL 0x73
-#define RT2860_MCU_CMD_BBP 0x80
-#define RT2860_MCU_CMD_PSLEVEL 0x83
+#define RT2860_MCU_CMD_SLEEP 0x30
+#define RT2860_MCU_CMD_WAKEUP 0x31
+#define RT2860_MCU_CMD_LEDS 0x50
+#define RT2860_MCU_CMD_LED_RSSI 0x51
+#define RT2860_MCU_CMD_LED1 0x52
+#define RT2860_MCU_CMD_LED2 0x53
+#define RT2860_MCU_CMD_LED3 0x54
+#define RT2860_MCU_CMD_RFRESET 0x72
+#define RT2860_MCU_CMD_ANTSEL 0x73
+#define RT2860_MCU_CMD_BBP 0x80
+#define RT2860_MCU_CMD_PSLEVEL 0x83
/* possible flags for register PBF_CFG */
-#define RT2860_TX1Q_NUM_SHIFT 21
-#define RT2860_TX2Q_NUM_SHIFT 16
-#define RT2860_NULL0_MODE (1 << 15)
-#define RT2860_NULL1_MODE (1 << 14)
-#define RT2860_RX_DROP_MODE (1 << 13)
-#define RT2860_TX0Q_MANUAL (1 << 12)
-#define RT2860_TX1Q_MANUAL (1 << 11)
-#define RT2860_TX2Q_MANUAL (1 << 10)
-#define RT2860_RX0Q_MANUAL (1 << 9)
-#define RT2860_HCCA_EN (1 << 8)
-#define RT2860_TX0Q_EN (1 << 4)
-#define RT2860_TX1Q_EN (1 << 3)
-#define RT2860_TX2Q_EN (1 << 2)
-#define RT2860_RX0Q_EN (1 << 1)
+#define RT2860_TX1Q_NUM_SHIFT 21
+#define RT2860_TX2Q_NUM_SHIFT 16
+#define RT2860_NULL0_MODE (1 << 15)
+#define RT2860_NULL1_MODE (1 << 14)
+#define RT2860_RX_DROP_MODE (1 << 13)
+#define RT2860_TX0Q_MANUAL (1 << 12)
+#define RT2860_TX1Q_MANUAL (1 << 11)
+#define RT2860_TX2Q_MANUAL (1 << 10)
+#define RT2860_RX0Q_MANUAL (1 << 9)
+#define RT2860_HCCA_EN (1 << 8)
+#define RT2860_TX0Q_EN (1 << 4)
+#define RT2860_TX1Q_EN (1 << 3)
+#define RT2860_TX2Q_EN (1 << 2)
+#define RT2860_RX0Q_EN (1 << 1)
/* possible flags for register BUF_CTRL */
-#define RT2860_WRITE_TXQ(qid) (1 << (11 - (qid)))
-#define RT2860_NULL0_KICK (1 << 7)
-#define RT2860_NULL1_KICK (1 << 6)
-#define RT2860_BUF_RESET (1 << 5)
-#define RT2860_READ_TXQ(qid) (1 << (3 - (qid))
-#define RT2860_READ_RX0Q (1 << 0)
+#define RT2860_WRITE_TXQ(qid) (1 << (11 - (qid)))
+#define RT2860_NULL0_KICK (1 << 7)
+#define RT2860_NULL1_KICK (1 << 6)
+#define RT2860_BUF_RESET (1 << 5)
+#define RT2860_READ_TXQ(qid) (1 << (3 - (qid))
+#define RT2860_READ_RX0Q (1 << 0)
/* possible flags for registers MCU_INT_STA/MCU_INT_ENA */
-#define RT2860_MCU_MAC_INT_8 (1 << 24)
-#define RT2860_MCU_MAC_INT_7 (1 << 23)
-#define RT2860_MCU_MAC_INT_6 (1 << 22)
-#define RT2860_MCU_MAC_INT_4 (1 << 20)
-#define RT2860_MCU_MAC_INT_3 (1 << 19)
-#define RT2860_MCU_MAC_INT_2 (1 << 18)
-#define RT2860_MCU_MAC_INT_1 (1 << 17)
-#define RT2860_MCU_MAC_INT_0 (1 << 16)
-#define RT2860_DTX0_INT (1 << 11)
-#define RT2860_DTX1_INT (1 << 10)
-#define RT2860_DTX2_INT (1 << 9)
-#define RT2860_DRX0_INT (1 << 8)
-#define RT2860_HCMD_INT (1 << 7)
-#define RT2860_N0TX_INT (1 << 6)
-#define RT2860_N1TX_INT (1 << 5)
-#define RT2860_BCNTX_INT (1 << 4)
-#define RT2860_MTX0_INT (1 << 3)
-#define RT2860_MTX1_INT (1 << 2)
-#define RT2860_MTX2_INT (1 << 1)
-#define RT2860_MRX0_INT (1 << 0)
+#define RT2860_MCU_MAC_INT_8 (1 << 24)
+#define RT2860_MCU_MAC_INT_7 (1 << 23)
+#define RT2860_MCU_MAC_INT_6 (1 << 22)
+#define RT2860_MCU_MAC_INT_4 (1 << 20)
+#define RT2860_MCU_MAC_INT_3 (1 << 19)
+#define RT2860_MCU_MAC_INT_2 (1 << 18)
+#define RT2860_MCU_MAC_INT_1 (1 << 17)
+#define RT2860_MCU_MAC_INT_0 (1 << 16)
+#define RT2860_DTX0_INT (1 << 11)
+#define RT2860_DTX1_INT (1 << 10)
+#define RT2860_DTX2_INT (1 << 9)
+#define RT2860_DRX0_INT (1 << 8)
+#define RT2860_HCMD_INT (1 << 7)
+#define RT2860_N0TX_INT (1 << 6)
+#define RT2860_N1TX_INT (1 << 5)
+#define RT2860_BCNTX_INT (1 << 4)
+#define RT2860_MTX0_INT (1 << 3)
+#define RT2860_MTX1_INT (1 << 2)
+#define RT2860_MTX2_INT (1 << 1)
+#define RT2860_MRX0_INT (1 << 0)
/* possible flags for register TXRXQ_PCNT */
-#define RT2860_RX0Q_PCNT_MASK 0xff000000
-#define RT2860_TX2Q_PCNT_MASK 0x00ff0000
-#define RT2860_TX1Q_PCNT_MASK 0x0000ff00
-#define RT2860_TX0Q_PCNT_MASK 0x000000ff
+#define RT2860_RX0Q_PCNT_MASK 0xff000000
+#define RT2860_TX2Q_PCNT_MASK 0x00ff0000
+#define RT2860_TX1Q_PCNT_MASK 0x0000ff00
+#define RT2860_TX0Q_PCNT_MASK 0x000000ff
/* possible flags for register CAP_CTRL */
-#define RT2860_CAP_ADC_FEQ (1 << 31)
-#define RT2860_CAP_START (1 << 30)
-#define RT2860_MAN_TRIG (1 << 29)
-#define RT2860_TRIG_OFFSET_SHIFT 16
-#define RT2860_START_ADDR_SHIFT 0
+#define RT2860_CAP_ADC_FEQ (1U << 31)
+#define RT2860_CAP_START (1 << 30)
+#define RT2860_MAN_TRIG (1 << 29)
+#define RT2860_TRIG_OFFSET_SHIFT 16
+#define RT2860_START_ADDR_SHIFT 0
/* possible flags for register RF_CSR_CFG */
-#define RT3070_RF_KICK (1 << 17)
-#define RT3070_RF_WRITE (1 << 16)
+#define RT3070_RF_KICK (1 << 17)
+#define RT3070_RF_WRITE (1 << 16)
/* possible flags for register EFUSE_CTRL */
-#define RT3070_SEL_EFUSE (1 << 31)
-#define RT3070_EFSROM_KICK (1 << 30)
-#define RT3070_EFSROM_AIN_MASK 0x03ff0000
-#define RT3070_EFSROM_AIN_SHIFT 16
-#define RT3070_EFSROM_MODE_MASK 0x000000c0
-#define RT3070_EFUSE_AOUT_MASK 0x0000003f
+#define RT3070_SEL_EFUSE (1U << 31)
+#define RT3070_EFSROM_KICK (1 << 30)
+#define RT3070_EFSROM_AIN_MASK 0x03ff0000
+#define RT3070_EFSROM_AIN_SHIFT 16
+#define RT3070_EFSROM_MODE_MASK 0x000000c0
+#define RT3070_EFUSE_AOUT_MASK 0x0000003f
+/* possible flag for register DEBUG_INDEX */
+#define RT5592_SEL_XTAL (1U << 31)
+
/* possible flags for register MAC_SYS_CTRL */
-#define RT2860_RX_TS_EN (1 << 7)
-#define RT2860_WLAN_HALT_EN (1 << 6)
-#define RT2860_PBF_LOOP_EN (1 << 5)
-#define RT2860_CONT_TX_TEST (1 << 4)
-#define RT2860_MAC_RX_EN (1 << 3)
-#define RT2860_MAC_TX_EN (1 << 2)
-#define RT2860_BBP_HRST (1 << 1)
-#define RT2860_MAC_SRST (1 << 0)
+#define RT2860_RX_TS_EN (1 << 7)
+#define RT2860_WLAN_HALT_EN (1 << 6)
+#define RT2860_PBF_LOOP_EN (1 << 5)
+#define RT2860_CONT_TX_TEST (1 << 4)
+#define RT2860_MAC_RX_EN (1 << 3)
+#define RT2860_MAC_TX_EN (1 << 2)
+#define RT2860_BBP_HRST (1 << 1)
+#define RT2860_MAC_SRST (1 << 0)
/* possible flags for register MAC_BSSID_DW1 */
-#define RT2860_MULTI_BCN_NUM_SHIFT 18
-#define RT2860_MULTI_BSSID_MODE_SHIFT 16
+#define RT2860_MULTI_BCN_NUM_SHIFT 18
+#define RT2860_MULTI_BSSID_MODE_SHIFT 16
/* possible flags for register MAX_LEN_CFG */
-#define RT2860_MIN_MPDU_LEN_SHIFT 16
-#define RT2860_MAX_PSDU_LEN_SHIFT 12
-#define RT2860_MAX_PSDU_LEN8K 0
-#define RT2860_MAX_PSDU_LEN16K 1
-#define RT2860_MAX_PSDU_LEN32K 2
-#define RT2860_MAX_PSDU_LEN64K 3
-#define RT2860_MAX_MPDU_LEN_SHIFT 0
+#define RT2860_MIN_MPDU_LEN_SHIFT 16
+#define RT2860_MAX_PSDU_LEN_SHIFT 12
+#define RT2860_MAX_PSDU_LEN8K 0
+#define RT2860_MAX_PSDU_LEN16K 1
+#define RT2860_MAX_PSDU_LEN32K 2
+#define RT2860_MAX_PSDU_LEN64K 3
+#define RT2860_MAX_MPDU_LEN_SHIFT 0
/* possible flags for registers BBP_CSR_CFG/H2M_BBPAGENT */
-#define RT2860_BBP_RW_PARALLEL (1 << 19)
-#define RT2860_BBP_PAR_DUR_112_5 (1 << 18)
-#define RT2860_BBP_CSR_KICK (1 << 17)
-#define RT2860_BBP_CSR_READ (1 << 16)
-#define RT2860_BBP_ADDR_SHIFT 8
-#define RT2860_BBP_DATA_SHIFT 0
+#define RT2860_BBP_RW_PARALLEL (1 << 19)
+#define RT2860_BBP_PAR_DUR_112_5 (1 << 18)
+#define RT2860_BBP_CSR_KICK (1 << 17)
+#define RT2860_BBP_CSR_READ (1 << 16)
+#define RT2860_BBP_ADDR_SHIFT 8
+#define RT2860_BBP_DATA_SHIFT 0
/* possible flags for register RF_CSR_CFG0 */
-#define RT2860_RF_REG_CTRL (1 << 31)
-#define RT2860_RF_LE_SEL1 (1 << 30)
-#define RT2860_RF_LE_STBY (1 << 29)
-#define RT2860_RF_REG_WIDTH_SHIFT 24
-#define RT2860_RF_REG_0_SHIFT 0
+#define RT2860_RF_REG_CTRL (1U << 31)
+#define RT2860_RF_LE_SEL1 (1 << 30)
+#define RT2860_RF_LE_STBY (1 << 29)
+#define RT2860_RF_REG_WIDTH_SHIFT 24
+#define RT2860_RF_REG_0_SHIFT 0
/* possible flags for register RF_CSR_CFG1 */
-#define RT2860_RF_DUR_5 (1 << 24)
-#define RT2860_RF_REG_1_SHIFT 0
+#define RT2860_RF_DUR_5 (1 << 24)
+#define RT2860_RF_REG_1_SHIFT 0
/* possible flags for register LED_CFG */
-#define RT2860_LED_POL (1 << 30)
-#define RT2860_Y_LED_MODE_SHIFT 28
-#define RT2860_G_LED_MODE_SHIFT 26
-#define RT2860_R_LED_MODE_SHIFT 24
-#define RT2860_LED_MODE_OFF 0
-#define RT2860_LED_MODE_BLINK_TX 1
-#define RT2860_LED_MODE_SLOW_BLINK 2
-#define RT2860_LED_MODE_ON 3
-#define RT2860_SLOW_BLK_TIME_SHIFT 16
-#define RT2860_LED_OFF_TIME_SHIFT 8
-#define RT2860_LED_ON_TIME_SHIFT 0
+#define RT2860_LED_POL (1 << 30)
+#define RT2860_Y_LED_MODE_SHIFT 28
+#define RT2860_G_LED_MODE_SHIFT 26
+#define RT2860_R_LED_MODE_SHIFT 24
+#define RT2860_LED_MODE_OFF 0
+#define RT2860_LED_MODE_BLINK_TX 1
+#define RT2860_LED_MODE_SLOW_BLINK 2
+#define RT2860_LED_MODE_ON 3
+#define RT2860_SLOW_BLK_TIME_SHIFT 16
+#define RT2860_LED_OFF_TIME_SHIFT 8
+#define RT2860_LED_ON_TIME_SHIFT 0
/* possible flags for register XIFS_TIME_CFG */
-#define RT2860_BB_RXEND_EN (1 << 29)
-#define RT2860_EIFS_TIME_SHIFT 20
-#define RT2860_OFDM_XIFS_TIME_SHIFT 16
-#define RT2860_OFDM_SIFS_TIME_SHIFT 8
-#define RT2860_CCK_SIFS_TIME_SHIFT 0
+#define RT2860_BB_RXEND_EN (1 << 29)
+#define RT2860_EIFS_TIME_SHIFT 20
+#define RT2860_OFDM_XIFS_TIME_SHIFT 16
+#define RT2860_OFDM_SIFS_TIME_SHIFT 8
+#define RT2860_CCK_SIFS_TIME_SHIFT 0
/* possible flags for register BKOFF_SLOT_CFG */
-#define RT2860_CC_DELAY_TIME_SHIFT 8
-#define RT2860_SLOT_TIME 0
+#define RT2860_CC_DELAY_TIME_SHIFT 8
+#define RT2860_SLOT_TIME 0
/* possible flags for register NAV_TIME_CFG */
-#define RT2860_NAV_UPD (1 << 31)
-#define RT2860_NAV_UPD_VAL_SHIFT 16
-#define RT2860_NAV_CLR_EN (1 << 15)
-#define RT2860_NAV_TIMER_SHIFT 0
+#define RT2860_NAV_UPD (1U << 31)
+#define RT2860_NAV_UPD_VAL_SHIFT 16
+#define RT2860_NAV_CLR_EN (1 << 15)
+#define RT2860_NAV_TIMER_SHIFT 0
/* possible flags for register CH_TIME_CFG */
-#define RT2860_EIFS_AS_CH_BUSY (1 << 4)
-#define RT2860_NAV_AS_CH_BUSY (1 << 3)
-#define RT2860_RX_AS_CH_BUSY (1 << 2)
-#define RT2860_TX_AS_CH_BUSY (1 << 1)
-#define RT2860_CH_STA_TIMER_EN (1 << 0)
+#define RT2860_EIFS_AS_CH_BUSY (1 << 4)
+#define RT2860_NAV_AS_CH_BUSY (1 << 3)
+#define RT2860_RX_AS_CH_BUSY (1 << 2)
+#define RT2860_TX_AS_CH_BUSY (1 << 1)
+#define RT2860_CH_STA_TIMER_EN (1 << 0)
/* possible values for register BCN_TIME_CFG */
-#define RT2860_TSF_INS_COMP_SHIFT 24
-#define RT2860_BCN_TX_EN (1 << 20)
-#define RT2860_TBTT_TIMER_EN (1 << 19)
-#define RT2860_TSF_SYNC_MODE_SHIFT 17
-#define RT2860_TSF_SYNC_MODE_DIS 0
-#define RT2860_TSF_SYNC_MODE_STA 1
-#define RT2860_TSF_SYNC_MODE_IBSS 2
-#define RT2860_TSF_SYNC_MODE_HOSTAP 3
-#define RT2860_TSF_TIMER_EN (1 << 16)
-#define RT2860_BCN_INTVAL_SHIFT 0
+#define RT2860_TSF_INS_COMP_SHIFT 24
+#define RT2860_BCN_TX_EN (1 << 20)
+#define RT2860_TBTT_TIMER_EN (1 << 19)
+#define RT2860_TSF_SYNC_MODE_SHIFT 17
+#define RT2860_TSF_SYNC_MODE_DIS 0
+#define RT2860_TSF_SYNC_MODE_STA 1
+#define RT2860_TSF_SYNC_MODE_IBSS 2
+#define RT2860_TSF_SYNC_MODE_HOSTAP 3
+#define RT2860_TSF_TIMER_EN (1 << 16)
+#define RT2860_BCN_INTVAL_SHIFT 0
/* possible flags for register TBTT_SYNC_CFG */
-#define RT2860_BCN_CWMIN_SHIFT 20
-#define RT2860_BCN_AIFSN_SHIFT 16
-#define RT2860_BCN_EXP_WIN_SHIFT 8
-#define RT2860_TBTT_ADJUST_SHIFT 0
+#define RT2860_BCN_CWMIN_SHIFT 20
+#define RT2860_BCN_AIFSN_SHIFT 16
+#define RT2860_BCN_EXP_WIN_SHIFT 8
+#define RT2860_TBTT_ADJUST_SHIFT 0
/* possible flags for register INT_TIMER_CFG */
-#define RT2860_GP_TIMER_SHIFT 16
-#define RT2860_PRE_TBTT_TIMER_SHIFT 0
+#define RT2860_GP_TIMER_SHIFT 16
+#define RT2860_PRE_TBTT_TIMER_SHIFT 0
/* possible flags for register INT_TIMER_EN */
-#define RT2860_GP_TIMER_EN (1 << 1)
-#define RT2860_PRE_TBTT_INT_EN (1 << 0)
+#define RT2860_GP_TIMER_EN (1 << 1)
+#define RT2860_PRE_TBTT_INT_EN (1 << 0)
/* possible flags for register MAC_STATUS_REG */
-#define RT2860_RX_STATUS_BUSY (1 << 1)
-#define RT2860_TX_STATUS_BUSY (1 << 0)
+#define RT2860_RX_STATUS_BUSY (1 << 1)
+#define RT2860_TX_STATUS_BUSY (1 << 0)
/* possible flags for register PWR_PIN_CFG */
-#define RT2860_IO_ADDA_PD (1 << 3)
-#define RT2860_IO_PLL_PD (1 << 2)
-#define RT2860_IO_RA_PE (1 << 1)
-#define RT2860_IO_RF_PE (1 << 0)
+#define RT2860_IO_ADDA_PD (1 << 3)
+#define RT2860_IO_PLL_PD (1 << 2)
+#define RT2860_IO_RA_PE (1 << 1)
+#define RT2860_IO_RF_PE (1 << 0)
/* possible flags for register AUTO_WAKEUP_CFG */
-#define RT2860_AUTO_WAKEUP_EN (1 << 15)
-#define RT2860_SLEEP_TBTT_NUM_SHIFT 8
-#define RT2860_WAKEUP_LEAD_TIME_SHIFT 0
+#define RT2860_AUTO_WAKEUP_EN (1 << 15)
+#define RT2860_SLEEP_TBTT_NUM_SHIFT 8
+#define RT2860_WAKEUP_LEAD_TIME_SHIFT 0
/* possible flags for register TX_PIN_CFG */
-#define RT2860_TRSW_POL (1 << 19)
-#define RT2860_TRSW_EN (1 << 18)
-#define RT2860_RFTR_POL (1 << 17)
-#define RT2860_RFTR_EN (1 << 16)
-#define RT2860_LNA_PE_G1_POL (1 << 15)
-#define RT2860_LNA_PE_A1_POL (1 << 14)
-#define RT2860_LNA_PE_G0_POL (1 << 13)
-#define RT2860_LNA_PE_A0_POL (1 << 12)
-#define RT2860_LNA_PE_G1_EN (1 << 11)
-#define RT2860_LNA_PE_A1_EN (1 << 10)
-#define RT2860_LNA_PE1_EN (RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN)
-#define RT2860_LNA_PE_G0_EN (1 << 9)
-#define RT2860_LNA_PE_A0_EN (1 << 8)
-#define RT2860_LNA_PE0_EN (RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN)
-#define RT2860_PA_PE_G1_POL (1 << 7)
-#define RT2860_PA_PE_A1_POL (1 << 6)
-#define RT2860_PA_PE_G0_POL (1 << 5)
-#define RT2860_PA_PE_A0_POL (1 << 4)
-#define RT2860_PA_PE_G1_EN (1 << 3)
-#define RT2860_PA_PE_A1_EN (1 << 2)
-#define RT2860_PA_PE_G0_EN (1 << 1)
-#define RT2860_PA_PE_A0_EN (1 << 0)
+#define RT2860_TRSW_POL (1 << 19)
+#define RT2860_TRSW_EN (1 << 18)
+#define RT2860_RFTR_POL (1 << 17)
+#define RT2860_RFTR_EN (1 << 16)
+#define RT2860_LNA_PE_G1_POL (1 << 15)
+#define RT2860_LNA_PE_A1_POL (1 << 14)
+#define RT2860_LNA_PE_G0_POL (1 << 13)
+#define RT2860_LNA_PE_A0_POL (1 << 12)
+#define RT2860_LNA_PE_G1_EN (1 << 11)
+#define RT2860_LNA_PE_A1_EN (1 << 10)
+#define RT2860_LNA_PE1_EN (RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN)
+#define RT2860_LNA_PE_G0_EN (1 << 9)
+#define RT2860_LNA_PE_A0_EN (1 << 8)
+#define RT2860_LNA_PE0_EN (RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN)
+#define RT2860_PA_PE_G1_POL (1 << 7)
+#define RT2860_PA_PE_A1_POL (1 << 6)
+#define RT2860_PA_PE_G0_POL (1 << 5)
+#define RT2860_PA_PE_A0_POL (1 << 4)
+#define RT2860_PA_PE_G1_EN (1 << 3)
+#define RT2860_PA_PE_A1_EN (1 << 2)
+#define RT2860_PA_PE_G0_EN (1 << 1)
+#define RT2860_PA_PE_A0_EN (1 << 0)
/* possible flags for register TX_BAND_CFG */
-#define RT2860_5G_BAND_SEL_N (1 << 2)
-#define RT2860_5G_BAND_SEL_P (1 << 1)
-#define RT2860_TX_BAND_SEL (1 << 0)
+#define RT2860_5G_BAND_SEL_N (1 << 2)
+#define RT2860_5G_BAND_SEL_P (1 << 1)
+#define RT2860_TX_BAND_SEL (1 << 0)
/* possible flags for register TX_SW_CFG0 */
-#define RT2860_DLY_RFTR_EN_SHIFT 24
-#define RT2860_DLY_TRSW_EN_SHIFT 16
-#define RT2860_DLY_PAPE_EN_SHIFT 8
-#define RT2860_DLY_TXPE_EN_SHIFT 0
+#define RT2860_DLY_RFTR_EN_SHIFT 24
+#define RT2860_DLY_TRSW_EN_SHIFT 16
+#define RT2860_DLY_PAPE_EN_SHIFT 8
+#define RT2860_DLY_TXPE_EN_SHIFT 0
/* possible flags for register TX_SW_CFG1 */
-#define RT2860_DLY_RFTR_DIS_SHIFT 16
-#define RT2860_DLY_TRSW_DIS_SHIFT 8
-#define RT2860_DLY_PAPE_DIS SHIFT 0
+#define RT2860_DLY_RFTR_DIS_SHIFT 16
+#define RT2860_DLY_TRSW_DIS_SHIFT 8
+#define RT2860_DLY_PAPE_DIS SHIFT 0
/* possible flags for register TX_SW_CFG2 */
-#define RT2860_DLY_LNA_EN_SHIFT 24
-#define RT2860_DLY_LNA_DIS_SHIFT 16
-#define RT2860_DLY_DAC_EN_SHIFT 8
-#define RT2860_DLY_DAC_DIS_SHIFT 0
+#define RT2860_DLY_LNA_EN_SHIFT 24
+#define RT2860_DLY_LNA_DIS_SHIFT 16
+#define RT2860_DLY_DAC_EN_SHIFT 8
+#define RT2860_DLY_DAC_DIS_SHIFT 0
/* possible flags for register TXOP_THRES_CFG */
-#define RT2860_TXOP_REM_THRES_SHIFT 24
-#define RT2860_CF_END_THRES_SHIFT 16
-#define RT2860_RDG_IN_THRES 8
-#define RT2860_RDG_OUT_THRES 0
+#define RT2860_TXOP_REM_THRES_SHIFT 24
+#define RT2860_CF_END_THRES_SHIFT 16
+#define RT2860_RDG_IN_THRES 8
+#define RT2860_RDG_OUT_THRES 0
/* possible flags for register TXOP_CTRL_CFG */
-#define RT2860_EXT_CW_MIN_SHIFT 16
-#define RT2860_EXT_CCA_DLY_SHIFT 8
-#define RT2860_EXT_CCA_EN (1 << 7)
-#define RT2860_LSIG_TXOP_EN (1 << 6)
-#define RT2860_TXOP_TRUN_EN_MIMOPS (1 << 4)
-#define RT2860_TXOP_TRUN_EN_TXOP (1 << 3)
-#define RT2860_TXOP_TRUN_EN_RATE (1 << 2)
-#define RT2860_TXOP_TRUN_EN_AC (1 << 1)
-#define RT2860_TXOP_TRUN_EN_TIMEOUT (1 << 0)
+#define RT2860_EXT_CW_MIN_SHIFT 16
+#define RT2860_EXT_CCA_DLY_SHIFT 8
+#define RT2860_EXT_CCA_EN (1 << 7)
+#define RT2860_LSIG_TXOP_EN (1 << 6)
+#define RT2860_TXOP_TRUN_EN_MIMOPS (1 << 4)
+#define RT2860_TXOP_TRUN_EN_TXOP (1 << 3)
+#define RT2860_TXOP_TRUN_EN_RATE (1 << 2)
+#define RT2860_TXOP_TRUN_EN_AC (1 << 1)
+#define RT2860_TXOP_TRUN_EN_TIMEOUT (1 << 0)
/* possible flags for register TX_RTS_CFG */
-#define RT2860_RTS_FBK_EN (1 << 24)
-#define RT2860_RTS_THRES_SHIFT 8
-#define RT2860_RTS_RTY_LIMIT_SHIFT 0
+#define RT2860_RTS_FBK_EN (1 << 24)
+#define RT2860_RTS_THRES_SHIFT 8
+#define RT2860_RTS_RTY_LIMIT_SHIFT 0
/* possible flags for register TX_TIMEOUT_CFG */
-#define RT2860_TXOP_TIMEOUT_SHIFT 16
-#define RT2860_RX_ACK_TIMEOUT_SHIFT 8
-#define RT2860_MPDU_LIFE_TIME_SHIFT 4
+#define RT2860_TXOP_TIMEOUT_SHIFT 16
+#define RT2860_RX_ACK_TIMEOUT_SHIFT 8
+#define RT2860_MPDU_LIFE_TIME_SHIFT 4
/* possible flags for register TX_RTY_CFG */
-#define RT2860_TX_AUTOFB_EN (1 << 30)
-#define RT2860_AGG_RTY_MODE_TIMER (1 << 29)
-#define RT2860_NAG_RTY_MODE_TIMER (1 << 28)
-#define RT2860_LONG_RTY_THRES_SHIFT 16
-#define RT2860_LONG_RTY_LIMIT_SHIFT 8
-#define RT2860_SHORT_RTY_LIMIT_SHIFT 0
+#define RT2860_TX_AUTOFB_EN (1 << 30)
+#define RT2860_AGG_RTY_MODE_TIMER (1 << 29)
+#define RT2860_NAG_RTY_MODE_TIMER (1 << 28)
+#define RT2860_LONG_RTY_THRES_SHIFT 16
+#define RT2860_LONG_RTY_LIMIT_SHIFT 8
+#define RT2860_SHORT_RTY_LIMIT_SHIFT 0
/* possible flags for register TX_LINK_CFG */
-#define RT2860_REMOTE_MFS_SHIFT 24
-#define RT2860_REMOTE_MFB_SHIFT 16
-#define RT2860_TX_CFACK_EN (1 << 12)
-#define RT2860_TX_RDG_EN (1 << 11)
-#define RT2860_TX_MRQ_EN (1 << 10)
-#define RT2860_REMOTE_UMFS_EN (1 << 9)
-#define RT2860_TX_MFB_EN (1 << 8)
-#define RT2860_REMOTE_MFB_LT_SHIFT 0
+#define RT2860_REMOTE_MFS_SHIFT 24
+#define RT2860_REMOTE_MFB_SHIFT 16
+#define RT2860_TX_CFACK_EN (1 << 12)
+#define RT2860_TX_RDG_EN (1 << 11)
+#define RT2860_TX_MRQ_EN (1 << 10)
+#define RT2860_REMOTE_UMFS_EN (1 << 9)
+#define RT2860_TX_MFB_EN (1 << 8)
+#define RT2860_REMOTE_MFB_LT_SHIFT 0
/* possible flags for registers *_PROT_CFG */
-#define RT2860_RTSTH_EN (1 << 26)
-#define RT2860_TXOP_ALLOW_GF40 (1 << 25)
-#define RT2860_TXOP_ALLOW_GF20 (1 << 24)
-#define RT2860_TXOP_ALLOW_MM40 (1 << 23)
-#define RT2860_TXOP_ALLOW_MM20 (1 << 22)
-#define RT2860_TXOP_ALLOW_OFDM (1 << 21)
-#define RT2860_TXOP_ALLOW_CCK (1 << 20)
-#define RT2860_TXOP_ALLOW_ALL (0x3f << 20)
-#define RT2860_PROT_NAV_SHORT (1 << 18)
-#define RT2860_PROT_NAV_LONG (2 << 18)
-#define RT2860_PROT_CTRL_RTS_CTS (1 << 16)
-#define RT2860_PROT_CTRL_CTS (2 << 16)
+#define RT2860_RTSTH_EN (1 << 26)
+#define RT2860_TXOP_ALLOW_GF40 (1 << 25)
+#define RT2860_TXOP_ALLOW_GF20 (1 << 24)
+#define RT2860_TXOP_ALLOW_MM40 (1 << 23)
+#define RT2860_TXOP_ALLOW_MM20 (1 << 22)
+#define RT2860_TXOP_ALLOW_OFDM (1 << 21)
+#define RT2860_TXOP_ALLOW_CCK (1 << 20)
+#define RT2860_TXOP_ALLOW_ALL (0x3f << 20)
+#define RT2860_PROT_NAV_SHORT (1 << 18)
+#define RT2860_PROT_NAV_LONG (2 << 18)
+#define RT2860_PROT_CTRL_RTS_CTS (1 << 16)
+#define RT2860_PROT_CTRL_CTS (2 << 16)
/* possible flags for registers EXP_{CTS,ACK}_TIME */
-#define RT2860_EXP_OFDM_TIME_SHIFT 16
-#define RT2860_EXP_CCK_TIME_SHIFT 0
+#define RT2860_EXP_OFDM_TIME_SHIFT 16
+#define RT2860_EXP_CCK_TIME_SHIFT 0
/* possible flags for register RX_FILTR_CFG */
-#define RT2860_DROP_CTRL_RSV (1 << 16)
-#define RT2860_DROP_BAR (1 << 15)
-#define RT2860_DROP_BA (1 << 14)
-#define RT2860_DROP_PSPOLL (1 << 13)
-#define RT2860_DROP_RTS (1 << 12)
-#define RT2860_DROP_CTS (1 << 11)
-#define RT2860_DROP_ACK (1 << 10)
-#define RT2860_DROP_CFEND (1 << 9)
-#define RT2860_DROP_CFACK (1 << 8)
-#define RT2860_DROP_DUPL (1 << 7)
-#define RT2860_DROP_BC (1 << 6)
-#define RT2860_DROP_MC (1 << 5)
-#define RT2860_DROP_VER_ERR (1 << 4)
-#define RT2860_DROP_NOT_MYBSS (1 << 3)
-#define RT2860_DROP_UC_NOME (1 << 2)
-#define RT2860_DROP_PHY_ERR (1 << 1)
-#define RT2860_DROP_CRC_ERR (1 << 0)
+#define RT2860_DROP_CTRL_RSV (1 << 16)
+#define RT2860_DROP_BAR (1 << 15)
+#define RT2860_DROP_BA (1 << 14)
+#define RT2860_DROP_PSPOLL (1 << 13)
+#define RT2860_DROP_RTS (1 << 12)
+#define RT2860_DROP_CTS (1 << 11)
+#define RT2860_DROP_ACK (1 << 10)
+#define RT2860_DROP_CFEND (1 << 9)
+#define RT2860_DROP_CFACK (1 << 8)
+#define RT2860_DROP_DUPL (1 << 7)
+#define RT2860_DROP_BC (1 << 6)
+#define RT2860_DROP_MC (1 << 5)
+#define RT2860_DROP_VER_ERR (1 << 4)
+#define RT2860_DROP_NOT_MYBSS (1 << 3)
+#define RT2860_DROP_UC_NOME (1 << 2)
+#define RT2860_DROP_PHY_ERR (1 << 1)
+#define RT2860_DROP_CRC_ERR (1 << 0)
/* possible flags for register AUTO_RSP_CFG */
-#define RT2860_CTRL_PWR_BIT (1 << 7)
-#define RT2860_BAC_ACK_POLICY (1 << 6)
-#define RT2860_CCK_SHORT_EN (1 << 4)
-#define RT2860_CTS_40M_REF_EN (1 << 3)
-#define RT2860_CTS_40M_MODE_EN (1 << 2)
-#define RT2860_BAC_ACKPOLICY_EN (1 << 1)
-#define RT2860_AUTO_RSP_EN (1 << 0)
+#define RT2860_CTRL_PWR_BIT (1 << 7)
+#define RT2860_BAC_ACK_POLICY (1 << 6)
+#define RT2860_CCK_SHORT_EN (1 << 4)
+#define RT2860_CTS_40M_REF_EN (1 << 3)
+#define RT2860_CTS_40M_MODE_EN (1 << 2)
+#define RT2860_BAC_ACKPOLICY_EN (1 << 1)
+#define RT2860_AUTO_RSP_EN (1 << 0)
/* possible flags for register SIFS_COST_CFG */
-#define RT2860_OFDM_SIFS_COST_SHIFT 8
-#define RT2860_CCK_SIFS_COST_SHIFT 0
+#define RT2860_OFDM_SIFS_COST_SHIFT 8
+#define RT2860_CCK_SIFS_COST_SHIFT 0
/* possible flags for register TXOP_HLDR_ET */
-#define RT2860_TXOP_ETM1_EN (1 << 25)
-#define RT2860_TXOP_ETM0_EN (1 << 24)
-#define RT2860_TXOP_ETM_THRES_SHIFT 16
-#define RT2860_TXOP_ETO_EN (1 << 8)
-#define RT2860_TXOP_ETO_THRES_SHIFT 1
-#define RT2860_PER_RX_RST_EN (1 << 0)
+#define RT2860_TXOP_ETM1_EN (1 << 25)
+#define RT2860_TXOP_ETM0_EN (1 << 24)
+#define RT2860_TXOP_ETM_THRES_SHIFT 16
+#define RT2860_TXOP_ETO_EN (1 << 8)
+#define RT2860_TXOP_ETO_THRES_SHIFT 1
+#define RT2860_PER_RX_RST_EN (1 << 0)
/* possible flags for register TX_STAT_FIFO */
-#define RT2860_TXQ_MCS_SHIFT 16
-#define RT2860_TXQ_WCID_SHIFT 8
-#define RT2860_TXQ_ACKREQ (1 << 7)
-#define RT2860_TXQ_AGG (1 << 6)
-#define RT2860_TXQ_OK (1 << 5)
-#define RT2860_TXQ_PID_SHIFT 1
-#define RT2860_TXQ_VLD (1 << 0)
+#define RT2860_TXQ_MCS_SHIFT 16
+#define RT2860_TXQ_WCID_SHIFT 8
+#define RT2860_TXQ_ACKREQ (1 << 7)
+#define RT2860_TXQ_AGG (1 << 6)
+#define RT2860_TXQ_OK (1 << 5)
+#define RT2860_TXQ_PID_SHIFT 1
+#define RT2860_TXQ_VLD (1 << 0)
/* possible flags for register WCID_ATTR */
-#define RT2860_MODE_NOSEC 0
-#define RT2860_MODE_WEP40 1
-#define RT2860_MODE_WEP104 2
-#define RT2860_MODE_TKIP 3
-#define RT2860_MODE_AES_CCMP 4
-#define RT2860_MODE_CKIP40 5
-#define RT2860_MODE_CKIP104 6
-#define RT2860_MODE_CKIP128 7
-#define RT2860_RX_PKEY_EN (1 << 0)
+#define RT2860_MODE_NOSEC 0
+#define RT2860_MODE_WEP40 1
+#define RT2860_MODE_WEP104 2
+#define RT2860_MODE_TKIP 3
+#define RT2860_MODE_AES_CCMP 4
+#define RT2860_MODE_CKIP40 5
+#define RT2860_MODE_CKIP104 6
+#define RT2860_MODE_CKIP128 7
+#define RT2860_RX_PKEY_EN (1 << 0)
/* possible flags for register H2M_MAILBOX */
-#define RT2860_H2M_BUSY (1 << 24)
-#define RT2860_TOKEN_NO_INTR 0xff
+#define RT2860_H2M_BUSY (1 << 24)
+#define RT2860_TOKEN_NO_INTR 0xff
-
/* possible flags for MCU command RT2860_MCU_CMD_LEDS */
-#define RT2860_LED_RADIO (1 << 13)
-#define RT2860_LED_LINK_2GHZ (1 << 14)
-#define RT2860_LED_LINK_5GHZ (1 << 15)
+#define RT2860_LED_RADIO (1 << 13)
+#define RT2860_LED_LINK_2GHZ (1 << 14)
+#define RT2860_LED_LINK_5GHZ (1 << 15)
-
/* possible flags for RT3020 RF register 1 */
-#define RT3070_RF_BLOCK (1 << 0)
-#define RT3070_RX0_PD (1 << 2)
-#define RT3070_TX0_PD (1 << 3)
-#define RT3070_RX1_PD (1 << 4)
-#define RT3070_TX1_PD (1 << 5)
+#define RT3070_RF_BLOCK (1 << 0)
+#define RT3070_PLL_PD (1 << 1)
+#define RT3070_RX0_PD (1 << 2)
+#define RT3070_TX0_PD (1 << 3)
+#define RT3070_RX1_PD (1 << 4)
+#define RT3070_TX1_PD (1 << 5)
+#define RT3070_RX2_PD (1 << 6)
+#define RT3070_TX2_PD (1 << 7)
/* possible flags for RT3020 RF register 15 */
-#define RT3070_TX_LO2 (1 << 3)
+#define RT3070_TX_LO2 (1 << 3)
/* possible flags for RT3020 RF register 17 */
-#define RT3070_TX_LO1 (1 << 3)
+#define RT3070_TX_LO1 (1 << 3)
/* possible flags for RT3020 RF register 20 */
-#define RT3070_RX_LO1 (1 << 3)
+#define RT3070_RX_LO1 (1 << 3)
/* possible flags for RT3020 RF register 21 */
-#define RT3070_RX_LO2 (1 << 3)
+#define RT3070_RX_LO2 (1 << 3)
+/* possible flags for RT3053 RF register 18 */
+#define RT3593_AUTOTUNE_BYPASS (1 << 6)
+/* possible flags for RT3053 RF register 50 */
+#define RT3593_TX_LO2 (1 << 4)
+
+/* possible flags for RT3053 RF register 51 */
+#define RT3593_TX_LO1 (1 << 4)
+
+/* Possible flags for RT5390 RF register 2. */
+#define RT5390_RESCAL (1 << 7)
+
+/* Possible flags for RT5390 RF register 3. */
+#define RT5390_VCOCAL (1 << 7)
+
+/* Possible flags for RT5390 RF register 38. */
+#define RT5390_RX_LO1 (1 << 5)
+
+/* Possible flags for RT5390 RF register 39. */
+#define RT5390_RX_LO2 (1 << 7)
+
+/* Possible flags for RT5390 BBP register 4. */
+#define RT5390_MAC_IF_CTRL (1 << 6)
+
+/* Possible flags for RT5390 BBP register 105. */
+#define RT5390_MLD (1 << 2)
+#define RT5390_EN_SIG_MODULATION (1 << 3)
+
/* RT2860 TX descriptor */
struct rt2860_txd {
uint32_t sdp0; /* Segment Data Pointer 0 */
uint16_t sdl1; /* Segment Data Length 1 */
-#define RT2860_TX_BURST (1 << 15)
-#define RT2860_TX_LS1 (1 << 14) /* SDP1 is the last segment */
+#define RT2860_TX_BURST (1 << 15)
+#define RT2860_TX_LS1 (1 << 14) /* SDP1 is the last segment */
uint16_t sdl0; /* Segment Data Length 0 */
-#define RT2860_TX_DDONE (1 << 15)
-#define RT2860_TX_LS0 (1 << 14) /* SDP0 is the last segment */
+#define RT2860_TX_DDONE (1 << 15)
+#define RT2860_TX_LS0 (1 << 14) /* SDP0 is the last segment */
uint32_t sdp1; /* Segment Data Pointer 1 */
uint8_t reserved[3];
uint8_t flags;
-#define RT2860_TX_QSEL_SHIFT 1
-#define RT2860_TX_QSEL_MGMT (0 << 1)
-#define RT2860_TX_QSEL_HCCA (1 << 1)
-#define RT2860_TX_QSEL_EDCA (2 << 1)
-#define RT2860_TX_WIV (1 << 0)
+#define RT2860_TX_QSEL_SHIFT 1
+#define RT2860_TX_QSEL_MGMT (0 << 1)
+#define RT2860_TX_QSEL_HCCA (1 << 1)
+#define RT2860_TX_QSEL_EDCA (2 << 1)
+#define RT2860_TX_WIV (1 << 0)
} __packed;
/* RT2870 TX descriptor */
@@ -737,38 +765,38 @@
/* TX Wireless Information */
struct rt2860_txwi {
uint8_t flags;
-#define RT2860_TX_MPDU_DSITY_SHIFT 5
-#define RT2860_TX_AMPDU (1 << 4)
-#define RT2860_TX_TS (1 << 3)
-#define RT2860_TX_CFACK (1 << 2)
-#define RT2860_TX_MMPS (1 << 1)
-#define RT2860_TX_FRAG (1 << 0)
+#define RT2860_TX_MPDU_DSITY_SHIFT 5
+#define RT2860_TX_AMPDU (1 << 4)
+#define RT2860_TX_TS (1 << 3)
+#define RT2860_TX_CFACK (1 << 2)
+#define RT2860_TX_MMPS (1 << 1)
+#define RT2860_TX_FRAG (1 << 0)
uint8_t txop;
-#define RT2860_TX_TXOP_HT 0
-#define RT2860_TX_TXOP_PIFS 1
-#define RT2860_TX_TXOP_SIFS 2
-#define RT2860_TX_TXOP_BACKOFF 3
+#define RT2860_TX_TXOP_HT 0
+#define RT2860_TX_TXOP_PIFS 1
+#define RT2860_TX_TXOP_SIFS 2
+#define RT2860_TX_TXOP_BACKOFF 3
uint16_t phy;
-#define RT2860_PHY_MODE 0xc000
-#define RT2860_PHY_CCK (0 << 14)
-#define RT2860_PHY_OFDM (1 << 14)
-#define RT2860_PHY_HT (2 << 14)
-#define RT2860_PHY_HT_GF (3 << 14)
-#define RT2860_PHY_SGI (1 << 8)
-#define RT2860_PHY_BW40 (1 << 7)
-#define RT2860_PHY_MCS 0x7f
-#define RT2860_PHY_SHPRE (1 << 3)
+#define RT2860_PHY_MODE 0xc000
+#define RT2860_PHY_CCK (0 << 14)
+#define RT2860_PHY_OFDM (1 << 14)
+#define RT2860_PHY_HT (2 << 14)
+#define RT2860_PHY_HT_GF (3 << 14)
+#define RT2860_PHY_SGI (1 << 8)
+#define RT2860_PHY_BW40 (1 << 7)
+#define RT2860_PHY_MCS 0x7f
+#define RT2860_PHY_SHPRE (1 << 3)
uint8_t xflags;
-#define RT2860_TX_BAWINSIZE_SHIFT 2
-#define RT2860_TX_NSEQ (1 << 1)
-#define RT2860_TX_ACK (1 << 0)
+#define RT2860_TX_BAWINSIZE_SHIFT 2
+#define RT2860_TX_NSEQ (1 << 1)
+#define RT2860_TX_ACK (1 << 0)
uint8_t wcid; /* Wireless Client ID */
uint16_t len;
-#define RT2860_TX_PID_SHIFT 12
+#define RT2860_TX_PID_SHIFT 12
uint32_t iv;
uint32_t eiv;
@@ -779,28 +807,28 @@
uint32_t sdp0;
uint16_t sdl1; /* unused */
uint16_t sdl0;
-#define RT2860_RX_DDONE (1 << 15)
-#define RT2860_RX_LS0 (1 << 14)
+#define RT2860_RX_DDONE (1 << 15)
+#define RT2860_RX_LS0 (1 << 14)
uint32_t sdp1; /* unused */
uint32_t flags;
-#define RT2860_RX_DEC (1 << 16)
-#define RT2860_RX_AMPDU (1 << 15)
-#define RT2860_RX_L2PAD (1 << 14)
-#define RT2860_RX_RSSI (1 << 13)
-#define RT2860_RX_HTC (1 << 12)
-#define RT2860_RX_AMSDU (1 << 11)
-#define RT2860_RX_MICERR (1 << 10)
-#define RT2860_RX_ICVERR (1 << 9)
-#define RT2860_RX_CRCERR (1 << 8)
-#define RT2860_RX_MYBSS (1 << 7)
-#define RT2860_RX_BC (1 << 6)
-#define RT2860_RX_MC (1 << 5)
-#define RT2860_RX_UC2ME (1 << 4)
-#define RT2860_RX_FRAG (1 << 3)
-#define RT2860_RX_NULL (1 << 2)
-#define RT2860_RX_DATA (1 << 1)
-#define RT2860_RX_BA (1 << 0)
+#define RT2860_RX_DEC (1 << 16)
+#define RT2860_RX_AMPDU (1 << 15)
+#define RT2860_RX_L2PAD (1 << 14)
+#define RT2860_RX_RSSI (1 << 13)
+#define RT2860_RX_HTC (1 << 12)
+#define RT2860_RX_AMSDU (1 << 11)
+#define RT2860_RX_MICERR (1 << 10)
+#define RT2860_RX_ICVERR (1 << 9)
+#define RT2860_RX_CRCERR (1 << 8)
+#define RT2860_RX_MYBSS (1 << 7)
+#define RT2860_RX_BC (1 << 6)
+#define RT2860_RX_MC (1 << 5)
+#define RT2860_RX_UC2ME (1 << 4)
+#define RT2860_RX_FRAG (1 << 3)
+#define RT2860_RX_NULL (1 << 2)
+#define RT2860_RX_DATA (1 << 1)
+#define RT2860_RX_BA (1 << 0)
} __packed;
/* RT2870 RX descriptor */
@@ -813,11 +841,11 @@
struct rt2860_rxwi {
uint8_t wcid;
uint8_t keyidx;
-#define RT2860_RX_UDF_SHIFT 5
-#define RT2860_RX_BSS_IDX_SHIFT 2
+#define RT2860_RX_UDF_SHIFT 5
+#define RT2860_RX_BSS_IDX_SHIFT 2
uint16_t len;
-#define RT2860_RX_TID_SHIFT 12
+#define RT2860_RX_TID_SHIFT 12
uint16_t seq;
uint16_t phy;
@@ -827,125 +855,112 @@
uint16_t reserved2;
} __packed;
+#define RT2860_RF_2820 0x0001 /* 2T3R */
+#define RT2860_RF_2850 0x0002 /* dual-band 2T3R */
+#define RT2860_RF_2720 0x0003 /* 1T2R */
+#define RT2860_RF_2750 0x0004 /* dual-band 1T2R */
+#define RT3070_RF_3020 0x0005 /* 1T1R */
+#define RT3070_RF_2020 0x0006 /* b/g */
+#define RT3070_RF_3021 0x0007 /* 1T2R */
+#define RT3070_RF_3022 0x0008 /* 2T2R */
+#define RT3070_RF_3052 0x0009 /* dual-band 2T2R */
+#define RT3593_RF_3053 0x000d /* dual-band 3T3R */
+#define RT5592_RF_5592 0x000f /* dual-band 2T2R */
+#define RT5390_RF_5370 0x5370 /* 1T1R */
+#define RT5390_RF_5372 0x5372 /* 2T2R */
-/* first DMA segment contains TXWI + 802.11 header + 32-bit padding */
-#define RT2860_TXWI_DMASZ \
- (sizeof (struct rt2860_txwi) + \
- sizeof (struct ieee80211_htframe) + \
- sizeof (uint16_t))
-
-#define RT2860_RF1 0
-#define RT2860_RF2 2
-#define RT2860_RF3 1
-#define RT2860_RF4 3
-
-#define RT2860_RF_2820 1 /* 2T3R */
-#define RT2860_RF_2850 2 /* dual-band 2T3R */
-#define RT2860_RF_2720 3 /* 1T2R */
-#define RT2860_RF_2750 4 /* dual-band 1T2R */
-#define RT3070_RF_3020 5 /* 1T1R */
-#define RT3070_RF_2020 6 /* b/g */
-#define RT3070_RF_3021 7 /* 1T2R */
-#define RT3070_RF_3022 8 /* 2T2R */
-#define RT3070_RF_3052 9 /* dual-band 2T2R */
-
/* USB commands for RT2870 only */
-#define RT2870_RESET 1
-#define RT2870_WRITE_2 2
-#define RT2870_WRITE_REGION_1 6
-#define RT2870_READ_REGION_1 7
-#define RT2870_EEPROM_READ 9
+#define RT2870_RESET 1
+#define RT2870_WRITE_2 2
+#define RT2870_WRITE_REGION_1 6
+#define RT2870_READ_REGION_1 7
+#define RT2870_EEPROM_READ 9
-#define RT2860_EEPROM_DELAY 1 /* minimum hold time (microsecond) */
+#define RT2860_EEPROM_DELAY 1 /* minimum hold time (microsecond) */
-#define RT2860_EEPROM_VERSION 0x01
-#define RT2860_EEPROM_MAC01 0x02
-#define RT2860_EEPROM_MAC23 0x03
-#define RT2860_EEPROM_MAC45 0x04
-#define RT2860_EEPROM_PCIE_PSLEVEL 0x11
-#define RT2860_EEPROM_REV 0x12
-#define RT2860_EEPROM_ANTENNA 0x1a
-#define RT2860_EEPROM_CONFIG 0x1b
-#define RT2860_EEPROM_COUNTRY 0x1c
-#define RT2860_EEPROM_FREQ_LEDS 0x1d
-#define RT2860_EEPROM_LED1 0x1e
-#define RT2860_EEPROM_LED2 0x1f
-#define RT2860_EEPROM_LED3 0x20
-#define RT2860_EEPROM_LNA 0x22
-#define RT2860_EEPROM_RSSI1_2GHZ 0x23
-#define RT2860_EEPROM_RSSI2_2GHZ 0x24
-#define RT2860_EEPROM_RSSI1_5GHZ 0x25
-#define RT2860_EEPROM_RSSI2_5GHZ 0x26
-#define RT2860_EEPROM_DELTAPWR 0x28
-#define RT2860_EEPROM_PWR2GHZ_BASE1 0x29
-#define RT2860_EEPROM_PWR2GHZ_BASE2 0x30
-#define RT2860_EEPROM_TSSI1_2GHZ 0x37
-#define RT2860_EEPROM_TSSI2_2GHZ 0x38
-#define RT2860_EEPROM_TSSI3_2GHZ 0x39
-#define RT2860_EEPROM_TSSI4_2GHZ 0x3a
-#define RT2860_EEPROM_TSSI5_2GHZ 0x3b
-#define RT2860_EEPROM_PWR5GHZ_BASE1 0x3c
-#define RT2860_EEPROM_PWR5GHZ_BASE2 0x53
-#define RT2860_EEPROM_TSSI1_5GHZ 0x6a
-#define RT2860_EEPROM_TSSI2_5GHZ 0x6b
-#define RT2860_EEPROM_TSSI3_5GHZ 0x6c
-#define RT2860_EEPROM_TSSI4_5GHZ 0x6d
-#define RT2860_EEPROM_TSSI5_5GHZ 0x6e
-#define RT2860_EEPROM_RPWR 0x6f
-#define RT2860_EEPROM_BBP_BASE 0x78
-#define RT3071_EEPROM_RF_BASE 0x82
+#define RT2860_EEPROM_VERSION 0x01
+#define RT2860_EEPROM_MAC01 0x02
+#define RT2860_EEPROM_MAC23 0x03
+#define RT2860_EEPROM_MAC45 0x04
+#define RT2860_EEPROM_PCIE_PSLEVEL 0x11
+#define RT2860_EEPROM_REV 0x12
+#define RT2860_EEPROM_ANTENNA 0x1a
+#define RT2860_EEPROM_CONFIG 0x1b
+#define RT2860_EEPROM_COUNTRY 0x1c
+#define RT2860_EEPROM_FREQ_LEDS 0x1d
+#define RT2860_EEPROM_LED1 0x1e
+#define RT2860_EEPROM_LED2 0x1f
+#define RT2860_EEPROM_LED3 0x20
+#define RT2860_EEPROM_LNA 0x22
+#define RT2860_EEPROM_RSSI1_2GHZ 0x23
+#define RT2860_EEPROM_RSSI2_2GHZ 0x24
+#define RT2860_EEPROM_RSSI1_5GHZ 0x25
+#define RT2860_EEPROM_RSSI2_5GHZ 0x26
+#define RT2860_EEPROM_DELTAPWR 0x28
+#define RT2860_EEPROM_PWR2GHZ_BASE1 0x29
+#define RT2860_EEPROM_PWR2GHZ_BASE2 0x30
+#define RT2860_EEPROM_TSSI1_2GHZ 0x37
+#define RT2860_EEPROM_TSSI2_2GHZ 0x38
+#define RT2860_EEPROM_TSSI3_2GHZ 0x39
+#define RT2860_EEPROM_TSSI4_2GHZ 0x3a
+#define RT2860_EEPROM_TSSI5_2GHZ 0x3b
+#define RT2860_EEPROM_PWR5GHZ_BASE1 0x3c
+#define RT2860_EEPROM_PWR5GHZ_BASE2 0x53
+#define RT2860_EEPROM_TSSI1_5GHZ 0x6a
+#define RT2860_EEPROM_TSSI2_5GHZ 0x6b
+#define RT2860_EEPROM_TSSI3_5GHZ 0x6c
+#define RT2860_EEPROM_TSSI4_5GHZ 0x6d
+#define RT2860_EEPROM_TSSI5_5GHZ 0x6e
+#define RT2860_EEPROM_RPWR 0x6f
+#define RT2860_EEPROM_BBP_BASE 0x78
+#define RT3071_EEPROM_RF_BASE 0x82
-#define RT2860_RIDX_CCK1 0
-#define RT2860_RIDX_CCK11 3
-#define RT2860_RIDX_OFDM6 4
-#define RT2860_RIDX_MAX 12
-static const struct rt2860_rate {
- uint8_t rate;
- uint8_t mcs;
- enum ieee80211_phytype phy;
- uint8_t ctl_ridx;
- uint16_t sp_ack_dur;
- uint16_t lp_ack_dur;
-} rt2860_rates[] = {
- { 2, 0, IEEE80211_T_DS, 0, 314, 314 },
- { 4, 1, IEEE80211_T_DS, 1, 258, 162 },
- { 11, 2, IEEE80211_T_DS, 2, 223, 127 },
- { 22, 3, IEEE80211_T_DS, 3, 213, 117 },
- { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 },
- { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 },
- { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 },
- { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 },
- { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 },
- { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 },
- { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 },
- { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 }
-};
+/* EEPROM registers for RT3593. */
+#define RT3593_EEPROM_FREQ_LEDS 0x21
+#define RT3593_EEPROM_FREQ 0x22
+#define RT3593_EEPROM_LED1 0x22
+#define RT3593_EEPROM_LED2 0x23
+#define RT3593_EEPROM_LED3 0x24
+#define RT3593_EEPROM_LNA 0x26
+#define RT3593_EEPROM_LNA_5GHZ 0x27
+#define RT3593_EEPROM_RSSI1_2GHZ 0x28
+#define RT3593_EEPROM_RSSI2_2GHZ 0x29
+#define RT3593_EEPROM_RSSI1_5GHZ 0x2a
+#define RT3593_EEPROM_RSSI2_5GHZ 0x2b
+#define RT3593_EEPROM_PWR2GHZ_BASE1 0x30
+#define RT3593_EEPROM_PWR2GHZ_BASE2 0x37
+#define RT3593_EEPROM_PWR2GHZ_BASE3 0x3e
+#define RT3593_EEPROM_PWR5GHZ_BASE1 0x4b
+#define RT3593_EEPROM_PWR5GHZ_BASE2 0x65
+#define RT3593_EEPROM_PWR5GHZ_BASE3 0x7f
/*
- * Control and status registers access macros.
+ * EEPROM IQ calibration.
*/
-#define RAL_READ(sc, reg) \
- bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ 0x130
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ 0x131
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ 0x133
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ 0x134
+#define RT5390_EEPROM_RF_IQ_COMPENSATION_CTL 0x13c
+#define RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL 0x13d
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ 0x144
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ 0x145
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ 0x146
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ 0x147
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ 0x148
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ 0x149
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ 0x14a
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ 0x14b
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ 0x14c
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ 0x14d
+#define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e
+#define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f
-#define RAL_WRITE(sc, reg, val) \
- bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+#define RT2860_RIDX_CCK1 0
+#define RT2860_RIDX_CCK11 3
+#define RT2860_RIDX_OFDM6 4
+#define RT2860_RIDX_MAX 12
-#define RAL_BARRIER_WRITE(sc) \
- bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \
- BUS_SPACE_BARRIER_WRITE)
-
-#define RAL_BARRIER_READ_WRITE(sc) \
- bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
-
-#define RAL_WRITE_REGION_1(sc, offset, datap, count) \
- bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset), \
- (datap), (count))
-
-#define RAL_SET_REGION_4(sc, offset, val, count) \
- bus_space_set_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \
- (val), (count))
-
/*
* EEPROM access macro.
*/
@@ -958,8 +973,9 @@
/*
* Default values for MAC registers; values taken from the reference driver.
*/
-#define RT2860_DEF_MAC \
+#define RT2870_DEF_MAC \
{ RT2860_BCN_OFFSET0, 0xf8f0e8e0 }, \
+ { RT2860_BCN_OFFSET1, 0x6f77d0c8 }, \
{ RT2860_LEGACY_BASIC_RATE, 0x0000013f }, \
{ RT2860_HT_BASIC_RATE, 0x00008003 }, \
{ RT2860_MAC_SYS_CTRL, 0x00000000 }, \
@@ -968,6 +984,7 @@
{ RT2860_TX_SW_CFG1, 0x00080606 }, \
{ RT2860_TX_LINK_CFG, 0x00001020 }, \
{ RT2860_TX_TIMEOUT_CFG, 0x000a2090 }, \
+ { RT2860_MAX_LEN_CFG, 0x00001f00 }, \
{ RT2860_LED_CFG, 0x7f031e46 }, \
{ RT2860_WMM_AIFSN_CFG, 0x00002273 }, \
{ RT2860_WMM_CWMIN_CFG, 0x00002344 }, \
@@ -977,37 +994,6 @@
{ RT2860_AUTO_RSP_CFG, 0x00000013 }, \
{ RT2860_CCK_PROT_CFG, 0x05740003 }, \
{ RT2860_OFDM_PROT_CFG, 0x05740003 }, \
- { RT2860_GF20_PROT_CFG, 0x01744004 }, \
- { RT2860_GF40_PROT_CFG, 0x03f44084 }, \
- { RT2860_MM20_PROT_CFG, 0x01744004 }, \
- { RT2860_MM40_PROT_CFG, 0x03f54084 }, \
- { RT2860_TXOP_CTRL_CFG, 0x0000583f }, \
- { RT2860_TXOP_HLDR_ET, 0x00000002 }, \
- { RT2860_TX_RTS_CFG, 0x00092b20 }, \
- { RT2860_EXP_ACK_TIME, 0x002400ca }, \
- { RT2860_XIFS_TIME_CFG, 0x33a41010 }, \
- { RT2860_PWR_PIN_CFG, 0x00000003 }
-
-/* XXX only a few registers differ from above, try to merge? */
-#define RT2870_DEF_MAC \
- { RT2860_BCN_OFFSET0, 0xf8f0e8e0 }, \
- { RT2860_LEGACY_BASIC_RATE, 0x0000013f }, \
- { RT2860_HT_BASIC_RATE, 0x00008003 }, \
- { RT2860_MAC_SYS_CTRL, 0x00000000 }, \
- { RT2860_BKOFF_SLOT_CFG, 0x00000209 }, \
- { RT2860_TX_SW_CFG0, 0x00000000 }, \
- { RT2860_TX_SW_CFG1, 0x00080606 }, \
- { RT2860_TX_LINK_CFG, 0x00001020 }, \
- { RT2860_TX_TIMEOUT_CFG, 0x000a2090 }, \
- { RT2860_LED_CFG, 0x7f031e46 }, \
- { RT2860_WMM_AIFSN_CFG, 0x00002273 }, \
- { RT2860_WMM_CWMIN_CFG, 0x00002344 }, \
- { RT2860_WMM_CWMAX_CFG, 0x000034aa }, \
- { RT2860_MAX_PCNT, 0x1f3fbf9f }, \
- { RT2860_TX_RTY_CFG, 0x47d01f0f }, \
- { RT2860_AUTO_RSP_CFG, 0x00000013 }, \
- { RT2860_CCK_PROT_CFG, 0x05740003 }, \
- { RT2860_OFDM_PROT_CFG, 0x05740003 }, \
{ RT2860_PBF_CFG, 0x00f40006 }, \
{ RT2860_WPDMA_GLO_CFG, 0x00000030 }, \
{ RT2860_GF20_PROT_CFG, 0x01744004 }, \
@@ -1024,9 +1010,10 @@
/*
* Default values for BBP registers; values taken from the reference driver.
*/
-#define RT2860_DEF_BBP \
+#define RT2860_DEF_BBP \
{ 65, 0x2c }, \
{ 66, 0x38 }, \
+ { 68, 0x0b }, \
{ 69, 0x12 }, \
{ 70, 0x0a }, \
{ 73, 0x10 }, \
@@ -1041,65 +1028,128 @@
{ 105, 0x05 }, \
{ 106, 0x35 }
+#define RT5390_DEF_BBP \
+ { 31, 0x08 }, \
+ { 65, 0x2c }, \
+ { 66, 0x38 }, \
+ { 68, 0x0b }, \
+ { 69, 0x0d }, \
+ { 70, 0x06 }, \
+ { 73, 0x13 }, \
+ { 75, 0x46 }, \
+ { 76, 0x28 }, \
+ { 77, 0x59 }, \
+ { 81, 0x37 }, \
+ { 82, 0x62 }, \
+ { 83, 0x7a }, \
+ { 84, 0x9a }, \
+ { 86, 0x38 }, \
+ { 91, 0x04 }, \
+ { 92, 0x02 }, \
+ { 103, 0xc0 }, \
+ { 104, 0x92 }, \
+ { 105, 0x3c }, \
+ { 106, 0x03 }, \
+ { 128, 0x12 }
+
+#define RT5592_DEF_BBP \
+ { 20, 0x06 }, \
+ { 31, 0x08 }, \
+ { 65, 0x2c }, \
+ { 66, 0x38 }, \
+ { 68, 0xdd }, \
+ { 69, 0x1a }, \
+ { 70, 0x05 }, \
+ { 73, 0x13 }, \
+ { 74, 0x0f }, \
+ { 75, 0x4f }, \
+ { 76, 0x28 }, \
+ { 77, 0x59 }, \
+ { 81, 0x37 }, \
+ { 82, 0x62 }, \
+ { 83, 0x6a }, \
+ { 84, 0x9a }, \
+ { 86, 0x38 }, \
+ { 88, 0x90 }, \
+ { 91, 0x04 }, \
+ { 92, 0x02 }, \
+ { 95, 0x9a }, \
+ { 98, 0x12 }, \
+ { 103, 0xc0 }, \
+ { 104, 0x92 }, \
+ { 105, 0x3c }, \
+ { 106, 0x35 }, \
+ { 128, 0x12 }, \
+ { 134, 0xd0 }, \
+ { 135, 0xf6 }, \
+ { 137, 0x0f }
+
/*
* Default settings for RF registers; values derived from the reference driver.
*/
-#define RT2860_RF2850 \
- { 1, 0x100bb3, 0x1301e1, 0x05a014, 0x001402 }, \
- { 2, 0x100bb3, 0x1301e1, 0x05a014, 0x001407 }, \
- { 3, 0x100bb3, 0x1301e2, 0x05a014, 0x001402 }, \
- { 4, 0x100bb3, 0x1301e2, 0x05a014, 0x001407 }, \
- { 5, 0x100bb3, 0x1301e3, 0x05a014, 0x001402 }, \
- { 6, 0x100bb3, 0x1301e3, 0x05a014, 0x001407 }, \
- { 7, 0x100bb3, 0x1301e4, 0x05a014, 0x001402 }, \
- { 8, 0x100bb3, 0x1301e4, 0x05a014, 0x001407 }, \
- { 9, 0x100bb3, 0x1301e5, 0x05a014, 0x001402 }, \
- { 10, 0x100bb3, 0x1301e5, 0x05a014, 0x001407 }, \
- { 11, 0x100bb3, 0x1301e6, 0x05a014, 0x001402 }, \
- { 12, 0x100bb3, 0x1301e6, 0x05a014, 0x001407 }, \
- { 13, 0x100bb3, 0x1301e7, 0x05a014, 0x001402 }, \
- { 14, 0x100bb3, 0x1301e8, 0x05a014, 0x001404 }, \
- { 36, 0x100bb3, 0x130266, 0x056014, 0x001408 }, \
- { 38, 0x100bb3, 0x130267, 0x056014, 0x001404 }, \
- { 40, 0x100bb2, 0x1301a0, 0x056014, 0x001400 }, \
- { 44, 0x100bb2, 0x1301a0, 0x056014, 0x001408 }, \
- { 46, 0x100bb2, 0x1301a1, 0x056014, 0x001402 }, \
- { 48, 0x100bb2, 0x1301a1, 0x056014, 0x001406 }, \
- { 52, 0x100bb2, 0x1301a2, 0x056014, 0x001404 }, \
- { 54, 0x100bb2, 0x1301a2, 0x056014, 0x001408 }, \
- { 56, 0x100bb2, 0x1301a3, 0x056014, 0x001402 }, \
- { 60, 0x100bb2, 0x1301a4, 0x056014, 0x001400 }, \
- { 62, 0x100bb2, 0x1301a4, 0x056014, 0x001404 }, \
- { 64, 0x100bb2, 0x1301a4, 0x056014, 0x001408 }, \
- { 100, 0x100bb2, 0x1301ac, 0x05e014, 0x001400 }, \
- { 102, 0x100bb2, 0x1701ac, 0x15e014, 0x001404 }, \
- { 104, 0x100bb2, 0x1701ac, 0x15e014, 0x001408 }, \
- { 108, 0x100bb3, 0x17028c, 0x15e014, 0x001404 }, \
- { 110, 0x100bb3, 0x13028d, 0x05e014, 0x001400 }, \
- { 112, 0x100bb3, 0x13028d, 0x05e014, 0x001406 }, \
- { 116, 0x100bb3, 0x13028e, 0x05e014, 0x001408 }, \
- { 118, 0x100bb3, 0x13028f, 0x05e014, 0x001404 }, \
- { 120, 0x100bb1, 0x1300e0, 0x05e014, 0x001400 }, \
- { 124, 0x100bb1, 0x1300e0, 0x05e014, 0x001404 }, \
- { 126, 0x100bb1, 0x1300e0, 0x05e014, 0x001406 }, \
- { 128, 0x100bb1, 0x1300e0, 0x05e014, 0x001408 }, \
- { 132, 0x100bb1, 0x1300e1, 0x05e014, 0x001402 }, \
- { 134, 0x100bb1, 0x1300e1, 0x05e014, 0x001404 }, \
- { 136, 0x100bb1, 0x1300e1, 0x05e014, 0x001406 }, \
- { 140, 0x100bb1, 0x1300e2, 0x05e014, 0x001400 }, \
- { 149, 0x100bb1, 0x1300e2, 0x05e014, 0x001409 }, \
- { 151, 0x100bb1, 0x1300e3, 0x05e014, 0x001401 }, \
- { 153, 0x100bb1, 0x1300e3, 0x05e014, 0x001403 }, \
- { 157, 0x100bb1, 0x1300e3, 0x05e014, 0x001407 }, \
- { 159, 0x100bb1, 0x1300e3, 0x05e014, 0x001409 }, \
- { 161, 0x100bb1, 0x1300e4, 0x05e014, 0x001401 }, \
- { 165, 0x100bb1, 0x1300e4, 0x05e014, 0x001405 }, \
- { 167, 0x100bb1, 0x1300f4, 0x05e014, 0x001407 }, \
- { 169, 0x100bb1, 0x1300f4, 0x05e014, 0x001409 }, \
- { 171, 0x100bb1, 0x1300f5, 0x05e014, 0x001401 }, \
- { 173, 0x100bb1, 0x1300f5, 0x05e014, 0x001403 }
+#define RT2860_RF2850 \
+ { 1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b }, \
+ { 2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f }, \
+ { 3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b }, \
+ { 4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f }, \
+ { 5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b }, \
+ { 6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f }, \
+ { 7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b }, \
+ { 8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f }, \
+ { 9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b }, \
+ { 10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f }, \
+ { 11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b }, \
+ { 12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f }, \
+ { 13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b }, \
+ { 14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193 }, \
+ { 36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3 }, \
+ { 38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193 }, \
+ { 40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183 }, \
+ { 44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3 }, \
+ { 46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b }, \
+ { 48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b }, \
+ { 52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193 }, \
+ { 54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3 }, \
+ { 56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b }, \
+ { 60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183 }, \
+ { 62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193 }, \
+ { 64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3 }, \
+ { 100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783 }, \
+ { 102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793 }, \
+ { 104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3 }, \
+ { 108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193 }, \
+ { 110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183 }, \
+ { 112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b }, \
+ { 116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3 }, \
+ { 118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193 }, \
+ { 120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183 }, \
+ { 124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193 }, \
+ { 126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b }, \
+ { 128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3 }, \
+ { 132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b }, \
+ { 134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193 }, \
+ { 136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b }, \
+ { 140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183 }, \
+ { 149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7 }, \
+ { 151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187 }, \
+ { 153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f }, \
+ { 157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f }, \
+ { 159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7 }, \
+ { 161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187 }, \
+ { 165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197 }, \
+ { 167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f }, \
+ { 169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327 }, \
+ { 171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307 }, \
+ { 173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f }, \
+ { 184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b }, \
+ { 188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13 }, \
+ { 192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b }, \
+ { 196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23 }, \
+ { 208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13 }, \
+ { 212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b }, \
+ { 216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23 }
-#define RT3070_RF3052 \
+#define RT3070_RF3052 \
{ 0xf1, 2, 2 }, \
{ 0xf1, 2, 7 }, \
{ 0xf2, 2, 2 }, \
@@ -1154,11 +1204,121 @@
{ 0x61, 0, 7 }, \
{ 0x61, 0, 9 }
-#define RT3070_DEF_RF \
+#define RT5592_RF5592_20MHZ \
+ { 0x1e2, 4, 10, 3 }, \
+ { 0x1e3, 4, 10, 3 }, \
+ { 0x1e4, 4, 10, 3 }, \
+ { 0x1e5, 4, 10, 3 }, \
+ { 0x1e6, 4, 10, 3 }, \
+ { 0x1e7, 4, 10, 3 }, \
+ { 0x1e8, 4, 10, 3 }, \
+ { 0x1e9, 4, 10, 3 }, \
+ { 0x1ea, 4, 10, 3 }, \
+ { 0x1eb, 4, 10, 3 }, \
+ { 0x1ec, 4, 10, 3 }, \
+ { 0x1ed, 4, 10, 3 }, \
+ { 0x1ee, 4, 10, 3 }, \
+ { 0x1f0, 8, 10, 3 }, \
+ { 0xac, 8, 12, 1 }, \
+ { 0xad, 0, 12, 1 }, \
+ { 0xad, 4, 12, 1 }, \
+ { 0xae, 0, 12, 1 }, \
+ { 0xae, 4, 12, 1 }, \
+ { 0xae, 8, 12, 1 }, \
+ { 0xaf, 4, 12, 1 }, \
+ { 0xaf, 8, 12, 1 }, \
+ { 0xb0, 0, 12, 1 }, \
+ { 0xb0, 8, 12, 1 }, \
+ { 0xb1, 0, 12, 1 }, \
+ { 0xb1, 4, 12, 1 }, \
+ { 0xb7, 4, 12, 1 }, \
+ { 0xb7, 8, 12, 1 }, \
+ { 0xb8, 0, 12, 1 }, \
+ { 0xb8, 8, 12, 1 }, \
+ { 0xb9, 0, 12, 1 }, \
+ { 0xb9, 4, 12, 1 }, \
+ { 0xba, 0, 12, 1 }, \
+ { 0xba, 4, 12, 1 }, \
+ { 0xba, 8, 12, 1 }, \
+ { 0xbb, 4, 12, 1 }, \
+ { 0xbb, 8, 12, 1 }, \
+ { 0xbc, 0, 12, 1 }, \
+ { 0xbc, 8, 12, 1 }, \
+ { 0xbd, 0, 12, 1 }, \
+ { 0xbd, 4, 12, 1 }, \
+ { 0xbe, 0, 12, 1 }, \
+ { 0xbf, 6, 12, 1 }, \
+ { 0xbf, 10, 12, 1 }, \
+ { 0xc0, 2, 12, 1 }, \
+ { 0xc0, 10, 12, 1 }, \
+ { 0xc1, 2, 12, 1 }, \
+ { 0xc1, 6, 12, 1 }, \
+ { 0xc2, 2, 12, 1 }, \
+ { 0xa4, 0, 12, 1 }, \
+ { 0xa4, 4, 12, 1 }, \
+ { 0xa5, 8, 12, 1 }, \
+ { 0xa6, 0, 12, 1 }
+
+#define RT5592_RF5592_40MHZ \
+ { 0xf1, 2, 10, 3 }, \
+ { 0xf1, 7, 10, 3 }, \
+ { 0xf2, 2, 10, 3 }, \
+ { 0xf2, 7, 10, 3 }, \
+ { 0xf3, 2, 10, 3 }, \
+ { 0xf3, 7, 10, 3 }, \
+ { 0xf4, 2, 10, 3 }, \
+ { 0xf4, 7, 10, 3 }, \
+ { 0xf5, 2, 10, 3 }, \
+ { 0xf5, 7, 10, 3 }, \
+ { 0xf6, 2, 10, 3 }, \
+ { 0xf6, 7, 10, 3 }, \
+ { 0xf7, 2, 10, 3 }, \
+ { 0xf8, 4, 10, 3 }, \
+ { 0x56, 4, 12, 1 }, \
+ { 0x56, 6, 12, 1 }, \
+ { 0x56, 8, 12, 1 }, \
+ { 0x57, 0, 12, 1 }, \
+ { 0x57, 2, 12, 1 }, \
+ { 0x57, 4, 12, 1 }, \
+ { 0x57, 8, 12, 1 }, \
+ { 0x57, 10, 12, 1 }, \
+ { 0x58, 0, 12, 1 }, \
+ { 0x58, 4, 12, 1 }, \
+ { 0x58, 6, 12, 1 }, \
+ { 0x58, 8, 12, 1 }, \
+ { 0x5b, 8, 12, 1 }, \
+ { 0x5b, 10, 12, 1 }, \
+ { 0x5c, 0, 12, 1 }, \
+ { 0x5c, 4, 12, 1 }, \
+ { 0x5c, 6, 12, 1 }, \
+ { 0x5c, 8, 12, 1 }, \
+ { 0x5d, 0, 12, 1 }, \
+ { 0x5d, 2, 12, 1 }, \
+ { 0x5d, 4, 12, 1 }, \
+ { 0x5d, 8, 12, 1 }, \
+ { 0x5d, 10, 12, 1 }, \
+ { 0x5e, 0, 12, 1 }, \
+ { 0x5e, 4, 12, 1 }, \
+ { 0x5e, 6, 12, 1 }, \
+ { 0x5e, 8, 12, 1 }, \
+ { 0x5f, 0, 12, 1 }, \
+ { 0x5f, 9, 12, 1 }, \
+ { 0x5f, 11, 12, 1 }, \
+ { 0x60, 1, 12, 1 }, \
+ { 0x60, 5, 12, 1 }, \
+ { 0x60, 7, 12, 1 }, \
+ { 0x60, 9, 12, 1 }, \
+ { 0x61, 1, 12, 1 }, \
+ { 0x52, 0, 12, 1 }, \
+ { 0x52, 4, 12, 1 }, \
+ { 0x52, 8, 12, 1 }, \
+ { 0x53, 0, 12, 1 }
+
+#define RT3070_DEF_RF \
{ 4, 0x40 }, \
{ 5, 0x03 }, \
{ 6, 0x02 }, \
- { 7, 0x70 }, \
+ { 7, 0x60 }, \
{ 9, 0x0f }, \
{ 10, 0x41 }, \
{ 11, 0x21 }, \
@@ -1172,10 +1332,10 @@
{ 20, 0xba }, \
{ 21, 0xdb }, \
{ 24, 0x16 }, \
- { 25, 0x01 }, \
+ { 25, 0x03 }, \
{ 29, 0x1f }
-#define RT3572_DEF_RF \
+#define RT3572_DEF_RF \
{ 0, 0x70 }, \
{ 1, 0x81 }, \
{ 2, 0xf1 }, \
@@ -1208,7 +1368,281 @@
{ 30, 0x09 }, \
{ 31, 0x10 }
+#define RT3593_DEF_RF \
+ { 1, 0x03 }, \
+ { 3, 0x80 }, \
+ { 5, 0x00 }, \
+ { 6, 0x40 }, \
+ { 8, 0xf1 }, \
+ { 9, 0x02 }, \
+ { 10, 0xd3 }, \
+ { 11, 0x40 }, \
+ { 12, 0x4e }, \
+ { 13, 0x12 }, \
+ { 18, 0x40 }, \
+ { 22, 0x20 }, \
+ { 30, 0x10 }, \
+ { 31, 0x80 }, \
+ { 32, 0x78 }, \
+ { 33, 0x3b }, \
+ { 34, 0x3c }, \
+ { 35, 0xe0 }, \
+ { 38, 0x86 }, \
+ { 39, 0x23 }, \
+ { 44, 0xd3 }, \
+ { 45, 0xbb }, \
+ { 46, 0x60 }, \
+ { 49, 0x81 }, \
+ { 50, 0x86 }, \
+ { 51, 0x75 }, \
+ { 52, 0x45 }, \
+ { 53, 0x18 }, \
+ { 54, 0x18 }, \
+ { 55, 0x18 }, \
+ { 56, 0xdb }, \
+ { 57, 0x6e }
+#define RT5390_DEF_RF \
+ { 1, 0x0f }, \
+ { 2, 0x80 }, \
+ { 3, 0x88 }, \
+ { 5, 0x10 }, \
+ { 6, 0xa0 }, \
+ { 7, 0x00 }, \
+ { 10, 0x53 }, \
+ { 11, 0x4a }, \
+ { 12, 0x46 }, \
+ { 13, 0x9f }, \
+ { 14, 0x00 }, \
+ { 15, 0x00 }, \
+ { 16, 0x00 }, \
+ { 18, 0x03 }, \
+ { 19, 0x00 }, \
+ { 20, 0x00 }, \
+ { 21, 0x00 }, \
+ { 22, 0x20 }, \
+ { 23, 0x00 }, \
+ { 24, 0x00 }, \
+ { 25, 0xc0 }, \
+ { 26, 0x00 }, \
+ { 27, 0x09 }, \
+ { 28, 0x00 }, \
+ { 29, 0x10 }, \
+ { 30, 0x10 }, \
+ { 31, 0x80 }, \
+ { 32, 0x80 }, \
+ { 33, 0x00 }, \
+ { 34, 0x07 }, \
+ { 35, 0x12 }, \
+ { 36, 0x00 }, \
+ { 37, 0x08 }, \
+ { 38, 0x85 }, \
+ { 39, 0x1b }, \
+ { 40, 0x0b }, \
+ { 41, 0xbb }, \
+ { 42, 0xd2 }, \
+ { 43, 0x9a }, \
+ { 44, 0x0e }, \
+ { 45, 0xa2 }, \
+ { 46, 0x7b }, \
+ { 47, 0x00 }, \
+ { 48, 0x10 }, \
+ { 49, 0x94 }, \
+ { 52, 0x38 }, \
+ { 53, 0x84 }, \
+ { 54, 0x78 }, \
+ { 55, 0x44 }, \
+ { 56, 0x22 }, \
+ { 57, 0x80 }, \
+ { 58, 0x7f }, \
+ { 59, 0x8f }, \
+ { 60, 0x45 }, \
+ { 61, 0xdd }, \
+ { 62, 0x00 }, \
+ { 63, 0x00 }
+
+#define RT5392_DEF_RF \
+ { 1, 0x17 }, \
+ { 3, 0x88 }, \
+ { 5, 0x10 }, \
+ { 6, 0xe0 }, \
+ { 7, 0x00 }, \
+ { 10, 0x53 }, \
+ { 11, 0x4a }, \
+ { 12, 0x46 }, \
+ { 13, 0x9f }, \
+ { 14, 0x00 }, \
+ { 15, 0x00 }, \
+ { 16, 0x00 }, \
+ { 18, 0x03 }, \
+ { 19, 0x4d }, \
+ { 20, 0x00 }, \
+ { 21, 0x8d }, \
+ { 22, 0x20 }, \
+ { 23, 0x0b }, \
+ { 24, 0x44 }, \
+ { 25, 0x80 }, \
+ { 26, 0x82 }, \
+ { 27, 0x09 }, \
+ { 28, 0x00 }, \
+ { 29, 0x10 }, \
+ { 30, 0x10 }, \
+ { 31, 0x80 }, \
+ { 32, 0x20 }, \
+ { 33, 0xc0 }, \
+ { 34, 0x07 }, \
+ { 35, 0x12 }, \
+ { 36, 0x00 }, \
+ { 37, 0x08 }, \
+ { 38, 0x89 }, \
+ { 39, 0x1b }, \
+ { 40, 0x0f }, \
+ { 41, 0xbb }, \
+ { 42, 0xd5 }, \
+ { 43, 0x9b }, \
+ { 44, 0x0e }, \
+ { 45, 0xa2 }, \
+ { 46, 0x73 }, \
+ { 47, 0x0c }, \
+ { 48, 0x10 }, \
+ { 49, 0x94 }, \
+ { 50, 0x94 }, \
+ { 51, 0x3a }, \
+ { 52, 0x48 }, \
+ { 53, 0x44 }, \
+ { 54, 0x38 }, \
+ { 55, 0x43 }, \
+ { 56, 0xa1 }, \
+ { 57, 0x00 }, \
+ { 58, 0x39 }, \
+ { 59, 0x07 }, \
+ { 60, 0x45 }, \
+ { 61, 0x91 }, \
+ { 62, 0x39 }, \
+ { 63, 0x07 }
+
+#define RT5592_DEF_RF \
+ { 1, 0x3f }, \
+ { 3, 0x08 }, \
+ { 5, 0x10 }, \
+ { 6, 0xe4 }, \
+ { 7, 0x00 }, \
+ { 14, 0x00 }, \
+ { 15, 0x00 }, \
+ { 16, 0x00 }, \
+ { 18, 0x03 }, \
+ { 19, 0x4d }, \
+ { 20, 0x10 }, \
+ { 21, 0x8d }, \
+ { 26, 0x82 }, \
+ { 28, 0x00 }, \
+ { 29, 0x10 }, \
+ { 33, 0xc0 }, \
+ { 34, 0x07 }, \
+ { 35, 0x12 }, \
+ { 47, 0x0c }, \
+ { 53, 0x22 }, \
+ { 63, 0x07 }
+
+#define RT5592_2GHZ_DEF_RF \
+ { 10, 0x90 }, \
+ { 11, 0x4a }, \
+ { 12, 0x52 }, \
+ { 13, 0x42 }, \
+ { 22, 0x40 }, \
+ { 24, 0x4a }, \
+ { 25, 0x80 }, \
+ { 27, 0x42 }, \
+ { 36, 0x80 }, \
+ { 37, 0x08 }, \
+ { 38, 0x89 }, \
+ { 39, 0x1b }, \
+ { 40, 0x0d }, \
+ { 41, 0x9b }, \
+ { 42, 0xd5 }, \
+ { 43, 0x72 }, \
+ { 44, 0x0e }, \
+ { 45, 0xa2 }, \
+ { 46, 0x6b }, \
+ { 48, 0x10 }, \
+ { 51, 0x3e }, \
+ { 52, 0x48 }, \
+ { 54, 0x38 }, \
+ { 56, 0xa1 }, \
+ { 57, 0x00 }, \
+ { 58, 0x39 }, \
+ { 60, 0x45 }, \
+ { 61, 0x91 }, \
+ { 62, 0x39 }
+
+#define RT5592_5GHZ_DEF_RF \
+ { 10, 0x97 }, \
+ { 11, 0x40 }, \
+ { 25, 0xbf }, \
+ { 27, 0x42 }, \
+ { 36, 0x00 }, \
+ { 37, 0x04 }, \
+ { 38, 0x85 }, \
+ { 40, 0x42 }, \
+ { 41, 0xbb }, \
+ { 42, 0xd7 }, \
+ { 45, 0x41 }, \
+ { 48, 0x00 }, \
+ { 57, 0x77 }, \
+ { 60, 0x05 }, \
+ { 61, 0x01 }
+
+#define RT5592_CHAN_5GHZ \
+ { 36, 64, 12, 0x2e }, \
+ { 100, 165, 12, 0x0e }, \
+ { 36, 64, 13, 0x22 }, \
+ { 100, 165, 13, 0x42 }, \
+ { 36, 64, 22, 0x60 }, \
+ { 100, 165, 22, 0x40 }, \
+ { 36, 64, 23, 0x7f }, \
+ { 100, 153, 23, 0x3c }, \
+ { 155, 165, 23, 0x38 }, \
+ { 36, 50, 24, 0x09 }, \
+ { 52, 64, 24, 0x07 }, \
+ { 100, 153, 24, 0x06 }, \
+ { 155, 165, 24, 0x05 }, \
+ { 36, 64, 39, 0x1c }, \
+ { 100, 138, 39, 0x1a }, \
+ { 140, 165, 39, 0x18 }, \
+ { 36, 64, 43, 0x5b }, \
+ { 100, 138, 43, 0x3b }, \
+ { 140, 165, 43, 0x1b }, \
+ { 36, 64, 44, 0x40 }, \
+ { 100, 138, 44, 0x20 }, \
+ { 140, 165, 44, 0x10 }, \
+ { 36, 64, 46, 0x00 }, \
+ { 100, 138, 46, 0x18 }, \
+ { 140, 165, 46, 0x08 }, \
+ { 36, 64, 51, 0xfe }, \
+ { 100, 124, 51, 0xfc }, \
+ { 126, 165, 51, 0xec }, \
+ { 36, 64, 52, 0x0c }, \
+ { 100, 138, 52, 0x06 }, \
+ { 140, 165, 52, 0x06 }, \
+ { 36, 64, 54, 0xf8 }, \
+ { 100, 165, 54, 0xeb }, \
+ { 36, 50, 55, 0x06 }, \
+ { 52, 64, 55, 0x04 }, \
+ { 100, 138, 55, 0x01 }, \
+ { 140, 165, 55, 0x00 }, \
+ { 36, 50, 56, 0xd3 }, \
+ { 52, 128, 56, 0xbb }, \
+ { 130, 165, 56, 0xab }, \
+ { 36, 64, 58, 0x15 }, \
+ { 100, 116, 58, 0x1d }, \
+ { 118, 165, 58, 0x15 }, \
+ { 36, 64, 59, 0x7f }, \
+ { 100, 138, 59, 0x3f }, \
+ { 140, 165, 59, 0x7c }, \
+ { 36, 64, 62, 0x15 }, \
+ { 100, 116, 62, 0x1d }, \
+ { 118, 165, 62, 0x15 }
+
union run_stats {
uint32_t raw;
struct {
Modified: stable/0.8/sys/dev/usb/wlan/if_runvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_runvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_runvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -17,37 +17,31 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/wlan/if_runvar.h 262605 2014-02-28 16:11:43Z kevlo $
*/
#ifndef _IF_RUNVAR_H_
#define _IF_RUNVAR_H_
-#define RUN_MAX_RXSZ \
+#define RUN_MAX_RXSZ \
MIN(4096, MJUMPAGESIZE)
-#if 0
- (sizeof (uint32_t) + \
- sizeof (struct rt2860_rxwi) + \
- sizeof (uint16_t) + \
- MCLBYTES + \
- sizeof (struct rt2870_rxd))
-#endif
+
/* NB: "11" is the maximum number of padding bytes needed for Tx */
-#define RUN_MAX_TXSZ \
+#define RUN_MAX_TXSZ \
(sizeof (struct rt2870_txd) + \
- sizeof (struct rt2860_rxwi) + \
+ sizeof (struct rt2860_txwi) + \
MCLBYTES + 11)
-#define RUN_TX_TIMEOUT 5000 /* ms */
+#define RUN_TX_TIMEOUT 5000 /* ms */
/* Tx ring count was 8/endpoint, now 32 for all 4 (or 6) endpoints. */
-#define RUN_TX_RING_COUNT 32
-#define RUN_RX_RING_COUNT 1
+#define RUN_TX_RING_COUNT 32
+#define RUN_RX_RING_COUNT 1
-#define RT2870_WCID_MAX 64
-#define RUN_AID2WCID(aid) ((aid) & 0xff)
+#define RT2870_WCID_MAX 64
+#define RUN_AID2WCID(aid) ((aid) & 0xff)
-#define RUN_VAP_MAX 8
+#define RUN_VAP_MAX 8
struct run_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
@@ -58,9 +52,9 @@
int8_t wr_dbm_antsignal;
uint8_t wr_antenna;
uint8_t wr_antsignal;
-} __packed;
+} __packed __aligned(8);
-#define RUN_RX_RADIOTAP_PRESENT \
+#define RUN_RX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
1 << IEEE80211_RADIOTAP_RATE | \
1 << IEEE80211_RADIOTAP_CHANNEL | \
@@ -75,11 +69,11 @@
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_hwqueue;
-} __packed;
+} __packed __aligned(8);
#define IEEE80211_RADIOTAP_HWQUEUE 15
-#define RUN_TX_RADIOTAP_PRESENT \
+#define RUN_TX_RADIOTAP_PRESENT \
(1 << IEEE80211_RADIOTAP_FLAGS | \
1 << IEEE80211_RADIOTAP_RATE | \
1 << IEEE80211_RADIOTAP_CHANNEL | \
@@ -128,7 +122,7 @@
uint8_t rvp_id;
};
-#define RUN_VAP(vap) ((struct run_vap *)(vap))
+#define RUN_VAP(vap) ((struct run_vap *)(vap))
/*
* There are 7 bulk endpoints: 1 for RX
@@ -160,6 +154,11 @@
device_t sc_dev;
struct usb_device *sc_udev;
struct ifnet *sc_ifp;
+ int sc_need_fwload;
+
+ int sc_flags;
+#define RUN_FLAG_FWLOAD_NEEDED 0x01
+
uint16_t wcid_stats[RT2870_WCID_MAX + 1][3];
#define RUN_TXCNT 0
#define RUN_SUCCESS 1
@@ -170,7 +169,7 @@
uint16_t mac_ver;
uint16_t mac_rev;
- uint8_t rf_rev;
+ uint16_t rf_rev;
uint8_t freq;
uint8_t ntxchains;
uint8_t nrxchains;
@@ -189,6 +188,7 @@
uint8_t txmixgain_5ghz;
int8_t txpow1[54];
int8_t txpow2[54];
+ int8_t txpow3[54];
int8_t rssi_2ghz[3];
int8_t rssi_5ghz[3];
uint8_t lna[4];
@@ -212,11 +212,11 @@
struct task ratectl_task;
struct usb_callout ratectl_ch;
uint8_t ratectl_run;
-#define RUN_RATECTL_OFF 0
+#define RUN_RATECTL_OFF 0
/* need to be power of 2, otherwise RUN_CMDQ_GET fails */
-#define RUN_CMDQ_MAX 16
-#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1)
+#define RUN_CMDQ_MAX 16
+#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1)
struct run_cmdq cmdq[RUN_CMDQ_MAX];
struct task cmdq_task;
uint32_t cmdq_store;
@@ -223,8 +223,8 @@
uint8_t cmdq_exec;
uint8_t cmdq_run;
uint8_t cmdq_key_set;
-#define RUN_CMDQ_ABORT 0
-#define RUN_CMDQ_GO 1
+#define RUN_CMDQ_ABORT 0
+#define RUN_CMDQ_GO 1
struct usb_xfer *sc_xfer[RUN_N_XFER];
@@ -239,6 +239,7 @@
uint8_t sta_running;
uint8_t rvp_cnt;
uint8_t rvp_bmap;
+ uint8_t sc_detached;
union {
struct run_rx_radiotap_header th;
@@ -255,8 +256,8 @@
int sc_txtap_len;
};
-#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
-#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
-#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t)
+#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t)
#endif /* _IF_RUNVAR_H_ */
Modified: stable/0.8/sys/dev/usb/wlan/if_uath.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uath.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uath.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_uath.c 259457 2013-12-16 09:07:09Z hselasky $");
/*-
* Driver for Atheros AR5523 USB parts.
@@ -217,9 +217,8 @@
.type = UE_BULK,
.endpoint = 0x1,
.direction = UE_DIR_OUT,
- .bufsize = UATH_MAX_CMDSZ,
+ .bufsize = UATH_MAX_CMDSZ * UATH_CMD_LIST_COUNT,
.flags = {
- .ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@@ -242,9 +241,8 @@
.type = UE_BULK,
.endpoint = 0x2,
.direction = UE_DIR_OUT,
- .bufsize = UATH_MAX_TXBUFSZ,
+ .bufsize = UATH_MAX_TXBUFSZ * UATH_TX_DATA_LIST_COUNT,
.flags = {
- .ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1
},
@@ -258,10 +256,8 @@
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void uath_vap_delete(struct ieee80211vap *);
-static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
- int, int);
-static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
- int);
+static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd []);
+static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd []);
static int uath_host_available(struct uath_softc *);
static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
static int uath_get_devcap(struct uath_softc *);
@@ -362,22 +358,26 @@
callout_init(&sc->stat_ch, 0);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+ error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+ uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "could not allocate USB transfers, "
+ "err=%s\n", usbd_errstr(error));
+ goto fail;
+ }
+
+ sc->sc_cmd_dma_buf =
+ usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_INTR_TX], 0);
+ sc->sc_tx_dma_buf =
+ usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0);
+
/*
- * Allocate xfers for firmware commands.
+ * Setup buffers for firmware commands.
*/
- error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
- UATH_MAX_CMDSZ);
+ error = uath_alloc_cmd_list(sc, sc->sc_cmd);
if (error != 0) {
device_printf(sc->sc_dev,
"could not allocate Tx command list\n");
- goto fail;
- }
-
- error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
- uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
- if (error) {
- device_printf(dev, "could not allocate USB transfers, "
- "err=%s\n", usbd_errstr(error));
goto fail1;
}
@@ -492,8 +492,8 @@
fail4: if_free(ifp);
fail3: UATH_UNLOCK(sc);
-fail2: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
-fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+fail2: uath_free_cmd_list(sc, sc->sc_cmd);
+fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail:
return (error);
}
@@ -504,29 +504,48 @@
struct uath_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ unsigned int x;
- if (!device_is_attached(dev))
- return (0);
-
+ /*
+ * Prevent further allocations from RX/TX/CMD
+ * data lists and ioctls
+ */
UATH_LOCK(sc);
sc->sc_flags |= UATH_FLAG_INVALID;
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ STAILQ_INIT(&sc->sc_cmd_active);
+ STAILQ_INIT(&sc->sc_cmd_pending);
+ STAILQ_INIT(&sc->sc_cmd_waiting);
+ STAILQ_INIT(&sc->sc_cmd_inactive);
UATH_UNLOCK(sc);
- ieee80211_ifdetach(ic);
uath_stop(ifp);
callout_drain(&sc->stat_ch);
callout_drain(&sc->watchdog_ch);
- usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+ /* drain USB transfers */
+ for (x = 0; x != UATH_N_XFERS; x++)
+ usbd_transfer_drain(sc->sc_xfer[x]);
- /* free buffers */
+ /* free data buffers */
UATH_LOCK(sc);
uath_free_rx_data_list(sc);
uath_free_tx_data_list(sc);
- uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+ uath_free_cmd_list(sc, sc->sc_cmd);
UATH_UNLOCK(sc);
+ /* free USB transfers and some data buffers */
+ usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+
+ ieee80211_ifdetach(ic);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -533,20 +552,18 @@
}
static void
-uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
+uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
{
int i;
- for (i = 0; i < ncmd; i++)
- if (cmds[i].buf != NULL)
- free(cmds[i].buf, M_USBDEV);
+ for (i = 0; i != UATH_CMD_LIST_COUNT; i++)
+ cmds[i].buf = NULL;
}
static int
-uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
- int ncmd, int maxsz)
+uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
{
- int i, error;
+ int i;
STAILQ_INIT(&sc->sc_cmd_active);
STAILQ_INIT(&sc->sc_cmd_pending);
@@ -553,25 +570,17 @@
STAILQ_INIT(&sc->sc_cmd_waiting);
STAILQ_INIT(&sc->sc_cmd_inactive);
- for (i = 0; i < ncmd; i++) {
+ for (i = 0; i != UATH_CMD_LIST_COUNT; i++) {
struct uath_cmd *cmd = &cmds[i];
cmd->sc = sc; /* backpointer for callbacks */
cmd->msgid = i;
- cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
- if (cmd->buf == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate xfer buffer\n");
- error = ENOMEM;
- goto fail;
- }
+ cmd->buf = ((uint8_t *)sc->sc_cmd_dma_buf) +
+ (i * UATH_MAX_CMDSZ);
STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
UATH_STAT_INC(sc, st_cmd_inactive);
}
return (0);
-
-fail: uath_free_cmd_list(sc, cmds, ncmd);
- return (error);
}
static int
@@ -942,21 +951,18 @@
dp->buf = NULL;
}
} else {
- if (dp->buf != NULL) {
- free(dp->buf, M_USBDEV);
- dp->buf = NULL;
- }
+ dp->buf = NULL;
}
-#ifdef UATH_DEBUG
- if (dp->ni != NULL)
- device_printf(sc->sc_dev, "Node isn't NULL\n");
-#endif
+ if (dp->ni != NULL) {
+ ieee80211_free_node(dp->ni);
+ dp->ni = NULL;
+ }
}
}
static int
uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
- int ndata, int maxsz, int fillmbuf)
+ int ndata, int maxsz, void *dma_buf)
{
int i, error;
@@ -964,7 +970,7 @@
struct uath_data *dp = &data[i];
dp->sc = sc;
- if (fillmbuf) {
+ if (dma_buf == NULL) {
/* XXX check maxsz */
dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (dp->m == NULL) {
@@ -976,13 +982,7 @@
dp->buf = mtod(dp->m, uint8_t *);
} else {
dp->m = NULL;
- dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
- if (dp->buf == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate buffer\n");
- error = ENOMEM;
- goto fail;
- }
+ dp->buf = ((uint8_t *)dma_buf) + (i * maxsz);
}
dp->ni = NULL;
}
@@ -989,7 +989,7 @@
return (0);
-fail: uath_free_data_list(sc, data, ndata, fillmbuf);
+fail: uath_free_data_list(sc, data, ndata, 1 /* free mbufs */);
return (error);
}
@@ -1001,7 +1001,7 @@
/* XXX is it enough to store the RX packet with MCLBYTES bytes? */
error = uath_alloc_data_list(sc,
sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
- 1 /* setup mbufs */);
+ NULL /* setup mbufs */);
if (error != 0)
return (error);
@@ -1024,7 +1024,7 @@
error = uath_alloc_data_list(sc,
sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
- 0 /* no mbufs */);
+ sc->sc_tx_dma_buf);
if (error != 0)
return (error);
@@ -1044,10 +1044,6 @@
static void
uath_free_rx_data_list(struct uath_softc *sc)
{
-
- STAILQ_INIT(&sc->sc_rx_active);
- STAILQ_INIT(&sc->sc_rx_inactive);
-
uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
1 /* free mbufs */);
}
@@ -1055,11 +1051,6 @@
static void
uath_free_tx_data_list(struct uath_softc *sc)
{
-
- STAILQ_INIT(&sc->sc_tx_active);
- STAILQ_INIT(&sc->sc_tx_inactive);
- STAILQ_INIT(&sc->sc_tx_pending);
-
uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
0 /* no mbufs */);
}
@@ -1081,9 +1072,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(uvp, M_80211_VAP);
+ return (NULL);
+ }
+
/* override state transition machine */
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = uath_newstate;
@@ -1562,8 +1558,16 @@
{
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct uath_softc *sc = ifp->if_softc;
+ int error;
+ int startall = 0;
+ UATH_LOCK(sc);
+ error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
+ UATH_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
@@ -2741,8 +2745,7 @@
UATH_STAT_DEC(sc, st_rx_inactive);
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
UATH_STAT_INC(sc, st_rx_active);
- usbd_xfer_set_frame_data(xfer, 0, data->buf,
- usbd_xfer_max_len(xfer));
+ usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
usbd_transfer_submit(xfer);
/*
@@ -2890,7 +2893,7 @@
DEVMETHOD(device_probe, uath_match),
DEVMETHOD(device_attach, uath_attach),
DEVMETHOD(device_detach, uath_detach),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t uath_driver = {
.name = "uath",
Modified: stable/0.8/sys/dev/usb/wlan/if_uathreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uathreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uathreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $OpenBSD: if_uathreg.h,v 1.2 2006/09/18 16:34:23 damien Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_uathreg.h 190688 2009-04-04 11:23:00Z weongyo $ */
/*-
* Copyright (c) 2006
Modified: stable/0.8/sys/dev/usb/wlan/if_uathvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uathvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uathvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $OpenBSD: if_uathvar.h,v 1.3 2006/09/20 19:47:17 damien Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_uathvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
/*-
* Copyright (c) 2006
@@ -52,7 +52,7 @@
int8_t wr_antsignal;
int8_t wr_antnoise;
u_int8_t wr_antenna;
-} __packed;
+} __packed __aligned(8);
#define UATH_RX_RADIOTAP_PRESENT ( \
(1 << IEEE80211_RADIOTAP_TSFT) | \
@@ -69,7 +69,7 @@
uint8_t wt_flags;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
#define UATH_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -186,6 +186,8 @@
struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
+ void *sc_cmd_dma_buf;
+ void *sc_tx_dma_buf;
struct mtx sc_mtx;
uint32_t sc_debug;
Modified: stable/0.8/sys/dev/usb/wlan/if_upgt.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_upgt.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_upgt.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $OpenBSD: if_upgt.c,v 1.35 2008/04/16 18:32:15 damien Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_upgt.c 292184 2015-12-14 09:42:39Z hselasky $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker at openbsd.org>
@@ -182,7 +182,7 @@
UPGT_DEV(FSC, E5400),
UPGT_DEV(GLOBESPAN, PRISM_GT_1),
UPGT_DEV(GLOBESPAN, PRISM_GT_2),
- UPGT_DEV(NETGEAR, WG111V2_2),
+ UPGT_DEV(NETGEAR, WG111V1_2),
UPGT_DEV(INTERSIL, PRISM_GT),
UPGT_DEV(SMC, 2862WG),
UPGT_DEV(USR, USR5422),
@@ -201,9 +201,8 @@
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .bufsize = MCLBYTES,
+ .bufsize = MCLBYTES * UPGT_TX_MAXCOUNT,
.flags = {
- .ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1
},
@@ -214,9 +213,8 @@
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .bufsize = MCLBYTES,
+ .bufsize = MCLBYTES * UPGT_RX_MAXCOUNT,
.flags = {
- .ext_buffer = 1,
.pipe_bof = 1,
.short_xfer_ok = 1
},
@@ -261,22 +259,27 @@
callout_init(&sc->sc_led_ch, 0);
callout_init(&sc->sc_watchdog_ch, 0);
- /* Allocate TX and RX xfers. */
- error = upgt_alloc_tx(sc);
- if (error)
- goto fail1;
- error = upgt_alloc_rx(sc);
- if (error)
- goto fail2;
-
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
if (error) {
device_printf(dev, "could not allocate USB transfers, "
"err=%s\n", usbd_errstr(error));
- goto fail3;
+ goto fail1;
}
+ sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer(
+ sc->sc_xfer[UPGT_BULK_RX], 0);
+ sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(
+ sc->sc_xfer[UPGT_BULK_TX], 0);
+
+ /* Setup TX and RX buffers */
+ error = upgt_alloc_tx(sc);
+ if (error)
+ goto fail2;
+ error = upgt_alloc_rx(sc);
+ if (error)
+ goto fail3;
+
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
@@ -379,9 +382,9 @@
return (0);
fail5: if_free(ifp);
-fail4: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
-fail3: upgt_free_rx(sc);
-fail2: upgt_free_tx(sc);
+fail4: upgt_free_rx(sc);
+fail3: upgt_free_tx(sc);
+fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
fail1: mtx_destroy(&sc->sc_mtx);
return (error);
@@ -425,7 +428,7 @@
data_cmd = upgt_getbuf(sc);
if (data_cmd == NULL) {
- device_printf(sc->sc_dev, "%s: out of buffer.\n", __func__);
+ device_printf(sc->sc_dev, "%s: out of buffers.\n", __func__);
return;
}
@@ -463,8 +466,15 @@
struct upgt_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ int error;
+ int startall = 0;
+ UPGT_LOCK(sc);
+ error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
+ UPGT_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
@@ -1030,9 +1040,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(uvp, M_80211_VAP);
+ return (NULL);
+ }
+
/* override state transition machine */
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = upgt_newstate;
@@ -1583,7 +1598,6 @@
data_tx->ni = NULL;
data_tx->addr = 0;
data_tx->m = NULL;
- data_tx->use = 0;
DPRINTF(sc, UPGT_DEBUG_TX_PROC,
"TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ",
@@ -1978,13 +1992,7 @@
for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_tx_data[i];
-
- data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
- if (data->buf == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate TX buffer\n");
- return (ENOMEM);
- }
+ data->buf = ((uint8_t *)sc->sc_tx_dma_buf) + (i * MCLBYTES);
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
UPGT_STAT_INC(sc, st_tx_inactive);
}
@@ -2002,16 +2010,9 @@
for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_rx_data[i];
-
- data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
- if (data->buf == NULL) {
- device_printf(sc->sc_dev,
- "could not allocate RX buffer\n");
- return (ENOMEM);
- }
+ data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES);
STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
}
-
return (0);
}
@@ -2021,20 +2022,42 @@
struct upgt_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ unsigned int x;
- if (!device_is_attached(dev))
- return 0;
+ /*
+ * Prevent further allocations from RX/TX/CMD
+ * data lists and ioctls
+ */
+ UPGT_LOCK(sc);
+ sc->sc_flags |= UPGT_FLAG_DETACHED;
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+ UPGT_UNLOCK(sc);
+
upgt_stop(sc);
callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
- usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
- ieee80211_ifdetach(ic);
+ /* drain USB transfers */
+ for (x = 0; x != UPGT_N_XFERS; x++)
+ usbd_transfer_drain(sc->sc_xfer[x]);
+
+ /* free data buffers */
+ UPGT_LOCK(sc);
upgt_free_rx(sc);
upgt_free_tx(sc);
+ UPGT_UNLOCK(sc);
+ /* free USB transfers and some data buffers */
+ usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
+
+ ieee80211_ifdetach(ic);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
@@ -2049,7 +2072,7 @@
for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_rx_data[i];
- free(data->buf, M_USBDEV);
+ data->buf = NULL;
data->ni = NULL;
}
}
@@ -2062,7 +2085,10 @@
for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
struct upgt_data *data = &sc->sc_tx_data[i];
- free(data->buf, M_USBDEV);
+ if (data->ni != NULL)
+ ieee80211_free_node(data->ni);
+
+ data->buf = NULL;
data->ni = NULL;
}
}
@@ -2304,8 +2330,7 @@
return;
STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
- usbd_xfer_set_frame_data(xfer, 0, data->buf,
- usbd_xfer_max_len(xfer));
+ usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
usbd_transfer_submit(xfer);
/*
@@ -2408,8 +2433,7 @@
DEVMETHOD(device_probe, upgt_match),
DEVMETHOD(device_attach, upgt_attach),
DEVMETHOD(device_detach, upgt_detach),
-
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t upgt_driver = {
Modified: stable/0.8/sys/dev/usb/wlan/if_upgtvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_upgtvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_upgtvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
/* $OpenBSD: if_upgtvar.h,v 1.14 2008/02/02 13:48:44 mglocker Exp $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_upgtvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker at openbsd.org>
@@ -352,7 +352,6 @@
struct ieee80211_node *ni;
struct mbuf *m;
uint32_t addr;
- uint8_t use;
STAILQ_ENTRY(upgt_data) next;
};
typedef STAILQ_HEAD(, upgt_data) upgt_datahead;
@@ -381,7 +380,7 @@
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_antsignal;
-} __packed;
+} __packed __aligned(8);
#define UPGT_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -395,7 +394,7 @@
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
#define UPGT_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -422,11 +421,14 @@
device_t sc_dev;
struct ifnet *sc_ifp;
struct usb_device *sc_udev;
+ void *sc_rx_dma_buf;
+ void *sc_tx_dma_buf;
struct mtx sc_mtx;
struct upgt_stat sc_stat;
int sc_flags;
#define UPGT_FLAG_FWLOADED (1 << 0)
#define UPGT_FLAG_INITDONE (1 << 1)
+#define UPGT_FLAG_DETACHED (1 << 2)
int sc_if_flags;
int sc_debug;
Modified: stable/0.8/sys/dev/usb/wlan/if_ural.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_ural.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_ural.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_ural.c 269267 2014-07-29 22:00:54Z hselasky $ */
/*-
* Copyright (c) 2005, 2006
@@ -21,7 +21,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_ural.c 269267 2014-07-29 22:00:54Z hselasky $");
/*-
* Ralink Technology RT2500USB chipset driver
@@ -385,8 +385,7 @@
DEVMETHOD(device_probe, ural_match),
DEVMETHOD(device_attach, ural_attach),
DEVMETHOD(device_detach, ural_detach),
-
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t ural_driver = {
@@ -528,6 +527,11 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
+ /* prevent further ioctls */
+ RAL_LOCK(sc);
+ sc->sc_detached = 1;
+ RAL_UNLOCK(sc);
+
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
@@ -585,9 +589,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(uvp, M_80211_VAP);
+ return (NULL);
+ }
+
/* override state transition machine */
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = ural_newstate;
@@ -1028,6 +1037,8 @@
desc->plcp_length_hi = plcp_length >> 6;
desc->plcp_length_lo = plcp_length & 0x3f;
} else {
+ if (rate == 0)
+ rate = 2; /* avoid division by zero */
plcp_length = (16 * len + rate - 1) / rate;
if (rate == 22) {
remainder = (16 * len) % 22;
@@ -1129,7 +1140,7 @@
dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
/* tell hardware to add timestamp for probe responses */
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
@@ -1320,7 +1331,7 @@
dur = ieee80211_ack_duration(ic->ic_rt, rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
}
ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate);
@@ -1371,8 +1382,15 @@
struct ural_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ int error;
+ int startall = 0;
+ RAL_LOCK(sc);
+ error = sc->sc_detached ? ENXIO : 0;
+ RAL_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
RAL_LOCK(sc);
Modified: stable/0.8/sys/dev/usb/wlan/if_uralreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uralreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uralreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_uralreg.h 196219 2009-08-14 20:03:53Z jhb $ */
/*-
* Copyright (c) 2005, 2006
Modified: stable/0.8/sys/dev/usb/wlan/if_uralvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uralvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uralvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_uralvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
/*-
* Copyright (c) 2005
@@ -34,7 +34,7 @@
int8_t wr_antsignal;
int8_t wr_antnoise;
uint8_t wr_antenna;
-};
+} __packed __aligned(8);
#define RAL_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -51,7 +51,7 @@
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
-};
+} __packed __aligned(8);
#define RAL_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -110,6 +110,7 @@
uint32_t rf_regs[4];
uint8_t txpow[14];
uint8_t sc_bssid[6];
+ uint8_t sc_detached;
struct {
uint8_t val;
Modified: stable/0.8/sys/dev/usb/wlan/if_urtw.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtw.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtw.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -15,7 +15,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_urtw.c 260575 2014-01-12 21:21:19Z hselasky $");
#include <sys/param.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
@@ -477,6 +477,7 @@
{ 96, 10 }, { 108, 11 }
};
+#if 0
static const uint8_t urtw_8187b_reg_table[][3] = {
{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
@@ -510,6 +511,7 @@
{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
};
+#endif
static usb_callback_t urtw_bulk_rx_callback;
static usb_callback_t urtw_bulk_tx_callback;
@@ -532,9 +534,8 @@
.type = UE_BULK,
.endpoint = 0x89,
.direction = UE_DIR_IN,
- .bufsize = MCLBYTES,
+ .bufsize = sizeof(uint64_t),
.flags = {
- .ext_buffer = 1,
.pipe_bof = 1,
.short_xfer_ok = 1
},
@@ -544,9 +545,8 @@
.type = UE_BULK,
.endpoint = URTW_8187B_TXPIPE_BE,
.direction = UE_DIR_OUT,
- .bufsize = URTW_TX_MAXSIZE,
+ .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
.flags = {
- .ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@@ -624,9 +624,8 @@
.type = UE_BULK,
.endpoint = 0x2,
.direction = UE_DIR_OUT,
- .bufsize = URTW_TX_MAXSIZE,
+ .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
.flags = {
- .ext_buffer = 1,
.force_short_xfer = 1,
.pipe_bof = 1,
},
@@ -654,8 +653,8 @@
const uint8_t [IEEE80211_ADDR_LEN]);
static void urtw_vap_delete(struct ieee80211vap *);
static void urtw_init(void *);
-static void urtw_stop(struct ifnet *, int);
-static void urtw_stop_locked(struct ifnet *, int);
+static void urtw_stop(struct ifnet *);
+static void urtw_stop_locked(struct ifnet *);
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 *);
@@ -827,6 +826,16 @@
goto fail0;
}
+ if (sc->sc_flags & URTW_RTL8187B) {
+ sc->sc_tx_dma_buf =
+ usbd_xfer_get_frame_buffer(sc->sc_xfer[
+ URTW_8187B_BULK_TX_BE], 0);
+ } else {
+ sc->sc_tx_dma_buf =
+ usbd_xfer_get_frame_buffer(sc->sc_xfer[
+ URTW_8187L_BULK_TX_LOW], 0);
+ }
+
URTW_LOCK(sc);
urtw_read32_m(sc, URTW_RX, &data);
@@ -926,11 +935,16 @@
struct urtw_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ unsigned int x;
+ unsigned int n_xfers;
- if (!device_is_attached(dev))
- return (0);
+ /* Prevent further ioctls */
+ URTW_LOCK(sc);
+ sc->sc_flags |= URTW_DETACHED;
+ URTW_UNLOCK(sc);
- urtw_stop(ifp, 1);
+ urtw_stop(ifp);
+
ieee80211_draintask(ic, &sc->sc_updateslot_task);
ieee80211_draintask(ic, &sc->sc_led_task);
@@ -937,16 +951,35 @@
usb_callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
- usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
- URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
- ieee80211_ifdetach(ic);
+ n_xfers = (sc->sc_flags & URTW_RTL8187B) ?
+ URTW_8187B_N_XFERS : URTW_8187L_N_XFERS;
+ /* prevent further allocations from RX/TX data lists */
+ URTW_LOCK(sc);
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+ URTW_UNLOCK(sc);
+
+ /* drain USB transfers */
+ for (x = 0; x != n_xfers; x++)
+ usbd_transfer_drain(sc->sc_xfer[x]);
+
+ /* free data buffers */
+ URTW_LOCK(sc);
urtw_free_tx_data_list(sc);
urtw_free_rx_data_list(sc);
+ URTW_UNLOCK(sc);
+ /* free USB transfers and some data buffers */
+ usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
+
+ ieee80211_ifdetach(ic);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
-
return (0);
}
@@ -953,7 +986,6 @@
static void
urtw_free_tx_data_list(struct urtw_softc *sc)
{
-
urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0);
}
@@ -960,7 +992,6 @@
static void
urtw_free_rx_data_list(struct urtw_softc *sc)
{
-
urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1);
}
@@ -980,10 +1011,7 @@
dp->buf = NULL;
}
} else {
- if (dp->buf != NULL) {
- free(dp->buf, M_USBDEV);
- dp->buf = NULL;
- }
+ dp->buf = NULL;
}
if (dp->ni != NULL) {
ieee80211_free_node(dp->ni);
@@ -1009,9 +1037,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(uvp, M_80211_VAP);
+ return (NULL);
+ }
+
/* override state transition machine */
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = urtw_newstate;
@@ -1041,7 +1074,7 @@
usb_error_t error;
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtw_stop_locked(ifp, 0);
+ urtw_stop_locked(ifp);
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
urtw_adapter_start(sc);
@@ -1304,13 +1337,12 @@
}
static void
-urtw_stop_locked(struct ifnet *ifp, int disable)
+urtw_stop_locked(struct ifnet *ifp)
{
struct urtw_softc *sc = ifp->if_softc;
uint8_t data8;
usb_error_t error;
- (void)disable;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
error = urtw_intr_disable(sc);
@@ -1344,12 +1376,12 @@
}
static void
-urtw_stop(struct ifnet *ifp, int disable)
+urtw_stop(struct ifnet *ifp)
{
struct urtw_softc *sc = ifp->if_softc;
URTW_LOCK(sc);
- urtw_stop_locked(ifp, disable);
+ urtw_stop_locked(ifp);
URTW_UNLOCK(sc);
}
@@ -1374,8 +1406,15 @@
struct urtw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ int error;
+ int startall = 0;
+ URTW_LOCK(sc);
+ error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
+ URTW_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
@@ -1389,7 +1428,7 @@
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtw_stop(ifp, 1);
+ urtw_stop(ifp);
}
sc->sc_if_flags = ifp->if_flags;
if (startall)
@@ -1405,7 +1444,6 @@
error = EINVAL;
break;
}
-
return (error);
}
@@ -1449,7 +1487,7 @@
static int
urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
- int ndata, int maxsz, int fillmbuf)
+ int ndata, int maxsz, void *dma_buf)
{
int i, error;
@@ -1457,7 +1495,7 @@
struct urtw_data *dp = &data[i];
dp->sc = sc;
- if (fillmbuf) {
+ if (dma_buf == NULL) {
dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (dp->m == NULL) {
device_printf(sc->sc_dev,
@@ -1468,24 +1506,15 @@
dp->buf = mtod(dp->m, uint8_t *);
} else {
dp->m = NULL;
- dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
- 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->buf = ((uint8_t *)dma_buf) +
+ (i * maxsz);
}
dp->ni = NULL;
}
+ return (0);
- return 0;
-
-fail: urtw_free_data_list(sc, data, ndata, fillmbuf);
- return error;
+fail: urtw_free_data_list(sc, data, ndata, 1);
+ return (error);
}
static int
@@ -1494,7 +1523,8 @@
int error, i;
error = urtw_alloc_data_list(sc,
- sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */);
+ sc->sc_rx, URTW_RX_DATA_LIST_COUNT,
+ MCLBYTES, NULL /* mbufs */);
if (error != 0)
return (error);
@@ -1514,7 +1544,7 @@
error = urtw_alloc_data_list(sc,
sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
- 0 /* no mbufs */);
+ sc->sc_tx_dma_buf /* no mbufs */);
if (error != 0)
return (error);
@@ -1738,7 +1768,7 @@
else
dur = URTW_ASIFS_TIME + acktime;
}
- *(uint16_t *)wh->i_dur = htole16(dur);
+ USETW(wh->i_dur, dur);
xferlen = m0->m_pkthdr.len;
xferlen += (sc->sc_flags & URTW_RTL8187B) ? (4 * 8) : (4 * 3);
@@ -1994,9 +2024,11 @@
data |= URTW_MSR_LINK_HOSTAP;
break;
default:
- panic("unsupported operation mode 0x%x\n",
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported operation mode 0x%x\n",
ic->ic_opmode);
- /* never reach */
+ error = USB_ERR_INVAL;
+ goto fail;
}
} else
data |= URTW_MSR_LINK_NONE;
@@ -2427,8 +2459,10 @@
sc->sc_rf_stop = urtw_8225_rf_stop;
break;
default:
- panic("unsupported RF chip %d\n", data & 0xff);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported RF chip %d\n", data & 0xff);
+ error = USB_ERR_INVAL;
+ goto fail;
}
device_printf(sc->sc_dev, "%s rf %s hwrev %s\n",
@@ -2709,42 +2743,28 @@
return (error);
}
-/* XXX why we should allocalte memory buffer instead of using memory stack? */
static usb_error_t
urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
uint16_t *data)
{
- uint8_t *buf;
+ uint8_t buf[2];
uint16_t data16;
- struct usb_device_request *req;
+ struct usb_device_request req;
usb_error_t 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));
+ 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 = urtw_do_request(sc, req, buf);
+ error = urtw_do_request(sc, &req, buf);
- free(buf, M_80211_VAP);
-fail1: free(req, M_80211_VAP);
-fail0: return (error);
+ return (error);
}
static usb_error_t
@@ -3622,8 +3642,10 @@
error = urtw_led_mode3(sc, mode);
break;
default:
- panic("unsupported LED mode %d\n", sc->sc_strategy);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED mode %d\n", sc->sc_strategy);
+ error = USB_ERR_INVAL;
+ break;
}
return (error);
@@ -3648,8 +3670,9 @@
sc->sc_gpio_ledstate = URTW_LED_ON;
break;
default:
- panic("unsupported LED mode 0x%x", mode);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED mode 0x%x", mode);
+ return (USB_ERR_INVAL);
}
switch (sc->sc_gpio_ledstate) {
@@ -3672,8 +3695,9 @@
urtw_led_off(sc, URTW_LED_GPIO);
break;
default:
- panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unknown LED status 0x%x", sc->sc_gpio_ledstate);
+ return (USB_ERR_INVAL);
}
return (0);
}
@@ -3681,7 +3705,6 @@
static usb_error_t
urtw_led_mode1(struct urtw_softc *sc, int mode)
{
-
return (USB_ERR_INVAL);
}
@@ -3688,7 +3711,6 @@
static usb_error_t
urtw_led_mode2(struct urtw_softc *sc, int mode)
{
-
return (USB_ERR_INVAL);
}
@@ -3695,7 +3717,6 @@
static usb_error_t
urtw_led_mode3(struct urtw_softc *sc, int mode)
{
-
return (USB_ERR_INVAL);
}
@@ -3711,13 +3732,17 @@
urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
break;
default:
- panic("unsupported LED PIN type 0x%x",
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED PIN type 0x%x",
sc->sc_gpio_ledpin);
- /* never reach */
+ error = USB_ERR_INVAL;
+ goto fail;
}
} else {
- panic("unsupported LED type 0x%x", type);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED type 0x%x", type);
+ error = USB_ERR_INVAL;
+ goto fail;
}
sc->sc_gpio_ledon = 1;
@@ -3738,13 +3763,17 @@
URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
break;
default:
- panic("unsupported LED PIN type 0x%x",
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED PIN type 0x%x",
sc->sc_gpio_ledpin);
- /* never reach */
+ error = USB_ERR_INVAL;
+ goto fail;
}
} else {
- panic("unsupported LED type 0x%x", type);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unsupported LED type 0x%x", type);
+ error = USB_ERR_INVAL;
+ goto fail;
}
sc->sc_gpio_ledon = 0;
@@ -3768,8 +3797,12 @@
{
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);
+ if (sc->sc_strategy != URTW_SW_LED_MODE0) {
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "could not process a LED strategy 0x%x",
+ sc->sc_strategy);
+ return;
+ }
URTW_LOCK(sc);
urtw_led_blink(sc);
@@ -3816,8 +3849,10 @@
usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
break;
default:
- panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
- /* never reach */
+ DPRINTF(sc, URTW_DEBUG_STATE,
+ "unknown LED status 0x%x",
+ sc->sc_gpio_ledstate);
+ return (USB_ERR_INVAL);
}
return (0);
}
@@ -4133,6 +4168,7 @@
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
+ void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
URTW_ASSERT_LOCKED(sc);
@@ -4142,8 +4178,8 @@
/* FALLTHROUGH */
case USB_ST_SETUP:
setup:
- usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus,
- sizeof(int64_t));
+ memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t));
+ usbd_xfer_set_frame_len(xfer, 0, sizeof(uint64_t));
usbd_transfer_submit(xfer);
break;
default:
@@ -4431,7 +4467,7 @@
DEVMETHOD(device_probe, urtw_match),
DEVMETHOD(device_attach, urtw_attach),
DEVMETHOD(device_detach, urtw_detach),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t urtw_driver = {
.name = "urtw",
Modified: stable/0.8/sys/dev/usb/wlan/if_urtwreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtwreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtwreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_urtwreg.h 198194 2009-10-18 00:11:49Z weongyo $ */
/*-
* Copyright (c) 2008 Weongyo Jeong <weongyo at FreeBSD.org>
Modified: stable/0.8/sys/dev/usb/wlan/if_urtwvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtwvar.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtwvar.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_urtwvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
/*-
* Copyright (c) 2008 Weongyo Jeong <weongyo at FreeBSD.org>
@@ -63,7 +63,7 @@
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
int8_t wr_dbm_antsignal;
-} __packed;
+} __packed __aligned(8);
#define URTW_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -75,7 +75,7 @@
uint8_t wt_flags;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
#define URTW_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -97,6 +97,7 @@
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
+ void *sc_tx_dma_buf;
int sc_debug;
int sc_if_flags;
@@ -106,6 +107,7 @@
#define URTW_RTL8187B_REV_B (1 << 3)
#define URTW_RTL8187B_REV_D (1 << 4)
#define URTW_RTL8187B_REV_E (1 << 5)
+#define URTW_DETACHED (1 << 6)
enum ieee80211_state sc_state;
int sc_epromtype;
Modified: stable/0.8/sys/dev/usb/wlan/if_zyd.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zyd.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zyd.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
/* $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 $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_zyd.c 269267 2014-07-29 22:00:54Z hselasky $ */
/*-
* Copyright (c) 2006 by Damien Bergamini <damien.bergamini at free.fr>
@@ -20,7 +20,7 @@
*/
#include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_zyd.c 269267 2014-07-29 22:00:54Z hselasky $");
/*
* ZyDAS ZD1211/ZD1211B USB WLAN driver.
@@ -438,13 +438,30 @@
struct zyd_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
+ unsigned int x;
- /* stop all USB transfers */
- usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
+ /*
+ * Prevent further allocations from RX/TX data
+ * lists and ioctls:
+ */
+ ZYD_LOCK(sc);
+ sc->sc_flags |= ZYD_FLAG_DETACHED;
+ STAILQ_INIT(&sc->tx_q);
+ STAILQ_INIT(&sc->tx_free);
+ ZYD_UNLOCK(sc);
+ /* drain USB transfers */
+ for (x = 0; x != ZYD_N_TRANSFER; x++)
+ usbd_transfer_drain(sc->sc_xfer[x]);
+
/* free TX list, if any */
+ ZYD_LOCK(sc);
zyd_unsetup_tx_list(sc);
+ ZYD_UNLOCK(sc);
+ /* free USB transfers and some data buffers */
+ usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
+
if (ifp) {
ic = ifp->if_l2com;
ieee80211_ifdetach(ic);
@@ -471,9 +488,14 @@
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);
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ /* out of memory */
+ free(zvp, M_80211_VAP);
+ return (NULL);
+ }
/* override state transition machine */
zvp->newstate = vap->iv_newstate;
@@ -2457,7 +2479,7 @@
const struct ieee80211_txparam *tp;
struct ieee80211_key *k;
int rate, totlen;
- static uint8_t ratediv[] = ZYD_TX_RATEDIV;
+ static const uint8_t ratediv[] = ZYD_TX_RATEDIV;
uint8_t phy;
uint16_t pktlen;
uint32_t bits;
@@ -2637,8 +2659,15 @@
struct zyd_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ int error;
+ int startall = 0;
+ ZYD_LOCK(sc);
+ error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
+ ZYD_UNLOCK(sc);
+ if (error)
+ return (error);
+
switch (cmd) {
case SIOCSIFFLAGS:
ZYD_LOCK(sc);
@@ -2928,8 +2957,7 @@
DEVMETHOD(device_probe, zyd_match),
DEVMETHOD(device_attach, zyd_attach),
DEVMETHOD(device_detach, zyd_detach),
-
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t zyd_driver = {
Modified: stable/0.8/sys/dev/usb/wlan/if_zydfw.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zydfw.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zydfw.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_zydfw.h 196219 2009-08-14 20:03:53Z jhb $ */
uint8_t zd1211_firmware[] = {
0x08, 0x91, 0xFF, 0xED, 0x09, 0x93, 0x1E, 0xEE,
Modified: stable/0.8/sys/dev/usb/wlan/if_zydreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zydreg.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zydreg.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
/* $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 $ */
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/wlan/if_zydreg.h 269267 2014-07-29 22:00:54Z hselasky $ */
/*-
* Copyright (c) 2006 by Damien Bergamini <damien.bergamini at free.fr>
@@ -970,7 +970,7 @@
#define ZYD_TX_RATEDIV \
{ \
- 0x1, 0x2, 0xb, 0xb, 0x0, 0x0, 0x0, 0x0, 0x30, 0x18, 0xc, 0x6, \
+ 0x1, 0x2, 0xb, 0xb, 0x1, 0x1, 0x1, 0x1, 0x30, 0x18, 0xc, 0x6, \
0x36, 0x24, 0x12, 0x9 \
}
@@ -1185,7 +1185,7 @@
uint16_t wr_chan_flags;
int8_t wr_antsignal;
int8_t wr_antnoise;
-} __packed;
+} __packed __aligned(8);
#define ZYD_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -1200,7 +1200,7 @@
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
#define ZYD_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
@@ -1259,6 +1259,7 @@
#define ZYD_FLAG_FWLOADED (1 << 0)
#define ZYD_FLAG_INITONCE (1 << 1)
#define ZYD_FLAG_INITDONE (1 << 2)
+#define ZYD_FLAG_DETACHED (1 << 3)
struct zyd_rf sc_rf;
Modified: stable/0.8/sys/fs/devfs/devfs_int.h
===================================================================
--- stable/0.8/sys/fs/devfs/devfs_int.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/fs/devfs/devfs_int.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -56,6 +56,7 @@
u_int cdp_flags;
#define CDP_ACTIVE (1 << 0)
#define CDP_SCHED_DTR (1 << 1)
+#define CDP_UNREF_DTR (1 << 2)
u_int cdp_inuse;
u_int cdp_maxdirent;
Property changes on: stable/0.8/sys/fs/devfs/devfs_int.h
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.7
\ No newline at end of property
Modified: stable/0.8/sys/kern/kern_conf.c
===================================================================
--- stable/0.8/sys/kern/kern_conf.c 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/kern/kern_conf.c 2017-08-19 02:11:51 UTC (rev 9518)
@@ -115,6 +115,8 @@
mtx_assert(&devmtx, MA_OWNED);
cdp = cdev2priv(cdev);
+ KASSERT((cdp->cdp_flags & CDP_UNREF_DTR) == 0,
+ ("destroy_dev() was not called after delist_dev(%p)", cdev));
TAILQ_INSERT_HEAD(&cdevp_free_list, cdp, cdp_list);
}
@@ -306,7 +308,6 @@
static struct cdevsw dead_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT, /* XXX: does dead_strategy need this ? */
.d_open = dead_open,
.d_close = dead_close,
.d_read = dead_read,
@@ -993,9 +994,10 @@
max_parentpath_len = SPECNAMELEN - physpath_len - /*/*/1;
parentpath_len = strlen(pdev->si_name);
if (max_parentpath_len < parentpath_len) {
- printf("make_dev_physpath_alias: WARNING - Unable to alias %s "
- "to %s/%s - path too long\n",
- pdev->si_name, physpath, pdev->si_name);
+ if (bootverbose)
+ printf("WARNING: Unable to alias %s "
+ "to %s/%s - path too long\n",
+ pdev->si_name, physpath, pdev->si_name);
ret = ENAMETOOLONG;
goto out;
}
@@ -1030,6 +1032,7 @@
{
struct cdevsw *csw;
struct cdev_privdata *p;
+ struct cdev_priv *cdp;
mtx_assert(&devmtx, MA_OWNED);
KASSERT(dev->si_flags & SI_NAMED,
@@ -1038,13 +1041,22 @@
("WARNING: Driver mistake: destroy_dev on eternal %d\n",
dev2unit(dev)));
- devfs_destroy(dev);
+ cdp = cdev2priv(dev);
+ if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
+ /*
+ * Avoid race with dev_rel(), e.g. from the populate
+ * loop. If CDP_UNREF_DTR flag is set, the reference
+ * to be dropped at the end of destroy_devl() was
+ * already taken by delist_dev_locked().
+ */
+ dev_refl(dev);
+ devfs_destroy(dev);
+ }
+
/* Remove name marking */
dev->si_flags &= ~SI_NAMED;
- dev->si_refcount++; /* Avoid race with dev_rel() */
-
/* If we are a child, remove us from the parents list */
if (dev->si_flags & SI_CHILD) {
LIST_REMOVE(dev, si_siblings);
@@ -1076,9 +1088,12 @@
}
dev_unlock();
- notify_destroy(dev);
+ if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
+ /* avoid out of order notify events */
+ notify_destroy(dev);
+ }
mtx_lock(&cdevpriv_mtx);
- while ((p = LIST_FIRST(&cdev2priv(dev)->cdp_fdpriv)) != NULL) {
+ while ((p = LIST_FIRST(&cdp->cdp_fdpriv)) != NULL) {
devfs_destroy_cdevpriv(p);
mtx_lock(&cdevpriv_mtx);
}
@@ -1100,16 +1115,55 @@
}
}
dev->si_flags &= ~SI_ALIAS;
- dev->si_refcount--; /* Avoid race with dev_rel() */
+ cdp->cdp_flags &= ~CDP_UNREF_DTR;
+ dev->si_refcount--;
- if (dev->si_refcount > 0) {
+ if (dev->si_refcount > 0)
LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
- } else {
+ else
dev_free_devlocked(dev);
- }
}
+static void
+delist_dev_locked(struct cdev *dev)
+{
+ struct cdev_priv *cdp;
+ struct cdev *child;
+
+ mtx_assert(&devmtx, MA_OWNED);
+ cdp = cdev2priv(dev);
+ if ((cdp->cdp_flags & CDP_UNREF_DTR) != 0)
+ return;
+ cdp->cdp_flags |= CDP_UNREF_DTR;
+ dev_refl(dev);
+ devfs_destroy(dev);
+ LIST_FOREACH(child, &dev->si_children, si_siblings)
+ delist_dev_locked(child);
+ dev_unlock();
+ /* ensure the destroy event is queued in order */
+ notify_destroy(dev);
+ dev_lock();
+}
+
+/*
+ * This function will delist a character device and its children from
+ * the directory listing and create a destroy event without waiting
+ * for all character device references to go away. At some later point
+ * destroy_dev() must be called to complete the character device
+ * destruction. After calling this function the character device name
+ * can instantly be re-used.
+ */
void
+delist_dev(struct cdev *dev)
+{
+
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "delist_dev");
+ dev_lock();
+ delist_dev_locked(dev);
+ dev_unlock();
+}
+
+void
destroy_dev(struct cdev *dev)
{
Modified: stable/0.8/sys/sys/conf.h
===================================================================
--- stable/0.8/sys/sys/conf.h 2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/sys/conf.h 2017-08-19 02:11:51 UTC (rev 9518)
@@ -64,6 +64,7 @@
#define SI_DUMPDEV 0x0080 /* is kernel dumpdev */
#define SI_CANDELETE 0x0100 /* can do BIO_DELETE */
#define SI_CLONELIST 0x0200 /* on a clone list */
+#define SI_UNMAPPED 0x0400 /* can handle unmapped I/O */
struct timespec si_atime;
struct timespec si_ctime;
struct timespec si_mtime;
@@ -171,6 +172,7 @@
#define D_PSEUDO 0x00200000 /* make_dev() can return NULL */
#define D_NEEDGIANT 0x00400000 /* driver want Giant */
#define D_NEEDMINOR 0x00800000 /* driver uses clone_create() */
+#define D_UNMAPPED_IO 0x01000000 /* d_strategy can accept unmapped IO */
/*
* Version numbers.
@@ -245,6 +247,7 @@
int clone_create(struct clonedevs **, struct cdevsw *, int *unit, struct cdev **dev, int extra);
int count_dev(struct cdev *_dev);
+void delist_dev(struct cdev *_dev);
void destroy_dev(struct cdev *_dev);
int destroy_dev_sched(struct cdev *dev);
int destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg);
@@ -258,6 +261,7 @@
void dev_refl(struct cdev *dev);
void dev_rel(struct cdev *dev);
void dev_strategy(struct cdev *dev, struct buf *bp);
+void dev_strategy_csw(struct cdev *dev, struct cdevsw *csw, struct buf *bp);
struct cdev *make_dev(struct cdevsw *_devsw, int _unit, uid_t _uid, gid_t _gid,
int _perms, const char *_fmt, ...) __printflike(6, 7);
struct cdev *make_dev_cred(struct cdevsw *_devsw, int _unit,
More information about the Midnightbsd-cvs
mailing list