aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2010-11-27 19:47:58 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2010-11-27 19:47:58 +0000
commit224cfbfc316bbf0701e5349f62a63b348fd7679d (patch)
treeb27ea77acfb4404088861fa28bd19995cf7b0d95
parentf5a2bc676668be61e35b35349d11a5ce43ca1d3a (diff)
Notes
-rw-r--r--sys/dev/usb/controller/ehci.c92
-rw-r--r--sys/dev/usb/controller/ehci.h3
-rw-r--r--sys/dev/usb/controller/ehci_pci.c2
-rw-r--r--sys/dev/usb/controller/ehcireg.h7
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