xref: /qemu/hw/alpha/dp264.c (revision 387a1dcb351be6a6ec4e27d36173df2de1017bcc)
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"
180d09e41aSPaolo Bonzini #include "hw/timer/i8254.h"
19a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h"
20f4564fc0SPhilippe Mathieu-Daudé #include "hw/dma/i8257.h"
21852c27e2SPaolo Bonzini #include "net/net.h"
22f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
232c65db5eSPaolo Bonzini #include "qemu/datadir.h"
24b58337ffSPhilippe Mathieu-Daudé #include "net/net.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;
60be1765f3SBALATON Zoltan     PCIDevice *pci_dev;
6148a18b3cSHervé Poussineau     ISABus *isa_bus;
6280bb2ff7SRichard Henderson     qemu_irq rtc_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 
75*387a1dcbSJason Thorpe     /*
76*387a1dcbSJason Thorpe      * arg0 -> memory size
77*387a1dcbSJason Thorpe      * arg1 -> kernel entry point
78*387a1dcbSJason Thorpe      * arg2 -> config word
79*387a1dcbSJason Thorpe      *
80*387a1dcbSJason Thorpe      * Config word: bits 0-5 -> ncpus
81*387a1dcbSJason Thorpe      *              bit  6   -> nographics option (for HWRPB CTB)
82*387a1dcbSJason Thorpe      *
83*387a1dcbSJason Thorpe      * See init_hwrpb() in the PALcode.
84*387a1dcbSJason Thorpe      */
85ad601177SAndreas Färber     cpus[0]->env.trap_arg0 = ram_size;
86ad601177SAndreas Färber     cpus[0]->env.trap_arg1 = 0;
87*387a1dcbSJason 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      */
93b844d822SIgor Mammedov     pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus,
943a8233dcSJason Thorpe                            clipper_pci_map_irq, PCI_DEVFN(1, 0));
9580bb2ff7SRichard Henderson 
96e605e969SRichard Henderson     /* Since we have an SRM-compatible PALcode, use the SRM epoch.  */
976c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(isa_bus, 1900, rtc_irq);
98e605e969SRichard Henderson 
99acf695ecSPhilippe Mathieu-Daudé     i8254_pit_init(isa_bus, 0x40, 0, NULL);
10080bb2ff7SRichard Henderson 
10180bb2ff7SRichard Henderson     /* VGA setup.  Don't bother loading the bios.  */
102606f90ccSAurelien Jarno     pci_vga_init(pci_bus);
10380bb2ff7SRichard Henderson 
10480bb2ff7SRichard Henderson     /* Network setup.  e1000 is good enough, failing Tulip support.  */
10580bb2ff7SRichard Henderson     for (i = 0; i < nb_nics; i++) {
10629b358f9SDavid Gibson         pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
10780bb2ff7SRichard Henderson     }
10880bb2ff7SRichard Henderson 
109f4564fc0SPhilippe Mathieu-Daudé     /* 2 82C37 (dma) */
110f4564fc0SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, "i82374");
111f4564fc0SPhilippe Mathieu-Daudé 
112a4cb7739SPhilippe Mathieu-Daudé     /* Super I/O */
113a4cb7739SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
114a4cb7739SPhilippe Mathieu-Daudé 
11580bb2ff7SRichard Henderson     /* IDE disk setup.  */
11625297910SMark Cave-Ayland     pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
117be1765f3SBALATON Zoltan     pci_ide_create_devs(pci_dev);
11880bb2ff7SRichard Henderson 
11980bb2ff7SRichard Henderson     /* Load PALcode.  Given that this is not "real" cpu palcode,
12080bb2ff7SRichard Henderson        but one explicitly written for the emulation, we might as
12180bb2ff7SRichard Henderson        well load it directly from and ELF image.  */
122c18f8556SShannon Zhao     palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
1232c4a83ebSPaolo Bonzini                                       machine->firmware ?: "palcode-clipper");
12480bb2ff7SRichard Henderson     if (palcode_filename == NULL) {
125c525436eSMarkus Armbruster         error_report("no palcode provided");
12680bb2ff7SRichard Henderson         exit(1);
12780bb2ff7SRichard Henderson     }
1284366e1dbSLiam Merwick     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
129617160c9SBALATON Zoltan                     NULL, &palcode_entry, NULL, NULL, NULL,
1307ef295eaSPeter Crosthwaite                     0, EM_ALPHA, 0, 0);
13180bb2ff7SRichard Henderson     if (size < 0) {
132c525436eSMarkus Armbruster         error_report("could not load palcode '%s'", palcode_filename);
13380bb2ff7SRichard Henderson         exit(1);
13480bb2ff7SRichard Henderson     }
135c18f8556SShannon Zhao     g_free(palcode_filename);
13680bb2ff7SRichard Henderson 
13780bb2ff7SRichard Henderson     /* Start all cpus at the PALcode RESET entry point.  */
13880bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
139ad601177SAndreas Färber         cpus[i]->env.pc = palcode_entry;
140ad601177SAndreas Färber         cpus[i]->env.palbr = palcode_entry;
14180bb2ff7SRichard Henderson     }
14280bb2ff7SRichard Henderson 
14380bb2ff7SRichard Henderson     /* Load a kernel.  */
14480bb2ff7SRichard Henderson     if (kernel_filename) {
14580bb2ff7SRichard Henderson         uint64_t param_offset;
14680bb2ff7SRichard Henderson 
1474366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
148617160c9SBALATON Zoltan                         NULL, &kernel_entry, &kernel_low, NULL, NULL,
1497ef295eaSPeter Crosthwaite                         0, EM_ALPHA, 0, 0);
15080bb2ff7SRichard Henderson         if (size < 0) {
151c525436eSMarkus Armbruster             error_report("could not load kernel '%s'", kernel_filename);
15280bb2ff7SRichard Henderson             exit(1);
15380bb2ff7SRichard Henderson         }
15480bb2ff7SRichard Henderson 
155ad601177SAndreas Färber         cpus[0]->env.trap_arg1 = kernel_entry;
15680bb2ff7SRichard Henderson 
15780bb2ff7SRichard Henderson         param_offset = kernel_low - 0x6000;
15880bb2ff7SRichard Henderson 
15980bb2ff7SRichard Henderson         if (kernel_cmdline) {
16080bb2ff7SRichard Henderson             pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
16180bb2ff7SRichard Henderson         }
16280bb2ff7SRichard Henderson 
16380bb2ff7SRichard Henderson         if (initrd_filename) {
164f3839fdaSLi Zhijian             long initrd_base;
165f3839fdaSLi Zhijian             int64_t initrd_size;
16680bb2ff7SRichard Henderson 
16780bb2ff7SRichard Henderson             initrd_size = get_image_size(initrd_filename);
16880bb2ff7SRichard Henderson             if (initrd_size < 0) {
169c525436eSMarkus Armbruster                 error_report("could not load initial ram disk '%s'",
17080bb2ff7SRichard Henderson                              initrd_filename);
17180bb2ff7SRichard Henderson                 exit(1);
17280bb2ff7SRichard Henderson             }
17380bb2ff7SRichard Henderson 
17480bb2ff7SRichard Henderson             /* Put the initrd image as high in memory as possible.  */
17580bb2ff7SRichard Henderson             initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
17680bb2ff7SRichard Henderson             load_image_targphys(initrd_filename, initrd_base,
17780bb2ff7SRichard Henderson                                 ram_size - initrd_base);
17880bb2ff7SRichard Henderson 
17942874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x100,
18042874d3aSPeter Maydell                               initrd_base + 0xfffffc0000000000ULL,
18142874d3aSPeter Maydell                               MEMTXATTRS_UNSPECIFIED,
18242874d3aSPeter Maydell                               NULL);
18342874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x108,
18442874d3aSPeter Maydell                               initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
18580bb2ff7SRichard Henderson         }
18680bb2ff7SRichard Henderson     }
18780bb2ff7SRichard Henderson }
18880bb2ff7SRichard Henderson 
189e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
19080bb2ff7SRichard Henderson {
191e264d29dSEduardo Habkost     mc->desc = "Alpha DP264/CLIPPER";
192e264d29dSEduardo Habkost     mc->init = clipper_init;
1932059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
194e264d29dSEduardo Habkost     mc->max_cpus = 4;
195ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
196fb92da84SIgor Mammedov     mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
197b844d822SIgor Mammedov     mc->default_ram_id = "ram";
19880bb2ff7SRichard Henderson }
19980bb2ff7SRichard Henderson 
200e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
201