kvm: testsuite: add minimal big real mode entry/exit
[qemu-kvm/fedora.git] / hw / device-hotplug.c
blob8e2bc35690a3d17d92017684230598fd5323fca8
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"
8 #include "block_int.h"
10 #define PCI_BASE_CLASS_STORAGE 0x01
11 #define PCI_BASE_CLASS_NETWORK 0x02
13 static PCIDevice *qemu_system_hot_add_nic(const char *opts, int bus_nr)
15 int ret;
16 PCIBus *pci_bus;
18 pci_bus = pci_find_bus (bus_nr);
19 if (!pci_bus) {
20 term_printf ("Can't find pci_bus %d\n", bus_nr);
21 return NULL;
24 ret = net_client_init ("nic", opts);
25 if (ret < 0 || !nd_table[ret].model)
26 return NULL;
27 return pci_nic_init (pci_bus, &nd_table[ret], -1);
30 static int add_init_drive(const char *opts)
32 int drive_opt_idx, drive_idx;
33 int ret = -1;
35 drive_opt_idx = drive_add(NULL, "%s", opts);
36 if (!drive_opt_idx)
37 return ret;
39 drive_idx = drive_init(&drives_opt[drive_opt_idx], 0, current_machine);
40 if (drive_idx == -1) {
41 drive_remove(drive_opt_idx);
42 return ret;
45 return drive_idx;
48 void drive_hot_add(int pcibus, const char *devfn_string, const char *opts)
50 int drive_idx, type, bus;
51 int devfn;
52 int success = 0;
53 PCIDevice *dev;
55 devfn = strtoul(devfn_string, NULL, 0);
57 dev = pci_find_device(pcibus, PCI_SLOT(devfn));
58 if (!dev) {
59 term_printf("no pci device with devfn %d (slot %d)\n", devfn,
60 PCI_SLOT(devfn));
61 return;
64 drive_idx = add_init_drive(opts);
65 if (drive_idx < 0)
66 return;
67 type = drives_table[drive_idx].type;
68 bus = drive_get_max_bus (type);
70 switch (type) {
71 case IF_SCSI:
72 success = 1;
73 lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
74 drives_table[drive_idx].unit);
75 break;
76 default:
77 term_printf("Can't hot-add drive to type %d\n", type);
80 if (success)
81 term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
82 drives_table[drive_idx].unit);
83 return;
86 static PCIDevice *qemu_system_hot_add_storage(const char *opts, int bus_nr)
88 void *opaque = NULL;
89 PCIBus *pci_bus;
90 int type = -1, drive_idx = -1;
91 char buf[128];
93 pci_bus = pci_find_bus(bus_nr);
94 if (!pci_bus) {
95 term_printf("Can't find pci_bus %d\n", bus_nr);
96 return NULL;
99 if (get_param_value(buf, sizeof(buf), "if", opts)) {
100 if (!strcmp(buf, "scsi"))
101 type = IF_SCSI;
102 else if (!strcmp(buf, "virtio")) {
103 type = IF_VIRTIO;
105 } else {
106 term_printf("no if= specified\n");
107 return NULL;
110 if (get_param_value(buf, sizeof(buf), "file", opts)) {
111 drive_idx = add_init_drive(opts);
112 if (drive_idx < 0)
113 return NULL;
114 } else if (type == IF_VIRTIO) {
115 term_printf("virtio requires a backing file/device.\n");
116 return NULL;
119 switch (type) {
120 case IF_SCSI:
121 opaque = lsi_scsi_init (pci_bus, -1);
122 if (opaque && drive_idx >= 0)
123 lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
124 drives_table[drive_idx].unit);
125 break;
126 case IF_VIRTIO:
127 opaque = virtio_blk_init (pci_bus, 0x1AF4, 0x1001,
128 drives_table[drive_idx].bdrv);
129 break;
130 default:
131 term_printf ("type %s not a hotpluggable PCI device.\n", buf);
134 return opaque;
137 #if defined(TARGET_I386) || defined(TARGET_X86_64)
138 void device_hot_add(int pcibus, const char *type, const char *opts)
140 PCIDevice *dev = NULL;
142 if (strcmp(type, "nic") == 0)
143 dev = qemu_system_hot_add_nic(opts, pcibus);
144 else if (strcmp(type, "storage") == 0)
145 dev = qemu_system_hot_add_storage(opts, pcibus);
146 else
147 term_printf("invalid type: %s\n", type);
149 if (dev) {
150 qemu_system_device_hot_add(pcibus, PCI_SLOT(dev->devfn), 1);
151 term_printf("OK bus %d, slot %d, function %d (devfn %d)\n",
152 pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
153 PCI_FUNC(dev->devfn), dev->devfn);
154 } else
155 term_printf("failed to add %s\n", opts);
158 void device_hot_remove(int pcibus, int slot)
160 PCIDevice *d = pci_find_device(pcibus, slot);
162 if (!d) {
163 term_printf("invalid slot %d\n", slot);
164 return;
167 qemu_system_device_hot_add(pcibus, slot, 0);
169 #endif
171 static void destroy_nic(int slot)
173 int i;
175 for (i = 0; i < MAX_NICS; i++)
176 if (nd_table[i].used &&
177 PCI_SLOT(nd_table[i].devfn) == slot)
178 net_client_uninit(&nd_table[i]);
181 static void destroy_bdrvs(int slot)
183 int i;
184 struct BlockDriverState *bs;
186 for (i = 0; i <= MAX_DRIVES; i++) {
187 bs = drives_table[i].bdrv;
188 if (bs && (PCI_SLOT(bs->devfn) == slot)) {
189 drive_uninit(bs);
190 bdrv_delete(bs);
196 * OS has executed _EJ0 method, we now can remove the device
198 void device_hot_remove_success(int pcibus, int slot)
200 PCIDevice *d = pci_find_device(pcibus, slot);
201 int class_code;
203 if (!d) {
204 term_printf("invalid slot %d\n", slot);
205 return;
208 class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
210 pci_unregister_device(d);
212 switch(class_code) {
213 case PCI_BASE_CLASS_STORAGE:
214 destroy_bdrvs(slot);
215 break;
216 case PCI_BASE_CLASS_NETWORK:
217 destroy_nic(slot);
218 break;