Beispiel #1
0
PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                            void *opaque, int devfn_min, int nirq)
{
    SHPCIC *p;
    int reg;

    p = qemu_mallocz(sizeof(SHPCIC));
    p->bus = pci_register_bus(NULL, "pci",
                              set_irq, map_irq, opaque, devfn_min, nirq);

    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
                                 -1, NULL, NULL);
    reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p,
                                 DEVICE_NATIVE_ENDIAN);
    cpu_register_physical_memory(0x1e200000, 0x224, reg);
    cpu_register_physical_memory(0xfe200000, 0x224, reg);

    p->iobr = 0xfe240000;
    isa_mmio_init(p->iobr, 0x40000);

    pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
    pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
    p->dev->config[0x04] = 0x80;
    p->dev->config[0x05] = 0x00;
    p->dev->config[0x06] = 0x90;
    p->dev->config[0x07] = 0x02;

    return p->bus;
}
PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                            qemu_irq *pic, int devfn_min, int nirq)
{
    SHPCIC *p;
    int mem, reg, iop;

    p = qemu_mallocz(sizeof(SHPCIC));
    p->bus = pci_register_bus(set_irq, map_irq, pic, devfn_min, nirq);

    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
                                 -1, NULL, NULL);
    reg = cpu_register_io_memory(0, sh_pci_reg.r, sh_pci_reg.w, p);
    iop = cpu_register_io_memory(0, sh_pci_iop.r, sh_pci_iop.w, p);
    mem = cpu_register_io_memory(0, sh_pci_mem.r, sh_pci_mem.w, p);
    cpu_register_physical_memory(0x1e200000, 0x224, reg);
    cpu_register_physical_memory(0x1e240000, 0x40000, iop);
    cpu_register_physical_memory(0x1d000000, 0x1000000, mem);
    cpu_register_physical_memory(0xfe200000, 0x224, reg);
    cpu_register_physical_memory(0xfe240000, 0x40000, iop);
    cpu_register_physical_memory(0xfd000000, 0x1000000, mem);

    pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
    pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
    p->dev->config[0x04] = 0x80;
    p->dev->config[0x05] = 0x00;
    p->dev->config[0x06] = 0x90;
    p->dev->config[0x07] = 0x02;

    return p->bus;
}
Beispiel #3
0
PCIBus *pci_prep_init(qemu_irq *pic)
{
    PREPPCIState *s;
    PCIDevice *d;
    int PPC_io_memory;

    s = qemu_mallocz(sizeof(PREPPCIState));
    s->bus = pci_register_bus(NULL, "pci",
                              prep_set_irq, prep_map_irq, pic, 0, 4);

    pci_host_conf_register_ioport(0xcf8, s);

    pci_host_data_register_ioport(0xcfc, s);

    PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
                                           PPC_PCIIO_write, s);
    cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);

    /* PCI host bridge */
    d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
                            sizeof(PCIDevice), 0, NULL, NULL);
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_RAVEN);
    d->config[0x08] = 0x00; // revision
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[0x34] = 0x00; // capabilities_pointer

    return s->bus;
}
Beispiel #4
0
/* XXX Interrupt acknowledge cycles not supported. */
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                        target_phys_addr_t config_space,
                        target_phys_addr_t int_ack,
                        target_phys_addr_t special_cycle,
                        target_phys_addr_t registers)
{
    PPC4xxPCIState *controller;
    int index;
    static int ppc4xx_pci_id;
    uint8_t *pci_conf;

    controller = qemu_mallocz(sizeof(PPC4xxPCIState));

    controller->pci_state.bus = pci_register_bus(ppc4xx_pci_set_irq,
                                                 ppc4xx_pci_map_irq,
                                                 pci_irqs, 0, 4);

    controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                              "host bridge", sizeof(PCIDevice),
                                              0, NULL, NULL);
    pci_conf = controller->pci_dev->config;
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_440GX);
    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_OTHER);

    /* CFGADDR */
    index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
                                   pci4xx_cfgaddr_write, controller);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);

    /* CFGDATA */
    index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
                                   pci4xx_cfgdata_write,
                                   &controller->pci_state);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);

    /* Internal registers */
    index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, controller);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(registers, PCI_REG_SIZE, index);

    qemu_register_reset(ppc4xx_pci_reset, controller);

    /* XXX load/save code not tested. */
    register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
                    ppc4xx_pci_save, ppc4xx_pci_load, controller);

    return controller->pci_state.bus;

