static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,

                                         const char *name, int devfn)

{

    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);

    PCIConfigReadFunc *config_read = pc->config_read;

    PCIConfigWriteFunc *config_write = pc->config_write;

    AddressSpace *dma_as;



    if (devfn < 0) {

        for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);

            devfn += PCI_FUNC_MAX) {

            if (!bus->devices[devfn])

                goto found;

        }

        error_report("PCI: no slot/function available for %s, all in use", name);

        return NULL;

    found: ;

    } else if (bus->devices[devfn]) {

        error_report("PCI: slot %d function %d not available for %s, in use by %s",

                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);

        return NULL;

    }



    pci_dev->bus = bus;

    dma_as = pci_device_iommu_address_space(pci_dev);



    memory_region_init_alias(&pci_dev->bus_master_enable_region,

                             OBJECT(pci_dev), "bus master",

                             dma_as->root, 0, memory_region_size(dma_as->root));

    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);

    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,

                       name);



    pci_dev->devfn = devfn;

    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);

    pci_dev->irq_state = 0;

    pci_config_alloc(pci_dev);



    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);

    pci_config_set_device_id(pci_dev->config, pc->device_id);

    pci_config_set_revision(pci_dev->config, pc->revision);

    pci_config_set_class(pci_dev->config, pc->class_id);



    if (!pc->is_bridge) {

        if (pc->subsystem_vendor_id || pc->subsystem_id) {

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,

                         pc->subsystem_vendor_id);

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,

                         pc->subsystem_id);

        } else {

            pci_set_default_subsystem_id(pci_dev);

        }

    } else {

        /* subsystem_vendor_id/subsystem_id are only for header type 0 */

        assert(!pc->subsystem_vendor_id);

        assert(!pc->subsystem_id);

    }

    pci_init_cmask(pci_dev);

    pci_init_wmask(pci_dev);

    pci_init_w1cmask(pci_dev);

    if (pc->is_bridge) {

        pci_init_mask_bridge(pci_dev);

    }

    if (pci_init_multifunction(bus, pci_dev)) {

        pci_config_free(pci_dev);

        return NULL;

    }



    if (!config_read)

        config_read = pci_default_read_config;

    if (!config_write)

        config_write = pci_default_write_config;

    pci_dev->config_read = config_read;

    pci_dev->config_write = config_write;

    bus->devices[devfn] = pci_dev;

    pci_dev->irq = qemu_allocate_irqs(pci_irq_handler, pci_dev, PCI_NUM_PINS);

    pci_dev->version_id = 2; /* Current pci device vmstate version */

    return pci_dev;

}

static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,

                                         const char *name, int devfn)

{

    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);

    PCIConfigReadFunc *config_read = pc->config_read;

    PCIConfigWriteFunc *config_write = pc->config_write;

    AddressSpace *dma_as;



    if (devfn < 0) {

        for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);

            devfn += PCI_FUNC_MAX) {

            if (!bus->devices[devfn])

                goto found;

        }

        error_report("PCI: no slot/function available for %s, all in use", name);

        return NULL;

    found: ;

    } else if (bus->devices[devfn]) {

        error_report("PCI: slot %d function %d not available for %s, in use by %s",

                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);

        return NULL;

    }



    pci_dev->bus = bus;

    dma_as = pci_device_iommu_address_space(pci_dev);



    memory_region_init_alias(&pci_dev->bus_master_enable_region,

                             OBJECT(pci_dev), "bus master",

                             dma_as->root, 0, memory_region_size(dma_as->root));

    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);

    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,

                       name);



    pci_dev->devfn = devfn;

    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);

    pci_dev->irq_state = 0;

    pci_config_alloc(pci_dev);



    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);

    pci_config_set_device_id(pci_dev->config, pc->device_id);

    pci_config_set_revision(pci_dev->config, pc->revision);

    pci_config_set_class(pci_dev->config, pc->class_id);



    if (!pc->is_bridge) {

        if (pc->subsystem_vendor_id || pc->subsystem_id) {

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,

                         pc->subsystem_vendor_id);

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,

                         pc->subsystem_id);

        } else {

            pci_set_default_subsystem_id(pci_dev);

        }

    } else {

        

        assert(!pc->subsystem_vendor_id);

        assert(!pc->subsystem_id);

    }

    pci_init_cmask(pci_dev);

    pci_init_wmask(pci_dev);

    pci_init_w1cmask(pci_dev);

    if (pc->is_bridge) {

        pci_init_mask_bridge(pci_dev);

    }

    if (pci_init_multifunction(bus, pci_dev)) {

        pci_config_free(pci_dev);

        return NULL;

    }



    if (!config_read)

        config_read = pci_default_read_config;

    if (!config_write)

        config_write = pci_default_write_config;

    pci_dev->config_read = config_read;

    pci_dev->config_write = config_write;

    bus->devices[devfn] = pci_dev;

    pci_dev->irq = qemu_allocate_irqs(pci_irq_handler, pci_dev, PCI_NUM_PINS);

    pci_dev->version_id = 2; 

    return pci_dev;

}

