2 * QEMU Generic PCIE-PCI Bridge
4 * Copyright (c) 2017 Aleksandr Bezzubikov
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
11 #include "qapi/error.h"
12 #include "hw/pci/pci.h"
13 #include "hw/pci/pci_bus.h"
14 #include "hw/pci/pci_bridge.h"
15 #include "hw/pci/msi.h"
16 #include "hw/pci/shpc.h"
17 #include "hw/pci/slotid_cap.h"
19 typedef struct PCIEPCIBridge
{
24 MemoryRegion shpc_bar
;
28 #define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
29 #define PCIE_PCI_BRIDGE_DEV(obj) \
30 OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
32 static void pcie_pci_bridge_realize(PCIDevice
*d
, Error
**errp
)
34 PCIBridge
*br
= PCI_BRIDGE(d
);
35 PCIEPCIBridge
*pcie_br
= PCIE_PCI_BRIDGE_DEV(d
);
38 pci_bridge_initfn(d
, TYPE_PCI_BUS
);
40 d
->config
[PCI_INTERRUPT_PIN
] = 0x1;
41 memory_region_init(&pcie_br
->shpc_bar
, OBJECT(d
), "shpc-bar",
43 rc
= shpc_init(d
, &br
->sec_bus
, &pcie_br
->shpc_bar
, 0, errp
);
48 rc
= pcie_cap_init(d
, 0, PCI_EXP_TYPE_PCI_BRIDGE
, 0, errp
);
53 pos
= pci_add_capability(d
, PCI_CAP_ID_PM
, 0, PCI_PM_SIZEOF
, errp
);
58 pci_set_word(d
->config
+ pos
+ PCI_PM_PMC
, 0x3);
60 pcie_cap_arifwd_init(d
);
61 pcie_cap_deverr_init(d
);
63 rc
= pcie_aer_init(d
, PCI_ERR_VER
, 0x100, PCI_ERR_SIZEOF
, errp
);
68 Error
*local_err
= NULL
;
69 if (pcie_br
->msi
!= ON_OFF_AUTO_OFF
) {
70 rc
= msi_init(d
, 0, 1, true, true, &local_err
);
72 assert(rc
== -ENOTSUP
);
73 if (pcie_br
->msi
!= ON_OFF_AUTO_ON
) {
74 error_free(local_err
);
76 /* failed to satisfy user's explicit request for MSI */
77 error_propagate(errp
, local_err
);
82 pci_register_bar(d
, 0, PCI_BASE_ADDRESS_SPACE_MEMORY
|
83 PCI_BASE_ADDRESS_MEM_TYPE_64
, &pcie_br
->shpc_bar
);
92 shpc_cleanup(d
, &pcie_br
->shpc_bar
);
97 static void pcie_pci_bridge_exit(PCIDevice
*d
)
99 PCIEPCIBridge
*bridge_dev
= PCIE_PCI_BRIDGE_DEV(d
);
101 shpc_cleanup(d
, &bridge_dev
->shpc_bar
);
102 pci_bridge_exitfn(d
);
105 static void pcie_pci_bridge_reset(DeviceState
*qdev
)
107 PCIDevice
*d
= PCI_DEVICE(qdev
);
108 pci_bridge_reset(qdev
);
109 if (msi_present(d
)) {
115 static void pcie_pci_bridge_write_config(PCIDevice
*d
,
116 uint32_t address
, uint32_t val
, int len
)
118 pci_bridge_write_config(d
, address
, val
, len
);
119 if (msi_present(d
)) {
120 msi_write_config(d
, address
, val
, len
);
122 shpc_cap_write_config(d
, address
, val
, len
);
125 static Property pcie_pci_bridge_dev_properties
[] = {
126 DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge
, msi
, ON_OFF_AUTO_AUTO
),
127 DEFINE_PROP_END_OF_LIST(),
130 static const VMStateDescription pcie_pci_bridge_dev_vmstate
= {
131 .name
= TYPE_PCIE_PCI_BRIDGE_DEV
,
132 .priority
= MIG_PRI_PCI_BUS
,
133 .fields
= (VMStateField
[]) {
134 VMSTATE_PCI_DEVICE(parent_obj
, PCIBridge
),
135 SHPC_VMSTATE(shpc
, PCIDevice
, NULL
),
136 VMSTATE_END_OF_LIST()
140 static void pcie_pci_bridge_hotplug_cb(HotplugHandler
*hotplug_dev
,
141 DeviceState
*dev
, Error
**errp
)
143 PCIDevice
*pci_hotplug_dev
= PCI_DEVICE(hotplug_dev
);
145 if (!shpc_present(pci_hotplug_dev
)) {
146 error_setg(errp
, "standard hotplug controller has been disabled for "
147 "this %s", TYPE_PCIE_PCI_BRIDGE_DEV
);
150 shpc_device_hotplug_cb(hotplug_dev
, dev
, errp
);
153 static void pcie_pci_bridge_hot_unplug_request_cb(HotplugHandler
*hotplug_dev
,
157 PCIDevice
*pci_hotplug_dev
= PCI_DEVICE(hotplug_dev
);
159 if (!shpc_present(pci_hotplug_dev
)) {
160 error_setg(errp
, "standard hotplug controller has been disabled for "
161 "this %s", TYPE_PCIE_PCI_BRIDGE_DEV
);
164 shpc_device_hot_unplug_request_cb(hotplug_dev
, dev
, errp
);
167 static void pcie_pci_bridge_class_init(ObjectClass
*klass
, void *data
)
169 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
170 DeviceClass
*dc
= DEVICE_CLASS(klass
);
171 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(klass
);
174 k
->vendor_id
= PCI_VENDOR_ID_REDHAT
;
175 k
->device_id
= PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE
;
176 k
->realize
= pcie_pci_bridge_realize
;
177 k
->exit
= pcie_pci_bridge_exit
;
178 k
->config_write
= pcie_pci_bridge_write_config
;
179 dc
->vmsd
= &pcie_pci_bridge_dev_vmstate
;
180 dc
->props
= pcie_pci_bridge_dev_properties
;
181 dc
->reset
= &pcie_pci_bridge_reset
;
182 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
183 hc
->plug
= pcie_pci_bridge_hotplug_cb
;
184 hc
->unplug_request
= pcie_pci_bridge_hot_unplug_request_cb
;
187 static const TypeInfo pcie_pci_bridge_info
= {
188 .name
= TYPE_PCIE_PCI_BRIDGE_DEV
,
189 .parent
= TYPE_PCI_BRIDGE
,
190 .instance_size
= sizeof(PCIEPCIBridge
),
191 .class_init
= pcie_pci_bridge_class_init
,
192 .interfaces
= (InterfaceInfo
[]) {
193 { TYPE_HOTPLUG_HANDLER
},
194 { INTERFACE_PCIE_DEVICE
},
199 static void pciepci_register(void)
201 type_register_static(&pcie_pci_bridge_info
);
204 type_init(pciepci_register
);