static void fw_cfg_mem_realize(DeviceState *dev, Error **errp) { FWCfgMemState *s = FW_CFG_MEM(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); const MemoryRegionOps *data_ops = &fw_cfg_data_mem_ops; memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, FW_CFG(s), "fwcfg.ctl", FW_CFG_SIZE); sysbus_init_mmio(sbd, &s->ctl_iomem); if (s->data_width > data_ops->valid.max_access_size) { /* memberwise copy because the "old_mmio" member is const */ s->wide_data_ops.read = data_ops->read; s->wide_data_ops.write = data_ops->write; s->wide_data_ops.endianness = data_ops->endianness; s->wide_data_ops.valid = data_ops->valid; s->wide_data_ops.impl = data_ops->impl; s->wide_data_ops.valid.max_access_size = s->data_width; s->wide_data_ops.impl.max_access_size = s->data_width; data_ops = &s->wide_data_ops; } memory_region_init_io(&s->data_iomem, OBJECT(s), data_ops, FW_CFG(s), "fwcfg.data", data_ops->valid.max_access_size); sysbus_init_mmio(sbd, &s->data_iomem); }
static void fw_cfg_io_realize(DeviceState *dev, Error **errp) { FWCfgIoState *s = FW_CFG_IO(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, FW_CFG(s), "fwcfg", FW_CFG_SIZE); sysbus_add_io(sbd, s->iobase, &s->comb_iomem); }
FWCfgState *fw_cfg_init_io(uint32_t iobase) { DeviceState *dev; dev = qdev_create(NULL, TYPE_FW_CFG_IO); qdev_prop_set_uint32(dev, "iobase", iobase); fw_cfg_init1(dev); return FW_CFG(dev); }
static void fw_cfg_initfn(Object *obj) { SysBusDevice *sbd = SYS_BUS_DEVICE(obj); FWCfgState *s = FW_CFG(obj); memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s, "fwcfg.ctl", FW_CFG_SIZE); sysbus_init_mmio(sbd, &s->ctl_iomem); memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s, "fwcfg.data", FW_CFG_DATA_SIZE); sysbus_init_mmio(sbd, &s->data_iomem); /* In case ctl and data overlap: */ memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s, "fwcfg", FW_CFG_SIZE); }
FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr, hwaddr data_addr, uint32_t data_width) { DeviceState *dev; SysBusDevice *sbd; dev = qdev_create(NULL, TYPE_FW_CFG_MEM); qdev_prop_set_uint32(dev, "data_width", data_width); fw_cfg_init1(dev); sbd = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sbd, 0, ctl_addr); sysbus_mmio_map(sbd, 1, data_addr); return FW_CFG(dev); }
static void fw_cfg_realize(DeviceState *dev, Error **errp) { FWCfgState *s = FW_CFG(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); if (s->ctl_iobase + 1 == s->data_iobase) { sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem); } else { if (s->ctl_iobase) { sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem); } if (s->data_iobase) { sysbus_add_io(sbd, s->data_iobase, &s->data_iomem); } } }
static void fw_cfg_init1(DeviceState *dev) { FWCfgState *s = FW_CFG(dev); assert(!object_resolve_path(FW_CFG_PATH, NULL)); object_property_add_child(qdev_get_machine(), FW_CFG_NAME, OBJECT(s), NULL); qdev_init_nofail(dev); fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4); fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16); fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC)); fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu); fw_cfg_bootsplash(s); fw_cfg_reboot(s); s->machine_ready.notify = fw_cfg_machine_ready; qemu_add_machine_init_done_notifier(&s->machine_ready); }
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, hwaddr ctl_addr, hwaddr data_addr) { DeviceState *dev; SysBusDevice *d; FWCfgState *s; dev = qdev_create(NULL, TYPE_FW_CFG); qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port); qdev_prop_set_uint32(dev, "data_iobase", data_port); d = SYS_BUS_DEVICE(dev); s = FW_CFG(dev); assert(!object_resolve_path(FW_CFG_PATH, NULL)); object_property_add_child(qdev_get_machine(), FW_CFG_NAME, OBJECT(s), NULL); qdev_init_nofail(dev); if (ctl_addr) { sysbus_mmio_map(d, 0, ctl_addr); } if (data_addr) { sysbus_mmio_map(d, 1, data_addr); } fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4); fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16); fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC)); fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu); fw_cfg_bootsplash(s); fw_cfg_reboot(s); s->machine_ready.notify = fw_cfg_machine_ready; qemu_add_machine_init_done_notifier(&s->machine_ready); return s; }
FWCfgState *fw_cfg_find(void) { return FW_CFG(object_resolve_path(FW_CFG_PATH, NULL)); }
static void fw_cfg_reset(DeviceState *d) { FWCfgState *s = FW_CFG(d); fw_cfg_select(s, 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); }
static void ppc_heathrow_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; MemoryRegion *sysmem = get_system_memory(); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; OldWorldMacIOState *macio; MACIOIDEState *macio_ide; SysBusDevice *s; DeviceState *dev, *pic_dev; BusState *adb_bus; int bios_size; uint16_t ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; uint64_t tbfreq; linux_boot = (kernel_filename != NULL); /* init CPUs */ for (i = 0; i < smp_cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; /* Set time-base frequency to 16.6 Mhz */ cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_heathrow_reset, cpu); } /* allocate RAM */ if (ram_size > 2047 * MiB) { error_report("Too much memory for this machine: %" PRId64 " MB, " "maximum 2047 MB", ram_size / MiB); exit(1); } memory_region_allocate_system_memory(ram, NULL, "ppc_heathrow.ram", ram_size); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, NULL, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { error_report("could not load kernel '%s'", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", initrd_filename); exit(1); } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; for (i = 0; boot_device[i] != '\0'; i++) { /* TOFIX: for now, the second IDE channel is not properly * used by OHW. The Mac floppy disk are not emulated. * For now, OHW cannot boot from the network. */ #if 0 if (boot_device[i] >= 'a' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } #else if (boot_device[i] >= 'c' && boot_device[i] <= 'd') { ppc_boot_device = boot_device[i]; break; } #endif } if (ppc_boot_device == '\0') { error_report("No valid boot device for G3 Beige machine"); exit(1); } } /* XXX: we register only 1 output pin for heathrow PIC */ pic_dev = qdev_create(NULL, TYPE_HEATHROW); qdev_init_nofail(pic_dev); /* Connect the heathrow PIC outputs to the 6xx bus */ for (i = 0; i < smp_cpus; i++) { switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: qdev_connect_gpio_out(pic_dev, 0, ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]); break; default: error_report("Bus model not supported on OldWorld Mac machine"); exit(1); } } /* Timebase Frequency */ if (kvm_enabled()) { tbfreq = kvmppc_get_tbfreq(); } else { tbfreq = TBFREQ; } /* init basic PC hardware */ if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { error_report("Only 6xx bus is supported on heathrow machine"); exit(1); } /* Grackle PCI host bridge */ dev = qdev_create(NULL, TYPE_GRACKLE_PCI_HOST_BRIDGE); qdev_prop_set_uint32(dev, "ofw-addr", 0x80000000); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, GRACKLE_BASE); sysbus_mmio_map(s, 1, GRACKLE_BASE + 0x200000); /* PCI hole */ memory_region_add_subregion(get_system_memory(), 0x80000000ULL, sysbus_mmio_get_region(s, 2)); /* Register 2 MB of ISA IO space */ memory_region_add_subregion(get_system_memory(), 0xfe000000, sysbus_mmio_get_region(s, 3)); pci_bus = PCI_HOST_BRIDGE(dev)->bus; pci_vga_init(pci_bus); 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)); /* MacIO */ macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO)); dev = DEVICE(macio); qdev_prop_set_uint64(dev, "frequency", tbfreq); object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); macio_ide_init_drives(macio_ide, hd); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) graphic_depth = 15; /* No PCI init: the BIOS will do it */ dev = qdev_create(NULL, TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg), NULL); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); 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, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); /* MacOS NDRV VGA driver */ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); if (filename) { gchar *ndrv_file; gsize ndrv_size; if (g_file_get_contents(filename, &ndrv_file, &ndrv_size, NULL)) { fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); } g_free(filename); } qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
/* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; Core99MachineState *core99_machine = CORE99_MACHINE(machine); PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; IrqLines *openpic_irqs; int linux_boot, i, j, k; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; UNINHostState *uninorth_pci; PCIBus *pci_bus; NewWorldMacIOState *macio; bool has_pmu, has_adb; MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; int bios_size; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; int machine_arch; SysBusDevice *s; DeviceState *dev, *pic_dev; hwaddr nvram_addr = 0xFFF04000; uint64_t tbfreq; linux_boot = (kernel_filename != NULL); /* init CPUs */ for (i = 0; i < smp_cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "ppc_core99.ram", ram_size); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { error_report("could not load kernel '%s'", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", initrd_filename); exit(1); } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); } 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') { error_report("No valid boot device for Mac99 machine"); exit(1); } } /* UniN init */ dev = qdev_create(NULL, TYPE_UNI_NORTH); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); memory_region_add_subregion(get_system_memory(), 0xf8000000, sysbus_mmio_get_region(s, 0)); openpic_irqs = g_new0(IrqLines, smp_cpus); 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].irq[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; break; #if defined(TARGET_PPC64) case PPC_FLAGS_INPUT_970: openpic_irqs[i].irq[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i].irq[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i].irq[OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i].irq[OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i].irq[OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET]; break; #endif /* defined(TARGET_PPC64) */ default: error_report("Bus model not supported on mac99 machine"); exit(1); } } pic_dev = qdev_create(NULL, TYPE_OPENPIC); qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO); qdev_init_nofail(pic_dev); s = SYS_BUS_DEVICE(pic_dev); k = 0; for (i = 0; i < smp_cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { sysbus_connect_irq(s, k++, openpic_irqs[i].irq[j]); } } g_free(openpic_irqs); if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ /* Uninorth AGP bus */ dev = qdev_create(NULL, TYPE_U3_AGP_HOST_BRIDGE); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); uninorth_pci = U3_AGP_HOST_BRIDGE(dev); s = SYS_BUS_DEVICE(dev); /* PCI hole */ memory_region_add_subregion(get_system_memory(), 0x80000000ULL, sysbus_mmio_get_region(s, 2)); /* Register 8 MB of ISA IO space */ memory_region_add_subregion(get_system_memory(), 0xf2000000, sysbus_mmio_get_region(s, 3)); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); machine_arch = ARCH_MAC99_U3; } else { /* Use values found on a real PowerMac */ /* Uninorth AGP bus */ dev = qdev_create(NULL, TYPE_UNI_NORTH_AGP_HOST_BRIDGE); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0xf0800000); sysbus_mmio_map(s, 1, 0xf0c00000); /* Uninorth internal bus */ dev = qdev_create(NULL, TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0xf4800000); sysbus_mmio_map(s, 1, 0xf4c00000); /* Uninorth main bus */ dev = qdev_create(NULL, TYPE_UNI_NORTH_PCI_HOST_BRIDGE); qdev_prop_set_uint32(dev, "ofw-addr", 0xf2000000); object_property_set_link(OBJECT(dev), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); uninorth_pci = UNI_NORTH_PCI_HOST_BRIDGE(dev); s = SYS_BUS_DEVICE(dev); /* PCI hole */ memory_region_add_subregion(get_system_memory(), 0x80000000ULL, sysbus_mmio_get_region(s, 2)); /* Register 8 MB of ISA IO space */ memory_region_add_subregion(get_system_memory(), 0xf2000000, sysbus_mmio_get_region(s, 3)); sysbus_mmio_map(s, 0, 0xf2800000); sysbus_mmio_map(s, 1, 0xf2c00000); machine_arch = ARCH_MAC99; } machine->usb |= defaults_enabled() && !machine->usb_disabled; has_pmu = (core99_machine->via_config != CORE99_VIA_CONFIG_CUDA); has_adb = (core99_machine->via_config == CORE99_VIA_CONFIG_CUDA || core99_machine->via_config == CORE99_VIA_CONFIG_PMU_ADB); /* Timebase Frequency */ if (kvm_enabled()) { tbfreq = kvmppc_get_tbfreq(); } else { tbfreq = TBFREQ; } /* init basic PC hardware */ pci_bus = PCI_HOST_BRIDGE(uninorth_pci)->bus; /* MacIO */ macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO)); dev = DEVICE(macio); qdev_prop_set_uint64(dev, "frequency", tbfreq); qdev_prop_set_bit(dev, "has-pmu", has_pmu); qdev_prop_set_bit(dev, "has-adb", has_adb); object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); macio_ide_init_drives(macio_ide, hd); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); if (has_adb) { if (has_pmu) { dev = DEVICE(object_resolve_path_component(OBJECT(macio), "pmu")); } else { dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); } adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_prop_set_bit(dev, "disable-direct-reg3-writes", true); qdev_init_nofail(dev); dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_prop_set_bit(dev, "disable-direct-reg3-writes", true); qdev_init_nofail(dev); } if (machine->usb) { pci_create_simple(pci_bus, -1, "pci-ohci"); /* U3 needs to use USB for input because Linux doesn't support via-cuda on PPC64 */ if (!has_adb || machine_arch == ARCH_MAC99_U3) { USBBus *usb_bus = usb_bus_find(-1); usb_create_simple(usb_bus, "usb-kbd"); usb_create_simple(usb_bus, "usb-mouse"); } } pci_vga_init(pci_bus); if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) { graphic_depth = 15; } for (i = 0; i < nb_nics; i++) { pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); } /* The NewWorld NVRAM is not located in the MacIO device */ #ifdef CONFIG_KVM if (kvm_enabled() && getpagesize() > 4096) { /* We can't combine read-write and read-only in a single page, so move the NVRAM out of ROM again for KVM */ nvram_addr = 0xFFE00000; } #endif dev = qdev_create(NULL, TYPE_MACIO_NVRAM); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 1); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr); nvr = MACIO_NVRAM(dev); pmac_format_nvram_partition(nvr, 0x2000); /* No PCI init: the BIOS will do it */ dev = qdev_create(NULL, TYPE_FW_CFG_MEM); fw_cfg = FW_CFG(dev); qdev_prop_set_uint32(dev, "data_width", 1); qdev_prop_set_bit(dev, "dma_enabled", false); object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, OBJECT(fw_cfg), NULL); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, CFG_ADDR); sysbus_mmio_map(s, 1, CFG_ADDR + 2); 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, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_VIACONFIG, core99_machine->via_config); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr); /* MacOS NDRV VGA driver */ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); if (filename) { gchar *ndrv_file; gsize ndrv_size; if (g_file_get_contents(filename, &ndrv_file, &ndrv_size, NULL)) { fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); } g_free(filename); } qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }