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 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" 27 #include "exec/memory.h" 28 #include "hw/pci/pci_bus.h" 29 30 struct PCIBridgeDev { 31 PCIBridge bridge; 32 MemoryRegion bar; 33 uint8_t chassis_nr; 34 #define PCI_BRIDGE_DEV_F_MSI_REQ 0 35 uint32_t flags; 36 }; 37 typedef struct PCIBridgeDev PCIBridgeDev; 38 39 static int pci_bridge_dev_initfn(PCIDevice *dev) 40 { 41 PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); 42 PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br); 43 int err; 44 45 err = pci_bridge_initfn(dev, TYPE_PCI_BUS); 46 if (err) { 47 goto bridge_error; 48 } 49 memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev)); 50 err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0); 51 if (err) { 52 goto shpc_error; 53 } 54 err = slotid_cap_init(dev, 0, bridge_dev->chassis_nr, 0); 55 if (err) { 56 goto slotid_error; 57 } 58 if ((bridge_dev->flags & (1 << PCI_BRIDGE_DEV_F_MSI_REQ)) && 59 msi_supported) { 60 err = msi_init(dev, 0, 1, true, true); 61 if (err < 0) { 62 goto msi_error; 63 } 64 } 65 /* TODO: spec recommends using 64 bit prefetcheable BAR. 66 * Check whether that works well. */ 67 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | 68 PCI_BASE_ADDRESS_MEM_TYPE_64, &bridge_dev->bar); 69 dev->config[PCI_INTERRUPT_PIN] = 0x1; 70 return 0; 71 msi_error: 72 slotid_cap_cleanup(dev); 73 slotid_error: 74 shpc_cleanup(dev, &bridge_dev->bar); 75 shpc_error: 76 memory_region_destroy(&bridge_dev->bar); 77 pci_bridge_exitfn(dev); 78 bridge_error: 79 return err; 80 } 81 82 static void pci_bridge_dev_exitfn(PCIDevice *dev) 83 { 84 PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev); 85 PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br); 86 if (msi_present(dev)) { 87 msi_uninit(dev); 88 } 89 slotid_cap_cleanup(dev); 90 shpc_cleanup(dev, &bridge_dev->bar); 91 memory_region_destroy(&bridge_dev->bar); 92 pci_bridge_exitfn(dev); 93 } 94 95 static void pci_bridge_dev_write_config(PCIDevice *d, 96 uint32_t address, uint32_t val, int len) 97 { 98 pci_bridge_write_config(d, address, val, len); 99 if (msi_present(d)) { 100 msi_write_config(d, address, val, len); 101 } 102 shpc_cap_write_config(d, address, val, len); 103 } 104 105 static void qdev_pci_bridge_dev_reset(DeviceState *qdev) 106 { 107 PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); 108 109 pci_bridge_reset(qdev); 110 shpc_reset(dev); 111 } 112 113 static Property pci_bridge_dev_properties[] = { 114 /* Note: 0 is not a legal chassis number. */ 115 DEFINE_PROP_UINT8("chassis_nr", PCIBridgeDev, chassis_nr, 0), 116 DEFINE_PROP_BIT("msi", PCIBridgeDev, flags, PCI_BRIDGE_DEV_F_MSI_REQ, true), 117 DEFINE_PROP_END_OF_LIST(), 118 }; 119 120 static const VMStateDescription pci_bridge_dev_vmstate = { 121 .name = "pci_bridge", 122 .fields = (VMStateField[]) { 123 VMSTATE_PCI_DEVICE(bridge.dev, PCIBridgeDev), 124 SHPC_VMSTATE(bridge.dev.shpc, PCIBridgeDev), 125 VMSTATE_END_OF_LIST() 126 } 127 }; 128 129 static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) 130 { 131 DeviceClass *dc = DEVICE_CLASS(klass); 132 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 133 k->init = pci_bridge_dev_initfn; 134 k->exit = pci_bridge_dev_exitfn; 135 k->config_write = pci_bridge_dev_write_config; 136 k->vendor_id = PCI_VENDOR_ID_REDHAT; 137 k->device_id = PCI_DEVICE_ID_REDHAT_BRIDGE; 138 k->class_id = PCI_CLASS_BRIDGE_PCI; 139 k->is_bridge = 1, 140 dc->desc = "Standard PCI Bridge"; 141 dc->reset = qdev_pci_bridge_dev_reset; 142 dc->props = pci_bridge_dev_properties; 143 dc->vmsd = &pci_bridge_dev_vmstate; 144 } 145 146 static const TypeInfo pci_bridge_dev_info = { 147 .name = "pci-bridge", 148 .parent = TYPE_PCI_DEVICE, 149 .instance_size = sizeof(PCIBridgeDev), 150 .class_init = pci_bridge_dev_class_init, 151 }; 152 153 static void pci_bridge_dev_register(void) 154 { 155 type_register_static(&pci_bridge_dev_info); 156 } 157 158 type_init(pci_bridge_dev_register); 159