xref: /qemu/hw/alpha/dp264.c (revision 2c65db5e58d2c74921077f6c064ba4c91ebde16a)
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"
169c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
17bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
1825297910SMark Cave-Ayland #include "hw/ide/pci.h"
190d09e41aSPaolo Bonzini #include "hw/timer/i8254.h"
20a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h"
21f4564fc0SPhilippe Mathieu-Daudé #include "hw/dma/i8257.h"
22852c27e2SPaolo Bonzini #include "net/net.h"
23f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
24*2c65db5eSPaolo Bonzini #include "qemu/datadir.h"
25b58337ffSPhilippe Mathieu-Daudé #include "net/net.h"
2680bb2ff7SRichard Henderson 
2780bb2ff7SRichard Henderson #define MAX_IDE_BUS 2
2880bb2ff7SRichard Henderson 
2980bb2ff7SRichard Henderson static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
3080bb2ff7SRichard Henderson {
3180bb2ff7SRichard Henderson     if (((addr >> 41) & 3) == 2) {
3280bb2ff7SRichard Henderson         addr &= 0xffffffffffull;
3380bb2ff7SRichard Henderson     }
3480bb2ff7SRichard Henderson     return addr;
3580bb2ff7SRichard Henderson }
3680bb2ff7SRichard Henderson 
3780bb2ff7SRichard Henderson /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
3880bb2ff7SRichard Henderson     (0) The dev_irq_n lines into the cpu, which we totally ignore,
3980bb2ff7SRichard Henderson     (1) The DRIR lines in the typhoon chipset,
4080bb2ff7SRichard Henderson     (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
4180bb2ff7SRichard Henderson     (3) The interrupt number assigned by the kernel.
4280bb2ff7SRichard Henderson    The following function is concerned with (1) only.  */
4380bb2ff7SRichard Henderson 
4480bb2ff7SRichard Henderson static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
4580bb2ff7SRichard Henderson {
4680bb2ff7SRichard Henderson     int slot = d->devfn >> 3;
4780bb2ff7SRichard Henderson 
4880bb2ff7SRichard Henderson     assert(irq_num >= 0 && irq_num <= 3);
4980bb2ff7SRichard Henderson 
5080bb2ff7SRichard Henderson     return (slot + 1) * 4 + irq_num;
5180bb2ff7SRichard Henderson }
5280bb2ff7SRichard Henderson 
533ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine)
5480bb2ff7SRichard Henderson {
553ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
563ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
573ef96221SMarcel Apfelbaum     const char *kernel_cmdline = machine->kernel_cmdline;
583ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
59ad601177SAndreas Färber     AlphaCPU *cpus[4];
6080bb2ff7SRichard Henderson     PCIBus *pci_bus;
61be1765f3SBALATON Zoltan     PCIDevice *pci_dev;
6248a18b3cSHervé Poussineau     ISABus *isa_bus;
6380bb2ff7SRichard Henderson     qemu_irq rtc_irq;
6480bb2ff7SRichard Henderson     long size, i;
65c18f8556SShannon Zhao     char *palcode_filename;
66617160c9SBALATON Zoltan     uint64_t palcode_entry;
67617160c9SBALATON Zoltan     uint64_t kernel_entry, kernel_low;
6833decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
6980bb2ff7SRichard Henderson 
7080bb2ff7SRichard Henderson     /* Create up to 4 cpus.  */
7180bb2ff7SRichard Henderson     memset(cpus, 0, sizeof(cpus));
7280bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
73fb92da84SIgor Mammedov         cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
7480bb2ff7SRichard Henderson     }
7580bb2ff7SRichard Henderson 
76ad601177SAndreas Färber     cpus[0]->env.trap_arg0 = ram_size;
77ad601177SAndreas Färber     cpus[0]->env.trap_arg1 = 0;
78ad601177SAndreas Färber     cpus[0]->env.trap_arg2 = smp_cpus;
7980bb2ff7SRichard Henderson 
8080bb2ff7SRichard Henderson     /* Init the chipset.  */
81b844d822SIgor Mammedov     pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus,
8271baa303SHervé Poussineau                            clipper_pci_map_irq);
8380bb2ff7SRichard Henderson 
84e605e969SRichard Henderson     /* Since we have an SRM-compatible PALcode, use the SRM epoch.  */
856c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(isa_bus, 1900, rtc_irq);
86e605e969SRichard Henderson 
87acf695ecSPhilippe Mathieu-Daudé     i8254_pit_init(isa_bus, 0x40, 0, NULL);
8880bb2ff7SRichard Henderson 
8980bb2ff7SRichard Henderson     /* VGA setup.  Don't bother loading the bios.  */
90606f90ccSAurelien Jarno     pci_vga_init(pci_bus);
9180bb2ff7SRichard Henderson 
9280bb2ff7SRichard Henderson     /* Network setup.  e1000 is good enough, failing Tulip support.  */
9380bb2ff7SRichard Henderson     for (i = 0; i < nb_nics; i++) {
9429b358f9SDavid Gibson         pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
9580bb2ff7SRichard Henderson     }
9680bb2ff7SRichard Henderson 
97f4564fc0SPhilippe Mathieu-Daudé     /* 2 82C37 (dma) */
98f4564fc0SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, "i82374");
99f4564fc0SPhilippe Mathieu-Daudé 
100a4cb7739SPhilippe Mathieu-Daudé     /* Super I/O */
101a4cb7739SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
102a4cb7739SPhilippe Mathieu-Daudé 
10380bb2ff7SRichard Henderson     /* IDE disk setup.  */
10425297910SMark Cave-Ayland     pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
105be1765f3SBALATON Zoltan     pci_ide_create_devs(pci_dev);
10680bb2ff7SRichard Henderson 
10780bb2ff7SRichard Henderson     /* Load PALcode.  Given that this is not "real" cpu palcode,
10880bb2ff7SRichard Henderson        but one explicitly written for the emulation, we might as
10980bb2ff7SRichard Henderson        well load it directly from and ELF image.  */
110c18f8556SShannon Zhao     palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
1112c4a83ebSPaolo Bonzini                                       machine->firmware ?: "palcode-clipper");
11280bb2ff7SRichard Henderson     if (palcode_filename == NULL) {
113c525436eSMarkus Armbruster         error_report("no palcode provided");
11480bb2ff7SRichard Henderson         exit(1);
11580bb2ff7SRichard Henderson     }
1164366e1dbSLiam Merwick     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
117617160c9SBALATON Zoltan                     NULL, &palcode_entry, NULL, NULL, NULL,
1187ef295eaSPeter Crosthwaite                     0, EM_ALPHA, 0, 0);
11980bb2ff7SRichard Henderson     if (size < 0) {
120c525436eSMarkus Armbruster         error_report("could not load palcode '%s'", palcode_filename);
12180bb2ff7SRichard Henderson         exit(1);
12280bb2ff7SRichard Henderson     }
123c18f8556SShannon Zhao     g_free(palcode_filename);
12480bb2ff7SRichard Henderson 
12580bb2ff7SRichard Henderson     /* Start all cpus at the PALcode RESET entry point.  */
12680bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
127ad601177SAndreas Färber         cpus[i]->env.pc = palcode_entry;
128ad601177SAndreas Färber         cpus[i]->env.palbr = palcode_entry;
12980bb2ff7SRichard Henderson     }
13080bb2ff7SRichard Henderson 
13180bb2ff7SRichard Henderson     /* Load a kernel.  */
13280bb2ff7SRichard Henderson     if (kernel_filename) {
13380bb2ff7SRichard Henderson         uint64_t param_offset;
13480bb2ff7SRichard Henderson 
1354366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
136617160c9SBALATON Zoltan                         NULL, &kernel_entry, &kernel_low, NULL, NULL,
1377ef295eaSPeter Crosthwaite                         0, EM_ALPHA, 0, 0);
13880bb2ff7SRichard Henderson         if (size < 0) {
139c525436eSMarkus Armbruster             error_report("could not load kernel '%s'", kernel_filename);
14080bb2ff7SRichard Henderson             exit(1);
14180bb2ff7SRichard Henderson         }
14280bb2ff7SRichard Henderson 
143ad601177SAndreas Färber         cpus[0]->env.trap_arg1 = kernel_entry;
14480bb2ff7SRichard Henderson 
14580bb2ff7SRichard Henderson         param_offset = kernel_low - 0x6000;
14680bb2ff7SRichard Henderson 
14780bb2ff7SRichard Henderson         if (kernel_cmdline) {
14880bb2ff7SRichard Henderson             pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
14980bb2ff7SRichard Henderson         }
15080bb2ff7SRichard Henderson 
15180bb2ff7SRichard Henderson         if (initrd_filename) {
152f3839fdaSLi Zhijian             long initrd_base;
153f3839fdaSLi Zhijian             int64_t initrd_size;
15480bb2ff7SRichard Henderson 
15580bb2ff7SRichard Henderson             initrd_size = get_image_size(initrd_filename);
15680bb2ff7SRichard Henderson             if (initrd_size < 0) {
157c525436eSMarkus Armbruster                 error_report("could not load initial ram disk '%s'",
15880bb2ff7SRichard Henderson                              initrd_filename);
15980bb2ff7SRichard Henderson                 exit(1);
16080bb2ff7SRichard Henderson             }
16180bb2ff7SRichard Henderson 
16280bb2ff7SRichard Henderson             /* Put the initrd image as high in memory as possible.  */
16380bb2ff7SRichard Henderson             initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
16480bb2ff7SRichard Henderson             load_image_targphys(initrd_filename, initrd_base,
16580bb2ff7SRichard Henderson                                 ram_size - initrd_base);
16680bb2ff7SRichard Henderson 
16742874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x100,
16842874d3aSPeter Maydell                               initrd_base + 0xfffffc0000000000ULL,
16942874d3aSPeter Maydell                               MEMTXATTRS_UNSPECIFIED,
17042874d3aSPeter Maydell                               NULL);
17142874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x108,
17242874d3aSPeter Maydell                               initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
17380bb2ff7SRichard Henderson         }
17480bb2ff7SRichard Henderson     }
17580bb2ff7SRichard Henderson }
17680bb2ff7SRichard Henderson 
177e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
17880bb2ff7SRichard Henderson {
179e264d29dSEduardo Habkost     mc->desc = "Alpha DP264/CLIPPER";
180e264d29dSEduardo Habkost     mc->init = clipper_init;
1812059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
182e264d29dSEduardo Habkost     mc->max_cpus = 4;
183ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
184fb92da84SIgor Mammedov     mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
185b844d822SIgor Mammedov     mc->default_ram_id = "ram";
18680bb2ff7SRichard Henderson }
18780bb2ff7SRichard Henderson 
188e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
189