aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/hcd-ehci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/hcd-ehci.c')
-rw-r--r--hw/usb/hcd-ehci.c69
1 files changed, 61 insertions, 8 deletions
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 5298204d9d..6d2d54940d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -414,16 +414,17 @@ struct EHCIState {
*/
QEMUTimer *frame_timer;
QEMUBH *async_bh;
- int astate; // Current state in asynchronous schedule
- int pstate; // Current state in periodic schedule
+ uint32_t astate; /* Current state in asynchronous schedule */
+ uint32_t pstate; /* Current state in periodic schedule */
USBPort ports[NB_PORTS];
USBPort *companion_ports[NB_PORTS];
uint32_t usbsts_pending;
EHCIQueueHead aqueues;
EHCIQueueHead pqueues;
- uint32_t a_fetch_addr; // which address to look at next
- uint32_t p_fetch_addr; // which address to look at next
+ /* which address to look at next */
+ uint32_t a_fetch_addr;
+ uint32_t p_fetch_addr;
USBPacket ipacket;
QEMUSGList isgl;
@@ -568,6 +569,7 @@ static inline void ehci_set_interrupt(EHCIState *s, int intr)
level = 1;
}
+ trace_usb_ehci_interrupt(level, s->usbsts, s->usbintr);
qemu_set_irq(s->irq, level);
}
@@ -821,8 +823,9 @@ static void ehci_attach(USBPort *port)
{
EHCIState *s = port->opaque;
uint32_t *portsc = &s->portsc[port->index];
+ const char *owner = (*portsc & PORTSC_POWNER) ? "comp" : "ehci";
- trace_usb_ehci_port_attach(port->index, port->dev->product_desc);
+ trace_usb_ehci_port_attach(port->index, owner, port->dev->product_desc);
if (*portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
@@ -841,8 +844,9 @@ static void ehci_detach(USBPort *port)
{
EHCIState *s = port->opaque;
uint32_t *portsc = &s->portsc[port->index];
+ const char *owner = (*portsc & PORTSC_POWNER) ? "comp" : "ehci";
- trace_usb_ehci_port_detach(port->index);
+ trace_usb_ehci_port_detach(port->index, owner);
if (*portsc & PORTSC_POWNER) {
USBPort *companion = s->companion_ports[port->index];
@@ -2390,9 +2394,58 @@ static USBBusOps ehci_bus_ops = {
.register_companion = ehci_register_companion,
};
+static int usb_ehci_post_load(void *opaque, int version_id)
+{
+ EHCIState *s = opaque;
+ int i;
+
+ for (i = 0; i < NB_PORTS; i++) {
+ USBPort *companion = s->companion_ports[i];
+ if (companion == NULL) {
+ continue;
+ }
+ if (s->portsc[i] & PORTSC_POWNER) {
+ companion->dev = s->ports[i].dev;
+ } else {
+ companion->dev = NULL;
+ }
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_ehci = {
- .name = "ehci",
- .unmigratable = 1,
+ .name = "ehci",
+ .version_id = 1,
+ .post_load = usb_ehci_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, EHCIState),
+ /* mmio registers */
+ VMSTATE_UINT32(usbcmd, EHCIState),
+ VMSTATE_UINT32(usbsts, EHCIState),
+ VMSTATE_UINT32(usbintr, EHCIState),
+ VMSTATE_UINT32(frindex, EHCIState),
+ VMSTATE_UINT32(ctrldssegment, EHCIState),
+ VMSTATE_UINT32(periodiclistbase, EHCIState),
+ VMSTATE_UINT32(asynclistaddr, EHCIState),
+ VMSTATE_UINT32(configflag, EHCIState),
+ VMSTATE_UINT32(portsc[0], EHCIState),
+ VMSTATE_UINT32(portsc[1], EHCIState),
+ VMSTATE_UINT32(portsc[2], EHCIState),
+ VMSTATE_UINT32(portsc[3], EHCIState),
+ VMSTATE_UINT32(portsc[4], EHCIState),
+ VMSTATE_UINT32(portsc[5], EHCIState),
+ /* frame timer */
+ VMSTATE_TIMER(frame_timer, EHCIState),
+ VMSTATE_UINT64(last_run_ns, EHCIState),
+ VMSTATE_UINT32(async_stepdown, EHCIState),
+ /* schedule state */
+ VMSTATE_UINT32(astate, EHCIState),
+ VMSTATE_UINT32(pstate, EHCIState),
+ VMSTATE_UINT32(a_fetch_addr, EHCIState),
+ VMSTATE_UINT32(p_fetch_addr, EHCIState),
+ VMSTATE_END_OF_LIST()
+ }
};
static Property ehci_properties[] = {