pcie_pci_bridge.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * QEMU Generic PCIE-PCI Bridge
  3. *
  4. * Copyright (c) 2017 Aleksandr Bezzubikov
  5. *
  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.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "qapi/error.h"
  11. #include "qemu/module.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"
  18. #include "hw/qdev-properties.h"
  19. typedef struct PCIEPCIBridge {
  20. /*< private >*/
  21. PCIBridge parent_obj;
  22. OnOffAuto msi;
  23. MemoryRegion shpc_bar;
  24. /*< public >*/
  25. } PCIEPCIBridge;
  26. #define TYPE_PCIE_PCI_BRIDGE_DEV "pcie-pci-bridge"
  27. #define PCIE_PCI_BRIDGE_DEV(obj) \
  28. OBJECT_CHECK(PCIEPCIBridge, (obj), TYPE_PCIE_PCI_BRIDGE_DEV)
  29. static void pcie_pci_bridge_realize(PCIDevice *d, Error **errp)
  30. {
  31. PCIBridge *br = PCI_BRIDGE(d);
  32. PCIEPCIBridge *pcie_br = PCIE_PCI_BRIDGE_DEV(d);
  33. int rc, pos;
  34. pci_bridge_initfn(d, TYPE_PCI_BUS);
  35. d->config[PCI_INTERRUPT_PIN] = 0x1;
  36. memory_region_init(&pcie_br->shpc_bar, OBJECT(d), "shpc-bar",
  37. shpc_bar_size(d));
  38. rc = shpc_init(d, &br->sec_bus, &pcie_br->shpc_bar, 0, errp);
  39. if (rc) {
  40. goto error;
  41. }
  42. rc = pcie_cap_init(d, 0, PCI_EXP_TYPE_PCI_BRIDGE, 0, errp);
  43. if (rc < 0) {
  44. goto cap_error;
  45. }
  46. pos = pci_add_capability(d, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF, errp);
  47. if (pos < 0) {
  48. goto pm_error;
  49. }
  50. d->exp.pm_cap = pos;
  51. pci_set_word(d->config + pos + PCI_PM_PMC, 0x3);
  52. pcie_cap_arifwd_init(d);
  53. pcie_cap_deverr_init(d);
  54. rc = pcie_aer_init(d, PCI_ERR_VER, 0x100, PCI_ERR_SIZEOF, errp);
  55. if (rc < 0) {
  56. goto aer_error;
  57. }
  58. Error *local_err = NULL;
  59. if (pcie_br->msi != ON_OFF_AUTO_OFF) {
  60. rc = msi_init(d, 0, 1, true, true, &local_err);
  61. if (rc < 0) {
  62. assert(rc == -ENOTSUP);
  63. if (pcie_br->msi != ON_OFF_AUTO_ON) {
  64. error_free(local_err);
  65. } else {
  66. /* failed to satisfy user's explicit request for MSI */
  67. error_propagate(errp, local_err);
  68. goto msi_error;
  69. }
  70. }
  71. }
  72. pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
  73. PCI_BASE_ADDRESS_MEM_TYPE_64, &pcie_br->shpc_bar);
  74. return;
  75. msi_error:
  76. pcie_aer_exit(d);
  77. aer_error:
  78. pm_error:
  79. pcie_cap_exit(d);
  80. cap_error:
  81. shpc_cleanup(d, &pcie_br->shpc_bar);
  82. error:
  83. pci_bridge_exitfn(d);
  84. }
  85. static void pcie_pci_bridge_exit(PCIDevice *d)
  86. {
  87. PCIEPCIBridge *bridge_dev = PCIE_PCI_BRIDGE_DEV(d);
  88. pcie_cap_exit(d);
  89. shpc_cleanup(d, &bridge_dev->shpc_bar);
  90. pci_bridge_exitfn(d);
  91. }
  92. static void pcie_pci_bridge_reset(DeviceState *qdev)
  93. {
  94. PCIDevice *d = PCI_DEVICE(qdev);
  95. pci_bridge_reset(qdev);
  96. if (msi_present(d)) {
  97. msi_reset(d);
  98. }
  99. shpc_reset(d);
  100. }
  101. static void pcie_pci_bridge_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. static Property pcie_pci_bridge_dev_properties[] = {
  111. DEFINE_PROP_ON_OFF_AUTO("msi", PCIEPCIBridge, msi, ON_OFF_AUTO_AUTO),
  112. DEFINE_PROP_END_OF_LIST(),
  113. };
  114. static const VMStateDescription pcie_pci_bridge_dev_vmstate = {
  115. .name = TYPE_PCIE_PCI_BRIDGE_DEV,
  116. .priority = MIG_PRI_PCI_BUS,
  117. .fields = (VMStateField[]) {
  118. VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
  119. SHPC_VMSTATE(shpc, PCIDevice, NULL),
  120. VMSTATE_END_OF_LIST()
  121. }
  122. };
  123. static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data)
  124. {
  125. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  126. DeviceClass *dc = DEVICE_CLASS(klass);
  127. HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
  128. k->is_bridge = true;
  129. k->vendor_id = PCI_VENDOR_ID_REDHAT;
  130. k->device_id = PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE;
  131. k->realize = pcie_pci_bridge_realize;
  132. k->exit = pcie_pci_bridge_exit;
  133. k->config_write = pcie_pci_bridge_write_config;
  134. dc->vmsd = &pcie_pci_bridge_dev_vmstate;
  135. device_class_set_props(dc, pcie_pci_bridge_dev_properties);
  136. dc->reset = &pcie_pci_bridge_reset;
  137. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  138. hc->plug = pci_bridge_dev_plug_cb;
  139. hc->unplug = pci_bridge_dev_unplug_cb;
  140. hc->unplug_request = pci_bridge_dev_unplug_request_cb;
  141. }
  142. static const TypeInfo pcie_pci_bridge_info = {
  143. .name = TYPE_PCIE_PCI_BRIDGE_DEV,
  144. .parent = TYPE_PCI_BRIDGE,
  145. .instance_size = sizeof(PCIEPCIBridge),
  146. .class_init = pcie_pci_bridge_class_init,
  147. .interfaces = (InterfaceInfo[]) {
  148. { TYPE_HOTPLUG_HANDLER },
  149. { INTERFACE_PCIE_DEVICE },
  150. { },
  151. }
  152. };
  153. static void pciepci_register(void)
  154. {
  155. type_register_static(&pcie_pci_bridge_info);
  156. }
  157. type_init(pciepci_register);