180bb2ff7SRichard Henderson /* 280bb2ff7SRichard Henderson * QEMU Alpha DP264/CLIPPER hardware system emulator. 380bb2ff7SRichard Henderson * 480bb2ff7SRichard Henderson * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK 566a0a2cbSDong Xu Wang * variants because CLIPPER doesn't have an SMC669 SuperIO controller 680bb2ff7SRichard Henderson * that we need to emulate as well. 780bb2ff7SRichard Henderson */ 880bb2ff7SRichard Henderson 9e2e5e114SPeter Maydell #include "qemu/osdep.h" 104771d756SPaolo Bonzini #include "cpu.h" 1180bb2ff7SRichard Henderson #include "elf.h" 1283c9f4caSPaolo Bonzini #include "hw/loader.h" 1347b43a1fSPaolo Bonzini #include "alpha_sys.h" 14c525436eSMarkus Armbruster #include "qemu/error-report.h" 15bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 1625297910SMark Cave-Ayland #include "hw/ide/pci.h" 17a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h" 18852c27e2SPaolo Bonzini #include "net/net.h" 19f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 202c65db5eSPaolo Bonzini #include "qemu/datadir.h" 2180bb2ff7SRichard Henderson 2280bb2ff7SRichard Henderson static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) 2380bb2ff7SRichard Henderson { 2480bb2ff7SRichard Henderson if (((addr >> 41) & 3) == 2) { 2580bb2ff7SRichard Henderson addr &= 0xffffffffffull; 2680bb2ff7SRichard Henderson } 2780bb2ff7SRichard Henderson return addr; 2880bb2ff7SRichard Henderson } 2980bb2ff7SRichard Henderson 3080bb2ff7SRichard Henderson /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. 3180bb2ff7SRichard Henderson (0) The dev_irq_n lines into the cpu, which we totally ignore, 3280bb2ff7SRichard Henderson (1) The DRIR lines in the typhoon chipset, 3380bb2ff7SRichard Henderson (2) The "vector" aka mangled interrupt number reported by SRM PALcode, 3480bb2ff7SRichard Henderson (3) The interrupt number assigned by the kernel. 3580bb2ff7SRichard Henderson The following function is concerned with (1) only. */ 3680bb2ff7SRichard Henderson 3780bb2ff7SRichard Henderson static int clipper_pci_map_irq(PCIDevice *d, int irq_num) 3880bb2ff7SRichard Henderson { 3980bb2ff7SRichard Henderson int slot = d->devfn >> 3; 4080bb2ff7SRichard Henderson 4180bb2ff7SRichard Henderson assert(irq_num >= 0 && irq_num <= 3); 4280bb2ff7SRichard Henderson 4380bb2ff7SRichard Henderson return (slot + 1) * 4 + irq_num; 4480bb2ff7SRichard Henderson } 4580bb2ff7SRichard Henderson 463ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine) 4780bb2ff7SRichard Henderson { 483ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size; 493ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 503ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 513ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 52*cdd684b8SThomas Huth MachineClass *mc = MACHINE_GET_CLASS(machine); 53ad601177SAndreas Färber AlphaCPU *cpus[4]; 5480bb2ff7SRichard Henderson PCIBus *pci_bus; 55be1765f3SBALATON Zoltan PCIDevice *pci_dev; 565ec4f1d3SJason Thorpe DeviceState *i82378_dev; 5748a18b3cSHervé Poussineau ISABus *isa_bus; 5880bb2ff7SRichard Henderson qemu_irq rtc_irq; 595ec4f1d3SJason Thorpe qemu_irq isa_irq; 6080bb2ff7SRichard Henderson long size, i; 61c18f8556SShannon Zhao char *palcode_filename; 62617160c9SBALATON Zoltan uint64_t palcode_entry; 63617160c9SBALATON Zoltan uint64_t kernel_entry, kernel_low; 6433decbd2SLike Xu unsigned int smp_cpus = machine->smp.cpus; 6580bb2ff7SRichard Henderson 6680bb2ff7SRichard Henderson /* Create up to 4 cpus. */ 6780bb2ff7SRichard Henderson memset(cpus, 0, sizeof(cpus)); 6880bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) { 69fb92da84SIgor Mammedov cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type)); 7080bb2ff7SRichard Henderson } 7180bb2ff7SRichard Henderson 72387a1dcbSJason Thorpe /* 73387a1dcbSJason Thorpe * arg0 -> memory size 74387a1dcbSJason Thorpe * arg1 -> kernel entry point 75387a1dcbSJason Thorpe * arg2 -> config word 76387a1dcbSJason Thorpe * 77387a1dcbSJason Thorpe * Config word: bits 0-5 -> ncpus 78387a1dcbSJason Thorpe * bit 6 -> nographics option (for HWRPB CTB) 79387a1dcbSJason Thorpe * 80387a1dcbSJason Thorpe * See init_hwrpb() in the PALcode. 81387a1dcbSJason Thorpe */ 82ad601177SAndreas Färber cpus[0]->env.trap_arg0 = ram_size; 83ad601177SAndreas Färber cpus[0]->env.trap_arg1 = 0; 84387a1dcbSJason Thorpe cpus[0]->env.trap_arg2 = smp_cpus | (!machine->enable_graphics << 6); 8580bb2ff7SRichard Henderson 863a8233dcSJason Thorpe /* 873a8233dcSJason Thorpe * Init the chipset. Because we're using CLIPPER IRQ mappings, 883a8233dcSJason Thorpe * the minimum PCI device IdSel is 1. 893a8233dcSJason Thorpe */ 905ec4f1d3SJason Thorpe pci_bus = typhoon_init(machine->ram, &isa_irq, &rtc_irq, cpus, 913a8233dcSJason Thorpe clipper_pci_map_irq, PCI_DEVFN(1, 0)); 9280bb2ff7SRichard Henderson 935ec4f1d3SJason Thorpe /* 945ec4f1d3SJason Thorpe * Init the PCI -> ISA bridge. 955ec4f1d3SJason Thorpe * 965ec4f1d3SJason Thorpe * Technically, PCI-based Alphas shipped with one of three different 975ec4f1d3SJason Thorpe * PCI-ISA bridges: 985ec4f1d3SJason Thorpe * 995ec4f1d3SJason Thorpe * - Intel i82378 SIO 1005ec4f1d3SJason Thorpe * - Cypress CY82c693UB 1015ec4f1d3SJason Thorpe * - ALI M1533 1025ec4f1d3SJason Thorpe * 1035ec4f1d3SJason Thorpe * (An Intel i82375 PCI-EISA bridge was also used on some models.) 1045ec4f1d3SJason Thorpe * 1055ec4f1d3SJason Thorpe * For simplicity, we model an i82378 here, even though it wouldn't 1065ec4f1d3SJason Thorpe * have been on any Tsunami/Typhoon systems; it's close enough, and 1075ec4f1d3SJason Thorpe * we don't want to deal with modelling the CY82c693UB (which has 1085ec4f1d3SJason Thorpe * incompatible edge/level control registers, plus other peripherals 1095ec4f1d3SJason Thorpe * like IDE and USB) or the M1533 (which also has IDE and USB). 1105ec4f1d3SJason Thorpe * 1115ec4f1d3SJason Thorpe * Importantly, we need to provide a PCI device node for it, otherwise 1125ec4f1d3SJason Thorpe * some operating systems won't notice there's an ISA bus to configure. 1135ec4f1d3SJason Thorpe */ 1145ec4f1d3SJason Thorpe i82378_dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(7, 0), "i82378")); 1155ec4f1d3SJason Thorpe isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0")); 1165ec4f1d3SJason Thorpe 1175ec4f1d3SJason Thorpe /* Connect the ISA PIC to the Typhoon IRQ used for ISA interrupts. */ 1185ec4f1d3SJason Thorpe qdev_connect_gpio_out(i82378_dev, 0, isa_irq); 1195ec4f1d3SJason Thorpe 120e605e969SRichard Henderson /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ 1216c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(isa_bus, 1900, rtc_irq); 122e605e969SRichard Henderson 12380bb2ff7SRichard Henderson /* VGA setup. Don't bother loading the bios. */ 124606f90ccSAurelien Jarno pci_vga_init(pci_bus); 12580bb2ff7SRichard Henderson 12680bb2ff7SRichard Henderson /* Network setup. e1000 is good enough, failing Tulip support. */ 12780bb2ff7SRichard Henderson for (i = 0; i < nb_nics; i++) { 128*cdd684b8SThomas Huth pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL); 12980bb2ff7SRichard Henderson } 13080bb2ff7SRichard Henderson 131a4cb7739SPhilippe Mathieu-Daudé /* Super I/O */ 132a4cb7739SPhilippe Mathieu-Daudé isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO); 133a4cb7739SPhilippe Mathieu-Daudé 13480bb2ff7SRichard Henderson /* IDE disk setup. */ 13525297910SMark Cave-Ayland pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide"); 136be1765f3SBALATON Zoltan pci_ide_create_devs(pci_dev); 13780bb2ff7SRichard Henderson 13880bb2ff7SRichard Henderson /* Load PALcode. Given that this is not "real" cpu palcode, 13980bb2ff7SRichard Henderson but one explicitly written for the emulation, we might as 14080bb2ff7SRichard Henderson well load it directly from and ELF image. */ 141c18f8556SShannon Zhao palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, 1422c4a83ebSPaolo Bonzini machine->firmware ?: "palcode-clipper"); 14380bb2ff7SRichard Henderson if (palcode_filename == NULL) { 144c525436eSMarkus Armbruster error_report("no palcode provided"); 14580bb2ff7SRichard Henderson exit(1); 14680bb2ff7SRichard Henderson } 1474366e1dbSLiam Merwick size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys, 148617160c9SBALATON Zoltan NULL, &palcode_entry, NULL, NULL, NULL, 1497ef295eaSPeter Crosthwaite 0, EM_ALPHA, 0, 0); 15080bb2ff7SRichard Henderson if (size < 0) { 151c525436eSMarkus Armbruster error_report("could not load palcode '%s'", palcode_filename); 15280bb2ff7SRichard Henderson exit(1); 15380bb2ff7SRichard Henderson } 154c18f8556SShannon Zhao g_free(palcode_filename); 15580bb2ff7SRichard Henderson 15680bb2ff7SRichard Henderson /* Start all cpus at the PALcode RESET entry point. */ 15780bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) { 158ad601177SAndreas Färber cpus[i]->env.pc = palcode_entry; 159ad601177SAndreas Färber cpus[i]->env.palbr = palcode_entry; 16080bb2ff7SRichard Henderson } 16180bb2ff7SRichard Henderson 16280bb2ff7SRichard Henderson /* Load a kernel. */ 16380bb2ff7SRichard Henderson if (kernel_filename) { 16480bb2ff7SRichard Henderson uint64_t param_offset; 16580bb2ff7SRichard Henderson 1664366e1dbSLiam Merwick size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys, 167617160c9SBALATON Zoltan NULL, &kernel_entry, &kernel_low, NULL, NULL, 1687ef295eaSPeter Crosthwaite 0, EM_ALPHA, 0, 0); 16980bb2ff7SRichard Henderson if (size < 0) { 170c525436eSMarkus Armbruster error_report("could not load kernel '%s'", kernel_filename); 17180bb2ff7SRichard Henderson exit(1); 17280bb2ff7SRichard Henderson } 17380bb2ff7SRichard Henderson 174ad601177SAndreas Färber cpus[0]->env.trap_arg1 = kernel_entry; 17580bb2ff7SRichard Henderson 17680bb2ff7SRichard Henderson param_offset = kernel_low - 0x6000; 17780bb2ff7SRichard Henderson 17880bb2ff7SRichard Henderson if (kernel_cmdline) { 17980bb2ff7SRichard Henderson pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); 18080bb2ff7SRichard Henderson } 18180bb2ff7SRichard Henderson 18280bb2ff7SRichard Henderson if (initrd_filename) { 183f3839fdaSLi Zhijian long initrd_base; 184f3839fdaSLi Zhijian int64_t initrd_size; 18580bb2ff7SRichard Henderson 18680bb2ff7SRichard Henderson initrd_size = get_image_size(initrd_filename); 18780bb2ff7SRichard Henderson if (initrd_size < 0) { 188c525436eSMarkus Armbruster error_report("could not load initial ram disk '%s'", 18980bb2ff7SRichard Henderson initrd_filename); 19080bb2ff7SRichard Henderson exit(1); 19180bb2ff7SRichard Henderson } 19280bb2ff7SRichard Henderson 19380bb2ff7SRichard Henderson /* Put the initrd image as high in memory as possible. */ 19480bb2ff7SRichard Henderson initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; 19580bb2ff7SRichard Henderson load_image_targphys(initrd_filename, initrd_base, 19680bb2ff7SRichard Henderson ram_size - initrd_base); 19780bb2ff7SRichard Henderson 19842874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x100, 19942874d3aSPeter Maydell initrd_base + 0xfffffc0000000000ULL, 20042874d3aSPeter Maydell MEMTXATTRS_UNSPECIFIED, 20142874d3aSPeter Maydell NULL); 20242874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x108, 20342874d3aSPeter Maydell initrd_size, MEMTXATTRS_UNSPECIFIED, NULL); 20480bb2ff7SRichard Henderson } 20580bb2ff7SRichard Henderson } 20680bb2ff7SRichard Henderson } 20780bb2ff7SRichard Henderson 208e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc) 20980bb2ff7SRichard Henderson { 210e264d29dSEduardo Habkost mc->desc = "Alpha DP264/CLIPPER"; 211e264d29dSEduardo Habkost mc->init = clipper_init; 2122059839bSMarkus Armbruster mc->block_default_type = IF_IDE; 213e264d29dSEduardo Habkost mc->max_cpus = 4; 214ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true; 215fb92da84SIgor Mammedov mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67"); 216b844d822SIgor Mammedov mc->default_ram_id = "ram"; 217*cdd684b8SThomas Huth mc->default_nic = "e1000"; 21880bb2ff7SRichard Henderson } 21980bb2ff7SRichard Henderson 220e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init) 221