free:
    printf("%s error\n", __func__);
    qemu_free(controller);
    return NULL;
}
PCIDevice *pci_tnetw1130_init(PCIBus * bus, NICInfo * nd, int devfn)
{
    pci_tnetw1130_t *d = (pci_tnetw1130_t *) pci_register_device(bus, "TNETW1130",
                         sizeof(pci_tnetw1130_t),
                         -1, NULL, NULL);
#if defined(DEBUG_TNETW1130)
    set_traceflags("DEBUG_TNETW1130");
#endif
    TRACE(TNETW, logout("\n"));
    tnetw1130_init(d, nd);
    return (PCIDevice *)d;
}
Beispiel #6
0
PCIBus *pci_vpb_init(void *pic, int irq, int realview)
{
    PCIBus *s;
    PCIDevice *d;
    int mem_config;
    uint32_t base;
    const char * name;

    pci_vpb_irq = irq;
    if (realview) {
        base = 0x60000000;
        name = "RealView EB PCI Controller";
    } else {
        base = 0x40000000;
        name = "Versatile/PB PCI Controller";
    }
    s = pci_register_bus(pci_vpb_set_irq, pci_vpb_map_irq, pic, 11 << 3, 4);
    /* ??? Register memory space.  */

    mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
                                        pci_vpb_config_write, s);
    /* Selfconfig area.  */
    cpu_register_physical_memory(base + 0x01000000, 0x1000000, mem_config);
    /* Normal config area.  */
    cpu_register_physical_memory(base + 0x02000000, 0x1000000, mem_config);

    d = pci_register_device(s, name, sizeof(PCIDevice), -1, NULL, NULL);

    if (realview) {
        /* IO memory area.  */
        isa_mmio_init(base + 0x03000000, 0x00100000);
    }

    d->config[0x00] = 0xee; // vendor_id
    d->config[0x01] = 0x10;
    /* Both boards have the same device ID.  Oh well.  */
    d->config[0x02] = 0x00; // device_id
    d->config[0x03] = 0x03;
    d->config[0x04] = 0x00;
    d->config[0x05] = 0x00;
    d->config[0x06] = 0x20;
    d->config[0x07] = 0x02;
    d->config[0x08] = 0x00; // revision
    d->config[0x09] = 0x00; // programming i/f
    d->config[0x0A] = 0x40; // class_sub = pci host
    d->config[0x0B] = 0x0b; // class_base = PCI_bridge
    d->config[0x0D] = 0x10; // latency_timer

    return s;
}
Beispiel #7
0
int plugin_qt_init(void)
{
	pthread_t mythread;
	char *args[]={ "plugin_qt" };
	threaddata mytd = { 1, args };

#ifdef DEBUG
	printf("Initializing \"framebuffer\" plugin...");
#endif
	pthread_create(&mythread, NULL, gui_thread, &mytd);
	while (!fb)
		usleep(20);

#if 0

	/* now we have the framebuffer start address.
	 * updating pci config space to reflect this
	 */
#if (BITS > 32)
	*(u32 *)(pci_config_space+0x14)=(u32)((unsigned long)fb>>32);
#else
	*(u32 *)(pci_config_space+0x14)=0;
#endif
	*(u32 *)(pci_config_space+0x10)=(u32)((unsigned long)fb&0xffffffff);

	/* next is to write the rom address. We write that at a random
	 * address in pci config space for now.
	 */
#if (BITS > 32)
	*(u32 *)(pci_config_space+0x34)=(u32)((unsigned long)qt_fcode>>32);
#else
	*(u32 *)(pci_config_space+0x34)=0;
#endif
	*(u32 *)(pci_config_space+0x30)=(u32)((unsigned long)qt_fcode&0xffffffff);

	/* FIXME: we need to put the fcode image for this
	 * device to the rom resource, once it exists
	 */

	/* register pci device to be available to beginagain */
	pci_register_device(0, 2, 0, pci_config_space);
#endif
#ifdef DEBUG
	printf("done.\n");
#endif
	return 0;
}
Beispiel #8
0
void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info)
{
    int instance_id;
    PCI_EMULATION_State *d;
    uint8_t *pci_conf;

#ifdef DEBUG
    fprintf(logfile, "qemu: pciinit\n");
#endif
    
    d = (PCI_EMULATION_State *)pci_register_device(bus,
                                                   pci_emulation_info->name, 
                                                   sizeof(PCI_EMULATION_State),
                                                   -1, 
                                                    NULL, NULL);
    pci_conf = d->dev.config;
    pci_conf[0x00] = pci_emulation_info->vendorid & 0xff;
    pci_conf[0x01] = (pci_emulation_info->vendorid & 0xff00) >> 8;
    pci_conf[0x02] = pci_emulation_info->deviceid & 0xff;
    pci_conf[0x03] = (pci_emulation_info->deviceid & 0xff00) >> 8;
    pci_conf[0x04] = pci_emulation_info->command & 0xff;
    pci_conf[0x05] = (pci_emulation_info->command & 0xff00) >> 8;
    pci_conf[0x06] = pci_emulation_info->status & 0xff;
    pci_conf[0x07] = (pci_emulation_info->status & 0xff00) >> 8;
    pci_conf[0x08] = pci_emulation_info->revision & 0xff;
    pci_conf[0x09] = pci_emulation_info->classcode & 0xff;
    pci_conf[0x0a] = (pci_emulation_info->classcode & 0xff00) >> 8;
    pci_conf[0x0b] = (pci_emulation_info->classcode & 0xff0000) >> 16;
    pci_conf[0x0e] = pci_emulation_info->headertype & 0xff;
    pci_conf[0x2c] = pci_emulation_info->subvendorid & 0xff;
    pci_conf[0x2d] = (pci_emulation_info->subvendorid & 0xff00) >> 8;
    pci_conf[0x2e] = pci_emulation_info->subsystemid & 0xff;
    pci_conf[0x2f] = (pci_emulation_info->subsystemid & 0xff00) >> 8;
    pci_conf[0x3c] = pci_emulation_info->interruputline & 0xff;
    pci_conf[0x3d] = pci_emulation_info->interruputpin & 0xff;

    instance_id = pci_bus_num(bus) << 8 | d->dev.devfn;
    register_savevm(pci_emulation_info->name, instance_id,
                    1, pci_emulation_save, pci_emulation_load, d);


    return;    
}
void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
                 int dbdma_mem_index, int cuda_mem_index, void *nvram,
                 int nb_ide, int *ide_mem_index, int escc_mem_index)
{
    PCIDevice *d;
    macio_state_t *macio_state;
    int i;

    d = pci_register_device(bus, "macio",
                            sizeof(PCIDevice) + sizeof(macio_state_t),
                            -1, NULL, NULL);
    macio_state = (macio_state_t *)(d + 1);
    macio_state->is_oldworld = is_oldworld;
    macio_state->pic_mem_index = pic_mem_index;
    macio_state->dbdma_mem_index = dbdma_mem_index;
    macio_state->cuda_mem_index = cuda_mem_index;
    macio_state->escc_mem_index = escc_mem_index;
    macio_state->nvram = nvram;
    if (nb_ide > 4)
        nb_ide = 4;
    macio_state->nb_ide = nb_ide;
    for (i = 0; i < nb_ide; i++)
        macio_state->ide_mem_index[i] = ide_mem_index[i];
    for (; i < 4; i++)
        macio_state->ide_mem_index[i] = -1;
    /* Note: this code is strongly inspirated from the corresponding code
       in PearPC */
    d->config[0x00] = 0x6b; // vendor_id
    d->config[0x01] = 0x10;
    d->config[0x02] = device_id;
    d->config[0x03] = device_id >> 8;

    d->config[0x0a] = 0x00; // class_sub = pci2pci
    d->config[0x0b] = 0xff; // class_base = bridge
    d->config[0x0e] = 0x00; // header_type

    d->config[0x3d] = 0x01; // interrupt on pin 1

    pci_register_io_region(d, 0, 0x80000,
                           PCI_ADDRESS_SPACE_MEM, macio_map);
}
PCIBus *pci_prep_init(qemu_irq *pic)
{
    PREPPCIState *s;
    PCIDevice *d;
    int PPC_io_memory;

    s = qemu_mallocz(sizeof(PREPPCIState));
    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 4);

    register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
    register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);

    register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
    register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
    register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
    register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
    register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
    register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);

    PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read,
                                           PPC_PCIIO_write, s);
    cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);

    /* PCI host bridge */
    d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
                            sizeof(PCIDevice), 0, NULL, NULL);
    d->config[0x00] = 0x57; // vendor_id : Motorola
    d->config[0x01] = 0x10;
    d->config[0x02] = 0x01; // device_id : Raven
    d->config[0x03] = 0x48;
    d->config[0x08] = 0x00; // revision
    d->config[0x0A] = 0x00; // class_sub = pci host
    d->config[0x0B] = 0x06; // class_base = PCI_bridge
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[0x0E] = 0x00; // header_type
    d->config[0x34] = 0x00; // capabilities_pointer

    return s->bus;
}
Beispiel #11
0
void macio_init (PCIBus *bus, int device_id, int is_oldworld,
                 MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
                 MemoryRegion *cuda_mem, void *nvram,
                 int nb_ide, MemoryRegion **ide_mem,
                 MemoryRegion *escc_mem)
{
    PCIDevice *d;
    macio_state_t *macio_state;
    int i;

    d = pci_register_device(bus, "macio",
                            sizeof(PCIDevice) + sizeof(macio_state_t),
                            -1, NULL, NULL);
    macio_state = (macio_state_t *)(d + 1);
    macio_state->is_oldworld = is_oldworld;
    macio_state->pic_mem = pic_mem;
    macio_state->dbdma_mem = dbdma_mem;
    macio_state->cuda_mem = cuda_mem;
    macio_state->escc_mem = escc_mem;
    macio_state->nvram = nvram;
    if (nb_ide > 4)
        nb_ide = 4;
    macio_state->nb_ide = nb_ide;
    for (i = 0; i < nb_ide; i++)
        macio_state->ide_mem[i] = ide_mem[i];
    for (; i < 4; i++)
        macio_state->ide_mem[i] = NULL;
    /* Note: this code is strongly inspirated from the corresponding code
       in PearPC */

    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
    pci_config_set_device_id(d->config, device_id);
    pci_config_set_class(d->config, PCI_CLASS_OTHERS << 8);

    d->config[0x3d] = 0x01; // interrupt on pin 1

    macio_bar_setup(macio_state);
    pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &macio_state->bar);
}
Beispiel #12
0
/* EBUS (Eight bit bus) bridge */
static void
pci_ebus_init(PCIBus *bus, int devfn)
{
    PCIDevice *s;

    s = pci_register_device(bus, "EBUS", sizeof(*s), devfn, NULL, NULL);
    pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN);
    pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS);
    s->config[0x04] = 0x06; // command = bus master, pci mem
    s->config[0x05] = 0x00;
    s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
    s->config[0x07] = 0x03; // status = medium devsel
    s->config[0x08] = 0x01; // revision
    s->config[0x09] = 0x00; // programming i/f
    pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
    s->config[0x0D] = 0x0a; // latency_timer
    s->config[0x0E] = 0x00; // header_type

    pci_register_io_region(s, 0, 0x1000000, PCI_ADDRESS_SPACE_MEM,
                           ebus_mmio_mapfunc);
    pci_register_io_region(s, 1, 0x800000,  PCI_ADDRESS_SPACE_MEM,
                           ebus_mmio_mapfunc);
}
Beispiel #13
0
PCIBus *pci_pmac_init(qemu_irq *pic)
{
    UNINState *s;
    PCIDevice *d;
    int pci_mem_config, pci_mem_data;

    /* Use values found on a real PowerMac */
    /* Uninorth main bus */
    s = qemu_mallocz(sizeof(UNINState));
    s->bus = pci_register_bus(NULL, "pci",
                              pci_unin_set_irq, pci_unin_map_irq,
                              pic, 11 << 3, 4);

    pci_mem_config = cpu_register_io_memory(pci_unin_main_config_read,
                                            pci_unin_main_config_write, s);
    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
                                          pci_unin_main_write, s);
    cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
    d = pci_register_device(s->bus, "Uni-north main", sizeof(PCIDevice),
                            11 << 3, NULL, NULL);
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
    d->config[0x08] = 0x00; // revision
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
    d->config[0x34] = 0x00; // capabilities_pointer

