Lines Matching refs:q

122 static int ehci_state_executing(EHCIQueue *q);
123 static int ehci_state_writeback(EHCIQueue *q);
124 static int ehci_state_advqueue(EHCIQueue *q);
301 static void ehci_trace_qh(EHCIQueue *q, hwaddr addr, EHCIqh *qh) in ehci_trace_qh() argument
304 trace_usb_ehci_qh_ptrs(q, addr, qh->next, in ehci_trace_qh()
319 static void ehci_trace_qtd(EHCIQueue *q, hwaddr addr, EHCIqtd *qtd) in ehci_trace_qtd() argument
322 trace_usb_ehci_qtd_ptrs(q, addr, qtd->next, qtd->altnext); in ehci_trace_qtd()
431 static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh) in ehci_verify_qh() argument
435 if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) || in ehci_verify_qh()
436 (endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) || in ehci_verify_qh()
437 (qh->current_qtd != q->qh.current_qtd) || in ehci_verify_qh()
438 (q->async && qh->next_qtd != q->qh.next_qtd) || in ehci_verify_qh()
439 (memcmp(&qh->altnext_qtd, &q->qh.altnext_qtd, in ehci_verify_qh()
441 (q->dev != NULL && q->dev->addr != devaddr)) { in ehci_verify_qh()
462 static bool ehci_verify_pid(EHCIQueue *q, EHCIqtd *qtd) in ehci_verify_pid() argument
464 int ep = get_field(q->qh.epchar, QH_EPCHAR_EP); in ehci_verify_pid()
468 if (q->last_pid && ep != 0 && pid != q->last_pid) { in ehci_verify_pid()
479 EHCIQueue *q = p->queue; in ehci_writeback_async_complete_packet() local
485 get_dwords(q->ehci, NLPTR_GET(q->qhaddr), in ehci_writeback_async_complete_packet()
487 get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), in ehci_writeback_async_complete_packet()
489 if (!ehci_verify_qh(q, &qh) || !ehci_verify_qtd(p, &qtd)) { in ehci_writeback_async_complete_packet()
495 state = ehci_get_state(q->ehci, q->async); in ehci_writeback_async_complete_packet()
496 ehci_state_executing(q); in ehci_writeback_async_complete_packet()
497 ehci_state_writeback(q); /* Frees the packet! */ in ehci_writeback_async_complete_packet()
498 if (!(q->qh.token & QTD_TOKEN_HALT)) { in ehci_writeback_async_complete_packet()
499 ehci_state_advqueue(q); in ehci_writeback_async_complete_packet()
501 ehci_set_state(q->ehci, q->async, state); in ehci_writeback_async_complete_packet()
506 static EHCIPacket *ehci_alloc_packet(EHCIQueue *q) in ehci_alloc_packet() argument
511 p->queue = q; in ehci_alloc_packet()
513 QTAILQ_INSERT_TAIL(&q->packets, p, next); in ehci_alloc_packet()
550 EHCIQueue *q; in ehci_alloc_queue() local
552 q = g_malloc0(sizeof(*q)); in ehci_alloc_queue()
553 q->ehci = ehci; in ehci_alloc_queue()
554 q->qhaddr = addr; in ehci_alloc_queue()
555 q->async = async; in ehci_alloc_queue()
556 QTAILQ_INIT(&q->packets); in ehci_alloc_queue()
557 QTAILQ_INSERT_HEAD(head, q, next); in ehci_alloc_queue()
558 trace_usb_ehci_queue_action(q, "alloc"); in ehci_alloc_queue()
559 return q; in ehci_alloc_queue()
562 static void ehci_queue_stopped(EHCIQueue *q) in ehci_queue_stopped() argument
564 int endp = get_field(q->qh.epchar, QH_EPCHAR_EP); in ehci_queue_stopped()
566 if (!q->last_pid || !q->dev) { in ehci_queue_stopped()
570 usb_device_ep_stopped(q->dev, usb_ep_get(q->dev, q->last_pid, endp)); in ehci_queue_stopped()
573 static int ehci_cancel_queue(EHCIQueue *q) in ehci_cancel_queue() argument
578 p = QTAILQ_FIRST(&q->packets); in ehci_cancel_queue()
583 trace_usb_ehci_queue_action(q, "cancel"); in ehci_cancel_queue()
587 } while ((p = QTAILQ_FIRST(&q->packets)) != NULL); in ehci_cancel_queue()
590 ehci_queue_stopped(q); in ehci_cancel_queue()
594 static int ehci_reset_queue(EHCIQueue *q) in ehci_reset_queue() argument
598 trace_usb_ehci_queue_action(q, "reset"); in ehci_reset_queue()
599 packets = ehci_cancel_queue(q); in ehci_reset_queue()
600 q->dev = NULL; in ehci_reset_queue()
601 q->qtdaddr = 0; in ehci_reset_queue()
602 q->last_pid = 0; in ehci_reset_queue()
606 static void ehci_free_queue(EHCIQueue *q, const char *warn) in ehci_free_queue() argument
608 EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues; in ehci_free_queue()
611 trace_usb_ehci_queue_action(q, "free"); in ehci_free_queue()
612 cancelled = ehci_cancel_queue(q); in ehci_free_queue()
614 ehci_trace_guest_bug(q->ehci, warn); in ehci_free_queue()
616 QTAILQ_REMOVE(head, q, next); in ehci_free_queue()
617 g_free(q); in ehci_free_queue()
624 EHCIQueue *q; in ehci_find_queue_by_qh() local
626 QTAILQ_FOREACH(q, head, next) { in ehci_find_queue_by_qh()
627 if (addr == q->qhaddr) { in ehci_find_queue_by_qh()
628 return q; in ehci_find_queue_by_qh()
639 EHCIQueue *q, *tmp; in ehci_queues_rip_unused() local
641 QTAILQ_FOREACH_SAFE(q, head, next, tmp) { in ehci_queues_rip_unused()
642 if (q->seen) { in ehci_queues_rip_unused()
643 q->seen = 0; in ehci_queues_rip_unused()
644 q->ts = ehci->last_run_ns; in ehci_queues_rip_unused()
647 if (ehci->last_run_ns < q->ts + maxage) { in ehci_queues_rip_unused()
650 ehci_free_queue(q, warn); in ehci_queues_rip_unused()
657 EHCIQueue *q, *tmp; in ehci_queues_rip_unseen() local
659 QTAILQ_FOREACH_SAFE(q, head, next, tmp) { in ehci_queues_rip_unseen()
660 if (!q->seen) { in ehci_queues_rip_unseen()
661 ehci_free_queue(q, NULL); in ehci_queues_rip_unseen()
669 EHCIQueue *q, *tmp; in ehci_queues_rip_device() local
671 QTAILQ_FOREACH_SAFE(q, head, next, tmp) { in ehci_queues_rip_device()
672 if (q->dev != dev) { in ehci_queues_rip_device()
675 ehci_free_queue(q, NULL); in ehci_queues_rip_device()
683 EHCIQueue *q, *tmp; in ehci_queues_rip_all() local
685 QTAILQ_FOREACH_SAFE(q, head, next, tmp) { in ehci_queues_rip_all()
686 ehci_free_queue(q, warn); in ehci_queues_rip_all()
1124 static void ehci_flush_qh(EHCIQueue *q) in ehci_flush_qh() argument
1126 uint32_t *qh = (uint32_t *) &q->qh; in ehci_flush_qh()
1128 uint32_t addr = NLPTR_GET(q->qhaddr); in ehci_flush_qh()
1130 put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3); in ehci_flush_qh()
1135 static int ehci_qh_do_overlay(EHCIQueue *q) in ehci_qh_do_overlay() argument
1137 EHCIPacket *p = QTAILQ_FIRST(&q->packets); in ehci_qh_do_overlay()
1145 assert(p->qtdaddr == q->qtdaddr); in ehci_qh_do_overlay()
1149 dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE; in ehci_qh_do_overlay()
1150 ping = q->qh.token & QTD_TOKEN_PING; in ehci_qh_do_overlay()
1152 q->qh.current_qtd = p->qtdaddr; in ehci_qh_do_overlay()
1153 q->qh.next_qtd = p->qtd.next; in ehci_qh_do_overlay()
1154 q->qh.altnext_qtd = p->qtd.altnext; in ehci_qh_do_overlay()
1155 q->qh.token = p->qtd.token; in ehci_qh_do_overlay()
1158 eps = get_field(q->qh.epchar, QH_EPCHAR_EPS); in ehci_qh_do_overlay()
1160 q->qh.token &= ~QTD_TOKEN_PING; in ehci_qh_do_overlay()
1161 q->qh.token |= ping; in ehci_qh_do_overlay()
1164 reload = get_field(q->qh.epchar, QH_EPCHAR_RL); in ehci_qh_do_overlay()
1165 set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT); in ehci_qh_do_overlay()
1168 q->qh.bufptr[i] = p->qtd.bufptr[i]; in ehci_qh_do_overlay()
1171 if (!(q->qh.epchar & QH_EPCHAR_DTC)) { in ehci_qh_do_overlay()
1173 q->qh.token &= ~QTD_TOKEN_DTOGGLE; in ehci_qh_do_overlay()
1174 q->qh.token |= dtoggle; in ehci_qh_do_overlay()
1177 q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK; in ehci_qh_do_overlay()
1178 q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK; in ehci_qh_do_overlay()
1180 ehci_flush_qh(q); in ehci_qh_do_overlay()
1217 static void ehci_finish_transfer(EHCIQueue *q, int len) in ehci_finish_transfer() argument
1223 cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); in ehci_finish_transfer()
1224 offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; in ehci_finish_transfer()
1230 set_field(&q->qh.token, cpage, QTD_TOKEN_CPAGE); in ehci_finish_transfer()
1231 q->qh.bufptr[0] &= QTD_BUFPTR_MASK; in ehci_finish_transfer()
1232 q->qh.bufptr[0] |= offset; in ehci_finish_transfer()
1266 static void ehci_execute_complete(EHCIQueue *q) in ehci_execute_complete() argument
1268 EHCIPacket *p = QTAILQ_FIRST(&q->packets); in ehci_execute_complete()
1272 assert(p->qtdaddr == q->qtdaddr); in ehci_execute_complete()
1278 q->qhaddr, q->qh.next, q->qtdaddr, in ehci_execute_complete()
1286 q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); in ehci_execute_complete()
1287 set_field(&q->qh.token, 0, QTD_TOKEN_CERR); in ehci_execute_complete()
1288 ehci_raise_irq(q->ehci, USBSTS_ERRINT); in ehci_execute_complete()
1291 q->qh.token |= QTD_TOKEN_HALT; in ehci_execute_complete()
1292 ehci_raise_irq(q->ehci, USBSTS_ERRINT); in ehci_execute_complete()
1295 set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT); in ehci_execute_complete()
1298 q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); in ehci_execute_complete()
1299 ehci_raise_irq(q->ehci, USBSTS_ERRINT); in ehci_execute_complete()
1308 tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); in ehci_execute_complete()
1313 ehci_raise_irq(q->ehci, USBSTS_INT); in ehci_execute_complete()
1314 if (q->async) { in ehci_execute_complete()
1315 q->ehci->int_req_by_async = true; in ehci_execute_complete()
1322 set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); in ehci_execute_complete()
1324 ehci_finish_transfer(q, p->packet.actual_length); in ehci_execute_complete()
1329 q->qh.token ^= QTD_TOKEN_DTOGGLE; in ehci_execute_complete()
1330 q->qh.token &= ~QTD_TOKEN_ACTIVE; in ehci_execute_complete()
1332 if (q->qh.token & QTD_TOKEN_IOC) { in ehci_execute_complete()
1333 ehci_raise_irq(q->ehci, USBSTS_INT); in ehci_execute_complete()
1334 if (q->async) { in ehci_execute_complete()
1335 q->ehci->int_req_by_async = true; in ehci_execute_complete()
1615 EHCIQueue *q; in ehci_state_fetchqh() local
1619 q = ehci_find_queue_by_qh(ehci, entry, async); in ehci_state_fetchqh()
1620 if (q == NULL) { in ehci_state_fetchqh()
1621 q = ehci_alloc_queue(ehci, entry, async); in ehci_state_fetchqh()
1624 q->seen++; in ehci_state_fetchqh()
1625 if (q->seen > 1) { in ehci_state_fetchqh()
1628 q = NULL; in ehci_state_fetchqh()
1632 if (get_dwords(ehci, NLPTR_GET(q->qhaddr), in ehci_state_fetchqh()
1634 q = NULL; in ehci_state_fetchqh()
1637 ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh); in ehci_state_fetchqh()
1643 if (!ehci_verify_qh(q, &qh)) { in ehci_state_fetchqh()
1644 if (ehci_reset_queue(q) > 0) { in ehci_state_fetchqh()
1648 q->qh = qh; in ehci_state_fetchqh()
1650 q->transact_ctr = get_field(q->qh.epcap, QH_EPCAP_MULT); in ehci_state_fetchqh()
1651 if (q->transact_ctr == 0) { /* Guest bug in some versions of windows */ in ehci_state_fetchqh()
1652 q->transact_ctr = 4; in ehci_state_fetchqh()
1655 if (q->dev == NULL) { in ehci_state_fetchqh()
1656 q->dev = ehci_find_device(q->ehci, in ehci_state_fetchqh()
1657 get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)); in ehci_state_fetchqh()
1660 if (async && (q->qh.epchar & QH_EPCHAR_H)) { in ehci_state_fetchqh()
1667 " - done processing\n", q->qhaddr); in ehci_state_fetchqh()
1669 q = NULL; in ehci_state_fetchqh()
1675 if (q->qhaddr != q->qh.next) { in ehci_state_fetchqh()
1677 q->qhaddr, in ehci_state_fetchqh()
1678 q->qh.epchar & QH_EPCHAR_H, in ehci_state_fetchqh()
1679 q->qh.token & QTD_TOKEN_HALT, in ehci_state_fetchqh()
1680 q->qh.token & QTD_TOKEN_ACTIVE, in ehci_state_fetchqh()
1681 q->qh.next); in ehci_state_fetchqh()
1685 if (q->qh.token & QTD_TOKEN_HALT) { in ehci_state_fetchqh()
1688 } else if ((q->qh.token & QTD_TOKEN_ACTIVE) && in ehci_state_fetchqh()
1689 (NLPTR_TBIT(q->qh.current_qtd) == 0) && in ehci_state_fetchqh()
1690 (q->qh.current_qtd != 0)) { in ehci_state_fetchqh()
1691 q->qtdaddr = q->qh.current_qtd; in ehci_state_fetchqh()
1700 return q; in ehci_state_fetchqh()
1756 static int ehci_state_advqueue(EHCIQueue *q) in ehci_state_advqueue() argument
1772 if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) && in ehci_state_advqueue()
1773 (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) { in ehci_state_advqueue()
1774 q->qtdaddr = q->qh.altnext_qtd; in ehci_state_advqueue()
1775 ehci_set_state(q->ehci, q->async, EST_FETCHQTD); in ehci_state_advqueue()
1780 } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) { in ehci_state_advqueue()
1781 q->qtdaddr = q->qh.next_qtd; in ehci_state_advqueue()
1782 ehci_set_state(q->ehci, q->async, EST_FETCHQTD); in ehci_state_advqueue()
1788 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_advqueue()
1795 static int ehci_state_fetchqtd(EHCIQueue *q) in ehci_state_fetchqtd() argument
1802 addr = NLPTR_GET(q->qtdaddr); in ehci_state_fetchqtd()
1803 if (get_dwords(q->ehci, addr + 8, &qtd.token, 1) < 0) { in ehci_state_fetchqtd()
1807 if (get_dwords(q->ehci, addr + 0, &qtd.next, 1) < 0 || in ehci_state_fetchqtd()
1808 get_dwords(q->ehci, addr + 4, &qtd.altnext, 1) < 0 || in ehci_state_fetchqtd()
1809 get_dwords(q->ehci, addr + 12, qtd.bufptr, in ehci_state_fetchqtd()
1813 ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd); in ehci_state_fetchqtd()
1815 p = QTAILQ_FIRST(&q->packets); in ehci_state_fetchqtd()
1818 ehci_cancel_queue(q); in ehci_state_fetchqtd()
1820 ehci_trace_guest_bug(q->ehci, "guest updated active qTD"); in ehci_state_fetchqtd()
1825 ehci_qh_do_overlay(q); in ehci_state_fetchqtd()
1830 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_fetchqtd()
1836 ehci_set_state(q->ehci, q->async, EST_EXECUTE); in ehci_state_fetchqtd()
1840 again = ehci_fill_queue(QTAILQ_LAST(&q->packets)); in ehci_state_fetchqtd()
1842 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_fetchqtd()
1846 ehci_set_state(q->ehci, q->async, EST_EXECUTING); in ehci_state_fetchqtd()
1849 } else if (q->dev == NULL) { in ehci_state_fetchqtd()
1850 ehci_trace_guest_bug(q->ehci, "no device attached to queue"); in ehci_state_fetchqtd()
1851 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_fetchqtd()
1853 p = ehci_alloc_packet(q); in ehci_state_fetchqtd()
1854 p->qtdaddr = q->qtdaddr; in ehci_state_fetchqtd()
1856 ehci_set_state(q->ehci, q->async, EST_EXECUTE); in ehci_state_fetchqtd()
1862 static int ehci_state_horizqh(EHCIQueue *q) in ehci_state_horizqh() argument
1866 if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) { in ehci_state_horizqh()
1867 ehci_set_fetch_addr(q->ehci, q->async, q->qh.next); in ehci_state_horizqh()
1868 ehci_set_state(q->ehci, q->async, EST_FETCHENTRY); in ehci_state_horizqh()
1871 ehci_set_state(q->ehci, q->async, EST_ACTIVE); in ehci_state_horizqh()
1881 EHCIQueue *q = p->queue; in ehci_fill_queue() local
1894 QTAILQ_FOREACH(p, &q->packets, next) { in ehci_fill_queue()
1899 if (get_dwords(q->ehci, NLPTR_GET(qtdaddr), in ehci_fill_queue()
1903 ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd); in ehci_fill_queue()
1907 if (!ehci_verify_pid(q, &qtd)) { in ehci_fill_queue()
1908 ehci_trace_guest_bug(q->ehci, "guest queued token with wrong pid"); in ehci_fill_queue()
1911 p = ehci_alloc_packet(q); in ehci_fill_queue()
1925 static int ehci_state_execute(EHCIQueue *q) in ehci_state_execute() argument
1927 EHCIPacket *p = QTAILQ_FIRST(&q->packets); in ehci_state_execute()
1931 assert(p->qtdaddr == q->qtdaddr); in ehci_state_execute()
1933 if (ehci_qh_do_overlay(q) != 0) { in ehci_state_execute()
1941 if (!q->async && q->transact_ctr == 0) { in ehci_state_execute()
1942 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_execute()
1947 if (q->async) { in ehci_state_execute()
1948 ehci_set_usbsts(q->ehci, USBSTS_REC); in ehci_state_execute()
1956 ehci_flush_qh(q); in ehci_state_execute()
1959 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_execute()
1960 if (q->async) { in ehci_state_execute()
1968 ehci_set_state(q->ehci, q->async, EST_EXECUTING); in ehci_state_execute()
1975 static int ehci_state_executing(EHCIQueue *q) in ehci_state_executing() argument
1977 EHCIPacket *p = QTAILQ_FIRST(&q->packets); in ehci_state_executing()
1980 assert(p->qtdaddr == q->qtdaddr); in ehci_state_executing()
1982 ehci_execute_complete(q); in ehci_state_executing()
1985 if (!q->async && q->transact_ctr > 0) { in ehci_state_executing()
1986 q->transact_ctr--; in ehci_state_executing()
1991 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_executing()
1993 ehci_set_state(q->ehci, q->async, EST_WRITEBACK); in ehci_state_executing()
1996 ehci_flush_qh(q); in ehci_state_executing()
2001 static int ehci_state_writeback(EHCIQueue *q) in ehci_state_writeback() argument
2003 EHCIPacket *p = QTAILQ_FIRST(&q->packets); in ehci_state_writeback()
2009 assert(p->qtdaddr == q->qtdaddr); in ehci_state_writeback()
2011 ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd); in ehci_state_writeback()
2012 qtd = (uint32_t *) &q->qh.next_qtd; in ehci_state_writeback()
2015 put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qtd + 3, 1); in ehci_state_writeback()
2017 put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 1); in ehci_state_writeback()
2028 if (q->qh.token & QTD_TOKEN_HALT) { in ehci_state_writeback()
2029 ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); in ehci_state_writeback()
2032 ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE); in ehci_state_writeback()
2044 EHCIQueue *q = NULL; in ehci_advance_state() local
2059 q = ehci_state_fetchqh(ehci, async); in ehci_advance_state()
2060 if (q != NULL) { in ehci_advance_state()
2061 assert(q->async == async); in ehci_advance_state()
2079 assert(q != NULL); in ehci_advance_state()
2080 again = ehci_state_advqueue(q); in ehci_advance_state()
2084 assert(q != NULL); in ehci_advance_state()
2085 again = ehci_state_fetchqtd(q); in ehci_advance_state()
2089 assert(q != NULL); in ehci_advance_state()
2090 again = ehci_state_horizqh(q); in ehci_advance_state()
2094 assert(q != NULL); in ehci_advance_state()
2095 again = ehci_state_execute(q); in ehci_advance_state()
2102 assert(q != NULL); in ehci_advance_state()
2106 again = ehci_state_executing(q); in ehci_advance_state()
2110 assert(q != NULL); in ehci_advance_state()
2111 again = ehci_state_writeback(q); in ehci_advance_state()