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

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;
                     98:         }
                     99:     } else {
                    100:         term_printf("no if= specified\n");
                    101:         return NULL;
                    102:     }
                    103: 
                    104:     if (get_param_value(buf, sizeof(buf), "file", opts)) {
                    105:         drive_idx = add_init_drive(opts);
                    106:         if (drive_idx < 0)
                    107:             return NULL;
                    108:     } else if (type == IF_VIRTIO) {
                    109:         term_printf("virtio requires a backing file/device.\n");
                    110:         return NULL;
                    111:     }
                    112: 
                    113:     switch (type) {
                    114:     case IF_SCSI:
                    115:         opaque = lsi_scsi_init (pci_bus, -1);
                    116:         if (opaque && drive_idx >= 0)
                    117:             lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
                    118:                              drives_table[drive_idx].unit);
                    119:         break;
                    120:     case IF_VIRTIO:
                    121:         opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
                    122:         break;
                    123:     default:
                    124:         term_printf ("type %s not a hotpluggable PCI device.\n", buf);
                    125:     }
                    126: 
                    127:     return opaque;
                    128: }
                    129: 
                    130: void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts)
                    131: {
                    132:     PCIDevice *dev = NULL;
                    133:     PCIBus *pci_bus;
                    134:     int dom, bus;
                    135:     unsigned slot;
                    136: 
                    137:     if (pci_assign_devaddr(pci_addr, &dom, &bus, &slot)) {
                    138:         term_printf("Invalid pci address\n");
                    139:         return;
                    140:     }
                    141: 
                    142:     pci_bus = pci_find_bus(bus);
                    143:     if (!pci_bus) {
                    144:         term_printf("Can't find pci_bus %d\n", bus);
                    145:         return;
                    146:     }
                    147: 
                    148:     if (strcmp(type, "nic") == 0)
                    149:         dev = qemu_pci_hot_add_nic(pci_bus, opts);
                    150:     else if (strcmp(type, "storage") == 0)
                    151:         dev = qemu_pci_hot_add_storage(pci_bus, opts);
                    152:     else
                    153:         term_printf("invalid type: %s\n", type);
                    154: 
                    155:     if (dev) {
                    156:         qemu_system_device_hot_add(bus, PCI_SLOT(dev->devfn), 1);
                    157:         term_printf("OK domain %d, bus %d, slot %d, function %d\n",
                    158:                     0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
                    159:                     PCI_FUNC(dev->devfn));
                    160:     } else
                    161:         term_printf("failed to add %s\n", opts);
                    162: }
                    163: #endif
                    164: 
                    165: void pci_device_hot_remove(const char *pci_addr)
                    166: {
                    167:     PCIDevice *d;
                    168:     int dom, bus;
                    169:     unsigned slot;
                    170: 
                    171:     if (pci_read_devaddr(pci_addr, &dom, &bus, &slot)) {
                    172:         term_printf("Invalid pci address\n");
                    173:         return;
                    174:     }
                    175: 
                    176:     d = pci_find_device(bus, slot, 0);
                    177:     if (!d) {
                    178:         term_printf("slot %d empty\n", slot);
                    179:         return;
                    180:     }
                    181: 
                    182:     qemu_system_device_hot_add(bus, slot, 0);
                    183: }
                    184: 
                    185: static int pci_match_fn(void *dev_private, void *arg)
                    186: {
                    187:     PCIDevice *dev = dev_private;
                    188:     PCIDevice *match = arg;
                    189: 
                    190:     return (dev == match);
                    191: }
                    192: 
                    193: /*
                    194:  * OS has executed _EJ0 method, we now can remove the device
                    195:  */
                    196: void pci_device_hot_remove_success(int pcibus, int slot)
                    197: {
                    198:     PCIDevice *d = pci_find_device(pcibus, slot, 0);
                    199:     int class_code;
                    200: 
                    201:     if (!d) {
                    202:         term_printf("invalid slot %d\n", slot);
                    203:         return;
                    204:     }
                    205: 
                    206:     class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
                    207: 
                    208:     switch(class_code) {
                    209:     case PCI_BASE_CLASS_STORAGE:
                    210:         destroy_bdrvs(pci_match_fn, d);
                    211:         break;
                    212:     case PCI_BASE_CLASS_NETWORK:
                    213:         destroy_nic(pci_match_fn, d);
                    214:         break;
                    215:     }
                    216: 
                    217:     pci_unregister_device(d);
                    218: }
                    219: 

unix.superglobalmegacorp.com

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