summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-08-29 14:58:27 +0200
committerHans de Goede <hdegoede@redhat.com>2012-08-29 14:58:27 +0200
commitda8cf17c7bdb0e15019befd03f2f31d7ef373b6f (patch)
tree3b461ebfee06b854f471baf968d5980182af2fd9
parentf58fa0095c67e281dd8d4b52fc8a98569e828e5e (diff)
-rw-r--r--hw/usb/hcd-ehci.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 1f6b03e59..a7cf860d0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -831,7 +831,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
if (!flush && ehci->last_run_ns < q->ts + maxage) {
continue;
}
- ehci_free_queue(q, flush ? NULL : "rip unused");
+ ehci_free_queue(q, flush ? "cancel" : "rip unused");
}
}
@@ -1688,6 +1688,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
entry |= (NLPTR_TYPE_QH << 1);
}
+ printf("fetch qh @ %08x starting loop\n", entry);
ehci_set_fetch_addr(ehci, async, entry);
ehci_set_state(ehci, async, EST_FETCHENTRY);
again = 1;
@@ -1718,6 +1719,7 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async)
uint32_t entry = ehci_get_fetch_addr(ehci, async);
if (NLPTR_TBIT(entry)) {
+ if (async) printf("TBIT in async sched?\n");
ehci_set_state(ehci, async, EST_ACTIVE);
goto out;
}
@@ -1758,12 +1760,13 @@ out:
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
EHCIPacket *p;
- uint32_t entry, devaddr;
+ uint32_t entry, devaddr, endp;
EHCIQueue *q;
EHCIqh qh;
bool new_qh = false;
entry = ehci_get_fetch_addr(ehci, async);
+ printf("fetch qh @ %08x\n", entry);
q = ehci_find_queue_by_qh(ehci, entry, async);
if (NULL == q) {
q = ehci_alloc_queue(ehci, entry, async);
@@ -1775,6 +1778,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
if (q->seen > 1) {
/* we are going in circles -- stop processing */
ehci_set_state(ehci, async, EST_ACTIVE);
+ printf("fetch qh @ %08x exit loop, circle\n", entry);
q = NULL;
goto out;
}
@@ -1784,12 +1788,31 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh);
/*
- * The qh should never be changed by the guest, except when idle,
- * in which case the reset is a nop.
+ * The overlay area of the qh should never be changed by the guest,
+ * except when idle, in which case the reset is a nop.
*/
devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR);
- if ((!new_qh && memcmp(&qh, &q->qh, sizeof(qh)) != 0) ||
+ endp = get_field(qh.epchar, QH_EPCHAR_EP);
+ if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
+ (endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
+ (memcmp(&qh.current_qtd, &q->qh.current_qtd,
+ 9 * sizeof(uint32_t)) != 0) ||
(q->dev != NULL && q->dev->addr != devaddr)) {
+ if (!new_qh) {
+ printf("qh mismatch old new @ %08x\n", entry);
+ printf("%08x %08x\n", q->qh.next, qh.next);
+ printf("%08x %08x\n", q->qh.epchar, qh.epchar);
+ printf("%08x %08x\n", q->qh.epcap, qh.epcap);
+ printf("%08x %08x\n", q->qh.current_qtd, qh.current_qtd);
+ printf("%08x %08x\n", q->qh.next_qtd, qh.next_qtd);
+ printf("%08x %08x\n", q->qh.altnext_qtd, qh.altnext_qtd);
+ printf("%08x %08x\n", q->qh.token, qh.token);
+ printf("%08x %08x\n", q->qh.bufptr[0], qh.bufptr[0]);
+ printf("%08x %08x\n", q->qh.bufptr[1], qh.bufptr[1]);
+ printf("%08x %08x\n", q->qh.bufptr[2], qh.bufptr[2]);
+ printf("%08x %08x\n", q->qh.bufptr[3], qh.bufptr[3]);
+ printf("%08x %08x\n", q->qh.bufptr[4], qh.bufptr[4]);
+ }
ehci_reset_queue(q);
p = NULL;
}
@@ -1810,8 +1833,10 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
/* EHCI spec version 1.0 Section 4.8.3 & 4.10.1 */
if (ehci->usbsts & USBSTS_REC) {
+ printf("fetch qh @ %08x clearing sts_rec\n", entry);
ehci_clear_usbsts(ehci, USBSTS_REC);
} else {
+ printf("fetch qh @ %08x exit loop, halt bit\n", entry);
DPRINTF("FETCHQH: QH 0x%08x. H-bit set, reclamation status reset"
" - done processing\n", q->qhaddr);
ehci_set_state(ehci, async, EST_ACTIVE);
@@ -1996,6 +2021,7 @@ static int ehci_state_horizqh(EHCIQueue *q)
ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
again = 1;
} else {
+ printf("1 on 1 circle\n");
ehci_set_state(q->ehci, q->async, EST_ACTIVE);
}
@@ -2285,7 +2311,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
if (ehci->usbcmd & USBCMD_IAAD) {
/* Remove all unseen qhs from the async qhs queue */
ehci_queues_rip_unused(ehci, async, 1);
- DPRINTF("ASYNC: doorbell request acknowledged\n");
+ printf("ASYNC: doorbell request acknowledged\n");
ehci->usbcmd &= ~USBCMD_IAAD;
ehci_raise_irq(ehci, USBSTS_IAA);
}