static PCIDevice *FUNC_0(PCIDevice *pci_dev, PCIBus *bus,

                                         const char *name, int devfn)

{

    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);

    PCIConfigReadFunc *config_read = pc->config_read;

    PCIConfigWriteFunc *config_write = pc->config_write;

    AddressSpace *dma_as;



    if (devfn < 0) {

        for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);

            devfn += PCI_FUNC_MAX) {

            if (!bus->devices[devfn])

                goto found;

        }

        error_report("PCI: no slot/function available for %s, all in use", name);

        return NULL;

    found: ;

    } else if (bus->devices[devfn]) {

        error_report("PCI: slot %d function %d not available for %s, in use by %s",

                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);

        return NULL;

    }



    pci_dev->bus = bus;

    dma_as = pci_device_iommu_address_space(pci_dev);



    memory_region_init_alias(&pci_dev->bus_master_enable_region,

                             OBJECT(pci_dev), "bus master",

                             dma_as->root, 0, memory_region_size(dma_as->root));

    memory_region_set_enabled(&pci_dev->bus_master_enable_region, false);

    address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,

                       name);



    pci_dev->devfn = devfn;

    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);

    pci_dev->irq_state = 0;

    pci_config_alloc(pci_dev);



    pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);

    pci_config_set_device_id(pci_dev->config, pc->device_id);

    pci_config_set_revision(pci_dev->config, pc->revision);

    pci_config_set_class(pci_dev->config, pc->class_id);



    if (!pc->is_bridge) {

        if (pc->subsystem_vendor_id || pc->subsystem_id) {

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,

                         pc->subsystem_vendor_id);

            pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,

                         pc->subsystem_id);

        } else {

            pci_set_default_subsystem_id(pci_dev);

        }

    } else {

        

        assert(!pc->subsystem_vendor_id);

        assert(!pc->subsystem_id);

    }

    pci_init_cmask(pci_dev);

    pci_init_wmask(pci_dev);

    pci_init_w1cmask(pci_dev);

    if (pc->is_bridge) {

        pci_init_mask_bridge(pci_dev);

    }

    if (pci_init_multifunction(bus, pci_dev)) {

        pci_config_free(pci_dev);

        return NULL;

    }



    if (!config_read)

        config_read = pci_default_read_config;

    if (!config_write)

        config_write = pci_default_write_config;

    pci_dev->config_read = config_read;

    pci_dev->config_write = config_write;

    bus->devices[devfn] = pci_dev;

    pci_dev->irq = qemu_allocate_irqs(pci_irq_handler, pci_dev, PCI_NUM_PINS);

    pci_dev->version_id = 2; 

    return pci_dev;

}

static PCIDevice *FUNC_0(PCIDevice *pci_dev, PCIBus *bus,
const char *name, int devfn)
{ PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); PCIConfigReadFunc *config_read = pc->config_read; PCIConfigWriteFunc *config_write = pc->config_write; AddressSpace *dma_as; if (devfn < 0) { for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); devfn += PCI_FUNC_MAX) { if (!bus->devices[devfn])
goto found; } error_report("PCI: no slot/function available for %s, all in use", name); return NULL; found: ; } else if (bus->devices[devfn]) { error_report("PCI: slot %d function %d not available for %s, in use by %s",
PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name); return NULL; } pci_dev->bus = bus; dma_as = pci_device_iommu_address_space(pci_dev); memory_region_init_alias(&pci_dev->bus_master_enable_region,
OBJECT(pci_dev), "bus master",
dma_as->root, 0, memory_region_size(dma_as->root)); memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region,
name); pci_dev->devfn = devfn; pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); pci_dev->irq_state = 0; pci_config_alloc(pci_dev); pci_config_set_vendor_id(pci_dev->config, pc->vendor_id); pci_config_set_device_id(pci_dev->config, pc->device_id); pci_config_set_revision(pci_dev->config, pc->revision); pci_config_set_class(pci_dev->config, pc->class_id); if (!pc->is_bridge) { if (pc->subsystem_vendor_id || pc->subsystem_id) { pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
pc->subsystem_vendor_id); pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
pc->subsystem_id); } else { pci_set_default_subsystem_id(pci_dev); } } else { assert(!pc->subsystem_vendor_id); assert(!pc->subsystem_id); } pci_init_cmask(pci_dev); pci_init_wmask(pci_dev); pci_init_w1cmask(pci_dev); if (pc->is_bridge) { pci_init_mask_bridge(pci_dev); } if (pci_init_multifunction(bus, pci_dev)) { pci_config_free(pci_dev); return NULL; } if (!config_read)
config_read = pci_default_read_config; if (!config_write)
config_write = pci_default_write_config; pci_dev->config_read = config_read; pci_dev->config_write = config_write; bus->devices[devfn] = pci_dev; pci_dev->irq = qemu_allocate_irqs(pci_irq_handler, pci_dev, PCI_NUM_PINS); pci_dev->version_id = 2; return pci_dev; }