xref: /qemu/hw/alpha/dp264.c (revision cdd684b8e1cb7cfa5818d9eb7b9eaa9b7b4d717e)
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