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 "qemu-common.h" 114771d756SPaolo Bonzini #include "cpu.h" 1280bb2ff7SRichard Henderson #include "elf.h" 1383c9f4caSPaolo Bonzini #include "hw/loader.h" 1447b43a1fSPaolo Bonzini #include "alpha_sys.h" 15c525436eSMarkus Armbruster #include "qemu/error-report.h" 16bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 1725297910SMark Cave-Ayland #include "hw/ide/pci.h" 18a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h" 19852c27e2SPaolo Bonzini #include "net/net.h" 20f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 212c65db5eSPaolo Bonzini #include "qemu/datadir.h" 22b58337ffSPhilippe Mathieu-Daudé #include "net/net.h" 2380bb2ff7SRichard Henderson 2480bb2ff7SRichard Henderson #define MAX_IDE_BUS 2 2580bb2ff7SRichard Henderson 2680bb2ff7SRichard Henderson static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) 2780bb2ff7SRichard Henderson { 2880bb2ff7SRichard Henderson if (((addr >> 41) & 3) == 2) { 2980bb2ff7SRichard Henderson addr &= 0xffffffffffull; 3080bb2ff7SRichard Henderson } 3180bb2ff7SRichard Henderson return addr; 3280bb2ff7SRichard Henderson } 3380bb2ff7SRichard Henderson 3480bb2ff7SRichard Henderson /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. 3580bb2ff7SRichard Henderson (0) The dev_irq_n lines into the cpu, which we totally ignore, 3680bb2ff7SRichard Henderson (1) The DRIR lines in the typhoon chipset, 3780bb2ff7SRichard Henderson (2) The "vector" aka mangled interrupt number reported by SRM PALcode, 3880bb2ff7SRichard Henderson (3) The interrupt number assigned by the kernel. 3980bb2ff7SRichard Henderson The following function is concerned with (1) only. */ 4080bb2ff7SRichard Henderson 4180bb2ff7SRichard Henderson static int clipper_pci_map_irq(PCIDevice *d, int irq_num) 4280bb2ff7SRichard Henderson { 4380bb2ff7SRichard Henderson int slot = d->devfn >> 3; 4480bb2ff7SRichard Henderson 4580bb2ff7SRichard Henderson assert(irq_num >= 0 && irq_num <= 3); 4680bb2ff7SRichard Henderson 4780bb2ff7SRichard Henderson return (slot + 1) * 4 + irq_num; 4880bb2ff7SRichard Henderson } 4980bb2ff7SRichard Henderson 503ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine) 5180bb2ff7SRichard Henderson { 523ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size; 533ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 543ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 553ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 56ad601177SAndreas Färber AlphaCPU *cpus[4]; 5780bb2ff7SRichard Henderson PCIBus *pci_bus; 58be1765f3SBALATON Zoltan PCIDevice *pci_dev; 59*5ec4f1d3SJason Thorpe DeviceState *i82378_dev; 6048a18b3cSHervé Poussineau ISABus *isa_bus; 6180bb2ff7SRichard Henderson qemu_irq rtc_irq; 62*5ec4f1d3SJason Thorpe qemu_irq isa_irq; 6380bb2ff7SRichard Henderson long size, i; 64c18f8556SShannon Zhao char *palcode_filename; 65617160c9SBALATON Zoltan uint64_t palcode_entry; 66617160c9SBALATON Zoltan uint64_t kernel_entry, kernel_low; 6733decbd2SLike Xu unsigned int smp_cpus = machine->smp.cpus; 6880bb2ff7SRichard Henderson 6980bb2ff7SRichard Henderson /* Create up to 4 cpus. */ 7080bb2ff7SRichard Henderson memset(cpus, 0, sizeof(cpus)); 7180bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) { 72fb92da84SIgor Mammedov cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type)); 7380bb2ff7SRichard Henderson } 7480bb2ff7SRichard Henderson 75387a1dcbSJason Thorpe /* 76387a1dcbSJason Thorpe * arg0 -> memory size 77387a1dcbSJason Thorpe * arg1 -> kernel entry point 78387a1dcbSJason Thorpe * arg2 -> config word 79387a1dcbSJason Thorpe * 80387a1dcbSJason Thorpe * Config word: bits 0-5 -> ncpus 81387a1dcbSJason Thorpe * bit 6 -> nographics option (for HWRPB CTB) 82387a1dcbSJason Thorpe * 83387a1dcbSJason Thorpe * See init_hwrpb() in the PALcode. 84387a1dcbSJason Thorpe */ 85ad601177SAndreas Färber cpus[0]->env.trap_arg0 = ram_size; 86ad601177SAndreas Färber cpus[0]->env.trap_arg1 = 0; 87387a1dcbSJason Thorpe cpus[0]->env.trap_arg2 = smp_cpus | (!machine->enable_graphics << 6); 8880bb2ff7SRichard Henderson 893a8233dcSJason Thorpe /* 903a8233dcSJason Thorpe * Init the chipset. Because we're using CLIPPER IRQ mappings, 913a8233dcSJason Thorpe * the minimum PCI device IdSel is 1. 923a8233dcSJason Thorpe */ 93*5ec4f1d3SJason Thorpe pci_bus = typhoon_init(machine->ram, &isa_irq, &rtc_irq, cpus, 943a8233dcSJason Thorpe clipper_pci_map_irq, PCI_DEVFN(1, 0)); 9580bb2ff7SRichard Henderson 96*5ec4f1d3SJason Thorpe /* 97*5ec4f1d3SJason Thorpe * Init the PCI -> ISA bridge. 98*5ec4f1d3SJason Thorpe * 99*5ec4f1d3SJason Thorpe * Technically, PCI-based Alphas shipped with one of three different 100*5ec4f1d3SJason Thorpe * PCI-ISA bridges: 101*5ec4f1d3SJason Thorpe * 102*5ec4f1d3SJason Thorpe * - Intel i82378 SIO 103*5ec4f1d3SJason Thorpe * - Cypress CY82c693UB 104*5ec4f1d3SJason Thorpe * - ALI M1533 105*5ec4f1d3SJason Thorpe * 106*5ec4f1d3SJason Thorpe * (An Intel i82375 PCI-EISA bridge was also used on some models.) 107*5ec4f1d3SJason Thorpe * 108*5ec4f1d3SJason Thorpe * For simplicity, we model an i82378 here, even though it wouldn't 109*5ec4f1d3SJason Thorpe * have been on any Tsunami/Typhoon systems; it's close enough, and 110*5ec4f1d3SJason Thorpe * we don't want to deal with modelling the CY82c693UB (which has 111*5ec4f1d3SJason Thorpe * incompatible edge/level control registers, plus other peripherals 112*5ec4f1d3SJason Thorpe * like IDE and USB) or the M1533 (which also has IDE and USB). 113*5ec4f1d3SJason Thorpe * 114*5ec4f1d3SJason Thorpe * Importantly, we need to provide a PCI device node for it, otherwise 115*5ec4f1d3SJason Thorpe * some operating systems won't notice there's an ISA bus to configure. 116*5ec4f1d3SJason Thorpe */ 117*5ec4f1d3SJason Thorpe i82378_dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(7, 0), "i82378")); 118*5ec4f1d3SJason Thorpe isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0")); 119*5ec4f1d3SJason Thorpe 120*5ec4f1d3SJason Thorpe /* Connect the ISA PIC to the Typhoon IRQ used for ISA interrupts. */ 121*5ec4f1d3SJason Thorpe qdev_connect_gpio_out(i82378_dev, 0, isa_irq); 122*5ec4f1d3SJason Thorpe 123e605e969SRichard Henderson /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ 1246c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(isa_bus, 1900, rtc_irq); 125e605e969SRichard Henderson 12680bb2ff7SRichard Henderson /* VGA setup. Don't bother loading the bios. */ 127606f90ccSAurelien Jarno pci_vga_init(pci_bus); 12880bb2ff7SRichard Henderson 12980bb2ff7SRichard Henderson /* Network setup. e1000 is good enough, failing Tulip support. */ 13080bb2ff7SRichard Henderson for (i = 0; i < nb_nics; i++) { 13129b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); 13280bb2ff7SRichard Henderson } 13380bb2ff7SRichard Henderson 134a4cb7739SPhilippe Mathieu-Daudé /* Super I/O */ 135a4cb7739SPhilippe Mathieu-Daudé isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO); 136a4cb7739SPhilippe Mathieu-Daudé 13780bb2ff7SRichard Henderson /* IDE disk setup. */ 13825297910SMark Cave-Ayland pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide"); 139be1765f3SBALATON Zoltan pci_ide_create_devs(pci_dev); 14080bb2ff7SRichard Henderson 14180bb2ff7SRichard Henderson /* Load PALcode. Given that this is not "real" cpu palcode, 14280bb2ff7SRichard Henderson but one explicitly written for the emulation, we might as 14380bb2ff7SRichard Henderson well load it directly from and ELF image. */ 144c18f8556SShannon Zhao palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, 1452c4a83ebSPaolo Bonzini machine->firmware ?: "palcode-clipper"); 14680bb2ff7SRichard Henderson if (palcode_filename == NULL) { 147c525436eSMarkus Armbruster error_report("no palcode provided"); 14880bb2ff7SRichard Henderson exit(1); 14980bb2ff7SRichard Henderson } 1504366e1dbSLiam Merwick size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys, 151617160c9SBALATON Zoltan NULL, &palcode_entry, NULL, NULL, NULL, 1527ef295eaSPeter Crosthwaite 0, EM_ALPHA, 0, 0); 15380bb2ff7SRichard Henderson if (size < 0) { 154c525436eSMarkus Armbruster error_report("could not load palcode '%s'", palcode_filename); 15580bb2ff7SRichard Henderson exit(1); 15680bb2ff7SRichard Henderson } 157c18f8556SShannon Zhao g_free(palcode_filename); 15880bb2ff7SRichard Henderson 15980bb2ff7SRichard Henderson /* Start all cpus at the PALcode RESET entry point. */ 16080bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) { 161ad601177SAndreas Färber cpus[i]->env.pc = palcode_entry; 162ad601177SAndreas Färber cpus[i]->env.palbr = palcode_entry; 16380bb2ff7SRichard Henderson } 16480bb2ff7SRichard Henderson 16580bb2ff7SRichard Henderson /* Load a kernel. */ 16680bb2ff7SRichard Henderson if (kernel_filename) { 16780bb2ff7SRichard Henderson uint64_t param_offset; 16880bb2ff7SRichard Henderson 1694366e1dbSLiam Merwick size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys, 170617160c9SBALATON Zoltan NULL, &kernel_entry, &kernel_low, NULL, NULL, 1717ef295eaSPeter Crosthwaite 0, EM_ALPHA, 0, 0); 17280bb2ff7SRichard Henderson if (size < 0) { 173c525436eSMarkus Armbruster error_report("could not load kernel '%s'", kernel_filename); 17480bb2ff7SRichard Henderson exit(1); 17580bb2ff7SRichard Henderson } 17680bb2ff7SRichard Henderson 177ad601177SAndreas Färber cpus[0]->env.trap_arg1 = kernel_entry; 17880bb2ff7SRichard Henderson 17980bb2ff7SRichard Henderson param_offset = kernel_low - 0x6000; 18080bb2ff7SRichard Henderson 18180bb2ff7SRichard Henderson if (kernel_cmdline) { 18280bb2ff7SRichard Henderson pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); 18380bb2ff7SRichard Henderson } 18480bb2ff7SRichard Henderson 18580bb2ff7SRichard Henderson if (initrd_filename) { 186f3839fdaSLi Zhijian long initrd_base; 187f3839fdaSLi Zhijian int64_t initrd_size; 18880bb2ff7SRichard Henderson 18980bb2ff7SRichard Henderson initrd_size = get_image_size(initrd_filename); 19080bb2ff7SRichard Henderson if (initrd_size < 0) { 191c525436eSMarkus Armbruster error_report("could not load initial ram disk '%s'", 19280bb2ff7SRichard Henderson initrd_filename); 19380bb2ff7SRichard Henderson exit(1); 19480bb2ff7SRichard Henderson } 19580bb2ff7SRichard Henderson 19680bb2ff7SRichard Henderson /* Put the initrd image as high in memory as possible. */ 19780bb2ff7SRichard Henderson initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; 19880bb2ff7SRichard Henderson load_image_targphys(initrd_filename, initrd_base, 19980bb2ff7SRichard Henderson ram_size - initrd_base); 20080bb2ff7SRichard Henderson 20142874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x100, 20242874d3aSPeter Maydell initrd_base + 0xfffffc0000000000ULL, 20342874d3aSPeter Maydell MEMTXATTRS_UNSPECIFIED, 20442874d3aSPeter Maydell NULL); 20542874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x108, 20642874d3aSPeter Maydell initrd_size, MEMTXATTRS_UNSPECIFIED, NULL); 20780bb2ff7SRichard Henderson } 20880bb2ff7SRichard Henderson } 20980bb2ff7SRichard Henderson } 21080bb2ff7SRichard Henderson 211e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc) 21280bb2ff7SRichard Henderson { 213e264d29dSEduardo Habkost mc->desc = "Alpha DP264/CLIPPER"; 214e264d29dSEduardo Habkost mc->init = clipper_init; 2152059839bSMarkus Armbruster mc->block_default_type = IF_IDE; 216e264d29dSEduardo Habkost mc->max_cpus = 4; 217ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true; 218fb92da84SIgor Mammedov mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67"); 219b844d822SIgor Mammedov mc->default_ram_id = "ram"; 22080bb2ff7SRichard Henderson } 22180bb2ff7SRichard Henderson 222e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init) 223