X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fusb%2Fhcd-ohci.c;h=a096ecf2142a70fb215fcf2633320bb11e2e076e;hb=f290e4988dd8eb012de0517a1ff93df130e87da1;hp=c36184ae4fe57e33915ea19939cc571f019b488a;hpb=e983395d30d1d5bfa0ed3ae9c028c130f7c498cc;p=qemu.git diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index c36184ae4..a096ecf21 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -27,9 +27,9 @@ */ #include "hw/hw.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "hw/usb.h" -#include "hw/pci.h" +#include "hw/pci/pci.h" #include "hw/sysbus.h" #include "hw/qdev-dma.h" @@ -62,7 +62,7 @@ typedef struct { USBBus bus; qemu_irq irq; MemoryRegion mem; - DMAContext *dma; + AddressSpace *as; int num_ports; const char *name; @@ -430,6 +430,23 @@ static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr) return NULL; } +static void ohci_stop_endpoints(OHCIState *ohci) +{ + USBDevice *dev; + int i, j; + + for (i = 0; i < ohci->num_ports; i++) { + dev = ohci->rhport[i].port.dev; + if (dev && dev->attached) { + usb_device_ep_stopped(dev, &dev->ep_ctl); + for (j = 0; j < USB_MAX_ENDPOINTS; j++) { + usb_device_ep_stopped(dev, &dev->ep_in[j]); + usb_device_ep_stopped(dev, &dev->ep_out[j]); + } + } + } +} + /* Reset the controller */ static void ohci_reset(void *opaque) { @@ -478,6 +495,7 @@ static void ohci_reset(void *opaque) usb_cancel_packet(&ohci->usb_packet); ohci->async_td = 0; } + ohci_stop_endpoints(ohci); DPRINTF("usb-ohci: Reset %s\n", ohci->name); } @@ -490,7 +508,7 @@ static inline int get_dwords(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ohci->dma, addr, buf, sizeof(*buf)); + dma_memory_read(ohci->as, addr, buf, sizeof(*buf)); *buf = le32_to_cpu(*buf); } @@ -507,7 +525,7 @@ static inline int put_dwords(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp)); + dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp)); } return 1; @@ -522,7 +540,7 @@ static inline int get_words(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ohci->dma, addr, buf, sizeof(*buf)); + dma_memory_read(ohci->as, addr, buf, sizeof(*buf)); *buf = le16_to_cpu(*buf); } @@ -539,7 +557,7 @@ static inline int put_words(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint16_t tmp = cpu_to_le16(*buf); - dma_memory_write(ohci->dma, addr, &tmp, sizeof(tmp)); + dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp)); } return 1; @@ -567,7 +585,7 @@ static inline int ohci_read_iso_td(OHCIState *ohci, static inline int ohci_read_hcca(OHCIState *ohci, dma_addr_t addr, struct ohci_hcca *hcca) { - dma_memory_read(ohci->dma, addr + ohci->localmem_base, hcca, sizeof(*hcca)); + dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, sizeof(*hcca)); return 1; } @@ -599,7 +617,7 @@ static inline int ohci_put_iso_td(OHCIState *ohci, static inline int ohci_put_hcca(OHCIState *ohci, dma_addr_t addr, struct ohci_hcca *hcca) { - dma_memory_write(ohci->dma, + dma_memory_write(ohci->as, addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, (char *)hcca + HCCA_WRITEBACK_OFFSET, HCCA_WRITEBACK_SIZE); @@ -616,12 +634,12 @@ static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir); + dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir); if (n == len) return; ptr = td->be & ~0xfffu; buf += n; - dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir); + dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir); } /* Read/Write the contents of an ISO TD from/to main memory. */ @@ -635,12 +653,12 @@ static void ohci_copy_iso_td(OHCIState *ohci, n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, n, dir); + dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir); if (n == len) return; ptr = end_addr & ~0xfffu; buf += n; - dma_memory_rw(ohci->dma, ptr + ohci->localmem_base, buf, len - n, dir); + dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir); } static void ohci_process_lists(OHCIState *ohci, int completion); @@ -807,18 +825,24 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, DMA_DIRECTION_TO_DEVICE); } - if (completion) { - ret = ohci->usb_packet.result; - } else { + if (!completion) { + bool int_req = relative_frame_number == frame_count && + OHCI_BM(iso_td.flags, TD_DI) == 0; dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr); + usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); - ret = usb_handle_packet(dev, &ohci->usb_packet); - if (ret == USB_RET_ASYNC) { + usb_handle_packet(dev, &ohci->usb_packet); + if (ohci->usb_packet.status == USB_RET_ASYNC) { + usb_device_flush_ep_queue(dev, ep); return 1; } } + if (ohci->usb_packet.status == USB_RET_SUCCESS) { + ret = ohci->usb_packet.actual_length; + } else { + ret = ohci->usb_packet.status; + } #ifdef DEBUG_ISOCH printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", @@ -994,7 +1018,6 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } #endif if (completion) { - ret = ohci->usb_packet.result; ohci->async_td = 0; ohci->async_complete = 0; } else { @@ -1011,17 +1034,25 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA)); ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN)); - usb_packet_setup(&ohci->usb_packet, pid, ep, addr); + usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r, + OHCI_BM(td.flags, TD_DI) == 0); usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); - ret = usb_handle_packet(dev, &ohci->usb_packet); + usb_handle_packet(dev, &ohci->usb_packet); #ifdef DEBUG_PACKET - DPRINTF("ret=%d\n", ret); + DPRINTF("status=%d\n", ohci->usb_packet.status); #endif - if (ret == USB_RET_ASYNC) { + if (ohci->usb_packet.status == USB_RET_ASYNC) { + usb_device_flush_ep_queue(dev, ep); ohci->async_td = addr; return 1; } } + if (ohci->usb_packet.status == USB_RET_SUCCESS) { + ret = ohci->usb_packet.actual_length; + } else { + ret = ohci->usb_packet.status; + } + if (ret >= 0) { if (dir == OHCI_TD_DIR_IN) { ohci_copy_td(ohci, &td, ohci->usb_buf, ret, @@ -1134,6 +1165,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) if (ohci->async_td && addr == ohci->async_td) { usb_cancel_packet(&ohci->usb_packet); ohci->async_td = 0; + usb_device_ep_stopped(ohci->usb_packet.ep->dev, + ohci->usb_packet.ep); } continue; } @@ -1214,10 +1247,12 @@ static void ohci_frame_boundary(void *opaque) } /* Cancel all pending packets if either of the lists has been disabled. */ - if (ohci->async_td && - ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { - usb_cancel_packet(&ohci->usb_packet); - ohci->async_td = 0; + if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { + if (ohci->async_td) { + usb_cancel_packet(&ohci->usb_packet); + ohci->async_td = 0; + } + ohci_stop_endpoints(ohci); } ohci->old_ctl = ohci->ctl; ohci_process_lists(ohci, 0); @@ -1470,12 +1505,10 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) if (old_state != port->ctrl) ohci_set_interrupt(ohci, OHCI_INTR_RHSC); - - return; } static uint64_t ohci_mem_read(void *opaque, - target_phys_addr_t addr, + hwaddr addr, unsigned size) { OHCIState *ohci = opaque; @@ -1598,7 +1631,7 @@ static uint64_t ohci_mem_read(void *opaque, } static void ohci_mem_write(void *opaque, - target_phys_addr_t addr, + hwaddr addr, uint64_t val, unsigned size) { @@ -1703,6 +1736,7 @@ static void ohci_mem_write(void *opaque, /* PXA27x specific registers */ case 24: /* HcStatus */ ohci->hstatus &= ~(val & ohci->hmask); + break; case 25: /* HcHReset */ ohci->hreset = val & ~OHCI_HRESET_FSBIR; @@ -1754,11 +1788,11 @@ static USBBusOps ohci_bus_ops = { static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, int num_ports, dma_addr_t localmem_base, char *masterbus, uint32_t firstport, - DMAContext *dma) + AddressSpace *as) { int i; - ohci->dma = dma; + ohci->as = as; if (usb_frame_time == 0) { #ifdef OHCI_TIME_WARP @@ -1796,7 +1830,8 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, } } - memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256); + memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops, + ohci, "ohci", 256); ohci->localmem_base = localmem_base; ohci->name = object_get_typename(OBJECT(dev)); @@ -1825,7 +1860,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev) if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0, ohci->masterbus, ohci->firstport, - pci_dma_context(dev)) != 0) { + pci_get_address_space(dev)) != 0) { return -1; } ohci->state.irq = ohci->pci_dev.irq[0]; @@ -1848,7 +1883,7 @@ static int ohci_init_pxa(SysBusDevice *dev) /* Cannot fail as we pass NULL for masterbus */ usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0, - NULL); + &address_space_memory); sysbus_init_irq(dev, &s->ohci.irq); sysbus_init_mmio(dev, &s->ohci.mem); @@ -1871,11 +1906,12 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) k->vendor_id = PCI_VENDOR_ID_APPLE; k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; k->class_id = PCI_CLASS_SERIAL_USB; + k->no_hotplug = 1; dc->desc = "Apple USB Controller"; dc->props = ohci_pci_properties; } -static TypeInfo ohci_pci_info = { +static const TypeInfo ohci_pci_info = { .name = "pci-ohci", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(OHCIPCIState), @@ -1898,7 +1934,7 @@ static void ohci_sysbus_class_init(ObjectClass *klass, void *data) dc->props = ohci_sysbus_properties; } -static TypeInfo ohci_sysbus_info = { +static const TypeInfo ohci_sysbus_info = { .name = "sysbus-ohci", .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(OHCISysBusState),