diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-08-29 14:58:27 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2012-08-29 14:58:27 +0200 |
commit | da8cf17c7bdb0e15019befd03f2f31d7ef373b6f (patch) | |
tree | 3b461ebfee06b854f471baf968d5980182af2fd9 | |
parent | f58fa0095c67e281dd8d4b52fc8a98569e828e5e (diff) |
wipusb-borken
-rw-r--r-- | hw/usb/hcd-ehci.c | 38 |
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); } |