Annotation of qemu/hw/pci-hotplug.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.