xref: /qemu/hw/alpha/dp264.c (revision 4366e1db16a3ec7bf24171e5c7619c8ea038e43b)
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"
1283c9f4caSPaolo Bonzini #include "hw/hw.h"
1380bb2ff7SRichard Henderson #include "elf.h"
1483c9f4caSPaolo Bonzini #include "hw/loader.h"
1583c9f4caSPaolo Bonzini #include "hw/boards.h"
1647b43a1fSPaolo Bonzini #include "alpha_sys.h"
17c525436eSMarkus Armbruster #include "qemu/error-report.h"
189c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
190d09e41aSPaolo Bonzini #include "hw/timer/mc146818rtc.h"
2083c9f4caSPaolo Bonzini #include "hw/ide.h"
210d09e41aSPaolo Bonzini #include "hw/timer/i8254.h"
22a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h"
23f4564fc0SPhilippe Mathieu-Daudé #include "hw/dma/i8257.h"
24f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
2580bb2ff7SRichard Henderson 
2680bb2ff7SRichard Henderson #define MAX_IDE_BUS 2
2780bb2ff7SRichard Henderson 
2880bb2ff7SRichard Henderson static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
2980bb2ff7SRichard Henderson {
3080bb2ff7SRichard Henderson     if (((addr >> 41) & 3) == 2) {
3180bb2ff7SRichard Henderson         addr &= 0xffffffffffull;
3280bb2ff7SRichard Henderson     }
3380bb2ff7SRichard Henderson     return addr;
3480bb2ff7SRichard Henderson }
3580bb2ff7SRichard Henderson 
3680bb2ff7SRichard Henderson /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
3780bb2ff7SRichard Henderson     (0) The dev_irq_n lines into the cpu, which we totally ignore,
3880bb2ff7SRichard Henderson     (1) The DRIR lines in the typhoon chipset,
3980bb2ff7SRichard Henderson     (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
4080bb2ff7SRichard Henderson     (3) The interrupt number assigned by the kernel.
4180bb2ff7SRichard Henderson    The following function is concerned with (1) only.  */
4280bb2ff7SRichard Henderson 
4380bb2ff7SRichard Henderson static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
4480bb2ff7SRichard Henderson {
4580bb2ff7SRichard Henderson     int slot = d->devfn >> 3;
4680bb2ff7SRichard Henderson 
4780bb2ff7SRichard Henderson     assert(irq_num >= 0 && irq_num <= 3);
4880bb2ff7SRichard Henderson 
4980bb2ff7SRichard Henderson     return (slot + 1) * 4 + irq_num;
5080bb2ff7SRichard Henderson }
5180bb2ff7SRichard Henderson 
523ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine)
5380bb2ff7SRichard Henderson {
543ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
553ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
563ef96221SMarcel Apfelbaum     const char *kernel_cmdline = machine->kernel_cmdline;
573ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
58ad601177SAndreas Färber     AlphaCPU *cpus[4];
5980bb2ff7SRichard Henderson     PCIBus *pci_bus;
6048a18b3cSHervé Poussineau     ISABus *isa_bus;
6180bb2ff7SRichard Henderson     qemu_irq rtc_irq;
6280bb2ff7SRichard Henderson     long size, i;
63c18f8556SShannon Zhao     char *palcode_filename;
6480bb2ff7SRichard Henderson     uint64_t palcode_entry, palcode_low, palcode_high;
6580bb2ff7SRichard Henderson     uint64_t kernel_entry, kernel_low, kernel_high;
6680bb2ff7SRichard Henderson 
6780bb2ff7SRichard Henderson     /* Create up to 4 cpus.  */
6880bb2ff7SRichard Henderson     memset(cpus, 0, sizeof(cpus));
6980bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
70fb92da84SIgor Mammedov         cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
7180bb2ff7SRichard Henderson     }
7280bb2ff7SRichard Henderson 
73ad601177SAndreas Färber     cpus[0]->env.trap_arg0 = ram_size;
74ad601177SAndreas Färber     cpus[0]->env.trap_arg1 = 0;
75ad601177SAndreas Färber     cpus[0]->env.trap_arg2 = smp_cpus;
7680bb2ff7SRichard Henderson 
7780bb2ff7SRichard Henderson     /* Init the chipset.  */
7871baa303SHervé Poussineau     pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
7971baa303SHervé Poussineau                            clipper_pci_map_irq);
8080bb2ff7SRichard Henderson 
81e605e969SRichard Henderson     /* Since we have an SRM-compatible PALcode, use the SRM epoch.  */
826c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(isa_bus, 1900, rtc_irq);
83e605e969SRichard Henderson 
84acf695ecSPhilippe Mathieu-Daudé     i8254_pit_init(isa_bus, 0x40, 0, NULL);
8580bb2ff7SRichard Henderson 
8680bb2ff7SRichard Henderson     /* VGA setup.  Don't bother loading the bios.  */
87606f90ccSAurelien Jarno     pci_vga_init(pci_bus);
8880bb2ff7SRichard Henderson 
8980bb2ff7SRichard Henderson     /* Network setup.  e1000 is good enough, failing Tulip support.  */
9080bb2ff7SRichard Henderson     for (i = 0; i < nb_nics; i++) {
9129b358f9SDavid Gibson         pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
9280bb2ff7SRichard Henderson     }
9380bb2ff7SRichard Henderson 
94f4564fc0SPhilippe Mathieu-Daudé     /* 2 82C37 (dma) */
95f4564fc0SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, "i82374");
96f4564fc0SPhilippe Mathieu-Daudé 
97a4cb7739SPhilippe Mathieu-Daudé     /* Super I/O */
98a4cb7739SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
99a4cb7739SPhilippe Mathieu-Daudé 
10080bb2ff7SRichard Henderson     /* IDE disk setup.  */
10180bb2ff7SRichard Henderson     {
10280bb2ff7SRichard Henderson         DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
103d8f94e1bSJohn Snow         ide_drive_get(hd, ARRAY_SIZE(hd));
10480bb2ff7SRichard Henderson 
10580bb2ff7SRichard Henderson         pci_cmd646_ide_init(pci_bus, hd, 0);
10680bb2ff7SRichard Henderson     }
10780bb2ff7SRichard Henderson 
10880bb2ff7SRichard Henderson     /* Load PALcode.  Given that this is not "real" cpu palcode,
10980bb2ff7SRichard Henderson        but one explicitly written for the emulation, we might as
11080bb2ff7SRichard Henderson        well load it directly from and ELF image.  */
111c18f8556SShannon Zhao     palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
112c18f8556SShannon Zhao                                 bios_name ? bios_name : "palcode-clipper");
11380bb2ff7SRichard Henderson     if (palcode_filename == NULL) {
114c525436eSMarkus Armbruster         error_report("no palcode provided");
11580bb2ff7SRichard Henderson         exit(1);
11680bb2ff7SRichard Henderson     }
117*4366e1dbSLiam Merwick     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
11880bb2ff7SRichard Henderson                     NULL, &palcode_entry, &palcode_low, &palcode_high,
1197ef295eaSPeter Crosthwaite                     0, EM_ALPHA, 0, 0);
12080bb2ff7SRichard Henderson     if (size < 0) {
121c525436eSMarkus Armbruster         error_report("could not load palcode '%s'", palcode_filename);
12280bb2ff7SRichard Henderson         exit(1);
12380bb2ff7SRichard Henderson     }
124c18f8556SShannon Zhao     g_free(palcode_filename);
12580bb2ff7SRichard Henderson 
12680bb2ff7SRichard Henderson     /* Start all cpus at the PALcode RESET entry point.  */
12780bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
128ad601177SAndreas Färber         cpus[i]->env.pc = palcode_entry;
129ad601177SAndreas Färber         cpus[i]->env.palbr = palcode_entry;
13080bb2ff7SRichard Henderson     }
13180bb2ff7SRichard Henderson 
13280bb2ff7SRichard Henderson     /* Load a kernel.  */
13380bb2ff7SRichard Henderson     if (kernel_filename) {
13480bb2ff7SRichard Henderson         uint64_t param_offset;
13580bb2ff7SRichard Henderson 
136*4366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
13780bb2ff7SRichard Henderson                         NULL, &kernel_entry, &kernel_low, &kernel_high,
1387ef295eaSPeter Crosthwaite                         0, EM_ALPHA, 0, 0);
13980bb2ff7SRichard Henderson         if (size < 0) {
140c525436eSMarkus Armbruster             error_report("could not load kernel '%s'", kernel_filename);
14180bb2ff7SRichard Henderson             exit(1);
14280bb2ff7SRichard Henderson         }
14380bb2ff7SRichard Henderson 
144ad601177SAndreas Färber         cpus[0]->env.trap_arg1 = kernel_entry;
14580bb2ff7SRichard Henderson 
14680bb2ff7SRichard Henderson         param_offset = kernel_low - 0x6000;
14780bb2ff7SRichard Henderson 
14880bb2ff7SRichard Henderson         if (kernel_cmdline) {
14980bb2ff7SRichard Henderson             pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
15080bb2ff7SRichard Henderson         }
15180bb2ff7SRichard Henderson 
15280bb2ff7SRichard Henderson         if (initrd_filename) {
153f3839fdaSLi Zhijian             long initrd_base;
154f3839fdaSLi Zhijian             int64_t initrd_size;
15580bb2ff7SRichard Henderson 
15680bb2ff7SRichard Henderson             initrd_size = get_image_size(initrd_filename);
15780bb2ff7SRichard Henderson             if (initrd_size < 0) {
158c525436eSMarkus Armbruster                 error_report("could not load initial ram disk '%s'",
15980bb2ff7SRichard Henderson                              initrd_filename);
16080bb2ff7SRichard Henderson                 exit(1);
16180bb2ff7SRichard Henderson             }
16280bb2ff7SRichard Henderson 
16380bb2ff7SRichard Henderson             /* Put the initrd image as high in memory as possible.  */
16480bb2ff7SRichard Henderson             initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
16580bb2ff7SRichard Henderson             load_image_targphys(initrd_filename, initrd_base,
16680bb2ff7SRichard Henderson                                 ram_size - initrd_base);
16780bb2ff7SRichard Henderson 
16842874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x100,
16942874d3aSPeter Maydell                               initrd_base + 0xfffffc0000000000ULL,
17042874d3aSPeter Maydell                               MEMTXATTRS_UNSPECIFIED,
17142874d3aSPeter Maydell                               NULL);
17242874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x108,
17342874d3aSPeter Maydell                               initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
17480bb2ff7SRichard Henderson         }
17580bb2ff7SRichard Henderson     }
17680bb2ff7SRichard Henderson }
17780bb2ff7SRichard Henderson 
178e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
17980bb2ff7SRichard Henderson {
180e264d29dSEduardo Habkost     mc->desc = "Alpha DP264/CLIPPER";
181e264d29dSEduardo Habkost     mc->init = clipper_init;
1822059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
183e264d29dSEduardo Habkost     mc->max_cpus = 4;
184e264d29dSEduardo Habkost     mc->is_default = 1;
185fb92da84SIgor Mammedov     mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
18680bb2ff7SRichard Henderson }
18780bb2ff7SRichard Henderson 
188e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
189