diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 47a7fb9de4..d8ef0cb422 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -149,6 +149,7 @@ typedef enum { EST_FETCHENTRY, EST_FETCHQH, EST_FETCHITD, + EST_FETCHSITD, EST_ADVANCEQUEUE, EST_FETCHQTD, EST_EXECUTE, @@ -646,6 +647,13 @@ static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd) get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR)); } +static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr, + EHCIsitd *sitd) +{ + trace_usb_ehci_sitd(addr, sitd->next, + (bool)(sitd->results & SITD_RESULTS_ACTIVE)); +} + /* queue management */ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async) @@ -1584,8 +1592,13 @@ static int ehci_state_fetchentry(EHCIState *ehci, int async) again = 1; break; + case NLPTR_TYPE_STITD: + ehci_set_state(ehci, async, EST_FETCHSITD); + again = 1; + break; + default: - // TODO: handle siTD and FSTN types + /* TODO: handle FSTN type */ fprintf(stderr, "FETCHENTRY: entry at %X is of type %d " "which is not supported yet\n", entry, NLPTR_TYPE_GET(entry)); return -1; @@ -1701,6 +1714,30 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async) return 1; } +static int ehci_state_fetchsitd(EHCIState *ehci, int async) +{ + uint32_t entry; + EHCIsitd sitd; + + assert(!async); + entry = ehci_get_fetch_addr(ehci, async); + + get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd, + sizeof(EHCIsitd) >> 2); + ehci_trace_sitd(ehci, entry, &sitd); + + if (!(sitd.results & SITD_RESULTS_ACTIVE)) { + /* siTD is not active, nothing to do */; + } else { + /* TODO: split transfers are not implemented */ + fprintf(stderr, "WARNING: Skipping active siTD\n"); + } + + ehci_set_fetch_addr(ehci, async, sitd.next); + ehci_set_state(ehci, async, EST_FETCHENTRY); + return 1; +} + /* Section 4.10.2 - paragraph 3 */ static int ehci_state_advqueue(EHCIQueue *q, int async) { @@ -1976,6 +2013,10 @@ static void ehci_advance_state(EHCIState *ehci, again = ehci_state_fetchitd(ehci, async); break; + case EST_FETCHSITD: + again = ehci_state_fetchsitd(ehci, async); + break; + case EST_ADVANCEQUEUE: again = ehci_state_advqueue(q, async); break; diff --git a/trace-events b/trace-events index a6e0cb4c48..5936192289 100644 --- a/trace-events +++ b/trace-events @@ -223,6 +223,7 @@ usb_ehci_qtd_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t altnext) "q %p usb_ehci_qtd_fields(uint32_t addr, int tbytes, int cpage, int cerr, int pid) "QTD @ %08x - tbytes %d, cpage %d, cerr %d, pid %d" usb_ehci_qtd_bits(uint32_t addr, int ioc, int active, int halt, int babble, int xacterr) "QTD @ %08x - ioc %d, active %d, halt %d, babble %d, xacterr %d" usb_ehci_itd(uint32_t addr, uint32_t nxt, uint32_t mplen, uint32_t mult, uint32_t ep, uint32_t devaddr) "ITD @ %08x: next %08x - mplen %d, mult %d, ep %d, dev %d" +usb_ehci_sitd(uint32_t addr, uint32_t nxt, uint32_t active) "ITD @ %08x: next %08x - active %d" usb_ehci_port_attach(uint32_t port, const char *device) "attach port #%d - %s" usb_ehci_port_detach(uint32_t port) "detach port #%d" usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"