]> Git Repo - qemu.git/blob - hw/pci-hotplug.c
kill dead nic unplug code.
[qemu.git] / hw / pci-hotplug.c
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
25 #include "hw.h"
26 #include "boards.h"
27 #include "pci.h"
28 #include "net.h"
29 #include "sysemu.h"
30 #include "pc.h"
31 #include "monitor.h"
32 #include "block_int.h"
33 #include "scsi-disk.h"
34 #include "virtio-blk.h"
35 #include "qemu-config.h"
36
37 #if defined(TARGET_I386)
38 static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
39                                        const char *devaddr,
40                                        const char *opts_str)
41 {
42     QemuOpts *opts;
43     int ret;
44
45     opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
46     if (!opts) {
47         monitor_printf(mon, "parsing network options '%s' failed\n",
48                        opts_str ? opts_str : "");
49         return NULL;
50     }
51
52     qemu_opt_set(opts, "type", "nic");
53
54     ret = net_client_init(mon, opts, 0);
55     if (ret < 0)
56         return NULL;
57     if (nd_table[ret].devaddr) {
58         monitor_printf(mon, "Parameter addr not supported\n");
59         return NULL;
60     }
61     return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
62 }
63
64 void drive_hot_add(Monitor *mon, const QDict *qdict)
65 {
66     int dom, pci_bus;
67     unsigned slot;
68     int type, bus;
69     PCIDevice *dev;
70     DriveInfo *dinfo = NULL;
71     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
72     const char *opts = qdict_get_str(qdict, "opts");
73     BusState *scsibus;
74
75     dinfo = add_init_drive(opts);
76     if (!dinfo)
77         goto err;
78     if (dinfo->devaddr) {
79         monitor_printf(mon, "Parameter addr not supported\n");
80         goto err;
81     }
82     type = dinfo->type;
83     bus = drive_get_max_bus (type);
84
85     switch (type) {
86     case IF_SCSI:
87         if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
88             goto err;
89         }
90         dev = pci_find_device(pci_bus, slot, 0);
91         if (!dev) {
92             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
93             goto err;
94         }
95         scsibus = QLIST_FIRST(&dev->qdev.child_bus);
96         scsi_bus_legacy_add_drive(DO_UPCAST(SCSIBus, qbus, scsibus),
97                                   dinfo, dinfo->unit);
98         monitor_printf(mon, "OK bus %d, unit %d\n",
99                        dinfo->bus,
100                        dinfo->unit);
101         break;
102     case IF_NONE:
103         monitor_printf(mon, "OK\n");
104         break;
105     default:
106         monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
107         goto err;
108     }
109     return;
110
111 err:
112     if (dinfo)
113         drive_uninit(dinfo);
114     return;
115 }
116
117 static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
118                                            const char *devaddr,
119                                            const char *opts)
120 {
121     PCIDevice *dev;
122     DriveInfo *dinfo = NULL;
123     int type = -1;
124     char buf[128];
125     PCIBus *bus;
126     int devfn;
127
128     if (get_param_value(buf, sizeof(buf), "if", opts)) {
129         if (!strcmp(buf, "scsi"))
130             type = IF_SCSI;
131         else if (!strcmp(buf, "virtio")) {
132             type = IF_VIRTIO;
133         } else {
134             monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf);
135             return NULL;
136         }
137     } else {
138         monitor_printf(mon, "no if= specified\n");
139         return NULL;
140     }
141
142     if (get_param_value(buf, sizeof(buf), "file", opts)) {
143         dinfo = add_init_drive(opts);
144         if (!dinfo)
145             return NULL;
146         if (dinfo->devaddr) {
147             monitor_printf(mon, "Parameter addr not supported\n");
148             return NULL;
149         }
150     } else {
151         dinfo = NULL;
152     }
153
154     bus = pci_get_bus_devfn(&devfn, devaddr);
155     if (!bus) {
156         monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
157         return NULL;
158     }
159
160     switch (type) {
161     case IF_SCSI:
162         dev = pci_create(bus, devfn, "lsi53c895a");
163         break;
164     case IF_VIRTIO:
165         if (!dinfo) {
166             monitor_printf(mon, "virtio requires a backing file/device.\n");
167             return NULL;
168         }
169         dev = pci_create(bus, devfn, "virtio-blk-pci");
170         qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
171         break;
172     default:
173         dev = NULL;
174     }
175     if (!dev || qdev_init(&dev->qdev) < 0)
176         return NULL;
177     return dev;
178 }
179
180 void pci_device_hot_add(Monitor *mon, const QDict *qdict)
181 {
182     PCIDevice *dev = NULL;
183     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
184     const char *type = qdict_get_str(qdict, "type");
185     const char *opts = qdict_get_try_str(qdict, "opts");
186
187     /* strip legacy tag */
188     if (!strncmp(pci_addr, "pci_addr=", 9)) {
189         pci_addr += 9;
190     }
191
192     if (!opts) {
193         opts = "";
194     }
195
196     if (!strcmp(pci_addr, "auto"))
197         pci_addr = NULL;
198
199     if (strcmp(type, "nic") == 0)
200         dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
201     else if (strcmp(type, "storage") == 0)
202         dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
203     else
204         monitor_printf(mon, "invalid type: %s\n", type);
205
206     if (dev) {
207         monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
208                        0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
209                        PCI_FUNC(dev->devfn));
210     } else
211         monitor_printf(mon, "failed to add %s\n", opts);
212 }
213 #endif
214
215 void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
216 {
217     PCIDevice *d;
218     int dom, bus;
219     unsigned slot;
220
221     if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
222         return;
223     }
224
225     d = pci_find_device(bus, slot, 0);
226     if (!d) {
227         monitor_printf(mon, "slot %d empty\n", slot);
228         return;
229     }
230     qdev_unplug(&d->qdev);
231 }
232
233 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict)
234 {
235     pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
236 }
This page took 0.037022 seconds and 4 git commands to generate.