/*
 * QEMU PCI hotplug support
 *
 * Copyright (c) 2004 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "hw.h"
#include "boards.h"
#include "pci.h"
#include "net.h"
#include "sysemu.h"
#include "pc.h"
#include "console.h"
#include "block_int.h"
#include "virtio-blk.h"

#if defined(TARGET_I386) || defined(TARGET_X86_64)
static PCIDevice *qemu_pci_hot_add_nic(PCIBus *pci_bus, const char *opts)
{
    int ret;

    ret = net_client_init ("nic", opts);
    if (ret < 0 || !nd_table[ret].model)
        return NULL;
    return pci_nic_init (pci_bus, &nd_table[ret], -1, "rtl8139");
}

void drive_hot_add(const char *pci_addr, const char *opts)
{
    int dom, pci_bus;
    unsigned slot;
    int drive_idx, type, bus;
    int success = 0;
    PCIDevice *dev;

    if (pci_read_devaddr(pci_addr, &dom, &pci_bus, &slot)) {
        term_printf("Invalid pci address\n");
        return;
    }

    dev = pci_find_device(pci_bus, slot, 0);
    if (!dev) {
        term_printf("no pci device with address %s\n", pci_addr);
        return;
    }

    drive_idx = add_init_drive(opts);
    if (drive_idx < 0)
        return;
    type = drives_table[drive_idx].type;
    bus = drive_get_max_bus (type);

    switch (type) {
    case IF_SCSI:
        success = 1;
        lsi_scsi_attach (dev, drives_table[drive_idx].bdrv,
                         drives_table[drive_idx].unit);
        break;
    default:
        term_printf("Can't hot-add drive to type %d\n", type);
    }

    if (success)
        term_printf("OK bus %d, unit %d\n", drives_table[drive_idx].bus,
                                            drives_table[drive_idx].unit);
    return;
}

static PCIDevice *qemu_pci_hot_add_storage(PCIBus *pci_bus, const char *opts)
{
    void *opaque = NULL;
    int type = -1, drive_idx = -1;
    char buf[128];

    if (get_param_value(buf, sizeof(buf), "if", opts)) {
        if (!strcmp(buf, "scsi"))
            type = IF_SCSI;
        else if (!strcmp(buf, "virtio")) {
            type = IF_VIRTIO;
        }
    } else {
        term_printf("no if= specified\n");
        return NULL;
    }

    if (get_param_value(buf, sizeof(buf), "file", opts)) {
        drive_idx = add_init_drive(opts);
        if (drive_idx < 0)
            return NULL;
    } else if (type == IF_VIRTIO) {
        term_printf("virtio requires a backing file/device.\n");
        return NULL;
    }

    switch (type) {
    case IF_SCSI:
        opaque = lsi_scsi_init (pci_bus, -1);
        if (opaque && drive_idx >= 0)
            lsi_scsi_attach (opaque, drives_table[drive_idx].bdrv,
                             drives_table[drive_idx].unit);
        break;
    case IF_VIRTIO:
        opaque = virtio_blk_init (pci_bus, drives_table[drive_idx].bdrv);
        break;
    default:
        term_printf ("type %s not a hotpluggable PCI device.\n", buf);
    }

    return opaque;
}

void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts)
{
    PCIDevice *dev = NULL;
    PCIBus *pci_bus;
    int dom, bus;
    unsigned slot;

    if (pci_assign_devaddr(pci_addr, &dom, &bus, &slot)) {
        term_printf("Invalid pci address\n");
        return;
    }

    pci_bus = pci_find_bus(bus);
    if (!pci_bus) {
        term_printf("Can't find pci_bus %d\n", bus);
        return;
    }

    if (strcmp(type, "nic") == 0)
        dev = qemu_pci_hot_add_nic(pci_bus, opts);
    else if (strcmp(type, "storage") == 0)
        dev = qemu_pci_hot_add_storage(pci_bus, opts);
    else
        term_printf("invalid type: %s\n", type);

    if (dev) {
        qemu_system_device_hot_add(bus, PCI_SLOT(dev->devfn), 1);
        term_printf("OK domain %d, bus %d, slot %d, function %d\n",
                    0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
                    PCI_FUNC(dev->devfn));
    } else
        term_printf("failed to add %s\n", opts);
}
#endif

void pci_device_hot_remove(const char *pci_addr)
{
    PCIDevice *d;
    int dom, bus;
    unsigned slot;

    if (pci_read_devaddr(pci_addr, &dom, &bus, &slot)) {
        term_printf("Invalid pci address\n");
        return;
    }

    d = pci_find_device(bus, slot, 0);
    if (!d) {
        term_printf("slot %d empty\n", slot);
        return;
    }

    qemu_system_device_hot_add(bus, slot, 0);
}

static int pci_match_fn(void *dev_private, void *arg)
{
    PCIDevice *dev = dev_private;
    PCIDevice *match = arg;

    return (dev == match);
}

/*
 * OS has executed _EJ0 method, we now can remove the device
 */
void pci_device_hot_remove_success(int pcibus, int slot)
{
    PCIDevice *d = pci_find_device(pcibus, slot, 0);
    int class_code;

    if (!d) {
        term_printf("invalid slot %d\n", slot);
        return;
    }

    class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);

    switch(class_code) {
    case PCI_BASE_CLASS_STORAGE:
        destroy_bdrvs(pci_match_fn, d);
        break;
    case PCI_BASE_CLASS_NETWORK:
        destroy_nic(pci_match_fn, d);
        break;
    }

    pci_unregister_device(d);
}

