ehci: Don't fetch a NULL current qtd but advance the queue instead.
Fetching qtd with the NULL address most likely makes no sense so from now on, we handle it this case similarly as if the terminate (T) bit is not set, which is already an exception as according to section 3.6 of the EHCI spec there is no T bit defined for the current_qtd field. The spec is a bit vague on how an EHCI driver should initialize these fields: "The general operational model is that the host controller can detect whether the overlay area contains a description of an active transfer" (p. 49). QEMU primarily uses the QTD_TOKEN_ACTIVE bit of the queue header to infer the activity state but there are other ways conceivable. This change allows QEMU to boot further into AmigaOS. The public available version of the EHCI driver recycles queue heads in some rare conditions but only clears the current_qtd field but not the status field. This works with many available EHCI PCI cards but e.g., not with the Freescale USB controller's found on the P5040. On the emulated EHCI controller of QEMU the consequence is that some garbage was read in, which resulted in a reset of the controller. This change fixes the problem. Signed-off-by: Sebastian Bauer <mail@sebastianbauer.info> Tested-by: BALATON Zoltan <balaton@eik.bme.hu> Message-id: 20180625222718.4488-1-mail@sebastianbauer.info Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
ab08440a4e
commit
8bb01b257f
|
@ -1672,7 +1672,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||||
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
ehci_set_state(ehci, async, EST_HORIZONTALQH);
|
||||||
|
|
||||||
} else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
|
} else if ((q->qh.token & QTD_TOKEN_ACTIVE) &&
|
||||||
(NLPTR_TBIT(q->qh.current_qtd) == 0)) {
|
(NLPTR_TBIT(q->qh.current_qtd) == 0) &&
|
||||||
|
(q->qh.current_qtd != 0)) {
|
||||||
q->qtdaddr = q->qh.current_qtd;
|
q->qtdaddr = q->qh.current_qtd;
|
||||||
ehci_set_state(ehci, async, EST_FETCHQTD);
|
ehci_set_state(ehci, async, EST_FETCHQTD);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue