qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

pci-pc.c (5176B)


      1 /*
      2  * libqos PCI bindings for PC
      3  *
      4  * Copyright IBM, Corp. 2012-2013
      5  *
      6  * Authors:
      7  *  Anthony Liguori   <aliguori@us.ibm.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10  * See the COPYING file in the top-level directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "../libqtest.h"
     15 #include "pci-pc.h"
     16 #include "qapi/qmp/qdict.h"
     17 #include "hw/pci/pci_regs.h"
     18 
     19 #include "qemu/module.h"
     20 
     21 #define ACPI_PCIHP_ADDR         0xae00
     22 #define PCI_EJ_BASE             0x0008
     23 
     24 static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
     25 {
     26     return qtest_inb(bus->qts, addr);
     27 }
     28 
     29 static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
     30 {
     31     qtest_outb(bus->qts, addr, val);
     32 }
     33 
     34 static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
     35 {
     36     return qtest_inw(bus->qts, addr);
     37 }
     38 
     39 static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
     40 {
     41     qtest_outw(bus->qts, addr, val);
     42 }
     43 
     44 static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
     45 {
     46     return qtest_inl(bus->qts, addr);
     47 }
     48 
     49 static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
     50 {
     51     qtest_outl(bus->qts, addr, val);
     52 }
     53 
     54 static uint64_t qpci_pc_pio_readq(QPCIBus *bus, uint32_t addr)
     55 {
     56     return (uint64_t)qtest_inl(bus->qts, addr) +
     57         ((uint64_t)qtest_inl(bus->qts, addr + 4) << 32);
     58 }
     59 
     60 static void qpci_pc_pio_writeq(QPCIBus *bus, uint32_t addr, uint64_t val)
     61 {
     62     qtest_outl(bus->qts, addr, val & 0xffffffff);
     63     qtest_outl(bus->qts, addr + 4, val >> 32);
     64 }
     65 
     66 static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
     67 {
     68     qtest_memread(bus->qts, addr, buf, len);
     69 }
     70 
     71 static void qpci_pc_memwrite(QPCIBus *bus, uint32_t addr,
     72                              const void *buf, size_t len)
     73 {
     74     qtest_memwrite(bus->qts, addr, buf, len);
     75 }
     76 
     77 static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
     78 {
     79     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     80     return qtest_inb(bus->qts, 0xcfc);
     81 }
     82 
     83 static uint16_t qpci_pc_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
     84 {
     85     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     86     return qtest_inw(bus->qts, 0xcfc);
     87 }
     88 
     89 static uint32_t qpci_pc_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
     90 {
     91     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     92     return qtest_inl(bus->qts, 0xcfc);
     93 }
     94 
     95 static void qpci_pc_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
     96 {
     97     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
     98     qtest_outb(bus->qts, 0xcfc, value);
     99 }
    100 
    101 static void qpci_pc_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
    102 {
    103     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
    104     qtest_outw(bus->qts, 0xcfc, value);
    105 }
    106 
    107 static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
    108 {
    109     qtest_outl(bus->qts, 0xcf8, (1U << 31) | (devfn << 8) | offset);
    110     qtest_outl(bus->qts, 0xcfc, value);
    111 }
    112 
    113 static void *qpci_pc_get_driver(void *obj, const char *interface)
    114 {
    115     QPCIBusPC *qpci = obj;
    116     if (!g_strcmp0(interface, "pci-bus")) {
    117         return &qpci->bus;
    118     }
    119     fprintf(stderr, "%s not present in pci-bus-pc\n", interface);
    120     g_assert_not_reached();
    121 }
    122 
    123 void qpci_init_pc(QPCIBusPC *qpci, QTestState *qts, QGuestAllocator *alloc)
    124 {
    125     assert(qts);
    126 
    127     /* tests can use pci-bus */
    128     qpci->bus.has_buggy_msi = false;
    129 
    130     qpci->bus.pio_readb = qpci_pc_pio_readb;
    131     qpci->bus.pio_readw = qpci_pc_pio_readw;
    132     qpci->bus.pio_readl = qpci_pc_pio_readl;
    133     qpci->bus.pio_readq = qpci_pc_pio_readq;
    134 
    135     qpci->bus.pio_writeb = qpci_pc_pio_writeb;
    136     qpci->bus.pio_writew = qpci_pc_pio_writew;
    137     qpci->bus.pio_writel = qpci_pc_pio_writel;
    138     qpci->bus.pio_writeq = qpci_pc_pio_writeq;
    139 
    140     qpci->bus.memread = qpci_pc_memread;
    141     qpci->bus.memwrite = qpci_pc_memwrite;
    142 
    143     qpci->bus.config_readb = qpci_pc_config_readb;
    144     qpci->bus.config_readw = qpci_pc_config_readw;
    145     qpci->bus.config_readl = qpci_pc_config_readl;
    146 
    147     qpci->bus.config_writeb = qpci_pc_config_writeb;
    148     qpci->bus.config_writew = qpci_pc_config_writew;
    149     qpci->bus.config_writel = qpci_pc_config_writel;
    150 
    151     qpci->bus.qts = qts;
    152     qpci->bus.pio_alloc_ptr = 0xc000;
    153     qpci->bus.pio_limit = 0x10000;
    154     qpci->bus.mmio_alloc_ptr = 0xE0000000;
    155     qpci->bus.mmio_limit = 0x100000000ULL;
    156 
    157     qpci->obj.get_driver = qpci_pc_get_driver;
    158 }
    159 
    160 QPCIBus *qpci_new_pc(QTestState *qts, QGuestAllocator *alloc)
    161 {
    162     QPCIBusPC *qpci = g_new0(QPCIBusPC, 1);
    163     qpci_init_pc(qpci, qts, alloc);
    164 
    165     return &qpci->bus;
    166 }
    167 
    168 void qpci_free_pc(QPCIBus *bus)
    169 {
    170     QPCIBusPC *s;
    171 
    172     if (!bus) {
    173         return;
    174     }
    175     s = container_of(bus, QPCIBusPC, bus);
    176 
    177     g_free(s);
    178 }
    179 
    180 void qpci_unplug_acpi_device_test(QTestState *qts, const char *id, uint8_t slot)
    181 {
    182     qtest_qmp_device_del_send(qts, id);
    183 
    184     qtest_outl(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot);
    185 
    186     qtest_qmp_eventwait(qts, "DEVICE_DELETED");
    187 }
    188 
    189 static void qpci_pc_register_nodes(void)
    190 {
    191     qos_node_create_driver("pci-bus-pc", NULL);
    192     qos_node_produces("pci-bus-pc", "pci-bus");
    193 }
    194 
    195 libqos_init(qpci_pc_register_nodes);