Beispiel #1
0
static void sun4c_hw_init(const struct hwdef *hwdef, int RAM_size,
                          const char *boot_device,
                          DisplayState *ds, const char *kernel_filename,
                          const char *kernel_cmdline,
                          const char *initrd_filename, const char *cpu_model)
{
    CPUState *env;
    unsigned int i;
    void *iommu, *espdma, *ledma, *main_esp, *nvram;
    qemu_irq *cpu_irqs, *slavio_irq, *espdma_irq, *ledma_irq;
    qemu_irq *esp_reset, *le_reset;
    unsigned long prom_offset, kernel_size;
    int ret;
    char buf[1024];
    BlockDriverState *fd[MAX_FD];
    int index;

    /* init CPU */
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
        exit(1);
    }

    cpu_sparc_set_id(env, 0);

    qemu_register_reset(main_cpu_reset, env);
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
    cpu_irqs = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
    env->prom_addr = hwdef->slavio_base;

    /* allocate RAM */
    if ((uint64_t)RAM_size > hwdef->max_mem) {
        fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
                (unsigned int)RAM_size / (1024 * 1024),
                (unsigned int)hwdef->max_mem / (1024 * 1024));
        exit(1);
    }
    cpu_register_physical_memory(0, RAM_size, 0);

    /* load boot prom */
    prom_offset = RAM_size + hwdef->vram_size;
    cpu_register_physical_memory(hwdef->slavio_base,
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) &
                                 TARGET_PAGE_MASK,
                                 prom_offset | IO_MEM_ROM);

    if (bios_name == NULL)
        bios_name = PROM_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL);
    if (ret < 0 || ret > PROM_SIZE_MAX)
        ret = load_image(buf, phys_ram_base + prom_offset);
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n",
                buf);
        exit(1);
    }
    prom_offset += (ret + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;

    /* set up devices */
    slavio_intctl = sun4c_intctl_init(hwdef->sun4c_intctl_base,
                                      &slavio_irq, cpu_irqs);

    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
                       slavio_irq[hwdef->me_irq]);

    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
                              iommu, &espdma_irq, &esp_reset);

    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
                             slavio_irq[hwdef->le_irq], iommu, &ledma_irq,
                             &le_reset);

    if (graphic_depth != 8 && graphic_depth != 24) {
        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
        exit (1);
    }
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);

    if (nd_table[0].model == NULL
        || strcmp(nd_table[0].model, "lance") == 0) {
        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
    } else if (strcmp(nd_table[0].model, "?") == 0) {
        fprintf(stderr, "qemu: Supported NICs: lance\n");
        exit (1);
    } else {
        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
        exit (1);
    }

    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
                        hwdef->nvram_size, 2);

    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],
                              nographic);
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
                       serial_hds[1], serial_hds[0]);

    if (hwdef->fd_base != (target_phys_addr_t)-1) {
        /* there is zero or one floppy drive */
        fd[1] = fd[0] = NULL;
        index = drive_get_index(IF_FLOPPY, 0, 0);
        if (index != -1)
            fd[0] = drives_table[index].bdrv;

        sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd);
    }

    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

    main_esp = esp_init(hwdef->esp_base, espdma, *espdma_irq,
                        esp_reset);

    for (i = 0; i < ESP_MAX_DEVS; i++) {
        index = drive_get_index(IF_SCSI, 0, i);
        if (index == -1)
            continue;
        esp_scsi_attach(main_esp, drives_table[index].bdrv, i);
    }

    kernel_size = sun4m_load_kernel(kernel_filename, kernel_cmdline,
                                    initrd_filename);

    nvram_init((m48t59_t *)nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
               boot_device, RAM_size, kernel_size, graphic_width,
               graphic_height, graphic_depth, hwdef->machine_id, "Sun4c");
}
Beispiel #2
0
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
                          MachineState *machine)
{
    const char *cpu_model = machine->cpu_model;
    unsigned int i;
    void *iommu, *espdma, *ledma, *nvram;
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
        espdma_irq, ledma_irq;
    qemu_irq esp_reset, dma_enable;
    qemu_irq fdc_tc;
    qemu_irq *cpu_halt;
    unsigned long kernel_size;
    DriveInfo *fd[MAX_FD];
    FWCfgState *fw_cfg;
    unsigned int num_vsimms;

    /* init CPUs */
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;

    for(i = 0; i < smp_cpus; i++) {
        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
    }

    for (i = smp_cpus; i < MAX_CPUS; i++)
        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);


    /* set up devices */
    ram_init(0, machine->ram_size, hwdef->max_mem);
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
        empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size);
    }

    prom_init(hwdef->slavio_base, bios_name);

    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
                                       cpu_irqs);

    for (i = 0; i < 32; i++) {
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
    }
    for (i = 0; i < MAX_CPUS; i++) {
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
    }

    if (hwdef->idreg_base) {
        idreg_init(hwdef->idreg_base);
    }

    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
                       slavio_irq[30]);

    if (hwdef->iommu_pad_base) {
        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
           Software shouldn't use aliased addresses, neither should it crash
           when does. Using empty_slot instead of aliasing can help with
           debugging such accesses */
        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
    }

    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
                              iommu, &espdma_irq, 0);

    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
                             slavio_irq[16], iommu, &ledma_irq, 1);

    if (graphic_depth != 8 && graphic_depth != 24) {
        error_report("Unsupported depth: %d", graphic_depth);
        exit (1);
    }
    num_vsimms = 0;
    if (num_vsimms == 0) {
        if (vga_interface_type == VGA_CG3) {
            if (graphic_depth != 8) {
                error_report("Unsupported depth: %d", graphic_depth);
                exit(1);
            }

            if (!(graphic_width == 1024 && graphic_height == 768) &&
                !(graphic_width == 1152 && graphic_height == 900)) {
                error_report("Unsupported resolution: %d x %d", graphic_width,
                             graphic_height);
                exit(1);
            }

            /* sbus irq 5 */
            cg3_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
        } else {
            /* If no display specified, default to TCX */
            if (graphic_depth != 8 && graphic_depth != 24) {
                error_report("Unsupported depth: %d", graphic_depth);
                exit(1);
            }

            if (!(graphic_width == 1024 && graphic_height == 768)) {
                error_report("Unsupported resolution: %d x %d",
                             graphic_width, graphic_height);
                exit(1);
            }

            tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
        }
    }

    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
        /* vsimm registers probed by OBP */
        if (hwdef->vsimm[i].reg_base) {
            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
        }
    }

    if (hwdef->sx_base) {
        empty_slot_init(hwdef->sx_base, 0x2000);
    }

    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);

    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);

    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);

    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);

    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
    if (hwdef->apc_base) {
        apc_init(hwdef->apc_base, cpu_halt[0]);
    }

    if (hwdef->fd_base) {
        /* there is zero or one floppy drive */
        memset(fd, 0, sizeof(fd));
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
                          &fdc_tc);
    } else {
        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
    }

    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

    esp_init(hwdef->esp_base, 2,
             espdma_memory_read, espdma_memory_write,
             espdma, espdma_irq, &esp_reset, &dma_enable);

    qdev_connect_gpio_out(espdma, 0, esp_reset);
    qdev_connect_gpio_out(espdma, 1, dma_enable);

    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
                             slavio_irq[5]);
    }

    if (hwdef->dbri_base) {
        /* ISDN chip with attached CS4215 audio codec */
        /* prom space */
        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
        /* reg space */
        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
    }

    if (hwdef->bpp_base) {
        /* parallel port */
        empty_slot_init(hwdef->bpp_base, 0x20);
    }

    kernel_size = sun4m_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    machine->ram_size);

    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline,
               machine->boot_order, machine->ram_size, kernel_size,
               graphic_width, graphic_height, graphic_depth,
               hwdef->nvram_machine_id, "Sun4m");

    if (hwdef->ecc_base)
        ecc_init(hwdef->ecc_base, slavio_irq[28],
                 hwdef->ecc_version);

    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
    if (machine->kernel_cmdline) {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
                         machine->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                       strlen(machine->kernel_cmdline) + 1);
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
    }
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
Beispiel #3
0
static void sun4uv_init(MemoryRegion *address_space_mem,
                        MachineState *machine,
                        const struct hwdef *hwdef)
{
    SPARCCPU *cpu;
    Nvram *nvram;
    unsigned int i;
    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
    SabreState *sabre;
    PCIBus *pci_bus, *pci_busA, *pci_busB;
    PCIDevice *ebus, *pci_dev;
    SysBusDevice *s;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    DeviceState *iommu, *dev;
    FWCfgState *fw_cfg;
    NICInfo *nd;
    MACAddr macaddr;
    bool onboard_nic;

    /* init CPUs */
    cpu = sparc64_cpu_devinit(machine->cpu_type, hwdef->prom_addr);

    /* IOMMU */
    iommu = qdev_create(NULL, TYPE_SUN4U_IOMMU);
    qdev_init_nofail(iommu);

    /* set up devices */
    ram_init(0, machine->ram_size);

    prom_init(hwdef->prom_addr, bios_name);

    /* Init sabre (PCI host bridge) */
    sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE));
    qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE);
    qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE);
    object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu",
                             &error_abort);
    qdev_init_nofail(DEVICE(sabre));

    /* Wire up PCI interrupts to CPU */
    for (i = 0; i < IVEC_MAX; i++) {
        qdev_connect_gpio_out_named(DEVICE(sabre), "ivec-irq", i,
            qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i));
    }

    pci_bus = PCI_HOST_BRIDGE(sabre)->bus;
    pci_busA = pci_bridge_get_sec_bus(sabre->bridgeA);
    pci_busB = pci_bridge_get_sec_bus(sabre->bridgeB);

    /* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is
       reserved (leaving no slots free after on-board devices) however slots
       0-3 are free on busB */
    pci_bus->slot_reserved_mask = 0xfffffffc;
    pci_busA->slot_reserved_mask = 0xfffffff1;
    pci_busB->slot_reserved_mask = 0xfffffff0;

    ebus = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 0), true, TYPE_EBUS);
    qdev_prop_set_uint64(DEVICE(ebus), "console-serial-base",
                         hwdef->console_serial_base);
    qdev_init_nofail(DEVICE(ebus));

    /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */
    qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7,
        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_LPT_IRQ));
    qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6,
        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_FDD_IRQ));
    qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1,
        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_KBD_IRQ));
    qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12,
        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_MSE_IRQ));
    qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4,
        qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ));

    pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA");

    memset(&macaddr, 0, sizeof(MACAddr));
    onboard_nic = false;
    for (i = 0; i < nb_nics; i++) {
        nd = &nd_table[i];

        if (!nd->model || strcmp(nd->model, "sunhme") == 0) {
            if (!onboard_nic) {
                pci_dev = pci_create_multifunction(pci_busA, PCI_DEVFN(1, 1),
                                                   true, "sunhme");
                memcpy(&macaddr, &nd->macaddr.a, sizeof(MACAddr));
                onboard_nic = true;
            } else {
                pci_dev = pci_create(pci_busB, -1, "sunhme");
            }
        } else {
            pci_dev = pci_create(pci_busB, -1, nd->model);
        }

        dev = &pci_dev->qdev;
        qdev_set_nic_properties(dev, nd);
        qdev_init_nofail(dev);
    }

    /* If we don't have an onboard NIC, grab a default MAC address so that
     * we have a valid machine id */
    if (!onboard_nic) {
        qemu_macaddr_default_if_unset(&macaddr);
    }

    ide_drive_get(hd, ARRAY_SIZE(hd));

    pci_dev = pci_create(pci_busA, PCI_DEVFN(3, 0), "cmd646-ide");
    qdev_prop_set_uint32(&pci_dev->qdev, "secondary", 1);
    qdev_init_nofail(&pci_dev->qdev);
    pci_ide_create_devs(pci_dev, hd);

    /* Map NVRAM into I/O (ebus) space */
    nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59);
    s = SYS_BUS_DEVICE(nvram);
    memory_region_add_subregion(pci_address_space_io(ebus), 0x2000,
                                sysbus_mmio_get_region(s, 0));
 
    initrd_size = 0;
    initrd_addr = 0;
    kernel_size = sun4u_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    ram_size, &initrd_size, &initrd_addr,
                                    &kernel_addr, &kernel_entry);

    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", machine->ram_size,
                           machine->boot_order,
                           kernel_addr, kernel_size,
                           machine->kernel_cmdline,
                           initrd_addr, initrd_size,
                           /* XXX: need an option to load a NVRAM image */
                           0,
                           graphic_width, graphic_height, graphic_depth,
                           (uint8_t *)&macaddr);

    dev = qdev_create(NULL, TYPE_FW_CFG_IO);
    qdev_prop_set_bit(dev, "dma_enabled", false);
    object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev), NULL);
    qdev_init_nofail(dev);
    memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT,
                                &FW_CFG_IO(dev)->comb_iomem);

    fw_cfg = FW_CFG(dev);
    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
    if (machine->kernel_cmdline) {
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                       strlen(machine->kernel_cmdline) + 1);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
    }
    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);

    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);

    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
Beispiel #4
0
/* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
                             const char *boot_device, DisplayState *ds,
                             const char *kernel_filename,
                             const char *kernel_cmdline,
                             const char *initrd_filename,
                             const char *cpu_model)
{
    CPUState *env = NULL, *envs[MAX_CPUS];
    char buf[1024];
    qemu_irq *pic, **openpic_irqs;
    int unin_memory;
    int linux_boot, i;
    unsigned long bios_offset, vga_bios_offset;
    uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
    PCIBus *pci_bus;
    nvram_t nvram;
#if 0
    MacIONVRAMState *nvr;
    int nvram_mem_index;
#endif
    m48t59_t *m48t59;
    int vga_bios_size, bios_size;
    qemu_irq *dummy_irq;
    int pic_mem_index, dbdma_mem_index, cuda_mem_index;
    int ide_mem_index[2];
    int ppc_boot_device;
    int index;
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */
    if (cpu_model == NULL)
        cpu_model = "default";
    for (i = 0; i < smp_cpus; i++) {
        env = cpu_init(cpu_model);
        if (!env) {
            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
            exit(1);
        }
        /* Set time-base frequency to 100 Mhz */
        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
#if 0
        env->osi_call = vga_osi_call;
#endif
        qemu_register_reset(&cpu_ppc_reset, env);
        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
        envs[i] = env;
    }
    if (env->nip < 0xFFF80000) {
        /* Special test for PowerPC 601:
         * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
         * But the NVRAM is located at 0xFFF04000...
         */
        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
    }

    /* allocate RAM */
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    /* allocate and load BIOS */
    bios_offset = ram_size + vga_ram_size;
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if (bios_size < 0 || bios_size > BIOS_SIZE) {
        cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
        exit(1);
    }
    bios_size = (bios_size + 0xfff) & ~0xfff;
    if (bios_size > 0x00080000) {
        /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
    }
    cpu_register_physical_memory((uint32_t)(-bios_size),
                                 bios_size, bios_offset | IO_MEM_ROM);

    /* allocate and load VGA BIOS */
    vga_bios_offset = bios_offset + bios_size;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
    vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
    if (vga_bios_size < 0) {
        /* if no bios is present, we can still work */
        fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
        vga_bios_size = 0;
    } else {
        /* set a specific header (XXX: find real Apple format for NDRV
           drivers) */
        phys_ram_base[vga_bios_offset] = 'N';
        phys_ram_base[vga_bios_offset + 1] = 'D';
        phys_ram_base[vga_bios_offset + 2] = 'R';
        phys_ram_base[vga_bios_offset + 3] = 'V';
        cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
                     vga_bios_size);
        vga_bios_size += 8;
    }
    vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;

    if (linux_boot) {
        kernel_base = KERNEL_LOAD_ADDR;
        /* now we can load the kernel */
        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
        if (kernel_size < 0) {
            cpu_abort(env, "qemu: could not load kernel '%s'\n",
                      kernel_filename);
            exit(1);
        }
        /* load initrd */
        if (initrd_filename) {
            initrd_base = INITRD_LOAD_ADDR;
            initrd_size = load_image(initrd_filename,
                                     phys_ram_base + initrd_base);
            if (initrd_size < 0) {
                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
                          initrd_filename);
                exit(1);
            }
        } else {
            initrd_base = 0;
            initrd_size = 0;
        }
        ppc_boot_device = 'm';
    } else {
        kernel_base = 0;
        kernel_size = 0;
        initrd_base = 0;
        initrd_size = 0;
        ppc_boot_device = '\0';
        /* We consider that NewWorld PowerMac never have any floppy drive
         * For now, OHW cannot boot from the network.
         */
        for (i = 0; boot_device[i] != '\0'; i++) {
            if (boot_device[i] >= 'c' && boot_device[i] <= 'f') {
                ppc_boot_device = boot_device[i];
                break;
            }
        }
        if (ppc_boot_device == '\0') {
            fprintf(stderr, "No valid boot device for Mac99 machine\n");
            exit(1);
        }
    }

    isa_mem_base = 0x80000000;

    /* Register 8 MB of ISA IO space */
    isa_mmio_init(0xf2000000, 0x00800000);

    /* UniN init */
    unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
    cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);

    openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
    openpic_irqs[0] =
        qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
    for (i = 0; i < smp_cpus; i++) {
        /* Mac99 IRQ connection between OpenPIC outputs pins
         * and PowerPC input pins
         */
        switch (PPC_INPUT(env)) {
        case PPC_FLAGS_INPUT_6xx:
            openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
            openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
            /* Not connected ? */
            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
            /* Check this */
            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
            break;
#if defined(TARGET_PPC64)
        case PPC_FLAGS_INPUT_970:
            openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
            openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
            /* Not connected ? */
            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
            /* Check this */
            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
            break;
#endif /* defined(TARGET_PPC64) */
        default:
            cpu_abort(env, "Bus model not supported on mac99 machine\n");
            exit(1);
        }
    }
    pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
    pci_bus = pci_pmac_init(pic);
    /* init basic PC hardware */
    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
                 ram_size, vga_ram_size,
                 vga_bios_offset, vga_bios_size);

    /* XXX: suppress that */
    dummy_irq = i8259_init(NULL);

    /* XXX: use Mac Serial port */
    serial_init(0x3f8, dummy_irq[4], 115200, serial_hds[0]);
    for(i = 0; i < nb_nics; i++) {
        if (!nd_table[i].model)
            nd_table[i].model = "ne2k_pci";
        pci_nic_init(pci_bus, &nd_table[i], -1);
    }
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
        if (index != -1)
            hd[i] = drives_table[index].bdrv;
        else
            hd[i] = NULL;
    }
