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:
Gerd Hoffmann 2011-08-26 14:13:48 +02:00
parent c0e5750bc3
commit 2fe80192ba
2 changed files with 43 additions and 1 deletions

View File

@ -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;

View File

@ -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"