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.
14 #include "libqos/pci-pc.h"
16 #include "hw/pci/pci_regs.h"
18 #include "qemu-common.h"
19 #include "qemu/host-utils.h"
23 typedef struct QPCIBusPC
27 uint32_t pci_hole_start
;
28 uint32_t pci_hole_size
;
29 uint32_t pci_hole_alloc
;
31 uint16_t pci_iohole_start
;
32 uint16_t pci_iohole_size
;
33 uint16_t pci_iohole_alloc
;
36 static uint8_t qpci_pc_io_readb(QPCIBus
*bus
, void *addr
)
38 uintptr_t port
= (uintptr_t)addr
;
44 memread(port
, &value
, sizeof(value
));
50 static uint16_t qpci_pc_io_readw(QPCIBus
*bus
, void *addr
)
52 uintptr_t port
= (uintptr_t)addr
;
58 memread(port
, &value
, sizeof(value
));
64 static uint32_t qpci_pc_io_readl(QPCIBus
*bus
, void *addr
)
66 uintptr_t port
= (uintptr_t)addr
;
72 memread(port
, &value
, sizeof(value
));
78 static void qpci_pc_io_writeb(QPCIBus
*bus
, void *addr
, uint8_t value
)
80 uintptr_t port
= (uintptr_t)addr
;
85 memwrite(port
, &value
, sizeof(value
));
89 static void qpci_pc_io_writew(QPCIBus
*bus
, void *addr
, uint16_t value
)
91 uintptr_t port
= (uintptr_t)addr
;
96 memwrite(port
, &value
, sizeof(value
));
100 static void qpci_pc_io_writel(QPCIBus
*bus
, void *addr
, uint32_t value
)
102 uintptr_t port
= (uintptr_t)addr
;
104 if (port
< 0x10000) {
107 memwrite(port
, &value
, sizeof(value
));
111 static uint8_t qpci_pc_config_readb(QPCIBus
*bus
, int devfn
, uint8_t offset
)
113 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
117 static uint16_t qpci_pc_config_readw(QPCIBus
*bus
, int devfn
, uint8_t offset
)
119 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
123 static uint32_t qpci_pc_config_readl(QPCIBus
*bus
, int devfn
, uint8_t offset
)
125 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
129 static void qpci_pc_config_writeb(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint8_t value
)
131 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
135 static void qpci_pc_config_writew(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint16_t value
)
137 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
141 static void qpci_pc_config_writel(QPCIBus
*bus
, int devfn
, uint8_t offset
, uint32_t value
)
143 outl(0xcf8, (1 << 31) | (devfn
<< 8) | offset
);
147 static void *qpci_pc_iomap(QPCIBus
*bus
, QPCIDevice
*dev
, int barno
)
149 QPCIBusPC
*s
= container_of(bus
, QPCIBusPC
, bus
);
150 static const int bar_reg_map
[] = {
151 PCI_BASE_ADDRESS_0
, PCI_BASE_ADDRESS_1
, PCI_BASE_ADDRESS_2
,
152 PCI_BASE_ADDRESS_3
, PCI_BASE_ADDRESS_4
, PCI_BASE_ADDRESS_5
,
159 g_assert(barno
>= 0 && barno
<= 5);
160 bar_reg
= bar_reg_map
[barno
];
162 qpci_config_writel(dev
, bar_reg
, 0xFFFFFFFF);
163 addr
= qpci_config_readl(dev
, bar_reg
);
165 io_type
= addr
& PCI_BASE_ADDRESS_SPACE
;
166 if (io_type
== PCI_BASE_ADDRESS_SPACE_IO
) {
167 addr
&= PCI_BASE_ADDRESS_IO_MASK
;
169 addr
&= PCI_BASE_ADDRESS_MEM_MASK
;
172 size
= (1ULL << ctzl(addr
));
177 if (io_type
== PCI_BASE_ADDRESS_SPACE_IO
) {
180 g_assert((s
->pci_iohole_alloc
+ size
) <= s
->pci_iohole_size
);
181 loc
= s
->pci_iohole_start
+ s
->pci_iohole_alloc
;
182 s
->pci_iohole_alloc
+= size
;
184 qpci_config_writel(dev
, bar_reg
, loc
| PCI_BASE_ADDRESS_SPACE_IO
);
186 return (void *)(intptr_t)loc
;
190 g_assert((s
->pci_hole_alloc
+ size
) <= s
->pci_hole_size
);
191 loc
= s
->pci_hole_start
+ s
->pci_hole_alloc
;
192 s
->pci_hole_alloc
+= size
;
194 qpci_config_writel(dev
, bar_reg
, loc
);
196 return (void *)(intptr_t)loc
;
200 static void qpci_pc_iounmap(QPCIBus
*bus
, void *data
)
205 QPCIBus
*qpci_init_pc(void)
209 ret
= g_malloc(sizeof(*ret
));
211 ret
->bus
.io_readb
= qpci_pc_io_readb
;
212 ret
->bus
.io_readw
= qpci_pc_io_readw
;
213 ret
->bus
.io_readl
= qpci_pc_io_readl
;
215 ret
->bus
.io_writeb
= qpci_pc_io_writeb
;
216 ret
->bus
.io_writew
= qpci_pc_io_writew
;
217 ret
->bus
.io_writel
= qpci_pc_io_writel
;
219 ret
->bus
.config_readb
= qpci_pc_config_readb
;
220 ret
->bus
.config_readw
= qpci_pc_config_readw
;
221 ret
->bus
.config_readl
= qpci_pc_config_readl
;
223 ret
->bus
.config_writeb
= qpci_pc_config_writeb
;
224 ret
->bus
.config_writew
= qpci_pc_config_writew
;
225 ret
->bus
.config_writel
= qpci_pc_config_writel
;
227 ret
->bus
.iomap
= qpci_pc_iomap
;
228 ret
->bus
.iounmap
= qpci_pc_iounmap
;
230 ret
->pci_hole_start
= 0xE0000000;
231 ret
->pci_hole_size
= 0x20000000;
232 ret
->pci_hole_alloc
= 0;
234 ret
->pci_iohole_start
= 0xc000;
235 ret
->pci_iohole_size
= 0x4000;
236 ret
->pci_iohole_alloc
= 0;