#if 1
    ide_mem_index[0] = pmac_ide_init(&hd[0], pic[0x13]);
    ide_mem_index[1] = pmac_ide_init(&hd[2], pic[0x14]);
#else
    pci_cmd646_ide_init(pci_bus, &hd[0], 0);
#endif
    /* cuda also initialize ADB */
    cuda_init(&cuda_mem_index, pic[0x19]);

    adb_kbd_init(&adb_bus);
    adb_mouse_init(&adb_bus);

    dbdma_init(&dbdma_mem_index);

    macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
               cuda_mem_index, NULL, 2, ide_mem_index);

    if (usb_enabled) {
        usb_ohci_init_pci(pci_bus, 3, -1);
    }

    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
        graphic_depth = 15;
#if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
    /* The NewWorld NVRAM is not located in the MacIO device */
    nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
    pmac_format_nvram_partition(nvr, 0x2000);
    macio_nvram_map(nvr, 0xFFF04000);
    nvram.opaque = nvr;
    nvram.read_fn = &macio_nvram_read;
    nvram.write_fn = &macio_nvram_write;
#else
    m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
    nvram.opaque = m48t59;
    nvram.read_fn = &m48t59_read;
    nvram.write_fn = &m48t59_write;
#endif
    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size,
                         ppc_boot_device, kernel_base, kernel_size,
                         kernel_cmdline,
                         initrd_base, initrd_size,
                         /* XXX: need an option to load a NVRAM image */
                         0,
                         graphic_width, graphic_height, graphic_depth);
    /* No PCI init: the BIOS will do it */

    /* Special port to get debug messages from Open-Firmware */
    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
}
Beispiel #5
0
static void sun4uv_init(MemoryRegion *address_space_mem,
                        MachineState *machine,
                        const struct hwdef *hwdef)
{
    SPARCCPU *cpu;
    Nvram *nvram;
    unsigned int i;
    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
    ISABus *isa_bus;
    SysBusDevice *s;
    qemu_irq *ivec_irqs, *pbm_irqs;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    DriveInfo *fd[MAX_FD];
    FWCfgState *fw_cfg;

    /* init CPUs */
    cpu = cpu_devinit(machine->cpu_model, hwdef);

    /* set up devices */
    ram_init(0, machine->ram_size);

    prom_init(hwdef->prom_addr, bios_name);

    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
                           &pci_bus3, &pbm_irqs);
    pci_vga_init(pci_bus);

    // XXX Should be pci_bus3
    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);

    i = 0;
    if (hwdef->console_serial_base) {
        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
        i++;
    }

    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
    parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);

    for(i = 0; i < nb_nics; i++)
        pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);

    ide_drive_get(hd, ARRAY_SIZE(hd));

    pci_cmd646_ide_init(pci_bus, hd, 1);

    isa_create_simple(isa_bus, "i8042");
    for(i = 0; i < MAX_FD; i++) {
        fd[i] = drive_get(IF_FLOPPY, 0, i);
    }
    fdctrl_init_isa(isa_bus, fd);

    /* Map NVRAM into I/O (ebus) space */
    nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59);
    s = SYS_BUS_DEVICE(nvram);
    memory_region_add_subregion(get_system_io(), 0x2000,
                                sysbus_mmio_get_region(s, 0));
 
    initrd_size = 0;
    initrd_addr = 0;
    kernel_size = sun4u_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    ram_size, &initrd_size, &initrd_addr,
                                    &kernel_addr, &kernel_entry);

    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", machine->ram_size,
                           machine->boot_order,
                           kernel_addr, kernel_size,
                           machine->kernel_cmdline,
                           initrd_addr, initrd_size,
                           /* XXX: need an option to load a NVRAM image */
                           0,
                           graphic_width, graphic_height, graphic_depth,
                           (uint8_t *)&nd_table[0].macaddr);

    fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
    if (machine->kernel_cmdline) {
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
                       strlen(machine->kernel_cmdline) + 1);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
    }
    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);

    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);

    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
