2
0

pci-hotplug.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * QEMU PCI hotplug support
  3. *
  4. * Copyright (c) 2004 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "boards.h"
  26. #include "pci.h"
  27. #include "net.h"
  28. #include "sysemu.h"
  29. #include "pc.h"
  30. #include "console.h"
  31. #include "block_int.h"
  32. #include "virtio-blk.h"
  33. #if defined(TARGET_I386) || defined(TARGET_X86_64)
  34. static PCIDevice *qemu_pci_hot_add_nic(PCIBus *pci_bus, const char *opts)
  35. {
  36. int ret;
  37. ret = net_client_init("nic", opts);
  38. if (ret < 0)
  39. return NULL;
  40. return pci_nic_init(pci_bus, &nd_table[ret], -1, "rtl8139");
  41. }
  42. void drive_hot_add(const char *pci_addr, const char *opts)
  43. {
  44. int dom, pci_bus;
  45. unsigned slot;
  46. int drive_idx, type, bus;
  47. int success = 0;
  48. PCIDevice *dev;
  49. if (pci_read_devaddr(pci_addr, &dom, &pci_bus, &slot)) {
  50. term_printf("Invalid pci address\n");
  51. return;
  52. }
  53. dev = pci_find_device(pci_bus, slot, 0);
  54. if (!dev) {
  55. term_printf("no pci device with address %s\n", pci_addr);
  56. return;
  57. }
  58. drive_idx = add_init_drive(opts);
  59. if (drive_idx < 0)
  60. return;
  61. type = drives_table[drive_idx].type;
  62. bus = drive_get_max_bus (type);
  63. switch (type) {
  64. case IF_SCSI:
  65. success = 1;
  66. lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
  67. drives_table[drive_idx].unit);
  68. break;
  69. default:
  70. term_printf("Can't hot-add drive to type %d\n", type);
  71. }
  72. if (success)
  73. term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
  74. drives_table[drive_idx].unit);
  75. return;
  76. }
  77. static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
  78. {
  79. void *opaque = NULL;
  80. int type = -1, drive_idx = -1;
  81. char buf[128];
  82. if (get_param_value(buf, sizeof(buf), "if", opts)) {
  83. if (!strcmp(buf, "scsi"))
  84. type = IF_SCSI;
  85. else if (!strcmp(buf, "virtio")) {
  86. type = IF_VIRTIO;
  87. } else {
  88. term_printf("type %s not a hotpluggable PCI device.\n", buf);
  89. goto out;
  90. }
  91. } else {
  92. term_printf("no if= specified\n");
  93. goto out;
  94. }
  95. if (get_param_value(buf, sizeof(buf), "file", opts)) {
  96. drive_idx = add_init_drive(opts);
  97. if (drive_idx < 0)
  98. goto out;
  99. } else if (type == IF_VIRTIO) {
  100. term_printf("virtio requires a backing file/device.\n");
  101. goto out;
  102. }
  103. switch (type) {
  104. case IF_SCSI:
  105. opaque = lsi_scsi_init (pci_bus, -1);
  106. if (opaque && drive_idx >= 0)
  107. lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
  108. drives_table[drive_idx].unit);
  109. break;
  110. case IF_VIRTIO:
  111. opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
  112. break;
  113. }
  114. out:
  115. return opaque;
  116. }
  117. void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts)
  118. {
  119. PCIDevice *dev = NULL;
  120. PCIBus *pci_bus;
  121. int dom, bus;
  122. unsigned slot;
  123. if (pci_assign_devaddr(pci_addr, &dom, &bus, &slot)) {
  124. term_printf("Invalid pci address\n");
  125. return;
  126. }
  127. pci_bus = pci_find_bus(bus);
  128. if (!pci_bus) {
  129. term_printf("Can't find pci_bus %d\n", bus);
  130. return;
  131. }
  132. if (strcmp(type, "nic") == 0)
  133. dev = qemu_pci_hot_add_nic(pci_bus, opts);
  134. else if (strcmp(type, "storage") == 0)
  135. dev = qemu_pci_hot_add_storage(pci_bus, opts);
  136. else
  137. term_printf("invalid type: %s\n", type);
  138. if (dev) {
  139. qemu_system_device_hot_add(bus, PCI_SLOT(dev->devfn), 1);
  140. term_printf("OK domain %d, bus %d, slot %d, function %d\n",
  141. 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
  142. PCI_FUNC(dev->devfn));
  143. } else
  144. term_printf("failed to add %s\n", opts);
  145. }
  146. #endif
  147. void pci_device_hot_remove(const char *pci_addr)
  148. {
  149. PCIDevice *d;
  150. int dom, bus;
  151. unsigned slot;
  152. if (pci_read_devaddr(pci_addr, &dom, &bus, &slot)) {
  153. term_printf("Invalid pci address\n");
  154. return;
  155. }
  156. d = pci_find_device(bus, slot, 0);
  157. if (!d) {
  158. term_printf("slot %d empty\n", slot);
  159. return;
  160. }
  161. qemu_system_device_hot_add(bus, slot, 0);
  162. }
  163. static int pci_match_fn(void *dev_private, void *arg)
  164. {
  165. PCIDevice *dev = dev_private;
  166. PCIDevice *match = arg;
  167. return (dev == match);
  168. }
  169. /*
  170. * OS has executed _EJ0 method, we now can remove the device
  171. */
  172. void pci_device_hot_remove_success(int pcibus, int slot)
  173. {
  174. PCIDevice *d = pci_find_device(pcibus, slot, 0);
  175. int class_code;
  176. if (!d) {
  177. term_printf("invalid slot %d\n", slot);
  178. return;
  179. }
  180. class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
  181. switch(class_code) {
  182. case PCI_BASE_CLASS_STORAGE:
  183. destroy_bdrvs(pci_match_fn, d);
  184. break;
  185. case PCI_BASE_CLASS_NETWORK:
  186. destroy_nic(pci_match_fn, d);
  187. break;
  188. }
  189. pci_unregister_device(d);
  190. }