From 8e65e1bf45102e481fda77f5b742de6c7d0840cd Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 23 Aug 2016 15:51:45 +0200 Subject: usb: Update to FreeBSD trunk 2016-08-23 FreeBSD trunk, 2016-08-23, 9fe7c416e6abb28b1398fd3e5687099846800cfd. --- freebsd/sys/dev/usb/controller/dwc_otg.c | 41 ++++++++------ freebsd/sys/dev/usb/controller/ehci.c | 69 ++++++++++++++--------- freebsd/sys/dev/usb/controller/ehci.h | 9 ++- freebsd/sys/dev/usb/controller/ehcireg.h | 26 ++++++++- freebsd/sys/dev/usb/controller/ohci.c | 4 +- freebsd/sys/dev/usb/controller/xhcireg.h | 10 ++-- freebsd/sys/dev/usb/quirk/usb_quirk.c | 8 ++- freebsd/sys/dev/usb/storage/umass.c | 15 +++-- freebsd/sys/dev/usb/usb_busdma.c | 31 +++++----- freebsd/sys/dev/usb/usb_cdc.h | 2 +- freebsd/sys/dev/usb/usb_dev.c | 10 +++- freebsd/sys/dev/usb/usb_device.c | 50 ++++++++++++---- freebsd/sys/dev/usb/usb_device.h | 3 + freebsd/sys/dev/usb/usb_handle_request.c | 2 +- freebsd/sys/dev/usb/usb_hid.c | 5 +- freebsd/sys/dev/usb/usb_hub.c | 8 ++- freebsd/sys/dev/usb/usb_lookup.c | 97 ++++++++++---------------------- freebsd/sys/dev/usb/usb_transfer.c | 8 +-- freebsd/sys/dev/usb/usbdi.h | 69 +++++++++++++++++------ 19 files changed, 279 insertions(+), 188 deletions(-) (limited to 'freebsd') diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c index 028047a3..d070f145 100644 --- a/freebsd/sys/dev/usb/controller/dwc_otg.c +++ b/freebsd/sys/dev/usb/controller/dwc_otg.c @@ -95,17 +95,6 @@ #define DWC_OTG_PC2UDEV(pc) \ (USB_DMATAG_TO_XROOT((pc)->tag_parent)->udev) -#define DWC_OTG_MSK_GINT_ENABLED \ - (GINTMSK_ENUMDONEMSK | \ - GINTMSK_USBRSTMSK | \ - GINTMSK_USBSUSPMSK | \ - GINTMSK_IEPINTMSK | \ - GINTMSK_SESSREQINTMSK | \ - GINTMSK_RXFLVLMSK | \ - GINTMSK_HCHINTMSK | \ - GINTMSK_OTGINTMSK | \ - GINTMSK_PRTINTMSK) - #define DWC_OTG_MSK_GINT_THREAD_IRQ \ (GINTSTS_USBRST | GINTSTS_ENUMDONE | GINTSTS_PRTINT | \ GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTMSK_OTGINTMSK | \ @@ -378,6 +367,11 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode) /* enable all host channel interrupts */ DWC_OTG_WRITE_4(sc, DOTG_HAINTMSK, (1U << sc->sc_host_ch_max) - 1U); + + /* enable proper host channel interrupts */ + sc->sc_irq_mask |= GINTMSK_HCHINTMSK; + sc->sc_irq_mask &= ~GINTMSK_IEPINTMSK; + DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); } if (mode == DWC_MODE_DEVICE) { @@ -438,6 +432,11 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode) pf->usb.max_in_frame_size, pf->usb.max_out_frame_size); } + + /* enable proper device channel interrupts */ + sc->sc_irq_mask &= ~GINTMSK_HCHINTMSK; + sc->sc_irq_mask |= GINTMSK_IEPINTMSK; + DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); } /* reset RX FIFO */ @@ -2872,10 +2871,13 @@ dwc_otg_filter_interrupt(void *arg) for (x = 0; x != sc->sc_dev_in_ep_max; x++) { temp = DWC_OTG_READ_4(sc, DOTG_DIEPINT(x)); - if (temp & DIEPMSK_XFERCOMPLMSK) { - DWC_OTG_WRITE_4(sc, DOTG_DIEPINT(x), - DIEPMSK_XFERCOMPLMSK); - } + /* + * NOTE: Need to clear all interrupt bits, + * because some appears to be unmaskable and + * can cause an interrupt loop: + */ + if (temp != 0) + DWC_OTG_WRITE_4(sc, DOTG_DIEPINT(x), temp); } } @@ -2987,7 +2989,8 @@ dwc_otg_interrupt(void *arg) else sc->sc_flags.status_bus_reset = 0; - if (hprt & HPRT_PRTENCHNG) + if ((hprt & HPRT_PRTENCHNG) && + (hprt & HPRT_PRTENA) == 0) sc->sc_flags.change_enabled = 1; if (hprt & HPRT_PRTENA) @@ -3334,7 +3337,7 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer) * type in general, as a means to workaround * that. This trick should work for both FULL and LOW * speed USB traffic going through a TT. For non-TT - * traffic it works aswell. The reason for using + * traffic it works as well. The reason for using * CONTROL type instead of BULK is that some TTs might * reject LOW speed BULK traffic. */ @@ -3981,7 +3984,7 @@ dwc_otg_init(struct dwc_otg_softc *sc) } /* enable interrupts */ - sc->sc_irq_mask = DWC_OTG_MSK_GINT_ENABLED; + sc->sc_irq_mask |= DWC_OTG_MSK_GINT_THREAD_IRQ; DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); if (sc->sc_mode == DWC_MODE_OTG || sc->sc_mode == DWC_MODE_DEVICE) { @@ -4747,6 +4750,8 @@ tr_handle_get_port_status: value = 0; + if (sc->sc_flags.change_enabled) + value |= UPS_C_PORT_ENABLED; if (sc->sc_flags.change_connect) value |= UPS_C_CONNECT_STATUS; if (sc->sc_flags.change_suspend) diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c index 7da7e27d..827399cb 100644 --- a/freebsd/sys/dev/usb/controller/ehci.c +++ b/freebsd/sys/dev/usb/controller/ehci.c @@ -191,24 +191,8 @@ ehci_reset(ehci_softc_t *sc) usb_pause_mtx(NULL, hz / 128); hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; if (!hcr) { - if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) { - /* - * Force USBMODE as requested. Controllers - * may have multiple operating modes. - */ - uint32_t usbmode = EOREAD4(sc, EHCI_USBMODE); - if (sc->sc_flags & EHCI_SCFLG_SETMODE) { - usbmode = (usbmode &~ EHCI_UM_CM) | EHCI_UM_CM_HOST; - device_printf(sc->sc_bus.bdev, - "set host controller mode\n"); - } - if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) { - usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE; - device_printf(sc->sc_bus.bdev, - "set big-endian mode\n"); - } - EOWRITE4(sc, EHCI_USBMODE, usbmode); - } + if (sc->sc_vendor_post_reset != NULL) + sc->sc_vendor_post_reset(sc); return (0); } } @@ -1685,8 +1669,7 @@ restart: /* update data toggle */ - if (((average + temp->max_frame_size - 1) / - temp->max_frame_size) & 1) { + if (howmany(average, temp->max_frame_size) & 1) { temp->qtd_status ^= htohc32(temp->sc, EHCI_QTD_TOGGLE_MASK); } @@ -3022,7 +3005,7 @@ struct usb_device_descriptor ehci_devd = UDPROTO_HSHUBSTT, /* protocol */ 64, /* max packet */ {0}, {0}, {0x00, 0x01}, /* device id */ - 1, 2, 0, /* string indicies */ + 1, 2, 0, /* string indexes */ 1 /* # of configurations */ }; @@ -3076,6 +3059,36 @@ struct usb_hub_descriptor ehci_hubd = .bDescriptorType = UDESC_HUB, }; +uint16_t +ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index) +{ + uint32_t v; + + v = EOREAD4(sc, EHCI_PORTSC(index)); + v = (v >> EHCI_PORTSC_PSPD_SHIFT) & EHCI_PORTSC_PSPD_MASK; + + if (v == EHCI_PORT_SPEED_HIGH) + return (UPS_HIGH_SPEED); + if (v == EHCI_PORT_SPEED_LOW) + return (UPS_LOW_SPEED); + return (0); +} + +uint16_t +ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index) +{ + uint32_t v; + + v = EOREAD4(sc, EHCI_HOSTC(index)); + v = (v >> EHCI_HOSTC_PSPD_SHIFT) & EHCI_HOSTC_PSPD_MASK; + + if (v == EHCI_PORT_SPEED_HIGH) + return (UPS_HIGH_SPEED); + if (v == EHCI_PORT_SPEED_LOW) + return (UPS_LOW_SPEED); + return (0); +} + static void ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed) { @@ -3340,13 +3353,15 @@ ehci_roothub_exec(struct usb_device *udev, } v = EOREAD4(sc, EHCI_PORTSC(index)); DPRINTFN(9, "port status=0x%04x\n", v); - if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) { - if ((v & 0xc000000) == 0x8000000) + if (sc->sc_flags & EHCI_SCFLG_TT) { + if (sc->sc_vendor_get_port_speed != NULL) { + i = sc->sc_vendor_get_port_speed(sc, index); + } else { + device_printf(sc->sc_bus.bdev, + "EHCI_SCFLG_TT quirk is set but " + "sc_vendor_get_hub_speed() is NULL\n"); i = UPS_HIGH_SPEED; - else if ((v & 0xc000000) == 0x4000000) - i = UPS_LOW_SPEED; - else - i = 0; + } } else { i = UPS_HIGH_SPEED; } diff --git a/freebsd/sys/dev/usb/controller/ehci.h b/freebsd/sys/dev/usb/controller/ehci.h index aaa1cedc..dd20c0a5 100644 --- a/freebsd/sys/dev/usb/controller/ehci.h +++ b/freebsd/sys/dev/usb/controller/ehci.h @@ -337,11 +337,8 @@ typedef struct ehci_softc { uint16_t sc_intr_stat[EHCI_VIRTUAL_FRAMELIST_COUNT]; uint16_t sc_id_vendor; /* vendor ID for root hub */ uint16_t sc_flags; /* chip specific flags */ -#define EHCI_SCFLG_SETMODE 0x0001 /* set bridge mode again after init */ -#define EHCI_SCFLG_FORCESPEED 0x0002 /* force speed */ #define EHCI_SCFLG_NORESTERM 0x0004 /* don't terminate reset sequence */ #define EHCI_SCFLG_BIGEDESC 0x0008 /* big-endian byte order descriptors */ -#define EHCI_SCFLG_BIGEMMIO 0x0010 /* big-endian byte order MMIO */ #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 */ @@ -358,6 +355,10 @@ typedef struct ehci_softc { char sc_vendor[16]; /* vendor string for root hub */ + void (*sc_vendor_post_reset)(struct ehci_softc *sc); + uint16_t (*sc_vendor_get_port_speed)(struct ehci_softc *sc, + uint16_t index); + } ehci_softc_t; #define EREAD1(sc, a) bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, (a)) @@ -476,5 +477,7 @@ void ehci_interrupt(ehci_softc_t *sc); void ehci_suspend(ehci_softc_t *sc); void ehci_resume(ehci_softc_t *sc); #endif /* __rtems__ */ +uint16_t ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index); +uint16_t ehci_get_port_speed_hostc(struct ehci_softc *sc, uint16_t index); #endif /* _EHCI_H_ */ diff --git a/freebsd/sys/dev/usb/controller/ehcireg.h b/freebsd/sys/dev/usb/controller/ehcireg.h index 1f5fc5c0..2394b2c1 100644 --- a/freebsd/sys/dev/usb/controller/ehcireg.h +++ b/freebsd/sys/dev/usb/controller/ehcireg.h @@ -157,7 +157,17 @@ #define EHCI_PS_CS 0x00000001 /* RO connect status */ #define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) -#define EHCI_USBMODE 0x68 /* RW USB Device mode register */ +#define EHCI_PORT_RESET_COMPLETE 2 /* ms */ + +/* + * Registers not covered by EHCI specification + * + * + * EHCI_USBMODE register offset is different for cores with LPM support, + * bits are equal + */ +#define EHCI_USBMODE_NOLPM 0x68 /* RW USB Device mode reg (no LPM) */ +#define EHCI_USBMODE_LPM 0xC8 /* RW USB Device mode reg (LPM) */ #define EHCI_UM_CM 0x00000003 /* R/WO Controller Mode */ #define EHCI_UM_CM_IDLE 0x0 /* Idle */ #define EHCI_UM_CM_HOST 0x3 /* Host Controller */ @@ -166,6 +176,18 @@ #define EHCI_UM_ES_BE 0x4 /* Big-endian byte alignment */ #define EHCI_UM_SDIS 0x00000010 /* R/WO Stream Disable Mode */ -#define EHCI_PORT_RESET_COMPLETE 2 /* ms */ +/* + * Actual port speed bits depends on EHCI_HOSTC(n) registers presence, + * speed encoding is equal + */ +#define EHCI_HOSTC(n) (0x80+(4*(n))) /* RO, RW Host mode control reg */ +#define EHCI_HOSTC_PSPD_SHIFT 25 +#define EHCI_HOSTC_PSPD_MASK 0x3 + +#define EHCI_PORTSC_PSPD_SHIFT 26 +#define EHCI_PORTSC_PSPD_MASK 0x3 +#define EHCI_PORT_SPEED_FULL 0 +#define EHCI_PORT_SPEED_LOW 1 +#define EHCI_PORT_SPEED_HIGH 2 #endif /* _EHCIREG_H_ */ diff --git a/freebsd/sys/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c index 91f535d5..4c77fdea 100644 --- a/freebsd/sys/dev/usb/controller/ohci.c +++ b/freebsd/sys/dev/usb/controller/ohci.c @@ -2045,7 +2045,7 @@ struct usb_device_descriptor ohci_devd = UDPROTO_FSHUB, /* protocol */ 64, /* max packet */ {0}, {0}, {0x00, 0x01}, /* device id */ - 1, 2, 0, /* string indicies */ + 1, 2, 0, /* string indexes */ 1 /* # of configurations */ }; @@ -2439,7 +2439,7 @@ ohci_xfer_setup(struct usb_setup_params *parm) usbd_transfer_setup_sub(parm); nitd = ((xfer->max_data_length / OHCI_PAGE_SIZE) + - ((xfer->nframes + OHCI_ITD_NOFFSET - 1) / OHCI_ITD_NOFFSET) + + howmany(xfer->nframes, OHCI_ITD_NOFFSET) + 1 /* EXTRA */ ); ntd = 0; nqh = 1; diff --git a/freebsd/sys/dev/usb/controller/xhcireg.h b/freebsd/sys/dev/usb/controller/xhcireg.h index a0b73971..0e588ecb 100644 --- a/freebsd/sys/dev/usb/controller/xhcireg.h +++ b/freebsd/sys/dev/usb/controller/xhcireg.h @@ -45,16 +45,16 @@ #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_HCSPARAMS1 0x04 /* RO structural 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_HCSPARAMS2 0x08 /* RO structural 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_HCS2_SPR(x) (((x) >> 26) & 0x1) +#define XHCI_HCS2_SPB_MAX(x) ((((x) >> 16) & 0x3E0) | (((x) >> 27) & 0x1F)) +#define XHCI_HCSPARAMS3 0x0C /* RO structural 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 */ diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index c6baeffc..1ff0afba 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -138,6 +138,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { 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), @@ -200,6 +202,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(GARMIN, FORERUNNER230, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE), @@ -531,6 +534,9 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { /* 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 @@ -684,8 +690,6 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk) return (1); } } - /* no quirk found */ - break; } mtx_unlock(&usb_quirk_mtx); done: diff --git a/freebsd/sys/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c index 9c6c8532..0fb810c1 100644 --- a/freebsd/sys/dev/usb/storage/umass.c +++ b/freebsd/sys/dev/usb/storage/umass.c @@ -710,20 +710,23 @@ static driver_t umass_driver = { .size = sizeof(struct umass_softc), }; +static const STRUCT_USB_HOST_ID __used umass_devs[] = { + /* generic mass storage class */ + {USB_IFACE_CLASS(UICLASS_MASS),}, +}; + DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, NULL, 0); MODULE_DEPEND(umass, usb, 1, 1, 1); MODULE_DEPEND(umass, cam, 1, 1, 1); MODULE_VERSION(umass, 1); +#ifndef __rtems__ +USB_PNP_HOST_INFO(umass_devs); +#endif /* __rtems__ */ /* * USB device probe/attach/detach */ -static const STRUCT_USB_HOST_ID __used umass_devs[] = { - /* generic mass storage class */ - {USB_IFACE_CLASS(UICLASS_MASS),}, -}; - static uint16_t umass_get_proto(struct usb_interface *iface) { @@ -2730,7 +2733,7 @@ umass_rbc_transform(struct umass_softc *sc, uint8_t *cmd_ptr, uint8_t cmd_len) cmd_len = 12; } sc->sc_transfer.cmd_len = cmd_len; - return (1); /* sucess */ + return (1); /* success */ /* All other commands are not legal in RBC */ default: diff --git a/freebsd/sys/dev/usb/usb_busdma.c b/freebsd/sys/dev/usb/usb_busdma.c index 52af6088..88566199 100644 --- a/freebsd/sys/dev/usb/usb_busdma.c +++ b/freebsd/sys/dev/usb/usb_busdma.c @@ -469,22 +469,27 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs, off = 0; pg = pc->page_start; - pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1); + pg->physaddr = rounddown2(segs->ds_addr, USB_PAGE_SIZE); rem = segs->ds_addr & (USB_PAGE_SIZE - 1); pc->page_offset_buf = rem; pc->page_offset_end += rem; #ifdef USB_DEBUG - if (nseg > 1 && - ((segs->ds_addr + segs->ds_len) & (USB_PAGE_SIZE - 1)) != - ((segs + 1)->ds_addr & (USB_PAGE_SIZE - 1))) { - /* - * 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; - goto done; + if (nseg > 1) { + int x; + + for (x = 0; x != nseg - 1; x++) { + if (((segs[x].ds_addr + segs[x].ds_len) & (USB_PAGE_SIZE - 1)) == + ((segs[x + 1].ds_addr & (USB_PAGE_SIZE - 1)))) + continue; + /* + * This check verifies there is no page offset + * hole between any of the segments. See the + * BUS_DMA_KEEP_PG_OFFSET flag. + */ + DPRINTFN(0, "Page offset was not preserved\n"); + error = 1; + goto done; + } } #endif while (pc->ismultiseg) { @@ -499,7 +504,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs, break; } pg++; - pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1); + pg->physaddr = rounddown2(segs->ds_addr + off, USB_PAGE_SIZE); } done: diff --git a/freebsd/sys/dev/usb/usb_cdc.h b/freebsd/sys/dev/usb/usb_cdc.h index b8f59fae..86f35170 100644 --- a/freebsd/sys/dev/usb/usb_cdc.h +++ b/freebsd/sys/dev/usb/usb_cdc.h @@ -161,7 +161,7 @@ struct usb_cdc_notification { #define UCDC_NOTIFICATION_LENGTH 8 /* - * Bits set in the SERIAL STATE notifcation (first byte of data) + * Bits set in the SERIAL STATE notification (first byte of data) */ #define UCDC_N_SERIAL_OVERRUN 0x40 diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index e5f98a9e..b31ba617 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -181,7 +181,7 @@ usb_loc_fill(struct usb_fs_privdata* pd, struct usb_cdev_privdata *cpd) * * This function is used to atomically refer an USB device by its * device location. If this function returns success the USB device - * will not dissappear until the USB device is unreferenced. + * will not disappear until the USB device is unreferenced. * * Return values: * 0: Success, refcount incremented on the given USB device. @@ -230,7 +230,7 @@ usb_ref_device(struct usb_cdev_privdata *cpd, * 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); @@ -238,6 +238,12 @@ usb_ref_device(struct usb_cdev_privdata *cpd, * 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 */ diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index 614e1e92..26c694e8 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -196,7 +196,7 @@ usbd_get_ep_by_addr(struct usb_device *udev, uint8_t ea_val) ea_val &= EA_MASK; /* - * Iterate accross all the USB endpoints searching for a match + * Iterate across all the USB endpoints searching for a match * based on the endpoint address: */ for (; ep != ep_end; ep++) { @@ -306,7 +306,7 @@ usbd_get_endpoint(struct usb_device *udev, uint8_t iface_index, } /* - * Iterate accross all the USB endpoints searching for a match + * Iterate across all the USB endpoints searching for a match * based on the endpoint address. Note that we are searching * the endpoints from the beginning of the "udev->endpoints" array. */ @@ -1730,8 +1730,8 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, /* Setup USB descriptors */ err = (usb_temp_setup_by_index_p) (udev, usb_template); if (err) { - DPRINTFN(0, "setting up USB template failed maybe the USB " - "template module has not been loaded\n"); + DPRINTFN(0, "setting up USB template failed - " + "usb_template(4) not loaded?\n"); goto done; } } @@ -1780,7 +1780,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, 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 */ @@ -1968,6 +1970,7 @@ usb_make_dev(struct usb_device *udev, const char *devname, int ep, int fi, int rwmode, uid_t uid, gid_t gid, int mode) { struct usb_fs_privdata* pd; + struct make_dev_args args; char buffer[32]; /* Store information to locate ourselves again later */ @@ -1986,17 +1989,19 @@ usb_make_dev(struct usb_device *udev, const char *devname, int ep, pd->bus_index, pd->dev_index, pd->ep_addr); } - pd->cdev = make_dev(&usb_devsw, 0, uid, gid, mode, "%s", devname); + /* Setup arguments for make_dev_s() */ + make_dev_args_init(&args); + args.mda_devsw = &usb_devsw; + args.mda_uid = uid; + args.mda_gid = gid; + args.mda_mode = mode; + args.mda_si_drv1 = pd; - if (pd->cdev == NULL) { + if (make_dev_s(&args, &pd->cdev, "%s", devname) != 0) { DPRINTFN(0, "Failed to create device %s\n", devname); free(pd, M_USBDEV); return (NULL); } - - /* XXX setting si_drv1 and creating the device is not atomic! */ - pd->cdev->si_drv1 = pd; - return (pd); } @@ -2741,7 +2746,7 @@ usbd_device_attached(struct usb_device *udev) /* * 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) @@ -2760,6 +2765,27 @@ usbd_enum_lock(struct usb_device *udev) 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 diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h index 4e9dbc4a..24a5a4a6 100644 --- a/freebsd/sys/dev/usb/usb_device.h +++ b/freebsd/sys/dev/usb/usb_device.h @@ -314,6 +314,9 @@ void usb_set_device_state(struct usb_device *, enum usb_dev_state); 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 *); diff --git a/freebsd/sys/dev/usb/usb_handle_request.c b/freebsd/sys/dev/usb/usb_handle_request.c index 1720fa02..308df345 100644 --- a/freebsd/sys/dev/usb/usb_handle_request.c +++ b/freebsd/sys/dev/usb/usb_handle_request.c @@ -315,7 +315,7 @@ tr_repeat: case UR_SET_INTERFACE: /* * We assume that the endpoints are the same - * accross the alternate settings. + * across the alternate settings. * * Reset the endpoints, because re-attaching * only a part of the device is not possible. diff --git a/freebsd/sys/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c index 879aaeae..9d9c9988 100644 --- a/freebsd/sys/dev/usb/usb_hid.c +++ b/freebsd/sys/dev/usb/usb_hid.c @@ -356,7 +356,8 @@ hid_get_item(struct hid_data *s, struct hid_item *h) /* 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; @@ -577,7 +578,7 @@ hid_report_size(const void *buf, usb_size_t len, enum hid_kind k, uint8_t *id) for (d = hid_start_parse(buf, len, 1 << k); hid_get_item(d, &h);) { if (h.kind == k) { - /* check for ID-byte presense */ + /* check for ID-byte presence */ if ((h.report_ID != 0) && !any_id) { if (id != NULL) *id = h.report_ID; diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index 0e2dde8c..a744a82e 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -1734,6 +1734,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, if (iface && iface->idesc) { snprintf(buf, buflen, "vendor=0x%04x product=0x%04x " "devclass=0x%02x devsubclass=0x%02x " + "devproto=0x%02x " "sernum=\"%s\" " "release=0x%04x " "mode=%s " @@ -1743,6 +1744,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, UGETW(res.udev->ddesc.idProduct), res.udev->ddesc.bDeviceClass, res.udev->ddesc.bDeviceSubClass, + res.udev->ddesc.bDeviceProtocol, usb_get_serial(res.udev), UGETW(res.udev->ddesc.bcdDevice), (res.udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device", @@ -1767,7 +1769,7 @@ done: * The USB Transaction Translator: * =============================== * - * When doing LOW- and FULL-speed USB transfers accross a HIGH-speed + * When doing LOW- and FULL-speed USB transfers across a HIGH-speed * USB HUB, bandwidth must be allocated for ISOCHRONOUS and INTERRUPT * USB transfers. To utilize bandwidth dynamically the "scatter and * gather" principle must be applied. This means that bandwidth must @@ -1839,7 +1841,7 @@ usb_intr_find_best_slot(usb_size_t *ptr, uint8_t start, /*------------------------------------------------------------------------* * usb_hs_bandwidth_adjust * - * This function will update the bandwith usage for the microframe + * This function will update the bandwidth usage for the microframe * having index "slot" by "len" bytes. "len" can be negative. If the * "slot" argument is greater or equal to "USB_HS_MICRO_FRAMES_MAX" * the "slot" argument will be replaced by the slot having least used @@ -2311,7 +2313,7 @@ usb_needs_explore_all(void) return; } /* - * Explore all USB busses in parallell. + * Explore all USB busses in parallel. */ max = devclass_get_maxunit(dc); while (max >= 0) { diff --git a/freebsd/sys/dev/usb/usb_lookup.c b/freebsd/sys/dev/usb/usb_lookup.c index 9ffdcd2e..5dea5188 100644 --- a/freebsd/sys/dev/usb/usb_lookup.c +++ b/freebsd/sys/dev/usb/usb_lookup.c @@ -156,28 +156,10 @@ usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, /*------------------------------------------------------------------------* * Export the USB device ID format we use to userspace tools. *------------------------------------------------------------------------*/ -#if BYTE_ORDER == BIG_ENDIAN -#define U16_XOR "8" -#define U32_XOR "12" -#define U64_XOR "56" -#define U8_BITFIELD_XOR "7" -#define U16_BITFIELD_XOR "15" -#define U32_BITFIELD_XOR "31" -#define U64_BITFIELD_XOR "63" -#else +#if BYTE_ORDER == LITTLE_ENDIAN #define U16_XOR "0" -#define U32_XOR "0" -#define U64_XOR "0" -#define U8_BITFIELD_XOR "0" -#define U16_BITFIELD_XOR "0" -#define U32_BITFIELD_XOR "0" -#define U64_BITFIELD_XOR "0" -#endif - -#if USB_HAVE_COMPAT_LINUX -#define MFL_SIZE "1" #else -#define MFL_SIZE "0" +#define U16_XOR "8" #endif #if defined(KLD_MODULE) && (USB_HAVE_ID_SECTION != 0) @@ -191,20 +173,19 @@ static const char __section("bus_autoconf_format") __used usb_id_format[] = { /* List size of fields in the usb_device_id structure */ -#if ULONG_MAX >= 0xFFFFFFFFUL - "unused{0,8}" - "unused{0,8}" - "unused{0,8}" - "unused{0,8}" -#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL - "unused{0,8}" - "unused{0,8}" - "unused{0,8}" - "unused{0,8}" -#endif -#else -#error "Please update code." -#endif + "mf_vendor{" U16_XOR ",1}" + "mf_product{" U16_XOR ",1}" + "mf_dev_lo{" U16_XOR ",1}" + "mf_dev_hi{" U16_XOR ",1}" + + "mf_dev_class{" U16_XOR ",1}" + "mf_dev_subclass{" U16_XOR ",1}" + "mf_dev_protocol{" U16_XOR ",1}" + "mf_int_class{" U16_XOR ",1}" + + "mf_int_subclass{" U16_XOR ",1}" + "mf_int_protocol{" U16_XOR ",1}" + "unused{" U16_XOR ",6}" "idVendor[0]{" U16_XOR ",8}" "idVendor[1]{" U16_XOR ",8}" @@ -222,38 +203,20 @@ static const char __section("bus_autoconf_format") __used usb_id_format[] = { "bInterfaceSubClass{0,8}" "bInterfaceProtocol{0,8}" - "mf_vendor{" U8_BITFIELD_XOR ",1}" - "mf_product{" U8_BITFIELD_XOR ",1}" - "mf_dev_lo{" U8_BITFIELD_XOR ",1}" - "mf_dev_hi{" U8_BITFIELD_XOR ",1}" - - "mf_dev_class{" U8_BITFIELD_XOR ",1}" - "mf_dev_subclass{" U8_BITFIELD_XOR ",1}" - "mf_dev_protocol{" U8_BITFIELD_XOR ",1}" - "mf_int_class{" U8_BITFIELD_XOR ",1}" - - "mf_int_subclass{" U8_BITFIELD_XOR ",1}" - "mf_int_protocol{" U8_BITFIELD_XOR ",1}" - "unused{" U8_BITFIELD_XOR ",6}" - - "mfl_vendor{" U16_XOR "," MFL_SIZE "}" - "mfl_product{" U16_XOR "," MFL_SIZE "}" - "mfl_dev_lo{" U16_XOR "," MFL_SIZE "}" - "mfl_dev_hi{" U16_XOR "," MFL_SIZE "}" - - "mfl_dev_class{" U16_XOR "," MFL_SIZE "}" - "mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}" - "mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}" - "mfl_int_class{" U16_XOR "," MFL_SIZE "}" - - "mfl_int_subclass{" U16_XOR "," MFL_SIZE "}" - "mfl_int_protocol{" U16_XOR "," MFL_SIZE "}" - "unused{" U16_XOR "," MFL_SIZE "}" - "unused{" U16_XOR "," MFL_SIZE "}" - - "unused{" U16_XOR "," MFL_SIZE "}" - "unused{" U16_XOR "," MFL_SIZE "}" - "unused{" U16_XOR "," MFL_SIZE "}" - "unused{" U16_XOR "," MFL_SIZE "}" +#if USB_HAVE_COMPAT_LINUX + "mfl_vendor{" U16_XOR ",1}" + "mfl_product{" U16_XOR ",1}" + "mfl_dev_lo{" U16_XOR ",1}" + "mfl_dev_hi{" U16_XOR ",1}" + + "mfl_dev_class{" U16_XOR ",1}" + "mfl_dev_subclass{" U16_XOR ",1}" + "mfl_dev_protocol{" U16_XOR ",1}" + "mfl_int_class{" U16_XOR ",1}" + + "mfl_int_subclass{" U16_XOR ",1}" + "mfl_int_protocol{" U16_XOR ",1}" + "unused{" U16_XOR ",6}" +#endif }; #endif diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index 7b39601d..9bb68fd3 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -258,7 +258,7 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, * Compute number of DMA chunks, rounded up * to nearest one: */ - n_dma_pc = ((count + n_obj - 1) / n_obj); + n_dma_pc = howmany(count, n_obj); n_dma_pg = 1; } @@ -627,7 +627,7 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm) /* * NOTE: we do not allow "max_packet_size" or "max_frame_size" * to be equal to zero when setting up USB transfers, hence - * this leads to alot of extra code in the USB kernel. + * this leads to a lot of extra code in the USB kernel. */ if ((xfer->max_frame_size == 0) || @@ -955,7 +955,7 @@ usbd_transfer_setup(struct usb_device *udev, DPRINTFN(6, "setup array has zero length!\n"); return (USB_ERR_INVAL); } - if (ifaces == 0) { + if (ifaces == NULL) { DPRINTFN(6, "ifaces array is NULL!\n"); return (USB_ERR_INVAL); } @@ -2478,7 +2478,7 @@ done: * * This function is called when the DMA delay has been exectuded, and * will make sure that the callback is called to complete the USB - * transfer. This code path is ususally only used when there is an USB + * transfer. This code path is usually only used when there is an USB * error like USB_ERR_CANCELLED. *------------------------------------------------------------------------*/ void diff --git a/freebsd/sys/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h index ecd5a812..202ad89f 100644 --- a/freebsd/sys/dev/usb/usbdi.h +++ b/freebsd/sys/dev/usb/usbdi.h @@ -241,7 +241,7 @@ struct usb_config { /* * Use these macro when defining USB device ID arrays if you want to * have your driver module automatically loaded in host, device or - * both modes respectivly: + * both modes respectively: */ #if USB_HAVE_ID_SECTION #define STRUCT_USB_HOST_ID \ @@ -266,8 +266,38 @@ struct usb_config { */ struct usb_device_id { - /* Hook for driver specific information */ - unsigned long driver_info; + /* Select which fields to match against */ +#if BYTE_ORDER == LITTLE_ENDIAN + uint16_t + match_flag_vendor:1, + match_flag_product:1, + match_flag_dev_lo:1, + match_flag_dev_hi:1, + + match_flag_dev_class:1, + match_flag_dev_subclass:1, + match_flag_dev_protocol:1, + match_flag_int_class:1, + + match_flag_int_subclass:1, + match_flag_int_protocol:1, + match_flag_unused:6; +#else + uint16_t + match_flag_unused:6, + match_flag_int_protocol:1, + match_flag_int_subclass:1, + + match_flag_int_class:1, + match_flag_dev_protocol:1, + match_flag_dev_subclass:1, + match_flag_dev_class:1, + + match_flag_dev_hi:1, + match_flag_dev_lo:1, + match_flag_product:1, + match_flag_vendor:1; +#endif /* Used for product specific matches; the BCD range is inclusive */ uint16_t idVendor; @@ -285,21 +315,6 @@ struct usb_device_id { uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; - /* Select which fields to match against */ - uint8_t match_flag_vendor:1; - uint8_t match_flag_product:1; - uint8_t match_flag_dev_lo:1; - uint8_t match_flag_dev_hi:1; - - uint8_t match_flag_dev_class:1; - uint8_t match_flag_dev_subclass:1; - uint8_t match_flag_dev_protocol:1; - uint8_t match_flag_int_class:1; - - uint8_t match_flag_int_subclass:1; - uint8_t match_flag_int_protocol:1; - uint8_t match_flag_unused:6; - #if USB_HAVE_COMPAT_LINUX /* which fields to match against */ uint16_t match_flags; @@ -314,8 +329,26 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #endif + + /* Hook for driver specific information */ + unsigned long driver_info; } __aligned(32); +#define USB_STD_PNP_INFO "M16:mask;U16:vendor;U16:product;L16:product;G16:product;" \ + "U8:devclass;U8:devsubclass;U8:devprotocol;" \ + "U8:intclass;U8:intsubclass;U8:intprotocol;" +#define USB_STD_PNP_HOST_INFO USB_STD_PNP_INFO "T:mode=host;" +#define USB_STD_PNP_DEVICE_INFO USB_STD_PNP_INFO "T:mode=device;" +#define USB_PNP_HOST_INFO(table) \ + MODULE_PNP_INFO(USB_STD_PNP_HOST_INFO, usb, table, table, sizeof(table[0]), \ + sizeof(table) / sizeof(table[0])) +#define USB_PNP_DEVICE_INFO(table) \ + MODULE_PNP_INFO(USB_STD_PNP_DEVICE_INFO, usb, table, table, sizeof(table[0]), \ + sizeof(table) / sizeof(table[0])) +#define USB_PNP_DUAL_INFO(table) \ + MODULE_PNP_INFO(USB_STD_PNP_INFO, usb, table, table, sizeof(table[0]), \ + sizeof(table) / sizeof(table[0])) + /* check that the size of the structure above is correct */ extern char usb_device_id_assert[(sizeof(struct usb_device_id) == 32) ? 1 : -1]; -- cgit v1.2.3