Beispiel #6
0
static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, int RAM_size,
                          const char *boot_device,
                          DisplayState *ds, const char *kernel_filename,
                          const char *kernel_cmdline,
                          const char *initrd_filename, const char *cpu_model)
{
    CPUState *env, *envs[MAX_CPUS];
    unsigned int i;
    void *iounits[MAX_IOUNITS], *espdma, *ledma, *main_esp, *nvram, *sbi;
    qemu_irq *cpu_irqs[MAX_CPUS], *sbi_irq, *sbi_cpu_irq,
        *espdma_irq, *ledma_irq;
    qemu_irq *esp_reset, *le_reset;
    unsigned long prom_offset, kernel_size;
    int ret;
    char buf[1024];
    int index;

    /* init CPUs */
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;

    for (i = 0; i < smp_cpus; i++) {
        env = cpu_init(cpu_model);
        if (!env) {
            fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
            exit(1);
        }
        cpu_sparc_set_id(env, i);
        envs[i] = env;
        if (i == 0) {
            qemu_register_reset(main_cpu_reset, env);
        } else {
            qemu_register_reset(secondary_cpu_reset, env);
            env->halted = 1;
        }
        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
        cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
        env->prom_addr = hwdef->slavio_base;
    }

    for (i = smp_cpus; i < MAX_CPUS; i++)
        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);

    /* allocate RAM */
    if ((uint64_t)RAM_size > hwdef->max_mem) {
        fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
                (unsigned int)RAM_size / (1024 * 1024),
                (unsigned int)(hwdef->max_mem / (1024 * 1024)));
        exit(1);
    }
    cpu_register_physical_memory(0, RAM_size, 0);

    /* load boot prom */
    prom_offset = RAM_size + hwdef->vram_size;
    cpu_register_physical_memory(hwdef->slavio_base,
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) &
                                 TARGET_PAGE_MASK,
                                 prom_offset | IO_MEM_ROM);

    if (bios_name == NULL)
        bios_name = PROM_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL);
    if (ret < 0 || ret > PROM_SIZE_MAX)
        ret = load_image(buf, phys_ram_base + prom_offset);
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n",
                buf);
        exit(1);
    }

    /* set up devices */
    sbi = sbi_init(hwdef->sbi_base, &sbi_irq, &sbi_cpu_irq, cpu_irqs);

    for (i = 0; i < MAX_IOUNITS; i++)
        if (hwdef->iounit_bases[i] != (target_phys_addr_t)-1)
            iounits[i] = iommu_init(hwdef->iounit_bases[i],
                                    hwdef->iounit_version,
                                    sbi_irq[hwdef->me_irq]);

    espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[hwdef->esp_irq],
                              iounits[0], &espdma_irq, &esp_reset);

    ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[hwdef->le_irq],
                             iounits[0], &ledma_irq, &le_reset);

    if (graphic_depth != 8 && graphic_depth != 24) {
        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
        exit (1);
    }
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);

    if (nd_table[0].model == NULL
        || strcmp(nd_table[0].model, "lance") == 0) {
        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
    } else if (strcmp(nd_table[0].model, "?") == 0) {
        fprintf(stderr, "qemu: Supported NICs: lance\n");
        exit (1);
    } else {
        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
        exit (1);
    }

    nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0,
                        hwdef->nvram_size, 8);

    slavio_timer_init_all(hwdef->counter_base, sbi_irq[hwdef->clock1_irq],
                          sbi_cpu_irq, smp_cpus);

    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[hwdef->ms_kb_irq],
                              nographic);
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
    slavio_serial_init(hwdef->serial_base, sbi_irq[hwdef->ser_irq],
                       serial_hds[1], serial_hds[0]);

    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

    main_esp = esp_init(hwdef->esp_base, espdma, *espdma_irq,
                        esp_reset);

    for (i = 0; i < ESP_MAX_DEVS; i++) {
        index = drive_get_index(IF_SCSI, 0, i);
        if (index == -1)
            continue;
        esp_scsi_attach(main_esp, drives_table[index].bdrv, i);
    }

    kernel_size = sun4m_load_kernel(kernel_filename, kernel_cmdline,
                                    initrd_filename);

    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
               boot_device, RAM_size, kernel_size, graphic_width,
               graphic_height, graphic_depth, hwdef->machine_id, "Sun4d");
}
Beispiel #7
0
static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
                        const char *boot_devices,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model,
                        const struct hwdef *hwdef)
{
    CPUState *env;
    char buf[1024];
    m48t59_t *nvram;
    int ret, linux_boot;
    unsigned int i;
    ram_addr_t ram_offset, prom_offset, vga_ram_offset;
    long initrd_size, kernel_size;
    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
    QEMUBH *bh;
    qemu_irq *irq;
    int drive_index;
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BlockDriverState *fd[MAX_FD];
    void *fw_cfg;
    ResetData *reset_info;

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;

    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
        exit(1);
    }
    bh = qemu_bh_new(tick_irq, env);
    env->tick = ptimer_init(bh);
    ptimer_set_period(env->tick, 1ULL);

    bh = qemu_bh_new(stick_irq, env);
    env->stick = ptimer_init(bh);
    ptimer_set_period(env->stick, 1ULL);

    bh = qemu_bh_new(hstick_irq, env);
    env->hstick = ptimer_init(bh);
    ptimer_set_period(env->hstick, 1ULL);

    reset_info = qemu_mallocz(sizeof(ResetData));
    reset_info->env = env;
    reset_info->reset_addr = hwdef->prom_addr + 0x40ULL;
    qemu_register_reset(main_cpu_reset, reset_info);
    main_cpu_reset(reset_info);
    // Override warm reset address with cold start address
    env->pc = hwdef->prom_addr + 0x20ULL;
    env->npc = env->pc + 4;

    /* allocate RAM */
    ram_offset = qemu_ram_alloc(RAM_size);
    cpu_register_physical_memory(0, RAM_size, ram_offset);

    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
    cpu_register_physical_memory(hwdef->prom_addr,
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE) &
                                 TARGET_PAGE_MASK,
                                 prom_offset | IO_MEM_ROM);

    if (bios_name == NULL)
        bios_name = PROM_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    ret = load_elf(buf, hwdef->prom_addr - PROM_VADDR, NULL, NULL, NULL);
    if (ret < 0) {
        ret = load_image_targphys(buf, hwdef->prom_addr,
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) &
                                  TARGET_PAGE_MASK);
        if (ret < 0) {
            fprintf(stderr, "qemu: could not load prom '%s'\n",
                    buf);
            exit(1);
        }
    }

    kernel_size = 0;
    initrd_size = 0;
    if (linux_boot) {
        /* XXX: put correct offset */
        kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL);
        if (kernel_size < 0)
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                                    ram_size - KERNEL_LOAD_ADDR);
        if (kernel_size < 0)
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              ram_size - KERNEL_LOAD_ADDR);
        if (kernel_size < 0) {
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }

        /* load initrd */
        if (initrd_filename) {
            initrd_size = load_image_targphys(initrd_filename,
                                              INITRD_LOAD_ADDR,
                                              ram_size - INITRD_LOAD_ADDR);
            if (initrd_size < 0) {
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                        initrd_filename);
                exit(1);
            }
        }
        if (initrd_size > 0) {
            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
                if (ldl_phys(KERNEL_LOAD_ADDR + i) == 0x48647253) { // HdrS
                    stl_phys(KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
                    stl_phys(KERNEL_LOAD_ADDR + i + 20, initrd_size);
                    break;
                }
            }
        }
    }
    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL, &pci_bus2,
                           &pci_bus3);
    isa_mem_base = VGA_BASE;
    vga_ram_offset = qemu_ram_alloc(vga_ram_size);
    pci_vga_init(pci_bus, phys_ram_base + vga_ram_offset,
                 vga_ram_offset, vga_ram_size,
                 0, 0);

    // XXX Should be pci_bus3
    pci_ebus_init(pci_bus, -1);

    i = 0;
    if (hwdef->console_serial_base) {
        serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
                       serial_hds[i], 1);
        i++;
    }
    for(; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
            serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200,
                        serial_hds[i]);
        }
    }

    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
        if (parallel_hds[i]) {
            parallel_init(parallel_io[i], NULL/*parallel_irq[i]*/,
                          parallel_hds[i]);
        }
    }

    for(i = 0; i < nb_nics; i++)
        pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");

    irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        drive_index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS,
                                      i % MAX_IDE_DEVS);
       if (drive_index != -1)
           hd[i] = drives_table[drive_index].bdrv;
       else
           hd[i] = NULL;
    }

    pci_cmd646_ide_init(pci_bus, hd, 1);

    /* FIXME: wire up interrupts.  */
    i8042_init(NULL/*1*/, NULL/*12*/, 0x60);
    for(i = 0; i < MAX_FD; i++) {
        drive_index = drive_get_index(IF_FLOPPY, 0, i);
       if (drive_index != -1)
           fd[i] = drives_table[drive_index].bdrv;
       else
           fd[i] = NULL;
    }
    floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd);
    nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
                           KERNEL_LOAD_ADDR, kernel_size,
                           kernel_cmdline,
                           INITRD_LOAD_ADDR, initrd_size,
                           /* XXX: need an option to load a NVRAM image */
                           0,
                           graphic_width, graphic_height, graphic_depth,
                           (uint8_t *)&nd_table[0].macaddr);

    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
}