diff options
| author | Andrew Thompson <thompsa@FreeBSD.org> | 2010-11-27 19:47:58 +0000 |
|---|---|---|
| committer | Andrew Thompson <thompsa@FreeBSD.org> | 2010-11-27 19:47:58 +0000 |
| commit | 224cfbfc316bbf0701e5349f62a63b348fd7679d (patch) | |
| tree | b27ea77acfb4404088861fa28bd19995cf7b0d95 | |
| parent | f5a2bc676668be61e35b35349d11a5ce43ca1d3a (diff) | |
Notes
| -rw-r--r-- | sys/dev/usb/controller/ehci.c | 92 | ||||
| -rw-r--r-- | sys/dev/usb/controller/ehci.h | 3 | ||||
| -rw-r--r-- | sys/dev/usb/controller/ehci_pci.c | 2 | ||||
| -rw-r--r-- | sys/dev/usb/controller/ehcireg.h | 7 |
4 files changed, 53 insertions, 51 deletions
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c index 2c13bc1fd96f..329c9d861efd 100644 --- a/sys/dev/usb/controller/ehci.c +++ b/sys/dev/usb/controller/ehci.c @@ -145,7 +145,6 @@ struct ehci_std_temp { uint8_t auto_data_toggle; uint8_t setup_alt_next; uint8_t last_frame; - uint8_t can_use_next; }; void @@ -157,6 +156,9 @@ ehci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb) cb(bus, &sc->sc_hw.pframes_pc, &sc->sc_hw.pframes_pg, sizeof(uint32_t) * EHCI_FRAMELIST_COUNT, EHCI_FRAMELIST_ALIGN); + cb(bus, &sc->sc_hw.terminate_pc, &sc->sc_hw.terminate_pg, + sizeof(struct ehci_qh_sub), EHCI_QH_ALIGN); + cb(bus, &sc->sc_hw.async_start_pc, &sc->sc_hw.async_start_pg, sizeof(ehci_qh_t), EHCI_QH_ALIGN); @@ -310,6 +312,24 @@ ehci_init(ehci_softc_t *sc) sc->sc_eintrs = EHCI_NORMAL_INTRS; + if (1) { + struct ehci_qh_sub *qh; + + usbd_get_page(&sc->sc_hw.terminate_pc, 0, &buf_res); + + qh = buf_res.buffer; + + sc->sc_terminate_self = htohc32(sc, buf_res.physaddr); + + /* init terminate TD */ + qh->qtd_next = + htohc32(sc, EHCI_LINK_TERMINATE); + qh->qtd_altnext = + htohc32(sc, EHCI_LINK_TERMINATE); + qh->qtd_status = + htohc32(sc, EHCI_QTD_HALTED); + } + for (i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++) { ehci_qh_t *qh; @@ -1416,15 +1436,7 @@ ehci_check_transfer(struct usb_xfer *xfer) */ if (status & EHCI_QTD_ACTIVE) { /* update cache */ - if (xfer->td_transfer_cache != td) { - xfer->td_transfer_cache = td; - if (qh->qh_qtd.qtd_next & - htohc32(sc, EHCI_LINK_TERMINATE)) { - /* XXX - manually advance to next frame */ - qh->qh_qtd.qtd_next = td->qtd_self; - usb_pc_cpu_flush(td->page_cache); - } - } + xfer->td_transfer_cache = td; goto done; } /* @@ -1634,10 +1646,12 @@ ehci_setup_standard_chain_sub(struct ehci_std_temp *temp) uint32_t average; uint32_t len_old; uint32_t terminate; + uint32_t qtd_altnext; uint8_t shortpkt_old; uint8_t precompute; - terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE); + terminate = temp->sc->sc_terminate_self; + qtd_altnext = temp->sc->sc_terminate_self; td_alt_next = NULL; buf_offset = 0; shortpkt_old = temp->shortpkt; @@ -1771,23 +1785,11 @@ restart: td->qtd_buffer_hi[x] = 0; } - if (temp->can_use_next) { - if (td_next) { - /* link the current TD with the next one */ - td->qtd_next = td_next->qtd_self; - } - } else { - /* - * BUG WARNING: The EHCI HW can use the - * qtd_next field instead of qtd_altnext when - * a short packet is received! We work this - * around in software by not queueing more - * than one job/TD at a time! - */ - td->qtd_next = terminate; + if (td_next) { + /* link the current TD with the next one */ + td->qtd_next = td_next->qtd_self; } - - td->qtd_altnext = terminate; + td->qtd_altnext = qtd_altnext; td->alt_next = td_alt_next; usb_pc_cpu_flush(td->page_cache); @@ -1799,9 +1801,15 @@ restart: /* setup alt next pointer, if any */ 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 */ @@ -1846,8 +1854,6 @@ ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last) temp.qtd_status = 0; temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; - temp.can_use_next = (xfer->flags_int.control_xfr || - (UE_GET_DIR(xfer->endpointno) == UE_DIR_OUT)); if (xfer->flags_int.control_xfr) { if (xfer->endpoint->toggle_next) { @@ -1860,7 +1866,8 @@ ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last) temp.auto_data_toggle = 1; } - if (usbd_get_speed(xfer->xroot->udev) != USB_SPEED_HIGH) { + if ((xfer->xroot->udev->parent_hs_hub != NULL) || + (xfer->xroot->udev->address != 0)) { /* max 3 retries */ temp.qtd_status |= htohc32(temp.sc, EHCI_QTD_SET_CERR(3)); @@ -3063,8 +3070,7 @@ static const struct ehci_config_desc ehci_confd = { .bNumEndpoints = 1, .bInterfaceClass = UICLASS_HUB, .bInterfaceSubClass = UISUBCLASS_HUB, - .bInterfaceProtocol = UIPROTO_HSHUBSTT, - 0 + .bInterfaceProtocol = 0, }, .endpd = { .bLength = sizeof(struct usb_endpoint_descriptor), @@ -3114,7 +3120,6 @@ ehci_roothub_exec(struct usb_device *udev, uint16_t i; uint16_t value; uint16_t index; - uint8_t l; usb_error_t err; USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); @@ -3318,20 +3323,23 @@ ehci_roothub_exec(struct usb_device *udev, err = USB_ERR_IOERROR; goto done; } - v = EOREAD4(sc, EHCI_HCSPARAMS); + v = EREAD4(sc, EHCI_HCSPARAMS); sc->sc_hub_desc.hubd = ehci_hubd; sc->sc_hub_desc.hubd.bNbrPorts = sc->sc_noport; - USETW(sc->sc_hub_desc.hubd.wHubCharacteristics, - (EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH) | - (EHCI_HCS_P_INDICATOR(EREAD4(sc, EHCI_HCSPARAMS)) ? - UHD_PORT_IND : 0)); + + if (EHCI_HCS_PPC(v)) + i = UHD_PWR_INDIVIDUAL; + else + i = UHD_PWR_NO_SWITCH; + + if (EHCI_HCS_P_INDICATOR(v)) + i |= UHD_PORT_IND; + + USETW(sc->sc_hub_desc.hubd.wHubCharacteristics, i); /* XXX can't find out? */ sc->sc_hub_desc.hubd.bPwrOn2PwrGood = 200; - for (l = 0; l < sc->sc_noport; l++) { - /* XXX can't find out? */ - sc->sc_hub_desc.hubd.DeviceRemovable[l / 8] &= ~(1 << (l % 8)); - } + /* XXX don't know if ports are removable or not */ sc->sc_hub_desc.hubd.bDescLength = 8 + ((sc->sc_noport + 7) / 8); len = sc->sc_hub_desc.hubd.bDescLength; diff --git a/sys/dev/usb/controller/ehci.h b/sys/dev/usb/controller/ehci.h index b6426c45ca36..04a81b729c2c 100644 --- a/sys/dev/usb/controller/ehci.h +++ b/sys/dev/usb/controller/ehci.h @@ -292,12 +292,14 @@ typedef struct ehci_fstn ehci_fstn_t; struct ehci_hw_softc { struct usb_page_cache pframes_pc; + struct usb_page_cache terminate_pc; struct usb_page_cache async_start_pc; struct usb_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page pframes_pg; + struct usb_page terminate_pg; struct usb_page async_start_pg; struct usb_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; struct usb_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT]; @@ -336,6 +338,7 @@ typedef struct ehci_softc { bus_space_tag_t sc_io_tag; bus_space_handle_t sc_io_hdl; + uint32_t sc_terminate_self; /* TD short packet termination pointer */ uint32_t sc_eintrs; uint32_t sc_cmd; /* shadow of cmd register during * suspend */ diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c index bd7afcf8ade1..f679e2b07bab 100644 --- a/sys/dev/usb/controller/ehci_pci.c +++ b/sys/dev/usb/controller/ehci_pci.c @@ -100,8 +100,6 @@ __FBSDID("$FreeBSD$"); #define PCI_EHCI_VENDORID_NVIDIA2 0x10DE #define PCI_EHCI_VENDORID_VIA 0x1106 -#define PCI_EHCI_BASE_REG 0x10 - static void ehci_pci_takecontroller(device_t self); static device_probe_t ehci_pci_probe; diff --git a/sys/dev/usb/controller/ehcireg.h b/sys/dev/usb/controller/ehcireg.h index 1f60df08d4e7..1f5fc5c06cad 100644 --- a/sys/dev/usb/controller/ehcireg.h +++ b/sys/dev/usb/controller/ehcireg.h @@ -14,13 +14,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
