qemu/tests/libqos/pci-pc.c
<<
>>
Prefs
   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 "libqos/pci-pc.h"
  16#include "qapi/qmp/qdict.h"
  17#include "hw/pci/pci_regs.h"
  18
  19#include "qemu-common.h"
  20
  21
  22#define ACPI_PCIHP_ADDR         0xae00
  23#define PCI_EJ_BASE             0x0008
  24
  25typedef struct QPCIBusPC
  26{
  27    QPCIBus bus;
  28} QPCIBusPC;
  29
  30static uint8_t qpci_pc_pio_readb(QPCIBus *bus, uint32_t addr)
  31{
  32    return inb(addr);
  33}
  34
  35static void qpci_pc_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
  36{
  37    outb(addr, val);
  38}
  39
  40static uint16_t qpci_pc_pio_readw(QPCIBus *bus, uint32_t addr)
  41{
  42    return inw(addr);
  43}
  44
  45static void qpci_pc_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
  46{
  47    outw(addr, val);
  48}
  49
  50static uint32_t qpci_pc_pio_readl(QPCIBus *bus, uint32_t addr)
  51{
  52    return inl(addr);
  53}
  54
  55static void qpci_pc_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
  56{
  57    outl(addr, val);
  58}
  59
  60static uint64_t qpci_pc_pio_readq(QPCIBus *bus, uint32_t addr)
  61{
  62    return (uint64_t)inl(addr) + ((uint64_t)inl(addr + 4) << 32);
  63}
  64
  65static void qpci_pc_pio_writeq(QPCIBus *bus, uint32_t addr, uint64_t val)
  66{
  67    outl(addr, val & 0xffffffff);
  68    outl(addr + 4, val >> 32);
  69}
  70
  71static void qpci_pc_memread(QPCIBus *bus, uint32_t addr, void *buf, size_t len)
  72{
  73    memread(addr, buf, len);
  74}
  75
  76static void qpci_pc_memwrite(QPCIBus *bus, uint32_t addr,
  77                             const void *buf, size_t len)
  78{
  79    memwrite(addr, buf, len);
  80}
  81
  82static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
  83{
  84    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
  85    return inb(0xcfc);
  86}
  87
  88static uint16_t qpci_pc_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
  89{
  90    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
  91    return inw(0xcfc);
  92}
  93
  94static uint32_t qpci_pc_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
  95{
  96    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
  97    return inl(0xcfc);
  98}
  99
 100static void qpci_pc_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
 101{
 102    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
 103    outb(0xcfc, value);
 104}
 105
 106static void qpci_pc_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
 107{
 108    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
 109    outw(0xcfc, value);
 110}
 111
 112static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
 113{
 114    outl(0xcf8, (1U << 31) | (devfn << 8) | offset);
 115    outl(0xcfc, value);
 116}
 117
 118QPCIBus *qpci_init_pc(QTestState *qts, QGuestAllocator *alloc)
 119{
 120    QPCIBusPC *ret = g_new0(QPCIBusPC, 1);
 121
 122    assert(qts);
 123
 124    ret->bus.pio_readb = qpci_pc_pio_readb;
 125    ret->bus.pio_readw = qpci_pc_pio_readw;
 126    ret->bus.pio_readl = qpci_pc_pio_readl;
 127    ret->bus.pio_readq = qpci_pc_pio_readq;
 128
 129    ret->bus.pio_writeb = qpci_pc_pio_writeb;
 130    ret->bus.pio_writew = qpci_pc_pio_writew;
 131    ret->bus.pio_writel = qpci_pc_pio_writel;
 132    ret->bus.pio_writeq = qpci_pc_pio_writeq;
 133
 134    ret->bus.memread = qpci_pc_memread;
 135    ret->bus.memwrite = qpci_pc_memwrite;
 136
 137    ret->bus.config_readb = qpci_pc_config_readb;
 138    ret->bus.config_readw = qpci_pc_config_readw;
 139    ret->bus.config_readl = qpci_pc_config_readl;
 140
 141    ret->bus.config_writeb = qpci_pc_config_writeb;
 142    ret->bus.config_writew = qpci_pc_config_writew;
 143    ret->bus.config_writel = qpci_pc_config_writel;
 144
 145    ret->bus.qts = qts;
 146    ret->bus.pio_alloc_ptr = 0xc000;
 147    ret->bus.mmio_alloc_ptr = 0xE0000000;
 148    ret->bus.mmio_limit = 0x100000000ULL;
 149
 150    return &ret->bus;
 151}
 152
 153void qpci_free_pc(QPCIBus *bus)
 154{
 155    QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
 156
 157    g_free(s);
 158}
 159
 160void qpci_unplug_acpi_device_test(const char *id, uint8_t slot)
 161{
 162    QDict *response;
 163    char *cmd;
 164
 165    cmd = g_strdup_printf("{'execute': 'device_del',"
 166                          " 'arguments': {"
 167                          "   'id': '%s'"
 168                          "}}", id);
 169    response = qmp(cmd);
 170    g_free(cmd);
 171    g_assert(response);
 172    g_assert(!qdict_haskey(response, "error"));
 173    qobject_unref(response);
 174
 175    outb(ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot);
 176
 177    qmp_eventwait("DEVICE_DELETED");
 178}
 179