]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/pci-bridge/pci_expander_bridge.c
Move QOM typedefs and add missing includes
[thirdparty/qemu.git] / hw / pci-bridge / pci_expander_bridge.c
CommitLineData
40d14bef
MA
1/*
2 * PCI Expander Bridge Device Emulation
3 *
4 * Copyright (C) 2015 Red Hat Inc
5 *
6 * Authors:
7 * Marcel Apfelbaum <marcel@redhat.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
97d5408f 13#include "qemu/osdep.h"
86395eb3 14#include "qapi/error.h"
40d14bef
MA
15#include "hw/pci/pci.h"
16#include "hw/pci/pci_bus.h"
17#include "hw/pci/pci_host.h"
a27bd6c7 18#include "hw/qdev-properties.h"
3cf0ecb3 19#include "hw/pci/pci_bridge.h"
40d14bef
MA
20#include "qemu/range.h"
21#include "qemu/error-report.h"
0b8fa32f 22#include "qemu/module.h"
0e79e51a 23#include "sysemu/numa.h"
aa570207 24#include "hw/boards.h"
db1015e9 25#include "qom/object.h"
40d14bef
MA
26
27#define TYPE_PXB_BUS "pxb-bus"
db1015e9 28typedef struct PXBBus PXBBus;
40d14bef
MA
29#define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
30
02b07434
MA
31#define TYPE_PXB_PCIE_BUS "pxb-pcie-bus"
32#define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS)
33
db1015e9 34struct PXBBus {
40d14bef
MA
35 /*< private >*/
36 PCIBus parent_obj;
37 /*< public >*/
38
39 char bus_path[8];
db1015e9 40};
40d14bef
MA
41
42#define TYPE_PXB_DEVICE "pxb"
db1015e9 43typedef struct PXBDev PXBDev;
40d14bef
MA
44#define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE)
45
02b07434
MA
46#define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
47#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
48
db1015e9 49struct PXBDev {
40d14bef
MA
50 /*< private >*/
51 PCIDevice parent_obj;
52 /*< public >*/
53
54 uint8_t bus_nr;
0e79e51a 55 uint16_t numa_node;
db1015e9 56};
40d14bef 57
02b07434
MA
58static PXBDev *convert_to_pxb(PCIDevice *dev)
59{
fd56e061
DG
60 return pci_bus_is_express(pci_get_bus(dev))
61 ? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
02b07434
MA
62}
63
48ea3ded
LE
64static GList *pxb_dev_list;
65
40d14bef
MA
66#define TYPE_PXB_HOST "pxb-host"
67
68static int pxb_bus_num(PCIBus *bus)
69{
02b07434 70 PXBDev *pxb = convert_to_pxb(bus->parent_dev);
40d14bef
MA
71
72 return pxb->bus_nr;
73}
74
0e79e51a
MA
75static uint16_t pxb_bus_numa_node(PCIBus *bus)
76{
02b07434 77 PXBDev *pxb = convert_to_pxb(bus->parent_dev);
0e79e51a
MA
78
79 return pxb->numa_node;
80}
81
40d14bef
MA
82static void pxb_bus_class_init(ObjectClass *class, void *data)
83{
84 PCIBusClass *pbc = PCI_BUS_CLASS(class);
85
86 pbc->bus_num = pxb_bus_num;
0e79e51a 87 pbc->numa_node = pxb_bus_numa_node;
40d14bef
MA
88}
89
90static const TypeInfo pxb_bus_info = {
91 .name = TYPE_PXB_BUS,
92 .parent = TYPE_PCI_BUS,
93 .instance_size = sizeof(PXBBus),
94 .class_init = pxb_bus_class_init,
95};
96
02b07434
MA
97static const TypeInfo pxb_pcie_bus_info = {
98 .name = TYPE_PXB_PCIE_BUS,
99 .parent = TYPE_PCIE_BUS,
100 .instance_size = sizeof(PXBBus),
101 .class_init = pxb_bus_class_init,
102};
103
40d14bef
MA
104static const char *pxb_host_root_bus_path(PCIHostState *host_bridge,
105 PCIBus *rootbus)
106{
02b07434
MA
107 PXBBus *bus = pci_bus_is_express(rootbus) ?
108 PXB_PCIE_BUS(rootbus) : PXB_BUS(rootbus);
40d14bef
MA
109
110 snprintf(bus->bus_path, 8, "0000:%02x", pxb_bus_num(rootbus));
111 return bus->bus_path;
112}
113
48ea3ded
LE
114static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
115{
116 const PCIHostState *pxb_host;
117 const PCIBus *pxb_bus;
118 const PXBDev *pxb_dev;
119 int position;
120 const DeviceState *pxb_dev_base;
121 const PCIHostState *main_host;
122 const SysBusDevice *main_host_sbd;
123
124 pxb_host = PCI_HOST_BRIDGE(dev);
125 pxb_bus = pxb_host->bus;
02b07434 126 pxb_dev = convert_to_pxb(pxb_bus->parent_dev);
48ea3ded
LE
127 position = g_list_index(pxb_dev_list, pxb_dev);
128 assert(position >= 0);
129
130 pxb_dev_base = DEVICE(pxb_dev);
131 main_host = PCI_HOST_BRIDGE(pxb_dev_base->parent_bus->parent);
132 main_host_sbd = SYS_BUS_DEVICE(main_host);
133
134 if (main_host_sbd->num_mmio > 0) {
135 return g_strdup_printf(TARGET_FMT_plx ",%x",
136 main_host_sbd->mmio[0].addr, position + 1);
137 }
138 if (main_host_sbd->num_pio > 0) {
139 return g_strdup_printf("i%04x,%x",
140 main_host_sbd->pio[0], position + 1);
141 }
142 return NULL;
143}
144
40d14bef
MA
145static void pxb_host_class_init(ObjectClass *class, void *data)
146{
147 DeviceClass *dc = DEVICE_CLASS(class);
48ea3ded 148 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
40d14bef
MA
149 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
150
151 dc->fw_name = "pci";
bf8d4924 152 /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself */
e90f2a8c 153 dc->user_creatable = false;
48ea3ded 154 sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
40d14bef
MA
155 hc->root_bus_path = pxb_host_root_bus_path;
156}
157
158static const TypeInfo pxb_host_info = {
159 .name = TYPE_PXB_HOST,
160 .parent = TYPE_PCI_HOST_BRIDGE,
161 .class_init = pxb_host_class_init,
162};
163
164/*
86395eb3 165 * Registers the PXB bus as a child of pci host root bus.
40d14bef 166 */
86395eb3 167static void pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus, Error **errp)
40d14bef 168{
fd56e061 169 PCIBus *bus = pci_get_bus(dev);
40d14bef
MA
170 int pxb_bus_num = pci_bus_num(pxb_bus);
171
172 if (bus->parent_dev) {
86395eb3
WJ
173 error_setg(errp, "PXB devices can be attached only to root bus");
174 return;
40d14bef
MA
175 }
176
177 QLIST_FOREACH(bus, &bus->child, sibling) {
178 if (pci_bus_num(bus) == pxb_bus_num) {
86395eb3
WJ
179 error_setg(errp, "Bus %d is already in use", pxb_bus_num);
180 return;
40d14bef
MA
181 }
182 }
fd56e061 183 QLIST_INSERT_HEAD(&pci_get_bus(dev)->child, pxb_bus, sibling);
40d14bef
MA
184}
185
0639b00d
MA
186static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
187{
fd56e061 188 PCIDevice *pxb = pci_get_bus(pci_dev)->parent_dev;
0639b00d
MA
189
190 /*
191 * The bios does not index the pxb slot number when
192 * it computes the IRQ because it resides on bus 0
193 * and not on the current bus.
194 * However QEMU routes the irq through bus 0 and adds
195 * the pxb slot to the IRQ computation of the PXB
196 * device.
197 *
198 * Synchronize between bios and QEMU by canceling
199 * pxb's effect.
200 */
201 return pin - PCI_SLOT(pxb->devfn);
202}
203
48ea3ded
LE
204static gint pxb_compare(gconstpointer a, gconstpointer b)
205{
206 const PXBDev *pxb_a = a, *pxb_b = b;
207
208 return pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
209 pxb_a->bus_nr > pxb_b->bus_nr ? 1 :
210 0;
211}
212
86395eb3 213static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
40d14bef 214{
02b07434
MA
215 PXBDev *pxb = convert_to_pxb(dev);
216 DeviceState *ds, *bds = NULL;
40d14bef
MA
217 PCIBus *bus;
218 const char *dev_name = NULL;
86395eb3 219 Error *local_err = NULL;
aa570207
TX
220 MachineState *ms = MACHINE(qdev_get_machine());
221
222 if (ms->numa_state == NULL) {
223 error_setg(errp, "NUMA is not supported by this machine-type");
224 return;
225 }
40d14bef 226
0e79e51a 227 if (pxb->numa_node != NUMA_NODE_UNASSIGNED &&
aa570207 228 pxb->numa_node >= ms->numa_state->num_nodes) {
86395eb3
WJ
229 error_setg(errp, "Illegal numa node %d", pxb->numa_node);
230 return;
0e79e51a
MA
231 }
232
40d14bef
MA
233 if (dev->qdev.id && *dev->qdev.id) {
234 dev_name = dev->qdev.id;
235 }
236
3e80f690 237 ds = qdev_new(TYPE_PXB_HOST);
02b07434 238 if (pcie) {
1115ff6d 239 bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
02b07434 240 } else {
1115ff6d 241 bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
df707969 242 bds = qdev_new("pci-bridge");
02b07434
MA
243 bds->id = dev_name;
244 qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
245 qdev_prop_set_bit(bds, PCI_BRIDGE_DEV_PROP_SHPC, false);
246 }
40d14bef
MA
247
248 bus->parent_dev = dev;
fd56e061
DG
249 bus->address_space_mem = pci_get_bus(dev)->address_space_mem;
250 bus->address_space_io = pci_get_bus(dev)->address_space_io;
0639b00d 251 bus->map_irq = pxb_map_irq_fn;
40d14bef 252
40d14bef
MA
253 PCI_HOST_BRIDGE(ds)->bus = bus;
254
86395eb3
WJ
255 pxb_register_bus(dev, bus, &local_err);
256 if (local_err) {
257 error_propagate(errp, local_err);
2e4278b5 258 goto err_register_bus;
40d14bef
MA
259 }
260
3c6ef471 261 sysbus_realize_and_unref(SYS_BUS_DEVICE(ds), &error_fatal);
02b07434 262 if (bds) {
df707969 263 qdev_realize_and_unref(bds, &bus->qbus, &error_fatal);
02b07434 264 }
40d14bef
MA
265
266 pci_word_test_and_set_mask(dev->config + PCI_STATUS,
267 PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
268 pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
269
48ea3ded 270 pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
86395eb3 271 return;
2e4278b5
WJ
272
273err_register_bus:
274 object_unref(OBJECT(bds));
275 object_unparent(OBJECT(bus));
276 object_unref(OBJECT(ds));
40d14bef
MA
277}
278
86395eb3 279static void pxb_dev_realize(PCIDevice *dev, Error **errp)
02b07434 280{
fd56e061 281 if (pci_bus_is_express(pci_get_bus(dev))) {
86395eb3
WJ
282 error_setg(errp, "pxb devices cannot reside on a PCIe bus");
283 return;
02b07434
MA
284 }
285
86395eb3 286 pxb_dev_realize_common(dev, false, errp);
02b07434
MA
287}
288
48ea3ded
LE
289static void pxb_dev_exitfn(PCIDevice *pci_dev)
290{
02b07434 291 PXBDev *pxb = convert_to_pxb(pci_dev);
48ea3ded
LE
292
293 pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
294}
295
40d14bef 296static Property pxb_dev_properties[] = {
f9735fd5 297 /* Note: 0 is not a legal PXB bus number. */
40d14bef 298 DEFINE_PROP_UINT8("bus_nr", PXBDev, bus_nr, 0),
0e79e51a 299 DEFINE_PROP_UINT16("numa_node", PXBDev, numa_node, NUMA_NODE_UNASSIGNED),
40d14bef
MA
300 DEFINE_PROP_END_OF_LIST(),
301};
302
303static void pxb_dev_class_init(ObjectClass *klass, void *data)
304{
305 DeviceClass *dc = DEVICE_CLASS(klass);
306 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
307
86395eb3 308 k->realize = pxb_dev_realize;
48ea3ded 309 k->exit = pxb_dev_exitfn;
40d14bef
MA
310 k->vendor_id = PCI_VENDOR_ID_REDHAT;
311 k->device_id = PCI_DEVICE_ID_REDHAT_PXB;
312 k->class_id = PCI_CLASS_BRIDGE_HOST;
313
314 dc->desc = "PCI Expander Bridge";
4f67d30b 315 device_class_set_props(dc, pxb_dev_properties);
7b346c74 316 dc->hotpluggable = false;
13d11b0b 317 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
40d14bef
MA
318}
319
320static const TypeInfo pxb_dev_info = {
321 .name = TYPE_PXB_DEVICE,
322 .parent = TYPE_PCI_DEVICE,
323 .instance_size = sizeof(PXBDev),
324 .class_init = pxb_dev_class_init,
fd3b02c8
EH
325 .interfaces = (InterfaceInfo[]) {
326 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
327 { },
328 },
40d14bef
MA
329};
330
86395eb3 331static void pxb_pcie_dev_realize(PCIDevice *dev, Error **errp)
02b07434 332{
fd56e061 333 if (!pci_bus_is_express(pci_get_bus(dev))) {
86395eb3
WJ
334 error_setg(errp, "pxb-pcie devices cannot reside on a PCI bus");
335 return;
02b07434
MA
336 }
337
86395eb3 338 pxb_dev_realize_common(dev, true, errp);
02b07434
MA
339}
340
341static void pxb_pcie_dev_class_init(ObjectClass *klass, void *data)
342{
343 DeviceClass *dc = DEVICE_CLASS(klass);
344 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
345
86395eb3 346 k->realize = pxb_pcie_dev_realize;
02b07434
MA
347 k->exit = pxb_dev_exitfn;
348 k->vendor_id = PCI_VENDOR_ID_REDHAT;
349 k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
350 k->class_id = PCI_CLASS_BRIDGE_HOST;
351
352 dc->desc = "PCI Express Expander Bridge";
4f67d30b 353 device_class_set_props(dc, pxb_dev_properties);
7b346c74 354 dc->hotpluggable = false;
13d11b0b 355 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
02b07434
MA
356}
357
358static const TypeInfo pxb_pcie_dev_info = {
359 .name = TYPE_PXB_PCIE_DEVICE,
360 .parent = TYPE_PCI_DEVICE,
361 .instance_size = sizeof(PXBDev),
362 .class_init = pxb_pcie_dev_class_init,
fd3b02c8
EH
363 .interfaces = (InterfaceInfo[]) {
364 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
365 { },
366 },
02b07434
MA
367};
368
40d14bef
MA
369static void pxb_register_types(void)
370{
371 type_register_static(&pxb_bus_info);
02b07434 372 type_register_static(&pxb_pcie_bus_info);
40d14bef
MA
373 type_register_static(&pxb_host_info);
374 type_register_static(&pxb_dev_info);
02b07434 375 type_register_static(&pxb_pcie_dev_info);
40d14bef
MA
376}
377
378type_init(pxb_register_types)