diff options
Diffstat (limited to 'hw/usb-ohci.c')
-rw-r--r-- | hw/usb-ohci.c | 137 |
1 files changed, 96 insertions, 41 deletions
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index e59bc8a463..09944d0dc3 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -32,6 +32,7 @@ #include "usb.h" #include "pci.h" #include "pxa.h" +#include "devices.h" //#define DEBUG_OHCI /* Dump packet contents. */ @@ -60,7 +61,8 @@ typedef struct OHCIPort { enum ohci_type { OHCI_TYPE_PCI, - OHCI_TYPE_PXA + OHCI_TYPE_PXA, + OHCI_TYPE_SM501, }; typedef struct { @@ -108,6 +110,9 @@ typedef struct { uint32_t hreset; uint32_t htest; + /* SM501 local memory offset */ + target_phys_addr_t localmem_base; + /* Active packets. */ uint32_t old_ctl; USBPacket usb_packet; @@ -425,10 +430,13 @@ static void ohci_reset(void *opaque) } /* Get an array of dwords from main memory */ -static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) +static inline int get_dwords(OHCIState *ohci, + uint32_t addr, uint32_t *buf, int num) { int i; + addr += ohci->localmem_base; + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0); *buf = le32_to_cpu(*buf); @@ -438,10 +446,13 @@ static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) } /* Put an array of dwords in to main memory */ -static inline int put_dwords(uint32_t addr, uint32_t *buf, int num) +static inline int put_dwords(OHCIState *ohci, + uint32_t addr, uint32_t *buf, int num) { int i; + addr += ohci->localmem_base; + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1); @@ -451,10 +462,13 @@ static inline int put_dwords(uint32_t addr, uint32_t *buf, int num) } /* Get an array of words from main memory */ -static inline int get_words(uint32_t addr, uint16_t *buf, int num) +static inline int get_words(OHCIState *ohci, + uint32_t addr, uint16_t *buf, int num) { int i; + addr += ohci->localmem_base; + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0); *buf = le16_to_cpu(*buf); @@ -464,10 +478,13 @@ static inline int get_words(uint32_t addr, uint16_t *buf, int num) } /* Put an array of words in to main memory */ -static inline int put_words(uint32_t addr, uint16_t *buf, int num) +static inline int put_words(OHCIState *ohci, + uint32_t addr, uint16_t *buf, int num) { int i; + addr += ohci->localmem_base; + for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint16_t tmp = cpu_to_le16(*buf); cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1); @@ -476,40 +493,63 @@ static inline int put_words(uint32_t addr, uint16_t *buf, int num) return 1; } -static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed) +static inline int ohci_read_ed(OHCIState *ohci, + uint32_t addr, struct ohci_ed *ed) { - return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); + return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); } -static inline int ohci_read_td(uint32_t addr, struct ohci_td *td) +static inline int ohci_read_td(OHCIState *ohci, + uint32_t addr, struct ohci_td *td) { - return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); + return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); } -static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td) +static inline int ohci_read_iso_td(OHCIState *ohci, + uint32_t addr, struct ohci_iso_td *td) { - return (get_dwords(addr, (uint32_t *)td, 4) && - get_words(addr + 16, td->offset, 8)); + return (get_dwords(ohci, addr, (uint32_t *)td, 4) && + get_words(ohci, addr + 16, td->offset, 8)); } -static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed) +static inline int ohci_read_hcca(OHCIState *ohci, + uint32_t addr, struct ohci_hcca *hcca) { - return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); + cpu_physical_memory_rw(addr + ohci->localmem_base, + (uint8_t *)hcca, sizeof(*hcca), 0); + return 1; } -static inline int ohci_put_td(uint32_t addr, struct ohci_td *td) +static inline int ohci_put_ed(OHCIState *ohci, + uint32_t addr, struct ohci_ed *ed) { - return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); + return put_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2); } -static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td) +static inline int ohci_put_td(OHCIState *ohci, + uint32_t addr, struct ohci_td *td) { - return (put_dwords(addr, (uint32_t *)td, 4) && - put_words(addr + 16, td->offset, 8)); + return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2); +} + +static inline int ohci_put_iso_td(OHCIState *ohci, + uint32_t addr, struct ohci_iso_td *td) +{ + return (put_dwords(ohci, addr, (uint32_t *)td, 4) && + put_words(ohci, addr + 16, td->offset, 8)); +} + +static inline int ohci_put_hcca(OHCIState *ohci, + uint32_t addr, struct ohci_hcca *hcca) +{ + cpu_physical_memory_rw(addr + ohci->localmem_base, + (uint8_t *)hcca, sizeof(*hcca), 1); + return 1; } /* Read/Write the contents of a TD from/to main memory. */ -static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write) +static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td, + uint8_t *buf, int len, int write) { uint32_t ptr; uint32_t n; @@ -518,16 +558,17 @@ static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write) n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - cpu_physical_memory_rw(ptr, buf, n, write); + cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write); if (n == len) return; ptr = td->be & ~0xfffu; buf += n; - cpu_physical_memory_rw(ptr, buf, len - n, write); + cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write); } /* Read/Write the contents of an ISO TD from/to main memory. */ -static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr, +static void ohci_copy_iso_td(OHCIState *ohci, + uint32_t start_addr, uint32_t end_addr, uint8_t *buf, int len, int write) { uint32_t ptr; @@ -537,12 +578,12 @@ static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr, n = 0x1000 - (ptr & 0xfff); if (n > len) n = len; - cpu_physical_memory_rw(ptr, buf, n, write); + cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write); if (n == len) return; ptr = end_addr & ~0xfffu; buf += n; - cpu_physical_memory_rw(ptr, buf, len - n, write); + cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write); } static void ohci_process_lists(OHCIState *ohci, int completion); @@ -579,7 +620,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, addr = ed->head & OHCI_DPTR_MASK; - if (!ohci_read_iso_td(addr, &iso_td)) { + if (!ohci_read_iso_td(ohci, addr, &iso_td)) { printf("usb-ohci: ISO_TD read error at %x\n", addr); return 0; } @@ -621,7 +662,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, i = OHCI_BM(iso_td.flags, TD_DI); if (i < ohci->done_count) ohci->done_count = i; - ohci_put_iso_td(addr, &iso_td); + ohci_put_iso_td(ohci, addr, &iso_td); return 0; } @@ -696,7 +737,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, } if (len && dir != OHCI_TD_DIR_IN) { - ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0); + ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0); } if (completion) { @@ -732,7 +773,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, /* Writeback */ if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { /* IN transfer succeeded */ - ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1); + ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, OHCI_CC_NOERROR); OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); @@ -788,7 +829,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, if (i < ohci->done_count) ohci->done_count = i; } - ohci_put_iso_td(addr, &iso_td); + ohci_put_iso_td(ohci, addr, &iso_td); return 1; } @@ -818,7 +859,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) #endif return 1; } - if (!ohci_read_td(addr, &td)) { + if (!ohci_read_td(ohci, addr, &td)) { fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); return 0; } @@ -859,7 +900,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } if (len && dir != OHCI_TD_DIR_IN && !completion) { - ohci_copy_td(&td, ohci->usb_buf, len, 0); + ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0); } } @@ -918,7 +959,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } if (ret >= 0) { if (dir == OHCI_TD_DIR_IN) { - ohci_copy_td(&td, ohci->usb_buf, ret, 1); + ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1); #ifdef DEBUG_PACKET dprintf(" data:"); for (i = 0; i < ret; i++) @@ -987,7 +1028,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) i = OHCI_BM(td.flags, TD_DI); if (i < ohci->done_count) ohci->done_count = i; - ohci_put_td(addr, &td); + ohci_put_td(ohci, addr, &td); return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; } @@ -1005,7 +1046,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) return 0; for (cur = head; cur; cur = next_ed) { - if (!ohci_read_ed(cur, &ed)) { + if (!ohci_read_ed(ohci, cur, &ed)) { fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); return 0; } @@ -1046,7 +1087,7 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) } } - ohci_put_ed(cur, &ed); + ohci_put_ed(ohci, cur, &ed); } return active; @@ -1087,7 +1128,7 @@ static void ohci_frame_boundary(void *opaque) OHCIState *ohci = opaque; struct ohci_hcca hcca; - cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 0); + ohci_read_hcca(ohci, ohci->hcca, &hcca); /* Process all the lists at the end of the frame */ if (ohci->ctl & OHCI_CTL_PLE) { @@ -1131,7 +1172,7 @@ static void ohci_frame_boundary(void *opaque) ohci_sof(ohci); /* Writeback HCCA */ - cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 1); + ohci_put_hcca(ohci, ohci->hcca, &hcca); } /* Start sending SOF tokens across the USB bus, lists are processed in @@ -1620,7 +1661,8 @@ static CPUWriteMemoryFunc *ohci_writefn[3]={ }; static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn, - qemu_irq irq, enum ohci_type type, const char *name) + qemu_irq irq, enum ohci_type type, + const char *name, uint32_t localmem_base) { int i; @@ -1641,6 +1683,7 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn, } ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci); + ohci->localmem_base = localmem_base; ohci->name = name; ohci->irq = irq; @@ -1687,7 +1730,7 @@ void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn) ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */ usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0], - OHCI_TYPE_PCI, ohci->pci_dev.name); + OHCI_TYPE_PCI, ohci->pci_dev.name, 0); pci_register_io_region((struct PCIDevice *)ohci, 0, 256, PCI_ADDRESS_SPACE_MEM, ohci_mapfunc); @@ -1699,7 +1742,19 @@ void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn, OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState)); usb_ohci_init(ohci, num_ports, devfn, irq, - OHCI_TYPE_PXA, "OHCI USB"); + OHCI_TYPE_PXA, "OHCI USB", 0); cpu_register_physical_memory(base, 0x1000, ohci->mem); } + +void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base, + int num_ports, int devfn, qemu_irq irq) +{ + OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState)); + + usb_ohci_init(ohci, num_ports, devfn, irq, + OHCI_TYPE_SM501, "OHCI USB", localmem_base); + + cpu_register_physical_memory(mmio_base, 0x1000, ohci->mem); +} + |