usb-ehci: handle siTDs
This patch adds code to do minimal siTD handling, which is basically just following the next pointer. This is good enougth to handle the inactive siTDs used by FreeBSD. Active siTDs are skipped too as we don't have split transfer support in qemu, additionally a warning is printed. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
c0e5750bc3
commit
2fe80192ba
@ -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;
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user