1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "qemu/osdep.h"
23#include "hw/pci/pci_ids.h"
24#include "hw/pci/msi.h"
25#include "hw/pci/pcie.h"
26#include "hw/pci/pcie_port.h"
27#include "qapi/error.h"
28
29#define PCI_DEVICE_ID_EPORT 0xd022
30#define PCI_DEVICE_ID_REV 0x1
31#define EP_EXP_OFFSET 0x60
32#define EP_AER_OFFSET 0x100
33
34static void xlnx_write_config(PCIDevice *d,
35 uint32_t address, uint32_t val, int len)
36{
37 uint32_t root_cmd =
38 pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
39
40 pci_bridge_write_config(d, address, val, len);
41 pcie_cap_slot_write_config(d, address, val, len);
42 pcie_aer_write_config(d, address, val, len);
43 pcie_aer_root_write_config(d, address, val, len, root_cmd);
44}
45
46static void xlnx_reset(DeviceState *qdev)
47{
48 PCIDevice *d = PCI_DEVICE(qdev);
49
50 pcie_cap_root_reset(d);
51 pcie_cap_deverr_reset(d);
52 pcie_cap_slot_reset(d);
53 pcie_cap_arifwd_reset(d);
54 pcie_aer_root_reset(d);
55 pci_bridge_reset(qdev);
56 pci_bridge_disable_base_limit(d);
57}
58
59static int xlnx_initfn(PCIDevice *d)
60{
61 PCIEPort *p = PCIE_PORT(d);
62 PCIESlot *s = PCIE_SLOT(d);
63 Error *err = NULL;
64 int rc;
65
66 pci_bridge_initfn(d, TYPE_PCIE_BUS);
67 pcie_port_init_reg(d);
68
69 rc = pcie_cap_init(d, EP_EXP_OFFSET, PCI_EXP_TYPE_ROOT_PORT, p->port,
70 &err);
71 if (rc < 0) {
72 error_report_err(err);
73 goto err_bridge;
74 }
75
76 pcie_cap_arifwd_init(d);
77 pcie_cap_deverr_init(d);
78 pcie_cap_slot_init(d, s->slot);
79 pcie_chassis_create(s->chassis);
80 rc = pcie_chassis_add_slot(s);
81 if (rc < 0) {
82 goto err_pcie_cap;
83 }
84 pcie_cap_root_init(d);
85 rc = pcie_aer_init(d, PCI_ERR_VER, EP_AER_OFFSET, PCI_ERR_SIZEOF, &err);
86 if (rc < 0) {
87 error_report_err(err);
88 goto err;
89 }
90
91 return 0;
92
93err:
94 pcie_chassis_del_slot(s);
95err_pcie_cap:
96 pcie_cap_exit(d);
97err_bridge:
98 pci_bridge_exitfn(d);
99 return rc;
100}
101
102static void xlnx_exitfn(PCIDevice *d)
103{
104 PCIESlot *s = PCIE_SLOT(d);
105
106 pcie_aer_exit(d);
107 pcie_chassis_del_slot(s);
108 pcie_cap_exit(d);
109 pci_bridge_exitfn(d);
110}
111
112static Property xlnx_props[] = {
113 DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
114 QEMU_PCIE_SLTCAP_PCP_BITNR, true),
115 DEFINE_PROP_END_OF_LIST()
116};
117
118static const VMStateDescription vmstate_xlnx = {
119 .name = "xlnx-pcie-rp",
120 .version_id = 1,
121 .minimum_version_id = 1,
122 .post_load = pcie_cap_slot_post_load,
123 .fields = (VMStateField[]) {
124 VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
125 VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
126 PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
127 VMSTATE_END_OF_LIST()
128 }
129};
130
131static void xlnx_class_init(ObjectClass *klass, void *data)
132{
133 DeviceClass *dc = DEVICE_CLASS(klass);
134 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
135
136 k->is_express = 1;
137 k->is_bridge = 1;
138 k->config_write = xlnx_write_config;
139 k->init = xlnx_initfn;
140 k->exit = xlnx_exitfn;
141 k->vendor_id = PCI_VENDOR_ID_XILINX;
142 k->device_id = PCI_DEVICE_ID_EPORT;
143 k->revision = PCI_DEVICE_ID_REV;
144 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
145 dc->desc = "Xilinx PCIe Root Port";
146 dc->reset = xlnx_reset;
147 dc->vmsd = &vmstate_xlnx;
148 dc->props = xlnx_props;
149}
150
151static const TypeInfo xlnx_info = {
152 .name = "xlnx-pcie-rp",
153 .parent = TYPE_PCIE_SLOT,
154 .class_init = xlnx_class_init,
155 .interfaces = (InterfaceInfo[]) {
156 { INTERFACE_PCIE_DEVICE },
157 { },
158 },
159
160};
161
162static void xlnx_register_types(void)
163{
164 type_register_static(&xlnx_info);
165}
166
167type_init(xlnx_register_types)
168