diff options
author | SeokYeon Hwang <syeon.hwang@samsung.com> | 2017-06-28 16:20:50 +0900 |
---|---|---|
committer | SeokYeon Hwang <syeon.hwang@samsung.com> | 2017-06-28 16:21:16 +0900 |
commit | e6230f92c2a7c924f4092b877ee70a74f76e6841 (patch) | |
tree | 3f6f4a364da163b80c9669f903eda6f8aeb4d19b /tests/libqos/pci.c | |
parent | e9775ba331166fc2de29a387b1070281c8ec0985 (diff) | |
parent | 6ca9395b240883513b16a1875a7080b081612c57 (diff) | |
download | qemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.tar.gz qemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.tar.bz2 qemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.zip |
Merge spin into tizen
Change-Id: I00f8d0dbf2d26f3c9c6754b9f1d986355037f5bb
Diffstat (limited to 'tests/libqos/pci.c')
-rw-r--r-- | tests/libqos/pci.c | 214 |
1 files changed, 181 insertions, 33 deletions
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c index ed78d91cea..2dcdeade2a 100644 --- a/tests/libqos/pci.c +++ b/tests/libqos/pci.c @@ -14,6 +14,7 @@ #include "libqos/pci.h" #include "hw/pci/pci_regs.h" +#include "qemu/host-utils.h" void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, void (*func)(QPCIDevice *dev, int devfn, void *data), @@ -103,7 +104,6 @@ void qpci_msix_enable(QPCIDevice *dev) uint32_t table; uint8_t bir_table; uint8_t bir_pba; - void *offset; addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX); g_assert_cmphex(addr, !=, 0); @@ -113,18 +113,16 @@ void qpci_msix_enable(QPCIDevice *dev) table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE); bir_table = table & PCI_MSIX_FLAGS_BIRMASK; - offset = qpci_iomap(dev, bir_table, NULL); - dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK); + dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL); + dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK; table = qpci_config_readl(dev, addr + PCI_MSIX_PBA); bir_pba = table & PCI_MSIX_FLAGS_BIRMASK; if (bir_pba != bir_table) { - offset = qpci_iomap(dev, bir_pba, NULL); + dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL); } - dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK); + dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK; - g_assert(dev->msix_table != NULL); - g_assert(dev->msix_pba != NULL); dev->msix_enabled = true; } @@ -140,22 +138,23 @@ void qpci_msix_disable(QPCIDevice *dev) qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, val & ~PCI_MSIX_FLAGS_ENABLE); - qpci_iounmap(dev, dev->msix_table); - qpci_iounmap(dev, dev->msix_pba); + qpci_iounmap(dev, dev->msix_table_bar); + qpci_iounmap(dev, dev->msix_pba_bar); dev->msix_enabled = 0; - dev->msix_table = NULL; - dev->msix_pba = NULL; + dev->msix_table_off = 0; + dev->msix_pba_off = 0; } bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry) { uint32_t pba_entry; uint8_t bit_n = entry % 32; - void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4; + uint64_t off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4; g_assert(dev->msix_enabled); - pba_entry = qpci_io_readl(dev, addr); - qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n)); + pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off); + qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off, + pba_entry & ~(1 << bit_n)); return (pba_entry & (1 << bit_n)) != 0; } @@ -163,7 +162,7 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry) { uint8_t addr; uint16_t val; - void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE); + uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE; g_assert(dev->msix_enabled); addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX); @@ -173,8 +172,9 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry) if (val & PCI_MSIX_FLAGS_MASKALL) { return true; } else { - return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL) - & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0; + return (qpci_io_readl(dev, dev->msix_table_bar, + vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL) + & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0; } } @@ -221,46 +221,194 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value) dev->bus->config_writel(dev->bus, dev->devfn, offset, value); } +uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off) +{ + if (token.addr < QPCI_PIO_LIMIT) { + return dev->bus->pio_readb(dev->bus, token.addr + off); + } else { + uint8_t val; + dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val)); + return val; + } +} -uint8_t qpci_io_readb(QPCIDevice *dev, void *data) +uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off) { - return dev->bus->io_readb(dev->bus, data); + if (token.addr < QPCI_PIO_LIMIT) { + return dev->bus->pio_readw(dev->bus, token.addr + off); + } else { + uint16_t val; + dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val)); + return le16_to_cpu(val); + } } -uint16_t qpci_io_readw(QPCIDevice *dev, void *data) +uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off) { - return dev->bus->io_readw(dev->bus, data); + if (token.addr < QPCI_PIO_LIMIT) { + return dev->bus->pio_readl(dev->bus, token.addr + off); + } else { + uint32_t val; + dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val)); + return le32_to_cpu(val); + } } -uint32_t qpci_io_readl(QPCIDevice *dev, void *data) +uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off) { - return dev->bus->io_readl(dev->bus, data); + if (token.addr < QPCI_PIO_LIMIT) { + return dev->bus->pio_readq(dev->bus, token.addr + off); + } else { + uint64_t val; + dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val)); + return le64_to_cpu(val); + } } +void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off, + uint8_t value) +{ + if (token.addr < QPCI_PIO_LIMIT) { + dev->bus->pio_writeb(dev->bus, token.addr + off, value); + } else { + dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value)); + } +} -void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value) +void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off, + uint16_t value) { - dev->bus->io_writeb(dev->bus, data, value); + if (token.addr < QPCI_PIO_LIMIT) { + dev->bus->pio_writew(dev->bus, token.addr + off, value); + } else { + value = cpu_to_le16(value); + dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value)); + } } -void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value) +void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off, + uint32_t value) { - dev->bus->io_writew(dev->bus, data, value); + if (token.addr < QPCI_PIO_LIMIT) { + dev->bus->pio_writel(dev->bus, token.addr + off, value); + } else { + value = cpu_to_le32(value); + dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value)); + } } -void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value) +void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off, + uint64_t value) { - dev->bus->io_writel(dev->bus, data, value); + if (token.addr < QPCI_PIO_LIMIT) { + dev->bus->pio_writeq(dev->bus, token.addr + off, value); + } else { + value = cpu_to_le64(value); + dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value)); + } } -void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr) +void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off, + void *buf, size_t len) { - return dev->bus->iomap(dev->bus, dev, barno, sizeptr); + g_assert(token.addr >= QPCI_PIO_LIMIT); + dev->bus->memread(dev->bus, token.addr + off, buf, len); } -void qpci_iounmap(QPCIDevice *dev, void *data) +void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off, + const void *buf, size_t len) { - dev->bus->iounmap(dev->bus, data); + g_assert(token.addr >= QPCI_PIO_LIMIT); + dev->bus->memwrite(dev->bus, token.addr + off, buf, len); } +QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr) +{ + QPCIBus *bus = dev->bus; + static const int bar_reg_map[] = { + PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5, + }; + QPCIBar bar; + int bar_reg; + uint32_t addr, size; + uint32_t io_type; + uint64_t loc; + + g_assert(barno >= 0 && barno <= 5); + bar_reg = bar_reg_map[barno]; + + qpci_config_writel(dev, bar_reg, 0xFFFFFFFF); + addr = qpci_config_readl(dev, bar_reg); + + io_type = addr & PCI_BASE_ADDRESS_SPACE; + if (io_type == PCI_BASE_ADDRESS_SPACE_IO) { + addr &= PCI_BASE_ADDRESS_IO_MASK; + } else { + addr &= PCI_BASE_ADDRESS_MEM_MASK; + } + g_assert(addr); /* Must have *some* size bits */ + + size = 1U << ctz32(addr); + if (sizeptr) { + *sizeptr = size; + } + + if (io_type == PCI_BASE_ADDRESS_SPACE_IO) { + loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size); + + g_assert(loc >= bus->pio_alloc_ptr); + g_assert(loc + size <= QPCI_PIO_LIMIT); /* Keep PIO below 64kiB */ + + bus->pio_alloc_ptr = loc + size; + + qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO); + } else { + loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size); + + /* Check for space */ + g_assert(loc >= bus->mmio_alloc_ptr); + g_assert(loc + size <= bus->mmio_limit); + + bus->mmio_alloc_ptr = loc + size; + + qpci_config_writel(dev, bar_reg, loc); + } + + bar.addr = loc; + return bar; +} + +void qpci_iounmap(QPCIDevice *dev, QPCIBar bar) +{ + /* FIXME */ +} + +QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr) +{ + QPCIBar bar = { .addr = addr }; + return bar; +} + +void qpci_plug_device_test(const char *driver, const char *id, + uint8_t slot, const char *opts) +{ + QDict *response; + char *cmd; + + cmd = g_strdup_printf("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': '%s'," + " 'addr': '%d'," + " %s%s" + " 'id': '%s'" + "}}", driver, slot, + opts ? opts : "", opts ? "," : "", + id); + response = qmp(cmd); + g_free(cmd); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); +} |