Revision 9bc3a3a2
b/hw/usb/hcd-ehci.c | ||
---|---|---|
365 | 365 |
uint32_t seen; |
366 | 366 |
uint64_t ts; |
367 | 367 |
int async; |
368 |
int revalidate; |
|
368 | 369 |
|
369 | 370 |
/* cached data from guest - needs to be flushed |
370 | 371 |
* when guest removes an entry (doorbell, handshake sequence) |
... | ... | |
775 | 776 |
return NULL; |
776 | 777 |
} |
777 | 778 |
|
778 |
static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush) |
|
779 |
static void ehci_queues_tag_unused_async(EHCIState *ehci) |
|
780 |
{ |
|
781 |
EHCIQueue *q; |
|
782 |
|
|
783 |
QTAILQ_FOREACH(q, &ehci->aqueues, next) { |
|
784 |
if (!q->seen) { |
|
785 |
q->revalidate = 1; |
|
786 |
} |
|
787 |
} |
|
788 |
} |
|
789 |
|
|
790 |
static void ehci_queues_rip_unused(EHCIState *ehci, int async) |
|
779 | 791 |
{ |
780 | 792 |
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues; |
781 | 793 |
uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4; |
... | ... | |
787 | 799 |
q->ts = ehci->last_run_ns; |
788 | 800 |
continue; |
789 | 801 |
} |
790 |
if (!flush && ehci->last_run_ns < q->ts + maxage) {
|
|
802 |
if (ehci->last_run_ns < q->ts + maxage) { |
|
791 | 803 |
continue; |
792 | 804 |
} |
793 | 805 |
ehci_free_queue(q); |
... | ... | |
1631 | 1643 |
ehci_set_usbsts(ehci, USBSTS_REC); |
1632 | 1644 |
} |
1633 | 1645 |
|
1634 |
ehci_queues_rip_unused(ehci, async, 0);
|
|
1646 |
ehci_queues_rip_unused(ehci, async); |
|
1635 | 1647 |
|
1636 | 1648 |
/* Find the head of the list (4.9.1.1) */ |
1637 | 1649 |
for(i = 0; i < MAX_QH; i++) { |
... | ... | |
1716 | 1728 |
EHCIPacket *p; |
1717 | 1729 |
uint32_t entry, devaddr; |
1718 | 1730 |
EHCIQueue *q; |
1731 |
EHCIqh qh; |
|
1719 | 1732 |
|
1720 | 1733 |
entry = ehci_get_fetch_addr(ehci, async); |
1721 | 1734 |
q = ehci_find_queue_by_qh(ehci, entry, async); |
... | ... | |
1733 | 1746 |
} |
1734 | 1747 |
|
1735 | 1748 |
get_dwords(ehci, NLPTR_GET(q->qhaddr), |
1736 |
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); |
|
1749 |
(uint32_t *) &qh, sizeof(EHCIqh) >> 2); |
|
1750 |
if (q->revalidate && (q->qh.epchar != qh.epchar || |
|
1751 |
q->qh.epcap != qh.epcap || |
|
1752 |
q->qh.current_qtd != qh.current_qtd)) { |
|
1753 |
ehci_free_queue(q); |
|
1754 |
q = ehci_alloc_queue(ehci, entry, async); |
|
1755 |
q->seen++; |
|
1756 |
p = NULL; |
|
1757 |
} |
|
1758 |
q->qh = qh; |
|
1759 |
q->revalidate = 0; |
|
1737 | 1760 |
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh); |
1738 | 1761 |
|
1739 | 1762 |
devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR); |
... | ... | |
2228 | 2251 |
*/ |
2229 | 2252 |
if (ehci->usbcmd & USBCMD_IAAD) { |
2230 | 2253 |
/* Remove all unseen qhs from the async qhs queue */ |
2231 |
ehci_queues_rip_unused(ehci, async, 1);
|
|
2254 |
ehci_queues_tag_unused_async(ehci);
|
|
2232 | 2255 |
DPRINTF("ASYNC: doorbell request acknowledged\n"); |
2233 | 2256 |
ehci->usbcmd &= ~USBCMD_IAAD; |
2234 | 2257 |
ehci_set_interrupt(ehci, USBSTS_IAA); |
... | ... | |
2281 | 2304 |
ehci_set_fetch_addr(ehci, async,entry); |
2282 | 2305 |
ehci_set_state(ehci, async, EST_FETCHENTRY); |
2283 | 2306 |
ehci_advance_state(ehci, async); |
2284 |
ehci_queues_rip_unused(ehci, async, 0);
|
|
2307 |
ehci_queues_rip_unused(ehci, async); |
|
2285 | 2308 |
break; |
2286 | 2309 |
|
2287 | 2310 |
default: |
Also available in: Unified diff