summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-06 16:20:21 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-11-11 10:08:08 +0100
commit66659ff1ad6831b0ea7425fa6ecd8a8687523658 (patch)
tree48e22b475fa8854128e0861a33fed6f78c8094b5 /freebsd/sys/dev/usb
parentDefine __GLOBL1() and __GLOBL() (diff)
downloadrtems-libbsd-66659ff1ad6831b0ea7425fa6ecd8a8687523658.tar.bz2
Update to FreeBSD 9.2
Diffstat (limited to 'freebsd/sys/dev/usb')
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.c18
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.h2
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.c2
-rw-r--r--freebsd/sys/dev/usb/controller/usb_controller.c27
-rw-r--r--freebsd/sys/dev/usb/controller/xhcireg.h221
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c15
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h1
-rw-r--r--freebsd/sys/dev/usb/storage/umass.c292
-rw-r--r--freebsd/sys/dev/usb/usb.h16
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c8
-rw-r--r--freebsd/sys/dev/usb/usb_device.c75
-rw-r--r--freebsd/sys/dev/usb/usb_device.h3
-rw-r--r--freebsd/sys/dev/usb/usb_freebsd.h8
-rw-r--r--freebsd/sys/dev/usb/usb_generic.c17
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c76
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c2
-rw-r--r--freebsd/sys/dev/usb/usb_ioctl.h3
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.c52
-rw-r--r--freebsd/sys/dev/usb/usb_process.c8
-rw-r--r--freebsd/sys/dev/usb/usb_process.h6
-rw-r--r--freebsd/sys/dev/usb/usb_request.c54
-rw-r--r--freebsd/sys/dev/usb/usb_request.h2
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c6
-rw-r--r--freebsd/sys/dev/usb/usb_util.c53
-rw-r--r--freebsd/sys/dev/usb/usb_util.h1
-rw-r--r--freebsd/sys/dev/usb/usbhid.h2
26 files changed, 621 insertions, 349 deletions
diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c
index 18864431..456aff61 100644
--- a/freebsd/sys/dev/usb/controller/ehci.c
+++ b/freebsd/sys/dev/usb/controller/ehci.c
@@ -96,7 +96,7 @@ static int ehcinohighspeed = 0;
static int ehciiaadbug = 0;
static int ehcilostintrbug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&ehcidebug, 0, "Debug level");
TUNABLE_INT("hw.usb.ehci.debug", &ehcidebug);
@@ -334,14 +334,18 @@ ehci_init(ehci_softc_t *sc)
sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
sc->sc_bus.usbrev = USB_REV_2_0;
- /* Reset the controller */
- DPRINTF("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev));
+ if (!(sc->sc_flags & EHCI_SCFLG_DONTRESET)) {
+ /* Reset the controller */
+ DPRINTF("%s: resetting\n",
+ device_get_nameunit(sc->sc_bus.bdev));
- err = ehci_hcreset(sc);
- if (err) {
- device_printf(sc->sc_bus.bdev, "reset timeout\n");
- return (err);
+ err = ehci_hcreset(sc);
+ if (err) {
+ device_printf(sc->sc_bus.bdev, "reset timeout\n");
+ return (err);
+ }
}
+
/*
* use current frame-list-size selection 0: 1024*4 bytes 1: 512*4
* bytes 2: 256*4 bytes 3: unknown
diff --git a/freebsd/sys/dev/usb/controller/ehci.h b/freebsd/sys/dev/usb/controller/ehci.h
index a64d48a0..f718a8a7 100644
--- a/freebsd/sys/dev/usb/controller/ehci.h
+++ b/freebsd/sys/dev/usb/controller/ehci.h
@@ -345,6 +345,8 @@ typedef struct ehci_softc {
#define EHCI_SCFLG_TT 0x0020 /* transaction translator present */
#define EHCI_SCFLG_LOSTINTRBUG 0x0040 /* workaround for VIA / ATI chipsets */
#define EHCI_SCFLG_IAADBUG 0x0080 /* workaround for nVidia chipsets */
+#define EHCI_SCFLG_DONTRESET 0x0100 /* don't reset ctrl. in ehci_init() */
+#define EHCI_SCFLG_DONEINIT 0x1000 /* ehci_init() has been called. */
uint8_t sc_offs; /* offset to operational registers */
uint8_t sc_doorbell_disable; /* set on doorbell failure */
diff --git a/freebsd/sys/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c
index 94e94fd9..42129a8e 100644
--- a/freebsd/sys/dev/usb/controller/ohci.c
+++ b/freebsd/sys/dev/usb/controller/ohci.c
@@ -82,7 +82,7 @@ __FBSDID("$FreeBSD$");
#ifdef USB_DEBUG
static int ohcidebug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&ohcidebug, 0, "ohci debug level");
TUNABLE_INT("hw.usb.ohci.debug", &ohcidebug);
diff --git a/freebsd/sys/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c
index 3f9c8742..37f79364 100644
--- a/freebsd/sys/dev/usb/controller/usb_controller.c
+++ b/freebsd/sys/dev/usb/controller/usb_controller.c
@@ -81,7 +81,7 @@ static void usb_attach_sub(device_t, struct usb_bus *);
#ifdef USB_DEBUG
static int usb_ctrl_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, ctrl, CTLFLAG_RW, 0, "USB controller");
SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
"Debug level");
#endif
@@ -889,3 +889,28 @@ usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
mtx_destroy(&bus->bus_mtx);
}
+
+/* convenience wrappers */
+void
+usb_proc_explore_mwait(struct usb_device *udev, void *pm1, void *pm2)
+{
+ usb_proc_mwait(&udev->bus->explore_proc, pm1, pm2);
+}
+
+void *
+usb_proc_explore_msignal(struct usb_device *udev, void *pm1, void *pm2)
+{
+ return (usb_proc_msignal(&udev->bus->explore_proc, pm1, pm2));
+}
+
+void
+usb_proc_explore_lock(struct usb_device *udev)
+{
+ USB_BUS_LOCK(udev->bus);
+}
+
+void
+usb_proc_explore_unlock(struct usb_device *udev)
+{
+ USB_BUS_UNLOCK(udev->bus);
+}
diff --git a/freebsd/sys/dev/usb/controller/xhcireg.h b/freebsd/sys/dev/usb/controller/xhcireg.h
new file mode 100644
index 00000000..85d989a6
--- /dev/null
+++ b/freebsd/sys/dev/usb/controller/xhcireg.h
@@ -0,0 +1,221 @@
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2010 Hans Petter Selasky. 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.
+ */
+
+#ifndef _XHCIREG_H_
+#define _XHCIREG_H_
+
+/* XHCI PCI config registers */
+#define PCI_XHCI_CBMEM 0x10 /* configuration base MEM */
+#define PCI_XHCI_USBREV 0x60 /* RO USB protocol revision */
+#define PCI_USB_REV_3_0 0x30 /* USB 3.0 */
+#define PCI_XHCI_FLADJ 0x61 /* RW frame length adjust */
+
+#define PCI_XHCI_INTEL_XUSB2PR 0xD0 /* Intel USB2 Port Routing */
+#define PCI_XHCI_INTEL_USB3_PSSEN 0xD8 /* Intel USB3 Port SuperSpeed Enable */
+
+/* XHCI capability registers */
+#define XHCI_CAPLENGTH 0x00 /* RO capability */
+#define XHCI_RESERVED 0x01 /* Reserved */
+#define XHCI_HCIVERSION 0x02 /* RO Interface version number */
+#define XHCI_HCIVERSION_0_9 0x0090 /* xHCI version 0.9 */
+#define XHCI_HCIVERSION_1_0 0x0100 /* xHCI version 1.0 */
+#define XHCI_HCSPARAMS1 0x04 /* RO structual parameters 1 */
+#define XHCI_HCS1_DEVSLOT_MAX(x)((x) & 0xFF)
+#define XHCI_HCS1_IRQ_MAX(x) (((x) >> 8) & 0x3FF)
+#define XHCI_HCS1_N_PORTS(x) (((x) >> 24) & 0xFF)
+#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_HCSPARAMS3 0x0C /* RO structual parameters 3 */
+#define XHCI_HCS3_U1_DEL(x) ((x) & 0xFF)
+#define XHCI_HCS3_U2_DEL(x) (((x) >> 16) & 0xFFFF)
+#define XHCI_HCSPARAMS0 0x10 /* RO capability parameters */
+#define XHCI_HCS0_AC64(x) ((x) & 0x1) /* 64-bit capable */
+#define XHCI_HCS0_BNC(x) (((x) >> 1) & 0x1) /* BW negotiation */
+#define XHCI_HCS0_CSZ(x) (((x) >> 2) & 0x1) /* context size */
+#define XHCI_HCS0_PPC(x) (((x) >> 3) & 0x1) /* port power control */
+#define XHCI_HCS0_PIND(x) (((x) >> 4) & 0x1) /* port indicators */
+#define XHCI_HCS0_LHRC(x) (((x) >> 5) & 0x1) /* light HC reset */
+#define XHCI_HCS0_LTC(x) (((x) >> 6) & 0x1) /* latency tolerance msg */
+#define XHCI_HCS0_NSS(x) (((x) >> 7) & 0x1) /* no secondary sid */
+#define XHCI_HCS0_PSA_SZ_MAX(x) (((x) >> 12) & 0xF) /* max pri. stream array size */
+#define XHCI_HCS0_XECP(x) (((x) >> 16) & 0xFFFF) /* extended capabilities pointer */
+#define XHCI_DBOFF 0x14 /* RO doorbell offset */
+#define XHCI_RTSOFF 0x18 /* RO runtime register space offset */
+
+/* XHCI operational registers. Offset given by XHCI_CAPLENGTH register */
+#define XHCI_USBCMD 0x00 /* XHCI command */
+#define XHCI_CMD_RS 0x00000001 /* RW Run/Stop */
+#define XHCI_CMD_HCRST 0x00000002 /* RW Host Controller Reset */
+#define XHCI_CMD_INTE 0x00000004 /* RW Interrupter Enable */
+#define XHCI_CMD_HSEE 0x00000008 /* RW Host System Error Enable */
+#define XHCI_CMD_LHCRST 0x00000080 /* RO/RW Light Host Controller Reset */
+#define XHCI_CMD_CSS 0x00000100 /* RW Controller Save State */
+#define XHCI_CMD_CRS 0x00000200 /* RW Controller Restore State */
+#define XHCI_CMD_EWE 0x00000400 /* RW Enable Wrap Event */
+#define XHCI_CMD_EU3S 0x00000800 /* RW Enable U3 MFINDEX Stop */
+#define XHCI_USBSTS 0x04 /* XHCI status */
+#define XHCI_STS_HCH 0x00000001 /* RO - Host Controller Halted */
+#define XHCI_STS_HSE 0x00000004 /* RW - Host System Error */
+#define XHCI_STS_EINT 0x00000008 /* RW - Event Interrupt */
+#define XHCI_STS_PCD 0x00000010 /* RW - Port Change Detect */
+#define XHCI_STS_SSS 0x00000100 /* RO - Save State Status */
+#define XHCI_STS_RSS 0x00000200 /* RO - Restore State Status */
+#define XHCI_STS_SRE 0x00000400 /* RW - Save/Restore Error */
+#define XHCI_STS_CNR 0x00000800 /* RO - Controller Not Ready */
+#define XHCI_STS_HCE 0x00001000 /* RO - Host Controller Error */
+#define XHCI_PAGESIZE 0x08 /* XHCI page size mask */
+#define XHCI_PAGESIZE_4K 0x00000001 /* 4K Page Size */
+#define XHCI_PAGESIZE_8K 0x00000002 /* 8K Page Size */
+#define XHCI_PAGESIZE_16K 0x00000004 /* 16K Page Size */
+#define XHCI_PAGESIZE_32K 0x00000008 /* 32K Page Size */
+#define XHCI_PAGESIZE_64K 0x00000010 /* 64K Page Size */
+#define XHCI_DNCTRL 0x14 /* XHCI device notification control */
+#define XHCI_DNCTRL_MASK(n) (1U << (n))
+#define XHCI_CRCR_LO 0x18 /* XHCI command ring control */
+#define XHCI_CRCR_LO_RCS 0x00000001 /* RW - consumer cycle state */
+#define XHCI_CRCR_LO_CS 0x00000002 /* RW - command stop */
+#define XHCI_CRCR_LO_CA 0x00000004 /* RW - command abort */
+#define XHCI_CRCR_LO_CRR 0x00000008 /* RW - command ring running */
+#define XHCI_CRCR_LO_MASK 0x0000000F
+#define XHCI_CRCR_HI 0x1C /* XHCI command ring control */
+#define XHCI_DCBAAP_LO 0x30 /* XHCI dev context BA pointer */
+#define XHCI_DCBAAP_HI 0x34 /* XHCI dev context BA pointer */
+#define XHCI_CONFIG 0x38
+#define XHCI_CONFIG_SLOTS_MASK 0x000000FF /* RW - number of device slots enabled */
+
+/* XHCI port status registers */
+#define XHCI_PORTSC(n) (0x3F0 + (0x10 * (n))) /* XHCI port status */
+#define XHCI_PS_CCS 0x00000001 /* RO - current connect status */
+#define XHCI_PS_PED 0x00000002 /* RW - port enabled / disabled */
+#define XHCI_PS_OCA 0x00000008 /* RO - over current active */
+#define XHCI_PS_PR 0x00000010 /* RW - port reset */
+#define XHCI_PS_PLS_GET(x) (((x) >> 5) & 0xF) /* RW - port link state */
+#define XHCI_PS_PLS_SET(x) (((x) & 0xF) << 5) /* RW - port link state */
+#define XHCI_PS_PP 0x00000200 /* RW - port power */
+#define XHCI_PS_SPEED_GET(x) (((x) >> 10) & 0xF) /* RO - port speed */
+#define XHCI_PS_PIC_GET(x) (((x) >> 14) & 0x3) /* RW - port indicator */
+#define XHCI_PS_PIC_SET(x) (((x) & 0x3) << 14) /* RW - port indicator */
+#define XHCI_PS_LWS 0x00010000 /* RW - port link state write strobe */
+#define XHCI_PS_CSC 0x00020000 /* RW - connect status change */
+#define XHCI_PS_PEC 0x00040000 /* RW - port enable/disable change */
+#define XHCI_PS_WRC 0x00080000 /* RW - warm port reset change */
+#define XHCI_PS_OCC 0x00100000 /* RW - over-current change */
+#define XHCI_PS_PRC 0x00200000 /* RW - port reset change */
+#define XHCI_PS_PLC 0x00400000 /* RW - port link state change */
+#define XHCI_PS_CEC 0x00800000 /* RW - config error change */
+#define XHCI_PS_CAS 0x01000000 /* RO - cold attach status */
+#define XHCI_PS_WCE 0x02000000 /* RW - wake on connect enable */
+#define XHCI_PS_WDE 0x04000000 /* RW - wake on disconnect enable */
+#define XHCI_PS_WOE 0x08000000 /* RW - wake on over-current enable */
+#define XHCI_PS_DR 0x40000000 /* RO - device removable */
+#define XHCI_PS_WPR 0x80000000U /* RW - warm port reset */
+#define XHCI_PS_CLEAR 0x80FF01FFU /* command bits */
+
+#define XHCI_PORTPMSC(n) (0x3F4 + (0x10 * (n))) /* XHCI status and control */
+#define XHCI_PM3_U1TO_GET(x) (((x) >> 0) & 0xFF) /* RW - U1 timeout */
+#define XHCI_PM3_U1TO_SET(x) (((x) & 0xFF) << 0) /* RW - U1 timeout */
+#define XHCI_PM3_U2TO_GET(x) (((x) >> 8) & 0xFF) /* RW - U2 timeout */
+#define XHCI_PM3_U2TO_SET(x) (((x) & 0xFF) << 8) /* RW - U2 timeout */
+#define XHCI_PM3_FLA 0x00010000 /* RW - Force Link PM Accept */
+#define XHCI_PM2_L1S_GET(x) (((x) >> 0) & 0x7) /* RO - L1 status */
+#define XHCI_PM2_RWE 0x00000008 /* RW - remote wakup enable */
+#define XHCI_PM2_HIRD_GET(x) (((x) >> 4) & 0xF) /* RW - host initiated resume duration */
+#define XHCI_PM2_HIRD_SET(x) (((x) & 0xF) << 4) /* RW - host initiated resume duration */
+#define XHCI_PM2_L1SLOT_GET(x) (((x) >> 8) & 0xFF) /* RW - L1 device slot */
+#define XHCI_PM2_L1SLOT_SET(x) (((x) & 0xFF) << 8) /* RW - L1 device slot */
+#define XHCI_PM2_HLE 0x00010000 /* RW - hardware LPM enable */
+#define XHCI_PORTLI(n) (0x3F8 + (0x10 * (n))) /* XHCI port link info */
+#define XHCI_PLI3_ERR_GET(x) (((x) >> 0) & 0xFFFF) /* RO - port link errors */
+#define XHCI_PORTRSV(n) (0x3FC + (0x10 * (n))) /* XHCI port reserved */
+
+/* XHCI runtime registers. Offset given by XHCI_CAPLENGTH + XHCI_RTSOFF registers */
+#define XHCI_MFINDEX 0x0000 /* RO - microframe index */
+#define XHCI_MFINDEX_GET(x) ((x) & 0x3FFF)
+#define XHCI_IMAN(n) (0x0020 + (0x20 * (n))) /* XHCI interrupt management */
+#define XHCI_IMAN_INTR_PEND 0x00000001 /* RW - interrupt pending */
+#define XHCI_IMAN_INTR_ENA 0x00000002 /* RW - interrupt enable */
+#define XHCI_IMOD(n) (0x0024 + (0x20 * (n))) /* XHCI interrupt moderation */
+#define XHCI_IMOD_IVAL_GET(x) (((x) >> 0) & 0xFFFF) /* 250ns unit */
+#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_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)
+#define XHCI_ERSTBA_LO(n) (0x0030 + (0x20 * (n))) /* XHCI event ring segment table BA */
+#define XHCI_ERSTBA_HI(n) (0x0034 + (0x20 * (n))) /* XHCI event ring segment table BA */
+#define XHCI_ERDP_LO(n) (0x0038 + (0x20 * (n))) /* XHCI event ring dequeue pointer */
+#define XHCI_ERDP_LO_SINDEX(x) ((x) & 0x7) /* RO - dequeue segment index */
+#define XHCI_ERDP_LO_BUSY 0x00000008 /* RW - event handler busy */
+#define XHCI_ERDP_HI(n) (0x003C + (0x20 * (n))) /* XHCI event ring dequeue pointer */
+
+/* XHCI doorbell registers. Offset given by XHCI_CAPLENGTH + XHCI_DBOFF registers */
+#define XHCI_DOORBELL(n) (0x0000 + (4 * (n)))
+#define XHCI_DB_TARGET_GET(x) ((x) & 0xFF) /* RW - doorbell target */
+#define XHCI_DB_TARGET_SET(x) ((x) & 0xFF) /* RW - doorbell target */
+#define XHCI_DB_SID_GET(x) (((x) >> 16) & 0xFFFF) /* RW - doorbell stream ID */
+#define XHCI_DB_SID_SET(x) (((x) & 0xFFFF) << 16) /* RW - doorbell stream ID */
+
+/* XHCI legacy support */
+#define XHCI_XECP_ID(x) ((x) & 0xFF)
+#define XHCI_XECP_NEXT(x) (((x) >> 8) & 0xFF)
+#define XHCI_XECP_BIOS_SEM 0x0002
+#define XHCI_XECP_OS_SEM 0x0003
+
+/* XHCI capability ID's */
+#define XHCI_ID_USB_LEGACY 0x0001
+#define XHCI_ID_PROTOCOLS 0x0002
+#define XHCI_ID_POWER_MGMT 0x0003
+#define XHCI_ID_VIRTUALIZATION 0x0004
+#define XHCI_ID_MSG_IRQ 0x0005
+#define XHCI_ID_USB_LOCAL_MEM 0x0006
+
+/* XHCI register R/W wrappers */
+#define XREAD1(sc, what, a) \
+ bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off)
+#define XREAD2(sc, what, a) \
+ bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off)
+#define XREAD4(sc, what, a) \
+ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off)
+#define XWRITE1(sc, what, a, x) \
+ bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off, (x))
+#define XWRITE2(sc, what, a, x) \
+ bus_space_write_2((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off, (x))
+#define XWRITE4(sc, what, a, x) \
+ bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, \
+ (a) + (sc)->sc_##what##_off, (x))
+
+#endif /* _XHCIREG_H_ */
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c
index 2df2de5e..9042c166 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.c
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c
@@ -96,6 +96,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
+ USB_QUIRK(PLANEX2, MZKUE150N, 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),
@@ -127,6 +128,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
/* MS keyboards do weird things */
USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO),
USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE),
+ /* Quirk for Corsair Vengeance K60 keyboard */
+ USB_QUIRK(CORSAIR, K60, 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),
@@ -254,6 +257,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(MICROTECH, DPCM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY,
UQ_MSC_NO_START_STOP),
+ USB_QUIRK(MICRON, REALSSD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(MICROTECH, SCSIDB25, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(MICROTECH, SCSIHD50, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -391,6 +395,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
+ USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW),
USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(TAUGA, CAMERAMATE, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
@@ -443,6 +448,9 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
+ USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+ USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+
/* Non-standard USB MIDI devices */
USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
@@ -460,7 +468,13 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+ USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
+ USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
+ USB_QUIRK(REDOCTANE, GHMIDI, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
+ USB_QUIRK(TEXTECH, U2M_1, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
+ USB_QUIRK(TEXTECH, U2M_2, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
+ USB_QUIRK(WCH2, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
/* Non-standard USB AUDIO devices */
USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
@@ -514,6 +528,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
[UQ_MSC_NO_GETMAXLUN] = "UQ_MSC_NO_GETMAXLUN",
[UQ_MSC_NO_INQUIRY] = "UQ_MSC_NO_INQUIRY",
[UQ_MSC_NO_INQUIRY_EVPD] = "UQ_MSC_NO_INQUIRY_EVPD",
+ [UQ_MSC_NO_PREVENT_ALLOW] = "UQ_MSC_NO_PREVENT_ALLOW",
[UQ_MSC_NO_SYNC_CACHE] = "UQ_MSC_NO_SYNC_CACHE",
[UQ_MSC_SHUTTLE_INIT] = "UQ_MSC_SHUTTLE_INIT",
[UQ_MSC_ALT_IFACE_1] = "UQ_MSC_ALT_IFACE_1",
diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h
index f2c10dd8..32a60a10 100644
--- a/freebsd/sys/dev/usb/quirk/usb_quirk.h
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h
@@ -75,6 +75,7 @@ enum {
UQ_MSC_NO_GETMAXLUN, /* does not support get max LUN */
UQ_MSC_NO_INQUIRY, /* fake generic inq response */
UQ_MSC_NO_INQUIRY_EVPD, /* does not support inq EVPD */
+ UQ_MSC_NO_PREVENT_ALLOW, /* does not support medium removal */
UQ_MSC_NO_SYNC_CACHE, /* does not support sync cache */
UQ_MSC_SHUTTLE_INIT, /* requires Shuttle init sequence */
UQ_MSC_ALT_IFACE_1, /* switch to alternate interface 1 */
diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c
index d3d2040f..76a1fcb6 100644
--- a/freebsd/sys/dev/usb/storage/umass.c
+++ b/freebsd/sys/dev/usb/storage/umass.c
@@ -139,14 +139,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
-#define UMASS_EXT_BUFFER
-#ifdef UMASS_EXT_BUFFER
-/* this enables loading of virtual buffers into DMA */
-#define UMASS_USB_FLAGS .ext_buffer=1,
-#else
-#define UMASS_USB_FLAGS
-#endif
-
#ifdef USB_DEBUG
#define DIF(m, x) \
do { \
@@ -173,19 +165,21 @@ __FBSDID("$FreeBSD$");
#define UDMASS_CBI 0x00400000 /* CBI transfers */
#define UDMASS_WIRE (UDMASS_BBB|UDMASS_CBI)
#define UDMASS_ALL 0xffff0000 /* all of the above */
-static int umass_debug = 0;
+static int umass_debug;
+static int umass_throttle;
-SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, umass, CTLFLAG_RW, 0, "USB umass");
SYSCTL_INT(_hw_usb_umass, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&umass_debug, 0, "umass debug level");
TUNABLE_INT("hw.usb.umass.debug", &umass_debug);
+SYSCTL_INT(_hw_usb_umass, OID_AUTO, throttle, CTLFLAG_RW | CTLFLAG_TUN,
+ &umass_throttle, 0, "Forced delay between commands in milliseconds");
+TUNABLE_INT("hw.usb.umass.throttle", &umass_throttle);
#else
#define DIF(...) do { } while (0)
#define DPRINTF(...) do { } while (0)
#endif
-#define UMASS_GONE ((struct umass_softc *)1)
-
#define UMASS_BULK_SIZE (1 << 17)
#define UMASS_CBI_DIAGNOSTIC_CMDLEN 12 /* bytes */
#define UMASS_MAX_CMDLEN MAX(12, CAM_MAX_CDBLEN) /* bytes */
@@ -373,6 +367,8 @@ typedef uint8_t (umass_transform_t)(struct umass_softc *sc, uint8_t *cmd_ptr,
* result.
*/
#define NO_SYNCHRONIZE_CACHE 0x4000
+ /* Device does not support 'PREVENT/ALLOW MEDIUM REMOVAL'. */
+#define NO_PREVENT_ALLOW 0x8000
struct umass_softc {
@@ -545,7 +541,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_bbb_data_read_callback,
.timeout = 0, /* overwritten later */
},
@@ -564,7 +560,7 @@ static struct usb_config umass_bbb_config[UMASS_T_BBB_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_bbb_data_write_callback,
.timeout = 0, /* overwritten later */
},
@@ -637,7 +633,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_cbi_data_read_callback,
.timeout = 0, /* overwritten later */
},
@@ -656,7 +652,7 @@ static struct usb_config umass_cbi_config[UMASS_T_CBI_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = UMASS_BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer=1,},
.callback = &umass_t_cbi_data_write_callback,
.timeout = 0, /* overwritten later */
},
@@ -845,6 +841,8 @@ umass_probe_proto(device_t dev, struct usb_attach_arg *uaa)
quirks |= NO_INQUIRY;
if (usb_test_quirk(uaa, UQ_MSC_NO_INQUIRY_EVPD))
quirks |= NO_INQUIRY_EVPD;
+ if (usb_test_quirk(uaa, UQ_MSC_NO_PREVENT_ALLOW))
+ quirks |= NO_PREVENT_ALLOW;
if (usb_test_quirk(uaa, UQ_MSC_NO_SYNC_CACHE))
quirks |= NO_SYNCHRONIZE_CACHE;
if (usb_test_quirk(uaa, UQ_MSC_SHUTTLE_INIT))
@@ -891,7 +889,7 @@ umass_attach(device_t dev)
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct umass_probe_proto temp = umass_probe_proto(dev, uaa);
struct usb_interface_descriptor *id;
- int32_t err;
+ int err;
/*
* NOTE: the softc struct is cleared in device_set_driver.
@@ -1004,6 +1002,24 @@ umass_attach(device_t dev)
"transfers, %s\n", usbd_errstr(err));
goto detach;
}
+#ifdef USB_DEBUG
+ if (umass_throttle > 0) {
+ uint8_t x;
+ int iv;
+
+ iv = umass_throttle;
+
+ if (iv < 1)
+ iv = 1;
+ else if (iv > 8000)
+ iv = 8000;
+
+ for (x = 0; x != UMASS_T_MAX; x++) {
+ if (sc->sc_xfer[x] != NULL)
+ usbd_xfer_set_interval(sc->sc_xfer[x], iv);
+ }
+ }
+#endif
sc->sc_transform =
(sc->sc_proto & UMASS_PROTO_SCSI) ? &umass_scsi_transform :
(sc->sc_proto & UMASS_PROTO_UFI) ? &umass_ufi_transform :
@@ -1058,14 +1074,16 @@ umass_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UMASS_T_MAX);
-#if (__FreeBSD_version >= 700037)
mtx_lock(&sc->sc_mtx);
-#endif
+
+ /* cancel any leftover CCB's */
+
+ umass_cancel_ccb(sc);
+
umass_cam_detach_sim(sc);
-#if (__FreeBSD_version >= 700037)
mtx_unlock(&sc->sc_mtx);
-#endif
+
mtx_destroy(&sc->sc_mtx);
return (0); /* success */
@@ -1206,7 +1224,6 @@ umass_t_bbb_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1245,7 +1262,6 @@ tr_transferred:
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1331,7 +1347,6 @@ umass_t_bbb_command_callback(struct usb_xfer *xfer, usb_error_t error)
default: /* Error */
umass_tr_error(xfer, error);
return;
-
}
}
@@ -1340,19 +1355,12 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-#ifndef UMASS_EXT_BUFFER
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen);
-#endif
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.actlen += actlen;
@@ -1374,12 +1382,9 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
+
usbd_transfer_submit(xfer);
return;
@@ -1390,7 +1395,6 @@ umass_t_bbb_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS);
}
return;
-
}
}
@@ -1406,9 +1410,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -1436,14 +1437,8 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk);
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
usbd_transfer_submit(xfer);
return;
@@ -1455,7 +1450,6 @@ umass_t_bbb_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_BBB_DATA_WR_CS);
}
return;
-
}
}
@@ -1581,7 +1575,6 @@ tr_error:
umass_transfer_start(sc, UMASS_T_BBB_DATA_RD_CS);
}
return;
-
}
}
@@ -1612,8 +1605,7 @@ umass_command_start(struct umass_softc *sc, uint8_t dir,
if (sc->sc_xfer[sc->sc_last_xfer_index]) {
usbd_transfer_start(sc->sc_xfer[sc->sc_last_xfer_index]);
} else {
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
+ umass_cancel_ccb(sc);
}
}
@@ -1733,7 +1725,6 @@ umass_t_cbi_reset1_callback(struct usb_xfer *xfer, usb_error_t error)
else
umass_transfer_start(sc, UMASS_T_CBI_RESET2);
break;
-
}
}
@@ -1788,7 +1779,6 @@ tr_transferred:
default: /* Error */
umass_tr_error(xfer, error);
break;
-
}
}
@@ -1878,19 +1868,12 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-#ifndef UMASS_EXT_BUFFER
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_out(pc, 0, sc->sc_transfer.data_ptr, actlen);
-#endif
sc->sc_transfer.data_rem -= actlen;
sc->sc_transfer.data_ptr += actlen;
sc->sc_transfer.actlen += actlen;
@@ -1912,12 +1895,9 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
+
usbd_transfer_submit(xfer);
break;
@@ -1929,7 +1909,6 @@ umass_t_cbi_data_read_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_CBI_DATA_RD_CS);
}
break;
-
}
}
@@ -1945,9 +1924,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct umass_softc *sc = usbd_xfer_softc(xfer);
uint32_t max_bulk = usbd_xfer_max_len(xfer);
-#ifndef UMASS_EXT_BUFFER
- struct usb_page_cache *pc;
-#endif
int actlen, sumlen;
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
@@ -1975,14 +1951,8 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
}
usbd_xfer_set_timeout(xfer, sc->sc_transfer.data_timeout);
-#ifdef UMASS_EXT_BUFFER
usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
max_bulk);
-#else
- pc = usbd_xfer_get_frame(xfer, 0);
- usbd_copy_in(pc, 0, sc->sc_transfer.data_ptr, max_bulk);
- usbd_xfer_set_frame_len(xfer, 0, max_bulk);
-#endif
usbd_transfer_submit(xfer);
break;
@@ -1995,7 +1965,6 @@ umass_t_cbi_data_write_callback(struct usb_xfer *xfer, usb_error_t error)
umass_transfer_start(sc, UMASS_T_CBI_DATA_WR_CS);
}
break;
-
}
}
@@ -2097,7 +2066,6 @@ tr_setup:
usbd_errstr(error));
umass_tr_error(xfer, error);
break;
-
}
}
@@ -2126,9 +2094,7 @@ umass_cam_attach_sim(struct umass_softc *sc)
DEVNAME_SIM,
sc /* priv */ ,
sc->sc_unit /* unit number */ ,
-#if (__FreeBSD_version >= 700037)
&sc->sc_mtx /* mutex */ ,
-#endif
1 /* maximum device openings */ ,
0 /* maximum tagged device openings */ ,
devq);
@@ -2138,27 +2104,15 @@ umass_cam_attach_sim(struct umass_softc *sc)
return (ENOMEM);
}
-#if (__FreeBSD_version >= 700037)
mtx_lock(&sc->sc_mtx);
-#endif
-#if (__FreeBSD_version >= 700048)
- if (xpt_bus_register(sc->sc_sim, sc->sc_dev, sc->sc_unit) != CAM_SUCCESS) {
+ if (xpt_bus_register(sc->sc_sim, sc->sc_dev,
+ sc->sc_unit) != CAM_SUCCESS) {
mtx_unlock(&sc->sc_mtx);
return (ENOMEM);
}
-#else
- if (xpt_bus_register(sc->sc_sim, sc->sc_unit) != CAM_SUCCESS) {
-#if (__FreeBSD_version >= 700037)
- mtx_unlock(&sc->sc_mtx);
-#endif
- return (ENOMEM);
- }
-#endif
-
-#if (__FreeBSD_version >= 700037)
mtx_unlock(&sc->sc_mtx);
-#endif
+
return (0);
}
@@ -2186,7 +2140,7 @@ umass_cam_detach_sim(struct umass_softc *sc)
if (sc->sc_sim != NULL) {
if (xpt_bus_deregister(cam_sim_path(sc->sc_sim))) {
/* accessing the softc is not possible after this */
- sc->sc_sim->softc = UMASS_GONE;
+ sc->sc_sim->softc = NULL;
cam_sim_free(sc->sc_sim, /* free_devq */ TRUE);
} else {
panic("%s: CAM layer is busy\n",
@@ -2205,68 +2159,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
{
struct umass_softc *sc = (struct umass_softc *)sim->softc;
- if (sc == UMASS_GONE ||
- (sc != NULL && !usbd_device_attached(sc->sc_udev))) {
+ if (sc == NULL) {
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
xpt_done(ccb);
return;
}
- if (sc) {
-#if (__FreeBSD_version < 700037)
- mtx_lock(&sc->sc_mtx);
-#endif
- }
- /*
- * Verify, depending on the operation to perform, that we either got
- * a valid sc, because an existing target was referenced, or
- * otherwise the SIM is addressed.
- *
- * This avoids bombing out at a printf and does give the CAM layer some
- * sensible feedback on errors.
- */
- switch (ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- case XPT_RESET_DEV:
- case XPT_GET_TRAN_SETTINGS:
- case XPT_SET_TRAN_SETTINGS:
- case XPT_CALC_GEOMETRY:
- /* the opcodes requiring a target. These should never occur. */
- if (sc == NULL) {
- DPRINTF(sc, UDMASS_GEN, "%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target (target needed)\n",
- DEVNAME_SIM, cam_sim_path(sc->sc_sim),
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code);
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- goto done;
- }
- break;
- case XPT_PATH_INQ:
- case XPT_NOOP:
- /*
- * The opcodes sometimes aimed at a target (sc is valid),
- * sometimes aimed at the SIM (sc is invalid and target is
- * CAM_TARGET_WILDCARD)
- */
- if ((sc == NULL) &&
- (ccb->ccb_h.target_id != CAM_TARGET_WILDCARD)) {
- DPRINTF(sc, UDMASS_SCSI, "%s:%d:%d:%d:func_code 0x%04x: "
- "Invalid target (no wildcard)\n",
- DEVNAME_SIM, cam_sim_path(sc->sc_sim),
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
- ccb->ccb_h.func_code);
-
- ccb->ccb_h.status = CAM_TID_INVALID;
- xpt_done(ccb);
- goto done;
- }
- break;
- default:
- /* XXX Hm, we should check the input parameters */
- break;
- }
/* Perform the requested action */
switch (ccb->ccb_h.func_code) {
@@ -2353,17 +2250,20 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
*/
if ((sc->sc_quirks & (NO_INQUIRY_EVPD | NO_INQUIRY)) &&
(sc->sc_transfer.cmd_data[1] & SI_EVPD)) {
- struct scsi_sense_data *sense;
-
- sense = &ccb->csio.sense_data;
- bzero(sense, sizeof(*sense));
- sense->error_code = SSD_CURRENT_ERROR;
- sense->flags = SSD_KEY_ILLEGAL_REQUEST;
- sense->add_sense_code = 0x24;
- sense->extra_len = 10;
+
+ scsi_set_sense_data(&ccb->csio.sense_data,
+ /*sense_format*/ SSD_TYPE_NONE,
+ /*current_error*/ 1,
+ /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
+ /*asc*/ 0x24,
+ /*ascq*/ 0x00,
+ /*extra args*/ SSD_ELEM_NONE);
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
- CAM_AUTOSNS_VALID;
+ ccb->ccb_h.status =
+ CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID |
+ CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
xpt_done(ccb);
goto done;
}
@@ -2382,6 +2282,13 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
if (sc->sc_quirks & FORCE_SHORT_INQUIRY) {
ccb->csio.dxfer_len = SHORT_INQUIRY_LENGTH;
}
+ } else if (sc->sc_transfer.cmd_data[0] == PREVENT_ALLOW) {
+ if (sc->sc_quirks & NO_PREVENT_ALLOW) {
+ ccb->csio.scsi_status = SCSI_STATUS_OK;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ goto done;
+ }
} else if (sc->sc_transfer.cmd_data[0] == SYNCHRONIZE_CACHE) {
if (sc->sc_quirks & NO_SYNCHRONIZE_CACHE) {
ccb->csio.scsi_status = SCSI_STATUS_OK;
@@ -2418,12 +2325,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
cpi->unit_number = cam_sim_unit(sim);
cpi->bus_id = sc->sc_unit;
-#if (__FreeBSD_version >= 700025)
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
cpi->transport = XPORT_USB;
cpi->transport_version = 0;
-#endif
+
if (sc == NULL) {
cpi->base_transfer_speed = 0;
cpi->max_lun = 0;
@@ -2475,16 +2381,12 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
cam_sim_path(sc->sc_sim), ccb->ccb_h.target_id,
ccb->ccb_h.target_lun);
-#if (__FreeBSD_version >= 700025)
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_USB;
cts->transport_version = 0;
cts->xport_specific.valid = 0;
-#else
- cts->valid = 0;
- cts->flags = 0; /* no disconnection, tagging */
-#endif
+
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -2529,11 +2431,6 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
}
done:
-#if (__FreeBSD_version < 700037)
- if (sc) {
- mtx_unlock(&sc->sc_mtx);
- }
-#endif
return;
}
@@ -2542,7 +2439,7 @@ umass_cam_poll(struct cam_sim *sim)
{
struct umass_softc *sc = (struct umass_softc *)sim->softc;
- if (sc == UMASS_GONE)
+ if (sc == NULL)
return;
DPRINTF(sc, UDMASS_SCSI, "CAM poll\n");
@@ -2628,7 +2525,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* recovered. We return an error to CAM and let CAM
* retry the command if necessary.
*/
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
xpt_done(ccb);
break;
}
@@ -2642,12 +2540,17 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
uint8_t status)
{
uint8_t *cmd;
- uint8_t key;
switch (status) {
case STATUS_CMD_OK:
case STATUS_CMD_UNKNOWN:
- case STATUS_CMD_FAILED:
+ case STATUS_CMD_FAILED: {
+ int key, sense_len;
+
+ ccb->csio.sense_resid = residue;
+ sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
+ key = scsi_get_sense_key(&ccb->csio.sense_data, sense_len,
+ /*show_errors*/ 1);
if (ccb->csio.ccb_h.flags & CAM_CDB_POINTER) {
cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_ptr);
@@ -2655,8 +2558,6 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
cmd = (uint8_t *)(ccb->csio.cdb_io.cdb_bytes);
}
- key = (ccb->csio.sense_data.flags & SSD_KEY);
-
/*
* Getting sense data always succeeds (apart from wire
* failures):
@@ -2688,8 +2589,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* usual.
*/
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
#if 0
@@ -2700,34 +2602,40 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/* the rest of the command was filled in at attach */
- if (umass_std_transform(sc, ccb,
+ if ((sc->sc_transform)(sc,
&sc->cam_scsi_test_unit_ready.opcode,
- sizeof(sc->cam_scsi_test_unit_ready))) {
+ sizeof(sc->cam_scsi_test_unit_ready)) == 1) {
umass_command_start(sc, DIR_NONE, NULL, 0,
ccb->ccb_h.timeout,
&umass_cam_quirk_cb, ccb);
+ break;
}
- break;
} else {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ if (key >= 0) {
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ } else
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL
+ | CAM_DEV_QFRZN;
}
xpt_done(ccb);
break;
-
+ }
default:
DPRINTF(sc, UDMASS_SCSI, "Autosense failed, "
"status %d\n", status);
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN;
xpt_done(ccb);
}
}
/*
* This completion code just handles the fact that we sent a test-unit-ready
- * after having previously failed a READ CAPACITY with CHECK_COND. Even
- * though this command succeeded, we have to tell CAM to retry.
+ * after having previously failed a READ CAPACITY with CHECK_COND. The CCB
+ * status for CAM is already set earlier.
*/
static void
umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
@@ -2736,9 +2644,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
DPRINTF(sc, UDMASS_SCSI, "Test unit ready "
"returned status %d\n", status);
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
xpt_done(ccb);
}
@@ -3027,7 +2932,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb,
xpt_done(ccb);
return (0);
} else if (retval == 0) {
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN;
xpt_done(ccb);
return (0);
}
diff --git a/freebsd/sys/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h
index 2f216d27..9492d491 100644
--- a/freebsd/sys/dev/usb/usb.h
+++ b/freebsd/sys/dev/usb/usb.h
@@ -223,7 +223,8 @@ typedef struct usb_device_request usb_device_request_t;
#define UR_RESET_TT 0x09
#define UR_GET_TT_STATE 0x0a
#define UR_STOP_TT 0x0b
-#define UR_SET_HUB_DEPTH 0x0c
+#define UR_SET_AND_TEST 0x0c /* USB 2.0 only */
+#define UR_SET_HUB_DEPTH 0x0c /* USB 3.0 only */
#define USB_SS_HUB_DEPTH_MAX 5
#define UR_GET_PORT_ERR_COUNT 0x0d
@@ -246,6 +247,7 @@ typedef struct usb_device_request usb_device_request_t;
#define UHF_PORT_LINK_STATE 5
#define UHF_PORT_POWER 8
#define UHF_PORT_LOW_SPEED 9
+#define UHF_PORT_L1 10
#define UHF_C_PORT_CONNECTION 16
#define UHF_C_PORT_ENABLE 17
#define UHF_C_PORT_SUSPEND 18
@@ -253,6 +255,7 @@ typedef struct usb_device_request usb_device_request_t;
#define UHF_C_PORT_RESET 20
#define UHF_PORT_TEST 21
#define UHF_PORT_INDICATOR 22
+#define UHF_C_PORT_L1 23
/* SuperSpeed HUB specific features */
#define UHF_PORT_U1_TIMEOUT 23
@@ -322,7 +325,12 @@ struct usb_devcap_usb2ext_descriptor {
uByte bDescriptorType;
uByte bDevCapabilityType;
uDWord bmAttributes;
-#define USB_V2EXT_LPM 0x02
+#define USB_V2EXT_LPM (1U << 1)
+#define USB_V2EXT_BESL_SUPPORTED (1U << 2)
+#define USB_V2EXT_BESL_BASELINE_VALID (1U << 3)
+#define USB_V2EXT_BESL_DEEP_VALID (1U << 4)
+#define USB_V2EXT_BESL_BASELINE_GET(x) (((x) >> 8) & 0xF)
+#define USB_V2EXT_BESL_DEEP_GET(x) (((x) >> 12) & 0xF)
} __packed;
typedef struct usb_devcap_usb2ext_descriptor usb_devcap_usb2ext_descriptor_t;
@@ -669,6 +677,7 @@ struct usb_port_status {
#define UPS_SUSPEND 0x0004
#define UPS_OVERCURRENT_INDICATOR 0x0008
#define UPS_RESET 0x0010
+#define UPS_PORT_L1 0x0020 /* USB 2.0 only */
/* The link-state bits are valid for Super-Speed USB HUBs */
#define UPS_PORT_LINK_STATE_GET(x) (((x) >> 5) & 0xF)
#define UPS_PORT_LINK_STATE_SET(x) (((x) & 0xF) << 5)
@@ -699,7 +708,8 @@ struct usb_port_status {
#define UPS_C_SUSPEND 0x0004
#define UPS_C_OVERCURRENT_INDICATOR 0x0008
#define UPS_C_PORT_RESET 0x0010
-#define UPS_C_BH_PORT_RESET 0x0020
+#define UPS_C_PORT_L1 0x0020 /* USB 2.0 only */
+#define UPS_C_BH_PORT_RESET 0x0020 /* USB 3.0 only */
#define UPS_C_PORT_LINK_STATE 0x0040
#define UPS_C_PORT_CONFIG_ERROR 0x0080
} __packed;
diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c
index 7ca10d7b..7697b64c 100644
--- a/freebsd/sys/dev/usb/usb_dev.c
+++ b/freebsd/sys/dev/usb/usb_dev.c
@@ -83,7 +83,7 @@
#ifdef USB_DEBUG
static int usb_fifo_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device");
SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
&usb_fifo_debug, 0, "Debug Level");
TUNABLE_INT("hw.usb.dev.debug", &usb_fifo_debug);
@@ -770,7 +770,7 @@ usb_fifo_close(struct usb_fifo *f, int fflags)
/* check if a thread wants SIGIO */
if (f->async_p != NULL) {
PROC_LOCK(f->async_p);
- psignal(f->async_p, SIGIO);
+ kern_psignal(f->async_p, SIGIO);
PROC_UNLOCK(f->async_p);
f->async_p = NULL;
}
@@ -844,7 +844,7 @@ usb_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
struct usb_cdev_privdata *cpd;
int err, ep;
- DPRINTFN(2, "%s fflags=0x%08x\n", dev->si_name, fflags);
+ DPRINTFN(2, "%s fflags=0x%08x\n", devtoname(dev), fflags);
KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags"));
if (((fflags & FREAD) && !(pd->mode & FREAD)) ||
@@ -1584,7 +1584,7 @@ usb_fifo_wakeup(struct usb_fifo *f)
}
if (f->async_p != NULL) {
PROC_LOCK(f->async_p);
- psignal(f->async_p, SIGIO);
+ kern_psignal(f->async_p, SIGIO);
PROC_UNLOCK(f->async_p);
}
}
diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c
index 3a58158d..78ae3d8c 100644
--- a/freebsd/sys/dev/usb/usb_device.c
+++ b/freebsd/sys/dev/usb/usb_device.c
@@ -2431,77 +2431,6 @@ usbd_get_device_index(struct usb_device *udev)
}
#if USB_HAVE_DEVCTL
-/*------------------------------------------------------------------------*
- * usb_notify_addq
- *
- * This function will generate events for dev.
- *------------------------------------------------------------------------*/
-#ifndef BURN_BRIDGES
-static void
-usb_notify_addq_compat(const char *type, struct usb_device *udev)
-{
- char *data = NULL;
- const char *ntype;
- struct malloc_type *mt;
- const size_t buf_size = 512;
-
- /* Convert notify type */
- if (strcmp(type, "ATTACH") == 0)
- ntype = "+";
- else if (strcmp(type, "DETACH") == 0)
- ntype = "-";
- else
- return;
-
- mtx_lock(&malloc_mtx);
- mt = malloc_desc2type("bus"); /* XXX M_BUS */
- mtx_unlock(&malloc_mtx);
- if (mt == NULL)
- return;
-
- data = malloc(buf_size, mt, M_NOWAIT);
- if (data == NULL)
- return;
-
- /* String it all together. */
- snprintf(data, buf_size,
- "%s"
-#if USB_HAVE_UGEN
- "%s "
-#endif
- "at port=%u "
- "vendor=0x%04x "
- "product=0x%04x "
- "devclass=0x%02x "
- "devsubclass=0x%02x "
- "sernum=\"%s\" "
- "release=0x%04x "
-#if USB_HAVE_UGEN
- "on %s\n"
-#endif
- "",
- ntype,
-#if USB_HAVE_UGEN
- udev->ugen_name,
-#endif
- udev->port_no,
- UGETW(udev->ddesc.idVendor),
- UGETW(udev->ddesc.idProduct),
- udev->ddesc.bDeviceClass,
- udev->ddesc.bDeviceSubClass,
- usb_get_serial(udev),
- UGETW(udev->ddesc.bcdDevice)
-#if USB_HAVE_UGEN
- , udev->parent_hub != NULL ?
- udev->parent_hub->ugen_name :
- device_get_nameunit(device_get_parent(udev->bus->bdev))
-#endif
- );
-
- devctl_queue_data(data);
-}
-#endif
-
static void
usb_notify_addq(const char *type, struct usb_device *udev)
{
@@ -2509,10 +2438,6 @@ usb_notify_addq(const char *type, struct usb_device *udev)
struct sbuf *sb;
int i;
-#ifndef BURN_BRIDGES
- usb_notify_addq_compat(type, udev);
-#endif
-
/* announce the device */
sb = sbuf_new_auto();
sbuf_printf(sb,
diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h
index 03ddf1e6..8e13e3de 100644
--- a/freebsd/sys/dev/usb/usb_device.h
+++ b/freebsd/sys/dev/usb/usb_device.h
@@ -215,6 +215,7 @@ struct usb_device {
uint16_t power; /* mA the device uses */
uint16_t langid; /* language for strings */
+ uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */
uint8_t address; /* device addess */
uint8_t device_index; /* device index in "bus->devices" */
@@ -257,8 +258,6 @@ struct usb_device {
uint32_t clear_stall_errors; /* number of clear-stall failures */
- uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */
-
union usb_device_scratch scratch;
};
diff --git a/freebsd/sys/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h
index 8f9bb4c6..06369a25 100644
--- a/freebsd/sys/dev/usb/usb_freebsd.h
+++ b/freebsd/sys/dev/usb/usb_freebsd.h
@@ -48,7 +48,15 @@
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
+#if (!defined(USB_HOST_ALIGN)) || (USB_HOST_ALIGN <= 0)
+/* Use default value. */
+#undef USB_HOST_ALIGN
#define USB_HOST_ALIGN 8 /* bytes, must be power of two */
+#endif
+/* Sanity check for USB_HOST_ALIGN: Verify power of two. */
+#if ((-USB_HOST_ALIGN) & USB_HOST_ALIGN) != USB_HOST_ALIGN
+#error "USB_HOST_ALIGN is not power of two."
+#endif
#define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */
#define USB_BUS_MAX 256 /* units */
#define USB_MAX_DEVICES 128 /* units */
diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c
index 361ee2ef..a0b7f007 100644
--- a/freebsd/sys/dev/usb/usb_generic.c
+++ b/freebsd/sys/dev/usb/usb_generic.c
@@ -128,7 +128,7 @@ struct usb_fifo_methods usb_ugen_methods = {
#ifdef USB_DEBUG
static int ugen_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, ugen, CTLFLAG_RW, 0, "USB generic");
SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &ugen_debug,
0, "Debug level");
TUNABLE_INT("hw.usb.ugen.debug", &ugen_debug);
@@ -1833,6 +1833,17 @@ ugen_get_power_mode(struct usb_fifo *f)
}
static int
+ugen_get_power_usage(struct usb_fifo *f)
+{
+ struct usb_device *udev = f->udev;
+
+ if (udev == NULL)
+ return (0);
+
+ return (udev->power);
+}
+
+static int
ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no,
uint8_t set, uint16_t feature)
{
@@ -2194,6 +2205,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
*u.pint = ugen_get_power_mode(f);
break;
+ case USB_GET_POWER_USAGE:
+ *u.pint = ugen_get_power_usage(f);
+ break;
+
case USB_SET_PORT_ENABLE:
error = ugen_do_port_feature(f,
*u.pint, 1, UHF_PORT_ENABLE);
diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index 86fa27b0..737237bd 100644
--- a/freebsd/sys/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
@@ -847,3 +847,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
}
return (USB_ERR_NORMAL_COMPLETION);
}
+
+/*------------------------------------------------------------------------*
+ * hid_is_mouse
+ *
+ * This function will decide if a USB descriptor belongs to a USB mouse.
+ *
+ * Return values:
+ * Zero: Not a USB mouse.
+ * Else: Is a USB mouse.
+ *------------------------------------------------------------------------*/
+int
+hid_is_mouse(const void *d_ptr, uint16_t d_len)
+{
+ struct hid_data *hd;
+ struct hid_item hi;
+ int mdepth;
+ int found;
+
+ hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+ if (hd == NULL)
+ return (0);
+
+ mdepth = 0;
+ found = 0;
+
+ while (hid_get_item(hd, &hi)) {
+ switch (hi.kind) {
+ case hid_collection:
+ if (mdepth != 0)
+ mdepth++;
+ else if (hi.collection == 1 &&
+ hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+ mdepth++;
+ break;
+ case hid_endcollection:
+ if (mdepth != 0)
+ mdepth--;
+ break;
+ case hid_input:
+ if (mdepth == 0)
+ break;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ break;
+ default:
+ break;
+ }
+ }
+ hid_end_parse(hd);
+ return (found);
+}
+
+/*------------------------------------------------------------------------*
+ * hid_is_keyboard
+ *
+ * This function will decide if a USB descriptor belongs to a USB keyboard.
+ *
+ * Return values:
+ * Zero: Not a USB keyboard.
+ * Else: Is a USB keyboard.
+ *------------------------------------------------------------------------*/
+int
+hid_is_keyboard(const void *d_ptr, uint16_t d_len)
+{
+ if (hid_is_collection(d_ptr, d_len,
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
+ return (1);
+ return (0);
+}
diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index 97b3a4dd..2dee6784 100644
--- a/freebsd/sys/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
@@ -78,7 +78,7 @@
#ifdef USB_DEBUG
static int uhub_debug = 0;
-SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB HUB");
SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &uhub_debug, 0,
"Debug level");
TUNABLE_INT("hw.usb.uhub.debug", &uhub_debug);
diff --git a/freebsd/sys/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h
index 9af6ee5c..9e66bd5a 100644
--- a/freebsd/sys/dev/usb/usb_ioctl.h
+++ b/freebsd/sys/dev/usb/usb_ioctl.h
@@ -270,7 +270,8 @@ struct usb_gen_quirk {
#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 - 135 unused */
+/* 128 - 134 unused */
+#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)
#define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int)
diff --git a/freebsd/sys/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c
index 5e8eebb3..fcb9f026 100644
--- a/freebsd/sys/dev/usb/usb_msctest.c
+++ b/freebsd/sys/dev/usb/usb_msctest.c
@@ -64,7 +64,6 @@
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_msctest.h>
#include <dev/usb/usb_debug.h>
-#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_util.h>
@@ -106,6 +105,8 @@ static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -481,7 +482,7 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
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, &sc->cbw.CBWCDB, ":");
+ DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
mtx_lock(&sc->mtx);
usbd_transfer_start(sc->xfer[sc->state]);
@@ -650,7 +651,7 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
}
is_no_direct = 1;
- for (timeout = 4; timeout; timeout--) {
+ for (timeout = 4; timeout != 0; timeout--) {
err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
USB_MS_HZ);
@@ -660,8 +661,11 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
if (sid_type == 0x00)
is_no_direct = 0;
break;
- } else if (err != ERR_CSW_FAILED)
- break; /* non retryable error */
+ } else if (err != ERR_CSW_FAILED) {
+ DPRINTF("Device is not responding "
+ "properly to SCSI INQUIRY command.\n");
+ goto error; /* non retryable error */
+ }
usb_pause_mtx(NULL, hz);
}
@@ -679,7 +683,9 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
if (err != ERR_CSW_FAILED)
goto error;
}
+ timeout = 1;
+retry_sync_cache:
err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
&scsi_sync_cache, sizeof(scsi_sync_cache),
USB_MS_HZ);
@@ -692,6 +698,42 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
DPRINTF("Device doesn't handle synchronize cache\n");
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+
+ } else {
+
+ /*
+ * Certain Kingston memory sticks fail the first
+ * read capacity after a synchronize cache command
+ * has been issued. Disable the synchronize cache
+ * command for such devices.
+ */
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err != 0) {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err == 0) {
+ if (timeout--)
+ goto retry_sync_cache;
+
+ DPRINTF("Device most likely doesn't "
+ "handle synchronize cache\n");
+
+ usbd_add_dynamic_quirk(udev,
+ UQ_MSC_NO_SYNC_CACHE);
+ } else {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+ }
}
/* clear sense status of any failed commands on the device */
diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c
index fb422df4..59b26567 100644
--- a/freebsd/sys/dev/usb/usb_process.c
+++ b/freebsd/sys/dev/usb/usb_process.c
@@ -69,17 +69,13 @@ static int usb_pcount;
#define USB_THREAD_CREATE(f, s, p, ...) \
kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \
0, "usb", __VA_ARGS__)
-#if (__FreeBSD_version >= 900000)
#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check()
-#else
-#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curthread)
-#endif
#define USB_THREAD_SUSPEND(p) kthread_suspend(p,0)
#define USB_THREAD_EXIT(err) kthread_exit()
#else
#define USB_THREAD_CREATE(f, s, p, ...) \
kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
-#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curproc)
+#define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check()
#define USB_THREAD_SUSPEND(p) kthread_suspend(p,0)
#define USB_THREAD_EXIT(err) kthread_exit(err)
#endif
@@ -87,7 +83,7 @@ static int usb_pcount;
#ifdef USB_DEBUG
static int usb_proc_debug;
-SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_proc_debug, 0,
"Debug level");
TUNABLE_INT("hw.usb.proc.debug", &usb_proc_debug);
diff --git a/freebsd/sys/dev/usb/usb_process.h b/freebsd/sys/dev/usb/usb_process.h
index 23cf6607..9b1a8534 100644
--- a/freebsd/sys/dev/usb/usb_process.h
+++ b/freebsd/sys/dev/usb/usb_process.h
@@ -42,6 +42,7 @@
/* structure prototypes */
struct usb_proc_msg;
+struct usb_device;
/*
* The following structure defines the USB process.
@@ -79,4 +80,9 @@ 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);
+void usb_proc_explore_mwait(struct usb_device *, void *, void *);
+void *usb_proc_explore_msignal(struct usb_device *, void *, void *);
+void usb_proc_explore_lock(struct usb_device *);
+void usb_proc_explore_unlock(struct usb_device *);
+
#endif /* _USB_PROCESS_H_ */
diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c
index 2897cadb..167a7228 100644
--- a/freebsd/sys/dev/usb/usb_request.c
+++ b/freebsd/sys/dev/usb/usb_request.c
@@ -2158,3 +2158,57 @@ usbd_req_set_port_link_state(struct usb_device *udev, struct mtx *mtx,
USETW(req.wLength, 0);
return (usbd_do_request(udev, mtx, &req, 0));
}
+
+/*------------------------------------------------------------------------*
+ * usbd_req_set_lpm_info
+ *
+ * USB 2.0 specific request for Link Power Management.
+ *
+ * Returns:
+ * 0: Success
+ * USB_ERR_PENDING_REQUESTS: NYET
+ * USB_ERR_TIMEOUT: TIMEOUT
+ * USB_ERR_STALL: STALL
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe)
+{
+ struct usb_device_request req;
+ usb_error_t err;
+ uint8_t buf[1];
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_SET_AND_TEST;
+ USETW(req.wValue, UHF_PORT_L1);
+ req.wIndex[0] = (port & 0xF) | ((besl & 0xF) << 4);
+ req.wIndex[1] = (addr & 0x7F) | (rwe ? 0x80 : 0x00);
+ USETW(req.wLength, sizeof(buf));
+
+ /* set default value in case of short transfer */
+ buf[0] = 0x00;
+
+ err = usbd_do_request(udev, mtx, &req, buf);
+ if (err)
+ return (err);
+
+ switch (buf[0]) {
+ case 0x00: /* SUCCESS */
+ break;
+ case 0x10: /* NYET */
+ err = USB_ERR_PENDING_REQUESTS;
+ break;
+ case 0x11: /* TIMEOUT */
+ err = USB_ERR_TIMEOUT;
+ break;
+ case 0x30: /* STALL */
+ err = USB_ERR_STALLED;
+ break;
+ default: /* reserved */
+ err = USB_ERR_IOERROR;
+ break;
+ }
+ return (err);
+}
+
diff --git a/freebsd/sys/dev/usb/usb_request.h b/freebsd/sys/dev/usb/usb_request.h
index 74823af2..5fcedd5e 100644
--- a/freebsd/sys/dev/usb/usb_request.h
+++ b/freebsd/sys/dev/usb/usb_request.h
@@ -91,5 +91,7 @@ usb_error_t usbd_req_clear_tt_buffer(struct usb_device *udev, struct mtx *mtx,
uint8_t port, uint8_t addr, uint8_t type, uint8_t endpoint);
usb_error_t usbd_req_set_port_link_state(struct usb_device *udev,
struct mtx *mtx, uint8_t port, uint8_t link_state);
+usb_error_t usbd_req_set_lpm_info(struct usb_device *udev, struct mtx *mtx,
+ uint8_t port, uint8_t besl, uint8_t addr, uint8_t rwe);
#endif /* _USB_REQUEST_H_ */
diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c
index d3d41709..b2528186 100644
--- a/freebsd/sys/dev/usb/usb_transfer.c
+++ b/freebsd/sys/dev/usb/usb_transfer.c
@@ -2206,7 +2206,7 @@ usbd_callback_wrapper(struct usb_xfer_queue *pq)
struct usb_xfer_root *info = xfer->xroot;
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
- if (!mtx_owned(info->xfer_mtx)) {
+ if (!mtx_owned(info->xfer_mtx) && !SCHEDULER_STOPPED()) {
/*
* Cases that end up here:
*
@@ -3179,14 +3179,14 @@ usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
/* make sure that the BUS mutex is not locked */
drop_bus = 0;
- while (mtx_owned(&xroot->udev->bus->bus_mtx)) {
+ while (mtx_owned(&xroot->udev->bus->bus_mtx) && !SCHEDULER_STOPPED()) {
mtx_unlock(&xroot->udev->bus->bus_mtx);
drop_bus++;
}
/* make sure that the transfer mutex is not locked */
drop_xfer = 0;
- while (mtx_owned(xroot->xfer_mtx)) {
+ while (mtx_owned(xroot->xfer_mtx) && !SCHEDULER_STOPPED()) {
mtx_unlock(xroot->xfer_mtx);
drop_xfer++;
}
diff --git a/freebsd/sys/dev/usb/usb_util.c b/freebsd/sys/dev/usb/usb_util.c
index 5c56da87..24558b84 100644
--- a/freebsd/sys/dev/usb/usb_util.c
+++ b/freebsd/sys/dev/usb/usb_util.c
@@ -60,31 +60,6 @@
#include <dev/usb/usb_bus.h>
/*------------------------------------------------------------------------*
- * device_delete_all_children - delete all children of a device
- *------------------------------------------------------------------------*/
-#ifndef device_delete_all_children
-int
-device_delete_all_children(device_t dev)
-{
- device_t *devlist;
- int devcount;
- int error;
-
- error = device_get_children(dev, &devlist, &devcount);
- if (error == 0) {
- while (devcount-- > 0) {
- error = device_delete_child(dev, devlist[devcount]);
- if (error) {
- break;
- }
- }
- free(devlist, M_TEMP);
- }
- return (error);
-}
-#endif
-
-/*------------------------------------------------------------------------*
* device_set_usb_desc
*
* This function can be called at probe or attach to set the USB
@@ -150,33 +125,21 @@ device_set_usb_desc(device_t dev)
*
* This function will delay the code by the passed number of system
* ticks. The passed mutex "mtx" will be dropped while waiting, if
- * "mtx" is not NULL.
+ * "mtx" is different from NULL.
*------------------------------------------------------------------------*/
void
-usb_pause_mtx(struct mtx *mtx, int _ticks)
+usb_pause_mtx(struct mtx *mtx, int timo)
{
if (mtx != NULL)
mtx_unlock(mtx);
- if (cold) {
- /* convert to milliseconds */
- _ticks = (_ticks * 1000) / hz;
- /* convert to microseconds, rounded up */
- _ticks = (_ticks + 1) * 1000;
- DELAY(_ticks);
-
- } else {
+ /*
+ * Add one tick to the timeout so that we don't return too
+ * early! Note that pause() will assert that the passed
+ * timeout is positive and non-zero!
+ */
+ pause("USBWAIT", timo + 1);
- /*
- * Add one to the number of ticks so that we don't return
- * too early!
- */
- _ticks++;
-
- if (pause("USBWAIT", _ticks)) {
- /* ignore */
- }
- }
if (mtx != NULL)
mtx_lock(mtx);
}
diff --git a/freebsd/sys/dev/usb/usb_util.h b/freebsd/sys/dev/usb/usb_util.h
index 35abeddd..7e52404f 100644
--- a/freebsd/sys/dev/usb/usb_util.h
+++ b/freebsd/sys/dev/usb/usb_util.h
@@ -27,7 +27,6 @@
#ifndef _USB_UTIL_H_
#define _USB_UTIL_H_
-int device_delete_all_children(device_t dev);
uint8_t usb_make_str_desc(void *ptr, uint16_t max_len, const char *s);
void usb_printbcd(char *p, uint16_t p_len, uint16_t bcd);
void usb_trim_spaces(char *p);
diff --git a/freebsd/sys/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h
index f40232aa..f6c447ca 100644
--- a/freebsd/sys/dev/usb/usbhid.h
+++ b/freebsd/sys/dev/usb/usbhid.h
@@ -242,5 +242,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb(
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
void **descp, uint16_t *sizep, struct malloc_type *mem,
uint8_t iface_index);
+int hid_is_mouse(const void *d_ptr, uint16_t d_len);
+int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
#endif /* _KERNEL */
#endif /* _USB_HID_H_ */