]> git.proxmox.com Git - qemu.git/blame - hw/pci-bridge/pci_bridge_dev.c
rng-egd: remove redundant free
[qemu.git] / hw / pci-bridge / pci_bridge_dev.c
CommitLineData
4eb812f7
MT
1/*
2 * Standard PCI Bridge Device
3 *
4 * Copyright (c) 2011 Red Hat Inc. Author: Michael S. Tsirkin <mst@redhat.com>
5 *
6 * http://www.pcisig.com/specifications/conventional/pci_to_pci_bridge_architecture/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
83c9f4ca
PB
22#include "hw/pci/pci_bridge.h"
23#include "hw/pci/pci_ids.h"
24#include "hw/pci/msi.h"
25#include "hw/pci/shpc.h"
26#include "hw/pci/slotid_cap.h"
022c62cb 27#include "exec/memory.h"
83c9f4ca 28#include "hw/pci/pci_bus.h"
4eb812f7 29
57524e14
AF
30#define TYPE_PCI_BRIDGE_DEV "pci-bridge"
31#define PCI_BRIDGE_DEV(obj) \
32 OBJECT_CHECK(PCIBridgeDev, (obj), TYPE_PCI_BRIDGE_DEV)
33
4eb812f7 34struct PCIBridgeDev {
57524e14
AF
35 /*< private >*/
36 PCIBridge parent_obj;
37 /*< public >*/
38
4eb812f7
MT
39 MemoryRegion bar;
40 uint8_t chassis_nr;
41#define PCI_BRIDGE_DEV_F_MSI_REQ 0
42 uint32_t flags;
43};
44typedef struct PCIBridgeDev PCIBridgeDev;
45
4eb812f7
MT
46static int pci_bridge_dev_initfn(PCIDevice *dev)
47{
f055e96b 48 PCIBridge *br = PCI_BRIDGE(dev);
57524e14 49 PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
f90c2bcd
AW
50 int err;
51
60a0e443 52 err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
4eb812f7
MT
53 if (err) {
54 goto bridge_error;
55 }
c008ac0c 56 dev->config[PCI_INTERRUPT_PIN] = 0x1;
40c5dce9 57 memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev));
4eb812f7
MT
58 err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0);
59 if (err) {
60 goto shpc_error;
61 }
62 err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0);
63 if (err) {
64 goto slotid_error;
65 }
66 if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) &&
67 msi_supported) {
68 err = msi_init(dev, 0, 1, true, true);
69 if (err < 0) {
70 goto msi_error;
71 }
72 }
73 /* TODO: spec recommends using 64 bit prefetcheable BAR.
74 * Check whether that works well. */
75 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
76 PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar);
4eb812f7
MT
77 return 0;
78msi_error:
79 slotid_cap_cleanup(dev);
80slotid_error:
81 shpc_cleanup(dev, &bridge_dev->bar);
82shpc_error:
83 memory_region_destroy(&bridge_dev->bar);
f90c2bcd 84 pci_bridge_exitfn(dev);
4eb812f7
MT
85bridge_error:
86 return err;
87}
88
f90c2bcd 89static void pci_bridge_dev_exitfn(PCIDevice *dev)
4eb812f7 90{
57524e14 91 PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
4eb812f7
MT
92 if (msi_present(dev)) {
93 msi_uninit(dev);
94 }
95 slotid_cap_cleanup(dev);
96 shpc_cleanup(dev, &bridge_dev->bar);
97 memory_region_destroy(&bridge_dev->bar);
f90c2bcd 98 pci_bridge_exitfn(dev);
4eb812f7
MT
99}
100
101static void pci_bridge_dev_write_config(PCIDevice *d,
102 uint32_t address, uint32_t val, int len)
103{
104 pci_bridge_write_config(d, address, val, len);
105 if (msi_present(d)) {
106 msi_write_config(d, address, val, len);
107 }
108 shpc_cap_write_config(d, address, val, len);
109}
110
111static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
112{
57524e14 113 PCIDevice *dev = PCI_DEVICE(qdev);
cbd2d434 114
4eb812f7 115 pci_bridge_reset(qdev);
4eb812f7
MT
116 shpc_reset(dev);
117}
118
119static Property pci_bridge_dev_properties[] = {
120 /* Note: 0 is not a legal chassis number. */
121 DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0),
122 DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true),
123 DEFINE_PROP_END_OF_LIST(),
124};
125
126static const VMStateDescription pci_bridge_dev_vmstate = {
127 .name = "pci_bridge",
128 .fields = (VMStateField[]) {
57524e14
AF
129 VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
130 SHPC_VMSTATE(shpc, PCIDevice),
4eb812f7
MT
131 VMSTATE_END_OF_LIST()
132 }
133};
134
135static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
136{
137 DeviceClass *dc = DEVICE_CLASS(klass);
138 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
139 k->init = pci_bridge_dev_initfn;
140 k->exit = pci_bridge_dev_exitfn;
141 k->config_write = pci_bridge_dev_write_config;
5c03a254
PB
142 k->vendor_id = PCI_VENDOR_ID_REDHAT;
143 k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE;
4eb812f7
MT
144 k->class_id = PCI_CLASS_BRIDGE_PCI;
145 k->is_bridge = 1,
146 dc->desc = "Standard PCI Bridge";
147 dc->reset = qdev_pci_bridge_dev_reset;
148 dc->props = pci_bridge_dev_properties;
149 dc->vmsd = &pci_bridge_dev_vmstate;
125ee0ed 150 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
4eb812f7
MT
151}
152
8c43a6f0 153static const TypeInfo pci_bridge_dev_info = {
57524e14 154 .name = TYPE_PCI_BRIDGE_DEV,
f055e96b 155 .parent = TYPE_PCI_BRIDGE,
4eb812f7
MT
156 .instance_size = sizeof(PCIBridgeDev),
157 .class_init = pci_bridge_dev_class_init,
158};
159
160static void pci_bridge_dev_register(void)
161{
162 type_register_static(&pci_bridge_dev_info);
163}
164
165type_init(pci_bridge_dev_register);