Date: Fri, 20 Mar 2009 21:57:54 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r190183 - head/sys/dev/usb/controller Message-ID: <200903202157.n2KLvsdj014880@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: thompsa Date: Fri Mar 20 21:57:54 2009 New Revision: 190183 URL: http://svn.freebsd.org/changeset/base/190183 Log: MFp4 //depot/projects/usb @159479,159502,159516,159522,159529 Workaround for buggy USB hardware not handling new SETUP packet before STATUS stage is complete, this allows xfers to endpoint0 to return a short frame. Submitted by: Hans Petter Selasky Reported by: me Modified: head/sys/dev/usb/controller/at91dci.c head/sys/dev/usb/controller/at91dci_atmelarm.c head/sys/dev/usb/controller/atmegadci.c head/sys/dev/usb/controller/atmegadci_atmelarm.c head/sys/dev/usb/controller/ehci.c head/sys/dev/usb/controller/ehci_ixp4xx.c head/sys/dev/usb/controller/ehci_mbus.c head/sys/dev/usb/controller/ehci_pci.c head/sys/dev/usb/controller/musb_otg.c head/sys/dev/usb/controller/musb_otg_atmelarm.c head/sys/dev/usb/controller/ohci.c head/sys/dev/usb/controller/ohci_atmelarm.c head/sys/dev/usb/controller/ohci_pci.c head/sys/dev/usb/controller/uhci.c head/sys/dev/usb/controller/uhci_pci.c head/sys/dev/usb/controller/uss820dci.c head/sys/dev/usb/controller/uss820dci_atmelarm.c Modified: head/sys/dev/usb/controller/at91dci.c ============================================================================== --- head/sys/dev/usb/controller/at91dci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/at91dci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -887,8 +887,8 @@ at91dci_setup_standard_chain(struct usb2 temp.td = NULL; temp.td_next = xfer->td_start[0]; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; temp.offset = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; sc = AT9100_DCI_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); @@ -902,6 +902,12 @@ at91dci_setup_standard_chain(struct usb2 temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.short_pkt = temp.len ? 1 : 0; + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) + temp.setup_alt_next = 0; + } at91dci_setup_standard_chain_sub(&temp); } @@ -933,7 +939,13 @@ at91dci_setup_standard_chain(struct usb2 x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_act) { + temp.setup_alt_next = 0; + } + } else { + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -958,47 +970,46 @@ at91dci_setup_standard_chain(struct usb2 } } - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - - /* check if we need to sync */ - if (need_sync && xfer->flags_int.control_xfr) { - - /* we need a SYNC point after TX */ - temp.func = &at91dci_data_tx_sync; - temp.len = 0; - temp.short_pkt = 0; - - at91dci_setup_standard_chain_sub(&temp); - } - /* check if we should append a status stage */ - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { + /* check for control transfer */ + if (xfer->flags_int.control_xfr) { - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - if (xfer->endpoint & UE_DIR_IN) { - temp.func = &at91dci_data_rx; - need_sync = 0; - } else { - temp.func = &at91dci_data_tx; - need_sync = 1; - } + /* always setup a valid "pc" pointer for status and sync */ + temp.pc = xfer->frbuffers + 0; temp.len = 0; temp.short_pkt = 0; + temp.setup_alt_next = 0; - at91dci_setup_standard_chain_sub(&temp); + /* check if we need to sync */ if (need_sync) { /* we need a SYNC point after TX */ temp.func = &at91dci_data_tx_sync; - temp.len = 0; - temp.short_pkt = 0; + at91dci_setup_standard_chain_sub(&temp); + } + + /* check if we should append a status stage */ + if (!xfer->flags_int.control_act) { + + /* + * Send a DATA1 message and invert the current + * endpoint direction. + */ + if (xfer->endpoint & UE_DIR_IN) { + temp.func = &at91dci_data_rx; + need_sync = 0; + } else { + temp.func = &at91dci_data_tx; + need_sync = 1; + } at91dci_setup_standard_chain_sub(&temp); + if (need_sync) { + /* we need a SYNC point after TX */ + temp.func = &at91dci_data_tx_sync; + at91dci_setup_standard_chain_sub(&temp); + } } } + /* must have at least one frame! */ td = temp.td; xfer->td_transfer_last = td; Modified: head/sys/dev/usb/controller/at91dci_atmelarm.c ============================================================================== --- head/sys/dev/usb/controller/at91dci_atmelarm.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/at91dci_atmelarm.c Fri Mar 20 21:57:54 2009 (r190183) @@ -204,10 +204,10 @@ at91_udp_attach(device_t dev) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl); + NULL, (driver_intr_t *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl); #else err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl); + (driver_intr_t *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl); #endif if (err) { sc->sc_dci.sc_intr_hdl = NULL; @@ -215,10 +215,10 @@ at91_udp_attach(device_t dev) } #if (__FreeBSD_version >= 700031) err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl); + NULL, (driver_intr_t *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl); #else err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl); + (driver_intr_t *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl); #endif if (err) { sc->sc_vbus_intr_hdl = NULL; Modified: head/sys/dev/usb/controller/atmegadci.c ============================================================================== --- head/sys/dev/usb/controller/atmegadci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/atmegadci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -791,8 +791,8 @@ atmegadci_setup_standard_chain(struct us temp.td = NULL; temp.td_next = xfer->td_start[0]; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; temp.offset = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; sc = ATMEGA_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); @@ -806,6 +806,12 @@ atmegadci_setup_standard_chain(struct us temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.short_pkt = temp.len ? 1 : 0; + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) + temp.setup_alt_next = 0; + } atmegadci_setup_standard_chain_sub(&temp); } @@ -837,7 +843,13 @@ atmegadci_setup_standard_chain(struct us x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_act) { + temp.setup_alt_next = 0; + } + } else { + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -862,45 +874,42 @@ atmegadci_setup_standard_chain(struct us } } - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - - /* check if we need to sync */ - if (need_sync && xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_xfr) { - /* we need a SYNC point after TX */ - temp.func = &atmegadci_data_tx_sync; + /* always setup a valid "pc" pointer for status and sync */ + temp.pc = xfer->frbuffers + 0; temp.len = 0; temp.short_pkt = 0; + temp.setup_alt_next = 0; - atmegadci_setup_standard_chain_sub(&temp); - } - /* check if we should append a status stage */ - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { - - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - if (xfer->endpoint & UE_DIR_IN) { - temp.func = &atmegadci_data_rx; - need_sync = 0; - } else { - temp.func = &atmegadci_data_tx; - need_sync = 1; - } - temp.len = 0; - temp.short_pkt = 0; - - atmegadci_setup_standard_chain_sub(&temp); + /* check if we need to sync */ if (need_sync) { /* we need a SYNC point after TX */ temp.func = &atmegadci_data_tx_sync; - temp.len = 0; - temp.short_pkt = 0; + atmegadci_setup_standard_chain_sub(&temp); + } + + /* check if we should append a status stage */ + if (!xfer->flags_int.control_act) { + + /* + * Send a DATA1 message and invert the current + * endpoint direction. + */ + if (xfer->endpoint & UE_DIR_IN) { + temp.func = &atmegadci_data_rx; + need_sync = 0; + } else { + temp.func = &atmegadci_data_tx; + need_sync = 1; + } atmegadci_setup_standard_chain_sub(&temp); + if (need_sync) { + /* we need a SYNC point after TX */ + temp.func = &atmegadci_data_tx_sync; + atmegadci_setup_standard_chain_sub(&temp); + } } } /* must have at least one frame! */ Modified: head/sys/dev/usb/controller/atmegadci_atmelarm.c ============================================================================== --- head/sys/dev/usb/controller/atmegadci_atmelarm.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/atmegadci_atmelarm.c Fri Mar 20 21:57:54 2009 (r190183) @@ -113,7 +113,7 @@ atmegadci_attach(device_t dev) device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus); err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl); + NULL, (driver_intr_t *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl); if (err) { sc->sc_otg.sc_intr_hdl = NULL; goto error; Modified: head/sys/dev/usb/controller/ehci.c ============================================================================== --- head/sys/dev/usb/controller/ehci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ehci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -117,7 +117,7 @@ struct ehci_std_temp { uint8_t shortpkt; uint8_t auto_data_toggle; uint8_t setup_alt_next; - uint8_t short_frames_ok; + uint8_t last_frame; }; void @@ -1546,10 +1546,12 @@ ehci_setup_standard_chain_sub(struct ehc uint32_t buf_offset; uint32_t average; uint32_t len_old; + uint32_t terminate; uint8_t shortpkt_old; uint8_t precompute; - qtd_altnext = htohc32(temp->sc, EHCI_LINK_TERMINATE); + terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE); + qtd_altnext = terminate; td_alt_next = NULL; buf_offset = 0; shortpkt_old = temp->shortpkt; @@ -1696,14 +1698,17 @@ restart: precompute = 0; /* setup alt next pointer, if any */ - if (temp->short_frames_ok) { - if (temp->setup_alt_next) { - td_alt_next = td_next; - qtd_altnext = td_next->qtd_self; - } + if (temp->last_frame) { + td_alt_next = NULL; + qtd_altnext = terminate; } else { /* we use this field internally */ td_alt_next = td_next; + if (temp->setup_alt_next) { + qtd_altnext = td_next->qtd_self; + } else { + qtd_altnext = terminate; + } } /* restore */ @@ -1746,8 +1751,8 @@ ehci_setup_standard_chain(struct usb2_xf temp.td = NULL; temp.td_next = td; temp.qtd_status = 0; + temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; - temp.short_frames_ok = xfer->flags_int.short_frames_ok; if (xfer->flags_int.control_xfr) { if (xfer->pipe->toggle_next) { @@ -1780,7 +1785,14 @@ ehci_setup_standard_chain(struct usb2_xf temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.shortpkt = temp.len ? 1 : 0; - + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } ehci_setup_standard_chain_sub(&temp); } x = 1; @@ -1798,7 +1810,16 @@ ehci_setup_standard_chain(struct usb2_xf x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + /* no STATUS stage yet, DATA is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } else { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } } /* keep previous data toggle and error count */ @@ -1855,6 +1876,8 @@ ehci_setup_standard_chain(struct usb2_xf temp.len = 0; temp.pc = NULL; temp.shortpkt = 0; + temp.last_frame = 1; + temp.setup_alt_next = 0; ehci_setup_standard_chain_sub(&temp); } Modified: head/sys/dev/usb/controller/ehci_ixp4xx.c ============================================================================== --- head/sys/dev/usb/controller/ehci_ixp4xx.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ehci_ixp4xx.c Fri Mar 20 21:57:54 2009 (r190183) @@ -189,7 +189,7 @@ ehci_ixp_attach(device_t self) err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; Modified: head/sys/dev/usb/controller/ehci_mbus.c ============================================================================== --- head/sys/dev/usb/controller/ehci_mbus.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ehci_mbus.c Fri Mar 20 21:57:54 2009 (r190183) @@ -210,7 +210,7 @@ ehci_mbus_attach(device_t self) MV_USB_DEVICE_UNDERFLOW); err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; Modified: head/sys/dev/usb/controller/ehci_pci.c ============================================================================== --- head/sys/dev/usb/controller/ehci_pci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ehci_pci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -338,10 +338,10 @@ ehci_pci_attach(device_t self) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); #else err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl); + (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); #endif if (err) { device_printf(self, "Could not setup irq, %d\n", err); Modified: head/sys/dev/usb/controller/musb_otg.c ============================================================================== --- head/sys/dev/usb/controller/musb_otg.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/musb_otg.c Fri Mar 20 21:57:54 2009 (r190183) @@ -1132,8 +1132,8 @@ musbotg_setup_standard_chain(struct usb2 temp.td = NULL; temp.td_next = xfer->td_start[0]; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; temp.offset = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; sc = MUSBOTG_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); @@ -1180,7 +1180,13 @@ musbotg_setup_standard_chain(struct usb2 x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_act) { + temp.setup_alt_next = 0; + } + } else { + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -1205,23 +1211,24 @@ musbotg_setup_standard_chain(struct usb2 } } - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - - /* check if we should append a status stage */ - - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { + /* check for control transfer */ + if (xfer->flags_int.control_xfr) { - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - temp.func = &musbotg_setup_status; + /* always setup a valid "pc" pointer for status and sync */ + temp.pc = xfer->frbuffers + 0; temp.len = 0; temp.short_pkt = 0; + temp.setup_alt_next = 0; - musbotg_setup_standard_chain_sub(&temp); + /* check if we should append a status stage */ + if (!xfer->flags_int.control_act) { + /* + * Send a DATA1 message and invert the current + * endpoint direction. + */ + temp.func = &musbotg_setup_status; + musbotg_setup_standard_chain_sub(&temp); + } } /* must have at least one frame! */ td = temp.td; Modified: head/sys/dev/usb/controller/musb_otg_atmelarm.c ============================================================================== --- head/sys/dev/usb/controller/musb_otg_atmelarm.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/musb_otg_atmelarm.c Fri Mar 20 21:57:54 2009 (r190183) @@ -130,10 +130,10 @@ musbotg_attach(device_t dev) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); + NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); #else err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); + (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl); #endif if (err) { sc->sc_otg.sc_intr_hdl = NULL; Modified: head/sys/dev/usb/controller/ohci.c ============================================================================== --- head/sys/dev/usb/controller/ohci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ohci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -115,7 +115,7 @@ struct ohci_std_temp { uint16_t max_frame_size; uint8_t shortpkt; uint8_t setup_alt_next; - uint8_t short_frames_ok; + uint8_t last_frame; }; static struct ohci_hcca * @@ -1020,6 +1020,23 @@ ohci_check_transfer_sub(struct usb2_xfer usb2_pc_cpu_flush(ed->page_cache); DPRINTFN(13, "xfer=%p following alt next\n", xfer); + + /* + * Make sure that the OHCI re-scans the schedule by + * writing the BLF and CLF bits: + */ + + if (xfer->xroot->udev->pwr_save.suspended) { + /* nothing to do */ + } else if (xfer->pipe->methods == &ohci_device_bulk_methods) { + ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus); + + OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); + } else if (xfer->pipe->methods == &ohci_device_ctrl_methods) { + ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus); + + OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); + } } } @@ -1034,7 +1051,6 @@ static uint8_t ohci_check_transfer(struct usb2_xfer *xfer) { ohci_ed_t *ed; - uint32_t ed_flags; uint32_t ed_headp; uint32_t ed_tailp; @@ -1043,12 +1059,10 @@ ohci_check_transfer(struct usb2_xfer *xf ed = xfer->qh_start[xfer->flags_int.curr_dma_set]; usb2_pc_cpu_invalidate(ed->page_cache); - ed_flags = le32toh(ed->ed_flags); ed_headp = le32toh(ed->ed_headp); ed_tailp = le32toh(ed->ed_tailp); - if ((ed_flags & OHCI_ED_SKIP) || - (ed_headp & OHCI_HALTED) || + if ((ed_headp & OHCI_HALTED) || (((ed_headp ^ ed_tailp) & (~0xF)) == 0)) { if (xfer->pipe->methods == &ohci_device_isoc_methods) { /* isochronous transfer */ @@ -1379,10 +1393,9 @@ restart: precompute = 0; /* setup alt next pointer, if any */ - if (temp->short_frames_ok) { - if (temp->setup_alt_next) { - td_alt_next = td_next; - } + if (temp->last_frame) { + /* no alternate next */ + td_alt_next = NULL; } else { /* we use this field internally */ td_alt_next = td_next; @@ -1425,8 +1438,8 @@ ohci_setup_standard_chain(struct usb2_xf temp.td = NULL; temp.td_next = td; + temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; - temp.short_frames_ok = xfer->flags_int.short_frames_ok; methods = xfer->pipe->methods; @@ -1441,7 +1454,14 @@ ohci_setup_standard_chain(struct usb2_xf temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.shortpkt = temp.len ? 1 : 0; - + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } ohci_setup_standard_chain_sub(&temp); /* @@ -1482,7 +1502,16 @@ ohci_setup_standard_chain(struct usb2_xf x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + /* no STATUS stage yet, DATA is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } else { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -1523,11 +1552,14 @@ ohci_setup_standard_chain(struct usb2_xf temp.len = 0; temp.pc = NULL; temp.shortpkt = 0; + temp.last_frame = 1; + temp.setup_alt_next = 0; ohci_setup_standard_chain_sub(&temp); } td = temp.td; + /* Ensure that last TD is terminating: */ td->td_next = htole32(OHCI_TD_NEXT_END); td->td_flags &= ~htole32(OHCI_TD_INTR_MASK); td->td_flags |= htole32(OHCI_TD_SET_DI(1)); Modified: head/sys/dev/usb/controller/ohci_atmelarm.c ============================================================================== --- head/sys/dev/usb/controller/ohci_atmelarm.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ohci_atmelarm.c Fri Mar 20 21:57:54 2009 (r190183) @@ -111,10 +111,10 @@ ohci_atmelarm_attach(device_t dev) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl); + NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl); #else err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl); + (driver_intr_t *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl); #endif if (err) { sc->sc_ohci.sc_intr_hdl = NULL; Modified: head/sys/dev/usb/controller/ohci_pci.c ============================================================================== --- head/sys/dev/usb/controller/ohci_pci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/ohci_pci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -289,10 +289,10 @@ ohci_pci_attach(device_t self) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl); #else err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl); + (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl); #endif if (err) { device_printf(self, "Could not setup irq, %d\n", err); Modified: head/sys/dev/usb/controller/uhci.c ============================================================================== --- head/sys/dev/usb/controller/uhci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/uhci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -124,7 +124,7 @@ struct uhci_std_temp { uint16_t max_frame_size; uint8_t shortpkt; uint8_t setup_alt_next; - uint8_t short_frames_ok; + uint8_t last_frame; }; extern struct usb2_bus_methods uhci_bus_methods; @@ -1253,30 +1253,33 @@ uhci_check_transfer_sub(struct usb2_xfer td_self = td->td_self; td_alt_next = td->alt_next; - if ((td->td_token ^ td_token) & htole32(UHCI_TD_SET_DT(1))) { + if (xfer->flags_int.control_xfr) + goto skip; /* don't touch the DT value! */ - /* - * The data toggle is wrong and - * we need to switch it ! - */ + if (!((td->td_token ^ td_token) & htole32(UHCI_TD_SET_DT(1)))) + goto skip; /* data toggle has correct value */ - while (1) { + /* + * The data toggle is wrong and we need to toggle it ! + */ + while (1) { - td->td_token ^= htole32(UHCI_TD_SET_DT(1)); - usb2_pc_cpu_flush(td->page_cache); + td->td_token ^= htole32(UHCI_TD_SET_DT(1)); + usb2_pc_cpu_flush(td->page_cache); - if (td == xfer->td_transfer_last) { - /* last transfer */ - break; - } - td = td->obj_next; + if (td == xfer->td_transfer_last) { + /* last transfer */ + break; + } + td = td->obj_next; - if (td->alt_next != td_alt_next) { - /* next frame */ - break; - } + if (td->alt_next != td_alt_next) { + /* next frame */ + break; } } +skip: + /* update the QH */ qh->qh_e_next = td_self; usb2_pc_cpu_flush(qh->page_cache); @@ -1631,10 +1634,8 @@ restart: precompute = 0; /* setup alt next pointer, if any */ - if (temp->short_frames_ok) { - if (temp->setup_alt_next) { - td_alt_next = td_next; - } + if (temp->last_frame) { + td_alt_next = NULL; } else { /* we use this field internally */ td_alt_next = td_next; @@ -1673,8 +1674,8 @@ uhci_setup_standard_chain(struct usb2_xf temp.td = NULL; temp.td_next = td; + temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; - temp.short_frames_ok = xfer->flags_int.short_frames_ok; uhci_mem_layout_init(&temp.ml, xfer); @@ -1707,7 +1708,14 @@ uhci_setup_standard_chain(struct usb2_xf temp.len = xfer->frlengths[0]; temp.ml.buf_pc = xfer->frbuffers + 0; temp.shortpkt = temp.len ? 1 : 0; - + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } uhci_setup_standard_chain_sub(&temp); } x = 1; @@ -1725,7 +1733,16 @@ uhci_setup_standard_chain(struct usb2_xf x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + /* no STATUS stage yet, DATA is last */ + if (xfer->flags_int.control_act) { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } + } else { + temp.last_frame = 1; + temp.setup_alt_next = 0; + } } /* * Keep previous data toggle, @@ -1780,11 +1797,14 @@ uhci_setup_standard_chain(struct usb2_xf temp.len = 0; temp.ml.buf_pc = NULL; temp.shortpkt = 0; + temp.last_frame = 1; + temp.setup_alt_next = 0; uhci_setup_standard_chain_sub(&temp); } td = temp.td; + /* Ensure that last TD is terminating: */ td->td_next = htole32(UHCI_PTR_T); /* set interrupt bit */ Modified: head/sys/dev/usb/controller/uhci_pci.c ============================================================================== --- head/sys/dev/usb/controller/uhci_pci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/uhci_pci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -323,10 +323,10 @@ uhci_pci_attach(device_t self) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl); #else err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl); + (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl); #endif if (err) { Modified: head/sys/dev/usb/controller/uss820dci.c ============================================================================== --- head/sys/dev/usb/controller/uss820dci.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/uss820dci.c Fri Mar 20 21:57:54 2009 (r190183) @@ -836,8 +836,8 @@ uss820dci_setup_standard_chain(struct us temp.td = NULL; temp.td_next = xfer->td_start[0]; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; temp.offset = 0; + temp.setup_alt_next = xfer->flags_int.short_frames_ok; sc = USS820_DCI_BUS2SC(xfer->xroot->bus); ep_no = (xfer->endpoint & UE_ADDR); @@ -851,6 +851,12 @@ uss820dci_setup_standard_chain(struct us temp.len = xfer->frlengths[0]; temp.pc = xfer->frbuffers + 0; temp.short_pkt = temp.len ? 1 : 0; + /* check for last frame */ + if (xfer->nframes == 1) { + /* no STATUS stage yet, SETUP is last */ + if (xfer->flags_int.control_act) + temp.setup_alt_next = 0; + } uss820dci_setup_standard_chain_sub(&temp); } @@ -878,7 +884,13 @@ uss820dci_setup_standard_chain(struct us x++; if (x == xfer->nframes) { - temp.setup_alt_next = 0; + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_act) { + temp.setup_alt_next = 0; + } + } else { + temp.setup_alt_next = 0; + } } if (temp.len == 0) { @@ -903,37 +915,39 @@ uss820dci_setup_standard_chain(struct us } } - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - - /* check if we should append a status stage */ - - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { + /* check for control transfer */ + if (xfer->flags_int.control_xfr) { uint8_t need_sync; - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - if (xfer->endpoint & UE_DIR_IN) { - temp.func = &uss820dci_data_rx; - need_sync = 0; - } else { - temp.func = &uss820dci_data_tx; - need_sync = 1; - } + /* always setup a valid "pc" pointer for status and sync */ + temp.pc = xfer->frbuffers + 0; temp.len = 0; temp.short_pkt = 0; + temp.setup_alt_next = 0; - uss820dci_setup_standard_chain_sub(&temp); - if (need_sync) { - /* we need a SYNC point after TX */ - temp.func = &uss820dci_data_tx_sync; + /* check if we should append a status stage */ + if (!xfer->flags_int.control_act) { + + /* + * Send a DATA1 message and invert the current + * endpoint direction. + */ + if (xfer->endpoint & UE_DIR_IN) { + temp.func = &uss820dci_data_rx; + need_sync = 0; + } else { + temp.func = &uss820dci_data_tx; + need_sync = 1; + } temp.len = 0; temp.short_pkt = 0; uss820dci_setup_standard_chain_sub(&temp); + if (need_sync) { + /* we need a SYNC point after TX */ + temp.func = &uss820dci_data_tx_sync; + uss820dci_setup_standard_chain_sub(&temp); + } } } /* must have at least one frame! */ Modified: head/sys/dev/usb/controller/uss820dci_atmelarm.c ============================================================================== --- head/sys/dev/usb/controller/uss820dci_atmelarm.c Fri Mar 20 21:51:27 2009 (r190182) +++ head/sys/dev/usb/controller/uss820dci_atmelarm.c Fri Mar 20 21:57:54 2009 (r190183) @@ -170,10 +170,10 @@ uss820_atmelarm_attach(device_t dev) #if (__FreeBSD_version >= 700031) err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - NULL, (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl); + NULL, (driver_intr_t *)uss820dci_interrupt, sc, &sc->sc_intr_hdl); #else err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, - (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl); + (driver_intr_t *)uss820dci_interrupt, sc, &sc->sc_intr_hdl); #endif if (err) { sc->sc_intr_hdl = NULL;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903202157.n2KLvsdj014880>