#if 0 // XXX: not activated as PPC BIOS doesn't handle multiple buses properly
    /* pci-to-pci bridge */
    d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
                            NULL, NULL);
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_DEC_21154);
    d->config[0x08] = 0x05; // revision
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x20; // latency_timer
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_BRIDGE; // header_type

    d->config[0x18] = 0x01; // primary_bus
    d->config[0x19] = 0x02; // secondary_bus
    d->config[0x1A] = 0x02; // subordinate_bus
    d->config[0x1B] = 0x20; // secondary_latency_timer
    d->config[0x1C] = 0x11; // io_base
    d->config[0x1D] = 0x01; // io_limit
    d->config[0x20] = 0x00; // memory_base
    d->config[0x21] = 0x80;
    d->config[0x22] = 0x00; // memory_limit
    d->config[0x23] = 0x80;
    d->config[0x24] = 0x01; // prefetchable_memory_base
    d->config[0x25] = 0x80;
    d->config[0x26] = 0xF1; // prefectchable_memory_limit
    d->config[0x27] = 0x7F;
    // d->config[0x34] = 0xdc // capabilities_pointer
#endif

    /* Uninorth AGP bus */
    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                            pci_unin_config_write, s);
    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,
                                          pci_unin_main_write, s);
    cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);

    d = pci_register_device(s->bus, "Uni-north AGP", sizeof(PCIDevice),
                            11 << 3, NULL, NULL);
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
    d->config[0x08] = 0x00; // revision
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
    //    d->config[0x34] = 0x80; // capabilities_pointer

