kvm: qemu: device and disk hot-add
[kvm-userspace.git] / qemu / hw / device-hotplug.c
blob02e3e17290373989423d5f86e15d6f2fe16e7d70
1 #include "hw.h"
2 #include "boards.h"
3 #include "pci.h"
4 #include "net.h"
5 #include "sysemu.h"
6 #include "pc.h"
7 #include "console.h"
9 static PCIDevice *qemu_system_hot_add_nic(const char *opts, int bus_nr)
11 int ret;
12 char buf[4096];
13 PCIBus *pci_bus;
15 pci_bus = pci_find_bus (bus_nr);
16 if (!pci_bus) {
17 term_printf ("Can't find pci_bus %d\n", bus_nr);
18 return NULL;
21 memset (buf, 0, sizeof (buf));
23 strcpy (buf, "nic,");
24 strncat (buf, opts, sizeof (buf) - strlen (buf) - 1);
26 ret = net_client_init (buf);
27 if (ret < 0 || !nd_table[ret].model)
28 return NULL;
29 return pci_nic_init (pci_bus, &nd_table[ret], -1);
32 static int add_init_drive(const char *opts)
34 int drive_opt_idx, drive_idx;
35 int ret = -1;
37 drive_opt_idx = drive_add(NULL, "%s", opts);
38 if (!drive_opt_idx)
39 return ret;
41 drive_idx = drive_init(&drives_opt[drive_opt_idx], 0, current_machine);
42 if (drive_idx == -1) {
43 drive_remove(drive_opt_idx);
44 return ret;
47 return drive_idx;
50 void drive_hot_add(int pcibus, const char *devfn_string, const char *opts)
52 int drive_idx, type, bus;
53 int devfn;
54 int success = 0;
55 PCIDevice *dev;
57 devfn = strtoul(devfn_string, NULL, 0);
59 dev = pci_find_device(pcibus, PCI_SLOT(devfn));
60 if (!dev) {
61 term_printf("no pci device with devfn %d (slot %d)\n", devfn,
62 PCI_SLOT(devfn));
63 return;
66 drive_idx = add_init_drive(opts);
67 if (drive_idx < 0)
68 return;
69 type = drives_table[drive_idx].type;
70 bus = drive_get_max_bus (type);
72 switch (type) {
73 case IF_SCSI:
74 success = 1;
75 lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
76 drives_table[drive_idx].unit);
77 break;
78 default:
79 term_printf("Can't hot-add drive to type %d\n", type);
82 if (success)
83 term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
84 drives_table[drive_idx].unit);
85 return;
88 static PCIDevice *qemu_system_hot_add_storage(const char *opts, int bus_nr)
90 void *opaque = NULL;
91 PCIBus *pci_bus;
92 int type = -1, drive_idx = -1;
93 char buf[128];
95 pci_bus = pci_find_bus(bus_nr);
96 if (!pci_bus) {
97 term_printf("Can't find pci_bus %d\n", bus_nr);
98 return NULL;
101 if (get_param_value(buf, sizeof(buf), "if", opts)) {
102 if (!strcmp(buf, "scsi"))
103 type = IF_SCSI;
104 else if (!strcmp(buf, "virtio")) {
105 type = IF_VIRTIO;
107 } else {
108 term_printf("no if= specified\n");
109 return NULL;
112 if (get_param_value(buf, sizeof(buf), "file", opts)) {
113 drive_idx = add_init_drive(opts);
114 if (drive_idx < 0)
115 return NULL;
116 } else if (type == IF_VIRTIO) {
117 term_printf("virtio requires a backing file/device.\n");
118 return NULL;
121 switch (type) {
122 case IF_SCSI:
123 opaque = lsi_scsi_init (pci_bus, -1);
124 if (drive_idx >= 0)
125 lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
126 drives_table[drive_idx].unit);
127 break;
128 case IF_VIRTIO:
129 opaque = virtio_blk_init (pci_bus, 0x1AF4, 0x1001,
130 drives_table[drive_idx].bdrv);
131 break;
132 default:
133 term_printf ("type %s not a hotpluggable PCI device.\n", buf);
136 return opaque;
139 void device_hot_add(int pcibus, const char *type, const char *opts)
141 PCIDevice *dev = NULL;
143 if (strcmp(type, "nic") == 0)
144 dev = qemu_system_hot_add_nic(opts, pcibus);
145 else if (strcmp(type, "storage") == 0)
146 dev = qemu_system_hot_add_storage(opts, pcibus);
147 else
148 term_printf("invalid type: %s\n", type);
150 if (dev) {
151 qemu_system_device_hot_add(PCI_SLOT(dev->devfn), 1);
152 term_printf("OK bus %d, slot %d, function %d (devfn %d)\n",
153 pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
154 PCI_FUNC(dev->devfn), dev->devfn);
155 } else
156 term_printf("failed to add %s\n", opts);