prep_pci.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * QEMU PREP PCI host
  3. *
  4. * Copyright (c) 2006 Fabrice Bellard
  5. * Copyright (c) 2011-2013 Andreas Färber
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "hw.h"
  26. #include "pci/pci.h"
  27. #include "pci/pci_bus.h"
  28. #include "pci/pci_host.h"
  29. #include "pc.h"
  30. #include "exec/address-spaces.h"
  31. #define TYPE_RAVEN_PCI_DEVICE "raven"
  32. #define TYPE_RAVEN_PCI_HOST_BRIDGE "raven-pcihost"
  33. #define RAVEN_PCI_DEVICE(obj) \
  34. OBJECT_CHECK(RavenPCIState, (obj), TYPE_RAVEN_PCI_DEVICE)
  35. typedef struct RavenPCIState {
  36. PCIDevice dev;
  37. } RavenPCIState;
  38. #define RAVEN_PCI_HOST_BRIDGE(obj) \
  39. OBJECT_CHECK(PREPPCIState, (obj), TYPE_RAVEN_PCI_HOST_BRIDGE)
  40. typedef struct PRePPCIState {
  41. PCIHostState parent_obj;
  42. MemoryRegion intack;
  43. qemu_irq irq[4];
  44. PCIBus pci_bus;
  45. RavenPCIState pci_dev;
  46. } PREPPCIState;
  47. static inline uint32_t PPC_PCIIO_config(hwaddr addr)
  48. {
  49. int i;
  50. for (i = 0; i < 11; i++) {
  51. if ((addr & (1 << (11 + i))) != 0) {
  52. break;
  53. }
  54. }
  55. return (addr & 0x7ff) | (i << 11);
  56. }
  57. static void ppc_pci_io_write(void *opaque, hwaddr addr,
  58. uint64_t val, unsigned int size)
  59. {
  60. PREPPCIState *s = opaque;
  61. PCIHostState *phb = PCI_HOST_BRIDGE(s);
  62. pci_data_write(phb->bus, PPC_PCIIO_config(addr), val, size);
  63. }
  64. static uint64_t ppc_pci_io_read(void *opaque, hwaddr addr,
  65. unsigned int size)
  66. {
  67. PREPPCIState *s = opaque;
  68. PCIHostState *phb = PCI_HOST_BRIDGE(s);
  69. return pci_data_read(phb->bus, PPC_PCIIO_config(addr), size);
  70. }
  71. static const MemoryRegionOps PPC_PCIIO_ops = {
  72. .read = ppc_pci_io_read,
  73. .write = ppc_pci_io_write,
  74. .endianness = DEVICE_LITTLE_ENDIAN,
  75. };
  76. static uint64_t ppc_intack_read(void *opaque, hwaddr addr,
  77. unsigned int size)
  78. {
  79. return pic_read_irq(isa_pic);
  80. }
  81. static const MemoryRegionOps PPC_intack_ops = {
  82. .read = ppc_intack_read,
  83. .valid = {
  84. .max_access_size = 1,
  85. },
  86. };
  87. static int prep_map_irq(PCIDevice *pci_dev, int irq_num)
  88. {
  89. return (irq_num + (pci_dev->devfn >> 3)) & 1;
  90. }
  91. static void prep_set_irq(void *opaque, int irq_num, int level)
  92. {
  93. qemu_irq *pic = opaque;
  94. qemu_set_irq(pic[irq_num] , level);
  95. }
  96. static void raven_pcihost_realizefn(DeviceState *d, Error **errp)
  97. {
  98. SysBusDevice *dev = SYS_BUS_DEVICE(d);
  99. PCIHostState *h = PCI_HOST_BRIDGE(dev);
  100. PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(dev);
  101. MemoryRegion *address_space_mem = get_system_memory();
  102. int i;
  103. for (i = 0; i < 4; i++) {
  104. sysbus_init_irq(dev, &s->irq[i]);
  105. }
  106. pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4);
  107. memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s,
  108. "pci-conf-idx", 1);
  109. sysbus_add_io(dev, 0xcf8, &h->conf_mem);
  110. sysbus_init_ioports(&h->busdev, 0xcf8, 1);
  111. memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s,
  112. "pci-conf-data", 1);
  113. sysbus_add_io(dev, 0xcfc, &h->data_mem);
  114. sysbus_init_ioports(&h->busdev, 0xcfc, 1);
  115. memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000);
  116. memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg);
  117. memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1);
  118. memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack);
  119. /* TODO Remove once realize propagates to child devices. */
  120. object_property_set_bool(OBJECT(&s->pci_dev), true, "realized", errp);
  121. }
  122. static void raven_pcihost_initfn(Object *obj)
  123. {
  124. PCIHostState *h = PCI_HOST_BRIDGE(obj);
  125. PREPPCIState *s = RAVEN_PCI_HOST_BRIDGE(obj);
  126. MemoryRegion *address_space_mem = get_system_memory();
  127. MemoryRegion *address_space_io = get_system_io();
  128. DeviceState *pci_dev;
  129. pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
  130. address_space_mem, address_space_io, 0);
  131. h->bus = &s->pci_bus;
  132. object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE);
  133. pci_dev = DEVICE(&s->pci_dev);
  134. qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
  135. object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
  136. NULL);
  137. qdev_prop_set_bit(pci_dev, "multifunction", false);
  138. }
  139. static int raven_init(PCIDevice *d)
  140. {
  141. d->config[0x0C] = 0x08; // cache_line_size
  142. d->config[0x0D] = 0x10; // latency_timer
  143. d->config[0x34] = 0x00; // capabilities_pointer
  144. return 0;
  145. }
  146. static const VMStateDescription vmstate_raven = {
  147. .name = "raven",
  148. .version_id = 0,
  149. .minimum_version_id = 0,
  150. .fields = (VMStateField[]) {
  151. VMSTATE_PCI_DEVICE(dev, RavenPCIState),
  152. VMSTATE_END_OF_LIST()
  153. },
  154. };
  155. static void raven_class_init(ObjectClass *klass, void *data)
  156. {
  157. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  158. DeviceClass *dc = DEVICE_CLASS(klass);
  159. k->init = raven_init;
  160. k->vendor_id = PCI_VENDOR_ID_MOTOROLA;
  161. k->device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN;
  162. k->revision = 0x00;
  163. k->class_id = PCI_CLASS_BRIDGE_HOST;
  164. dc->desc = "PReP Host Bridge - Motorola Raven";
  165. dc->vmsd = &vmstate_raven;
  166. dc->no_user = 1;
  167. }
  168. static const TypeInfo raven_info = {
  169. .name = TYPE_RAVEN_PCI_DEVICE,
  170. .parent = TYPE_PCI_DEVICE,
  171. .instance_size = sizeof(RavenPCIState),
  172. .class_init = raven_class_init,
  173. };
  174. static void raven_pcihost_class_init(ObjectClass *klass, void *data)
  175. {
  176. DeviceClass *dc = DEVICE_CLASS(klass);
  177. dc->realize = raven_pcihost_realizefn;
  178. dc->fw_name = "pci";
  179. dc->no_user = 1;
  180. }
  181. static const TypeInfo raven_pcihost_info = {
  182. .name = TYPE_RAVEN_PCI_HOST_BRIDGE,
  183. .parent = TYPE_PCI_HOST_BRIDGE,
  184. .instance_size = sizeof(PREPPCIState),
  185. .instance_init = raven_pcihost_initfn,
  186. .class_init = raven_pcihost_class_init,
  187. };
  188. static void raven_register_types(void)
  189. {
  190. type_register_static(&raven_pcihost_info);
  191. type_register_static(&raven_info);
  192. }
  193. type_init(raven_register_types)