#if 0 // XXX: not needed for now
    /* Uninorth internal bus */
    s = &pci_bridge[2];
    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,
                                            pci_unin_config_write, s);
    pci_mem_data = cpu_register_io_memory(pci_unin_read,
                                          pci_unin_write, s);
    cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
    cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);

    d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
                            3, 11 << 3, NULL, NULL);
    pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
    pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
    d->config[0x08] = 0x00; // revision
    pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
    d->config[0x0C] = 0x08; // cache_line_size
    d->config[0x0D] = 0x10; // latency_timer
    d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
    d->config[0x34] = 0x00; // capabilities_pointer
#endif
    register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, d);
    qemu_register_reset(pci_unin_reset, d);
    pci_unin_reset(d);

    return s->bus;
}
/* XXX Interrupt acknowledge cycles not supported. */
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
                        target_phys_addr_t config_space,
                        target_phys_addr_t int_ack,
                        target_phys_addr_t special_cycle,
                        target_phys_addr_t registers)
{
    PPC4xxPCIState *controller;
    int index;
    static int ppc4xx_pci_id;

    controller = qemu_mallocz(sizeof(PPC4xxPCIState));
    if (!controller)
        return NULL;

    controller->pci_state.bus = pci_register_bus(ppc4xx_pci_set_irq,
                                                 ppc4xx_pci_map_irq,
                                                 pci_irqs, 0, 4);

    controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                              "host bridge", sizeof(PCIDevice),
                                              0, NULL, NULL);
    controller->pci_dev->config[0x00] = 0x14; // vendor_id
    controller->pci_dev->config[0x01] = 0x10;
    controller->pci_dev->config[0x02] = 0x7f; // device_id
    controller->pci_dev->config[0x03] = 0x02;
    controller->pci_dev->config[0x0a] = 0x80; // class_sub = other bridge type
    controller->pci_dev->config[0x0b] = 0x06; // class_base = PCI_bridge

    /* CFGADDR */
    index = cpu_register_io_memory(0, pci4xx_cfgaddr_read,
                                   pci4xx_cfgaddr_write, controller);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);

    /* CFGDATA */
    index = cpu_register_io_memory(0, pci4xx_cfgdata_read,
                                   pci4xx_cfgdata_write,
                                   &controller->pci_state);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);

    /* Internal registers */
    index = cpu_register_io_memory(0, pci_reg_read, pci_reg_write, controller);
    if (index < 0)
        goto free;
    cpu_register_physical_memory(registers, PCI_REG_SIZE, index);

    qemu_register_reset(ppc4xx_pci_reset, controller);

    /* XXX load/save code not tested. */
    register_savevm("ppc4xx_pci", ppc4xx_pci_id++, 1,
                    ppc4xx_pci_save, ppc4xx_pci_load, controller);

    return controller->pci_state.bus;

free:
    printf("%s error\n", __func__);
    qemu_free(controller);
    return NULL;
}