diff options
Diffstat (limited to 'hw/usb/hcd-ohci.c')
-rw-r--r-- | hw/usb/hcd-ohci.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 51fa111390..1a1cc88b1f 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -121,6 +121,11 @@ struct ohci_hcca { uint16_t frame, pad; uint32_t done; }; +#define HCCA_WRITEBACK_OFFSET offsetof(struct ohci_hcca, frame) +#define HCCA_WRITEBACK_SIZE 8 /* frame, pad, done */ + +#define ED_WBACK_OFFSET offsetof(struct ohci_ed, head) +#define ED_WBACK_SIZE 4 static void ohci_bus_stop(OHCIState *ohci); static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev); @@ -568,7 +573,13 @@ static inline int ohci_read_hcca(OHCIState *ohci, static inline int ohci_put_ed(OHCIState *ohci, uint32_t addr, struct ohci_ed *ed) { - return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); + /* ed->tail is under control of the HCD. + * Since just ed->head is changed by HC, just write back this + */ + + return put_dwords(ohci, addr + ED_WBACK_OFFSET, + (uint32_t *)((char *)ed + ED_WBACK_OFFSET), + ED_WBACK_SIZE >> 2); } static inline int ohci_put_td(OHCIState *ohci, @@ -587,7 +598,9 @@ static inline int ohci_put_iso_td(OHCIState *ohci, static inline int ohci_put_hcca(OHCIState *ohci, uint32_t addr, struct ohci_hcca *hcca) { - cpu_physical_memory_write(addr + ohci->localmem_base, hcca, sizeof(*hcca)); + cpu_physical_memory_write(addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, + (char *)hcca + HCCA_WRITEBACK_OFFSET, + HCCA_WRITEBACK_SIZE); return 1; } |