2 * libqos PCI bindings for PC
4 * Copyright IBM, Corp. 2012-2013
7 * Anthony Liguori <aliguori@us.ibm.com>
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.
13 #include "qemu/osdep.h"
15 #include "libqos/pci-pc.h"
16 #include "qapi/qmp/qdict.h"
17 #include "hw/pci/pci_regs.h"
19 #include "qemu-common.h"
22 #define ACPI_PCIHP_ADDR 0xae00
23 #define PCI_EJ_BASE 0x0008
25 typedef struct QPCIBusPC
30 static uint8_t qpci_pc_pio_readb(QPCIBus
*bus
, uint32_t addr
)
32 return qtest_inb(bus
->qts
, addr
);
35 static void qpci_pc_pio_writeb(QPCIBus
*bus
, uint32_t addr
, uint8_t val
)
37 qtest_outb(bus
->qts
, addr
, val
);
40 static uint16_t qpci_pc_pio_readw(QPCIBus
*bus
, uint32_t addr
)
42 return qtest_inw(bus
->qts
, addr
);
45 static void qpci_pc_pio_writew(QPCIBus
*bus
, uint32_t addr
, uint16_t val
)
47 qtest_outw(bus
->qts
, addr
, val
);
50 static uint32_t qpci_pc_pio_readl(QPCIBus
*bus
, uint32_t addr
)
52 return qtest_inl(bus
->qts
, addr
);
55 static void qpci_pc_pio_writel(QPCIBus
*bus
, uint32_t addr
, uint32_t val
)
57 qtest_outl(bus
->qts
, addr
, val
);
60 static uint64_t qpci_pc_pio_readq(QPCIBus
*bus
, uint32_t addr
)
62 return (uint64_t)qtest_inl(bus
->qts
, addr
) +
63 ((uint64_t)qtest_inl(bus
->qts
, addr
+ 4) << 32);
66 static void qpci_pc_pio_writeq(QPCIBus
*bus
, uint32_t addr
, uint64_t val
)
68 qtest_outl(bus
->qts
, addr
, val
& 0xffffffff);
69 qtest_outl(bus
->qts
, addr
+ 4, val
>> 32);
72 static void qpci_pc_memread(QPCIBus
*bus
, uint32_t addr
, void *buf
, size_t len
)
74 qtest_memread(bus
->qts
, addr
, buf
, len
);
77 static void qpci_pc_memwrite(QPCIBus
*bus
, uint32_t addr
,
78 const void *buf
, size_t len
)
80 qtest_memwrite(bus
->qts
, addr
, buf
, len
);
83 static uint8_t qpci_pc_config_readb(QPCIBus
*bus
, int devfn
, uint8_t offset
)
85 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
86 return qtest_inb(bus
->qts
, 0xcfc);
89 static uint16_t qpci_pc_config_readw(QPCIBus
*bus
, int devfn
, uint8_t offset
)
91 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
92 return qtest_inw(bus
->qts
, 0xcfc);
95 static uint32_t qpci_pc_config_readl(QPCIBus
*bus
, int devfn
, uint8_t offset
)
97 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
98 return qtest_inl(bus
->qts
, 0xcfc);
101 static void qpci_pc_config_writeb(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint8_t value
)
103 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
104 qtest_outb(bus
->qts
, 0xcfc, value
);
107 static void qpci_pc_config_writew(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint16_t value
)
109 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
110 qtest_outw(bus
->qts
, 0xcfc, value
);
113 static void qpci_pc_config_writel(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint32_t value
)
115 qtest_outl(bus
->qts
, 0xcf8, (1U << 31) | (devfn
<< 8) | offset
);
116 qtest_outl(bus
->qts
, 0xcfc, value
);
119 QPCIBus
*qpci_init_pc(QTestState
*qts
, QGuestAllocator
*alloc
)
121 QPCIBusPC
*ret
= g_new0(QPCIBusPC
, 1);
125 ret
->bus
.pio_readb
= qpci_pc_pio_readb
;
126 ret
->bus
.pio_readw
= qpci_pc_pio_readw
;
127 ret
->bus
.pio_readl
= qpci_pc_pio_readl
;
128 ret
->bus
.pio_readq
= qpci_pc_pio_readq
;
130 ret
->bus
.pio_writeb
= qpci_pc_pio_writeb
;
131 ret
->bus
.pio_writew
= qpci_pc_pio_writew
;
132 ret
->bus
.pio_writel
= qpci_pc_pio_writel
;
133 ret
->bus
.pio_writeq
= qpci_pc_pio_writeq
;
135 ret
->bus
.memread
= qpci_pc_memread
;
136 ret
->bus
.memwrite
= qpci_pc_memwrite
;
138 ret
->bus
.config_readb
= qpci_pc_config_readb
;
139 ret
->bus
.config_readw
= qpci_pc_config_readw
;
140 ret
->bus
.config_readl
= qpci_pc_config_readl
;
142 ret
->bus
.config_writeb
= qpci_pc_config_writeb
;
143 ret
->bus
.config_writew
= qpci_pc_config_writew
;
144 ret
->bus
.config_writel
= qpci_pc_config_writel
;
147 ret
->bus
.pio_alloc_ptr
= 0xc000;
148 ret
->bus
.mmio_alloc_ptr
= 0xE0000000;
149 ret
->bus
.mmio_limit
= 0x100000000ULL
;
154 void qpci_free_pc(QPCIBus
*bus
)
156 QPCIBusPC
*s
= container_of(bus
, QPCIBusPC
, bus
);
161 void qpci_unplug_acpi_device_test(const char *id
, uint8_t slot
)
165 response
= qmp("{'execute': 'device_del', 'arguments': {'id': %s}}",
168 g_assert(!qdict_haskey(response
, "error"));
169 qobject_unref(response
);
171 outb(ACPI_PCIHP_ADDR
+ PCI_EJ_BASE
, 1 << slot
);
173 qmp_eventwait("DEVICE_DELETED");