diff options
Diffstat (limited to 'hw/usb/hcd-ehci.c')
-rw-r--r-- | hw/usb/hcd-ehci.c | 69 |
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[] = { |