isa-bus.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * isa bus support for qdev.
  3. *
  4. * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "hw.h"
  20. #include "monitor.h"
  21. #include "sysbus.h"
  22. #include "isa.h"
  23. struct ISABus {
  24. BusState qbus;
  25. qemu_irq *irqs;
  26. };
  27. static ISABus *isabus;
  28. target_phys_addr_t isa_mem_base = 0;
  29. static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
  30. static char *isabus_get_fw_dev_path(DeviceState *dev);
  31. static struct BusInfo isa_bus_info = {
  32. .name = "ISA",
  33. .size = sizeof(ISABus),
  34. .print_dev = isabus_dev_print,
  35. .get_fw_dev_path = isabus_get_fw_dev_path,
  36. };
  37. ISABus *isa_bus_new(DeviceState *dev)
  38. {
  39. if (isabus) {
  40. fprintf(stderr, "Can't create a second ISA bus\n");
  41. return NULL;
  42. }
  43. if (NULL == dev) {
  44. dev = qdev_create(NULL, "isabus-bridge");
  45. qdev_init_nofail(dev);
  46. }
  47. isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL));
  48. return isabus;
  49. }
  50. void isa_bus_irqs(qemu_irq *irqs)
  51. {
  52. isabus->irqs = irqs;
  53. }
  54. /*
  55. * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
  56. *
  57. * This function is only for special cases such as the 'ferr', and
  58. * temporary use for normal devices until they are converted to qdev.
  59. */
  60. qemu_irq isa_get_irq(int isairq)
  61. {
  62. if (isairq < 0 || isairq > 15) {
  63. hw_error("isa irq %d invalid", isairq);
  64. }
  65. return isabus->irqs[isairq];
  66. }
  67. void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
  68. {
  69. assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
  70. dev->isairq[dev->nirqs] = isairq;
  71. *p = isa_get_irq(isairq);
  72. dev->nirqs++;
  73. }
  74. static void isa_init_ioport_one(ISADevice *dev, uint16_t ioport)
  75. {
  76. assert(dev->nioports < ARRAY_SIZE(dev->ioports));
  77. dev->ioports[dev->nioports++] = ioport;
  78. }
  79. static int isa_cmp_ports(const void *p1, const void *p2)
  80. {
  81. return *(uint16_t*)p1 - *(uint16_t*)p2;
  82. }
  83. void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length)
  84. {
  85. int i;
  86. for (i = start; i < start + length; i++) {
  87. isa_init_ioport_one(dev, i);
  88. }
  89. qsort(dev->ioports, dev->nioports, sizeof(dev->ioports[0]), isa_cmp_ports);
  90. }
  91. void isa_init_ioport(ISADevice *dev, uint16_t ioport)
  92. {
  93. isa_init_ioport_range(dev, ioport, 1);
  94. }
  95. static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
  96. {
  97. ISADevice *dev = DO_UPCAST(ISADevice, qdev, qdev);
  98. ISADeviceInfo *info = DO_UPCAST(ISADeviceInfo, qdev, base);
  99. dev->isairq[0] = -1;
  100. dev->isairq[1] = -1;
  101. return info->init(dev);
  102. }
  103. void isa_qdev_register(ISADeviceInfo *info)
  104. {
  105. info->qdev.init = isa_qdev_init;
  106. info->qdev.bus_info = &isa_bus_info;
  107. qdev_register(&info->qdev);
  108. }
  109. ISADevice *isa_create(const char *name)
  110. {
  111. DeviceState *dev;
  112. if (!isabus) {
  113. hw_error("Tried to create isa device %s with no isa bus present.",
  114. name);
  115. }
  116. dev = qdev_create(&isabus->qbus, name);
  117. return DO_UPCAST(ISADevice, qdev, dev);
  118. }
  119. ISADevice *isa_try_create(const char *name)
  120. {
  121. DeviceState *dev;
  122. if (!isabus) {
  123. hw_error("Tried to create isa device %s with no isa bus present.",
  124. name);
  125. }
  126. dev = qdev_try_create(&isabus->qbus, name);
  127. return DO_UPCAST(ISADevice, qdev, dev);
  128. }
  129. ISADevice *isa_create_simple(const char *name)
  130. {
  131. ISADevice *dev;
  132. dev = isa_create(name);
  133. qdev_init_nofail(&dev->qdev);
  134. return dev;
  135. }
  136. static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
  137. {
  138. ISADevice *d = DO_UPCAST(ISADevice, qdev, dev);
  139. if (d->isairq[1] != -1) {
  140. monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
  141. d->isairq[0], d->isairq[1]);
  142. } else if (d->isairq[0] != -1) {
  143. monitor_printf(mon, "%*sisa irq %d\n", indent, "",
  144. d->isairq[0]);
  145. }
  146. }
  147. static int isabus_bridge_init(SysBusDevice *dev)
  148. {
  149. /* nothing */
  150. return 0;
  151. }
  152. static SysBusDeviceInfo isabus_bridge_info = {
  153. .init = isabus_bridge_init,
  154. .qdev.name = "isabus-bridge",
  155. .qdev.fw_name = "isa",
  156. .qdev.size = sizeof(SysBusDevice),
  157. .qdev.no_user = 1,
  158. };
  159. static void isabus_register_devices(void)
  160. {
  161. sysbus_register_withprop(&isabus_bridge_info);
  162. }
  163. static char *isabus_get_fw_dev_path(DeviceState *dev)
  164. {
  165. ISADevice *d = (ISADevice*)dev;
  166. char path[40];
  167. int off;
  168. off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
  169. if (d->nioports) {
  170. snprintf(path + off, sizeof(path) - off, "@%04x", d->ioports[0]);
  171. }
  172. return strdup(path);
  173. }
  174. device_init(isabus_register_devices)