|
|
1.1 root 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"
1.1.1.4 ! root 31: #include "monitor.h"
1.1 root 32: #include "block_int.h"
33: #include "virtio-blk.h"
34:
35: #if defined(TARGET_I386) || defined(TARGET_X86_64)
1.1.1.4 ! root 36: static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
! 37: const char *devaddr, const char *opts)
1.1 root 38: {
39: int ret;
40:
1.1.1.4 ! root 41: ret = net_client_init(mon, "nic", opts);
1.1.1.3 root 42: if (ret < 0)
1.1 root 43: return NULL;
1.1.1.4 ! root 44: if (nd_table[ret].devaddr) {
! 45: monitor_printf(mon, "Parameter addr not supported\n");
! 46: return NULL;
! 47: }
! 48: return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
1.1 root 49: }
50:
1.1.1.4 ! root 51: void drive_hot_add(Monitor *mon, const char *pci_addr, const char *opts)
1.1 root 52: {
53: int dom, pci_bus;
54: unsigned slot;
55: int drive_idx, type, bus;
56: int success = 0;
57: PCIDevice *dev;
58:
1.1.1.4 ! root 59: if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
1.1 root 60: return;
61: }
62:
63: dev = pci_find_device(pci_bus, slot, 0);
64: if (!dev) {
1.1.1.4 ! root 65: monitor_printf(mon, "no pci device with address %s\n", pci_addr);
1.1 root 66: return;
67: }
68:
69: drive_idx = add_init_drive(opts);
70: if (drive_idx < 0)
71: return;
1.1.1.4 ! root 72: if (drives_table[drive_idx].devaddr) {
! 73: monitor_printf(mon, "Parameter addr not supported\n");
! 74: return;
! 75: }
1.1 root 76: type = drives_table[drive_idx].type;
77: bus = drive_get_max_bus (type);
78:
79: switch (type) {
80: case IF_SCSI:
81: success = 1;
1.1.1.4 ! root 82: lsi_scsi_attach(&dev->qdev, drives_table[drive_idx].bdrv,
! 83: drives_table[drive_idx].unit);
1.1 root 84: break;
85: default:
1.1.1.4 ! root 86: monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
1.1 root 87: }
88:
89: if (success)
1.1.1.4 ! root 90: monitor_printf(mon, "OK bus %d, unit %d\n",
! 91: drives_table[drive_idx].bus,
! 92: drives_table[drive_idx].unit);
1.1 root 93: return;
94: }
95:
1.1.1.4 ! root 96: static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
! 97: const char *devaddr,
! 98: const char *opts)
1.1 root 99: {
1.1.1.4 ! root 100: PCIDevice *dev;
1.1 root 101: int type = -1, drive_idx = -1;
102: char buf[128];
103:
104: if (get_param_value(buf, sizeof(buf), "if", opts)) {
105: if (!strcmp(buf, "scsi"))
106: type = IF_SCSI;
107: else if (!strcmp(buf, "virtio")) {
108: type = IF_VIRTIO;
1.1.1.2 root 109: } else {
1.1.1.4 ! root 110: monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf);
! 111: return NULL;
1.1 root 112: }
113: } else {
1.1.1.4 ! root 114: monitor_printf(mon, "no if= specified\n");
! 115: return NULL;
1.1 root 116: }
117:
118: if (get_param_value(buf, sizeof(buf), "file", opts)) {
119: drive_idx = add_init_drive(opts);
120: if (drive_idx < 0)
1.1.1.4 ! root 121: return NULL;
! 122: if (drives_table[drive_idx].devaddr) {
! 123: monitor_printf(mon, "Parameter addr not supported\n");
! 124: return NULL;
! 125: }
1.1 root 126: } else if (type == IF_VIRTIO) {
1.1.1.4 ! root 127: monitor_printf(mon, "virtio requires a backing file/device.\n");
! 128: return NULL;
1.1 root 129: }
130:
131: switch (type) {
132: case IF_SCSI:
1.1.1.4 ! root 133: dev = pci_create("lsi53c895a", devaddr);
1.1 root 134: break;
135: case IF_VIRTIO:
1.1.1.4 ! root 136: dev = pci_create("virtio-blk-pci", devaddr);
1.1 root 137: break;
1.1.1.4 ! root 138: default:
! 139: dev = NULL;
1.1 root 140: }
1.1.1.4 ! root 141: if (dev)
! 142: qdev_init(&dev->qdev);
! 143: return dev;
1.1 root 144: }
145:
1.1.1.4 ! root 146: void pci_device_hot_add(Monitor *mon, const char *pci_addr, const char *type,
! 147: const char *opts)
1.1 root 148: {
149: PCIDevice *dev = NULL;
150:
1.1.1.4 ! root 151: /* strip legacy tag */
! 152: if (!strncmp(pci_addr, "pci_addr=", 9)) {
! 153: pci_addr += 9;
1.1 root 154: }
155:
1.1.1.4 ! root 156: if (!opts) {
! 157: opts = "";
1.1 root 158: }
159:
1.1.1.4 ! root 160: if (!strcmp(pci_addr, "auto"))
! 161: pci_addr = NULL;
! 162:
1.1 root 163: if (strcmp(type, "nic") == 0)
1.1.1.4 ! root 164: dev = qemu_pci_hot_add_nic(mon, pci_addr, opts);
1.1 root 165: else if (strcmp(type, "storage") == 0)
1.1.1.4 ! root 166: dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
1.1 root 167: else
1.1.1.4 ! root 168: monitor_printf(mon, "invalid type: %s\n", type);
1.1 root 169:
170: if (dev) {
1.1.1.4 ! root 171: qemu_system_device_hot_add(pci_bus_num(dev->bus),
! 172: PCI_SLOT(dev->devfn), 1);
! 173: monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
! 174: 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
! 175: PCI_FUNC(dev->devfn));
1.1 root 176: } else
1.1.1.4 ! root 177: monitor_printf(mon, "failed to add %s\n", opts);
1.1 root 178: }
179: #endif
180:
1.1.1.4 ! root 181: void pci_device_hot_remove(Monitor *mon, const char *pci_addr)
1.1 root 182: {
183: PCIDevice *d;
184: int dom, bus;
185: unsigned slot;
186:
1.1.1.4 ! root 187: if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
1.1 root 188: return;
189: }
190:
191: d = pci_find_device(bus, slot, 0);
192: if (!d) {
1.1.1.4 ! root 193: monitor_printf(mon, "slot %d empty\n", slot);
1.1 root 194: return;
195: }
196:
197: qemu_system_device_hot_add(bus, slot, 0);
198: }
199:
200: static int pci_match_fn(void *dev_private, void *arg)
201: {
202: PCIDevice *dev = dev_private;
203: PCIDevice *match = arg;
204:
205: return (dev == match);
206: }
207:
208: /*
209: * OS has executed _EJ0 method, we now can remove the device
210: */
211: void pci_device_hot_remove_success(int pcibus, int slot)
212: {
213: PCIDevice *d = pci_find_device(pcibus, slot, 0);
214: int class_code;
215:
216: if (!d) {
1.1.1.4 ! root 217: monitor_printf(cur_mon, "invalid slot %d\n", slot);
1.1 root 218: return;
219: }
220:
221: class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
222:
223: switch(class_code) {
224: case PCI_BASE_CLASS_STORAGE:
225: destroy_bdrvs(pci_match_fn, d);
226: break;
227: case PCI_BASE_CLASS_NETWORK:
228: destroy_nic(pci_match_fn, d);
229: break;
230: }
231:
232: pci_unregister_device(d);
233: }
234:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.