xref: /qemu/hw/alpha/dp264.c (revision 861bbc88127b834b1eee241eebe5f2d3fbff07f3)
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;
52cdd684b8SThomas 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.  */
127*861bbc88SDavid Woodhouse     pci_init_nic_devices(pci_bus, mc->default_nic);
12880bb2ff7SRichard Henderson 
129a4cb7739SPhilippe Mathieu-Daudé     /* Super I/O */
130a4cb7739SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
131a4cb7739SPhilippe Mathieu-Daudé 
13280bb2ff7SRichard Henderson     /* IDE disk setup.  */
13325297910SMark Cave-Ayland     pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
134be1765f3SBALATON Zoltan     pci_ide_create_devs(pci_dev);
13580bb2ff7SRichard Henderson 
13680bb2ff7SRichard Henderson     /* Load PALcode.  Given that this is not "real" cpu palcode,
13780bb2ff7SRichard Henderson        but one explicitly written for the emulation, we might as
13880bb2ff7SRichard Henderson        well load it directly from and ELF image.  */
139c18f8556SShannon Zhao     palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
1402c4a83ebSPaolo Bonzini                                       machine->firmware ?: "palcode-clipper");
14180bb2ff7SRichard Henderson     if (palcode_filename == NULL) {
142c525436eSMarkus Armbruster         error_report("no palcode provided");
14380bb2ff7SRichard Henderson         exit(1);
14480bb2ff7SRichard Henderson     }
1454366e1dbSLiam Merwick     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
146617160c9SBALATON Zoltan                     NULL, &palcode_entry, NULL, NULL, NULL,
1477ef295eaSPeter Crosthwaite                     0, EM_ALPHA, 0, 0);
14880bb2ff7SRichard Henderson     if (size < 0) {
149c525436eSMarkus Armbruster         error_report("could not load palcode '%s'", palcode_filename);
15080bb2ff7SRichard Henderson         exit(1);
15180bb2ff7SRichard Henderson     }
152c18f8556SShannon Zhao     g_free(palcode_filename);
15380bb2ff7SRichard Henderson 
15480bb2ff7SRichard Henderson     /* Start all cpus at the PALcode RESET entry point.  */
15580bb2ff7SRichard Henderson     for (i = 0; i < smp_cpus; ++i) {
156ad601177SAndreas Färber         cpus[i]->env.pc = palcode_entry;
157ad601177SAndreas Färber         cpus[i]->env.palbr = palcode_entry;
15880bb2ff7SRichard Henderson     }
15980bb2ff7SRichard Henderson 
16080bb2ff7SRichard Henderson     /* Load a kernel.  */
16180bb2ff7SRichard Henderson     if (kernel_filename) {
16280bb2ff7SRichard Henderson         uint64_t param_offset;
16380bb2ff7SRichard Henderson 
1644366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
165617160c9SBALATON Zoltan                         NULL, &kernel_entry, &kernel_low, NULL, NULL,
1667ef295eaSPeter Crosthwaite                         0, EM_ALPHA, 0, 0);
16780bb2ff7SRichard Henderson         if (size < 0) {
168c525436eSMarkus Armbruster             error_report("could not load kernel '%s'", kernel_filename);
16980bb2ff7SRichard Henderson             exit(1);
17080bb2ff7SRichard Henderson         }
17180bb2ff7SRichard Henderson 
172ad601177SAndreas Färber         cpus[0]->env.trap_arg1 = kernel_entry;
17380bb2ff7SRichard Henderson 
17480bb2ff7SRichard Henderson         param_offset = kernel_low - 0x6000;
17580bb2ff7SRichard Henderson 
17680bb2ff7SRichard Henderson         if (kernel_cmdline) {
17780bb2ff7SRichard Henderson             pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
17880bb2ff7SRichard Henderson         }
17980bb2ff7SRichard Henderson 
18080bb2ff7SRichard Henderson         if (initrd_filename) {
181f3839fdaSLi Zhijian             long initrd_base;
182f3839fdaSLi Zhijian             int64_t initrd_size;
18380bb2ff7SRichard Henderson 
18480bb2ff7SRichard Henderson             initrd_size = get_image_size(initrd_filename);
18580bb2ff7SRichard Henderson             if (initrd_size < 0) {
186c525436eSMarkus Armbruster                 error_report("could not load initial ram disk '%s'",
18780bb2ff7SRichard Henderson                              initrd_filename);
18880bb2ff7SRichard Henderson                 exit(1);
18980bb2ff7SRichard Henderson             }
19080bb2ff7SRichard Henderson 
19180bb2ff7SRichard Henderson             /* Put the initrd image as high in memory as possible.  */
19280bb2ff7SRichard Henderson             initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
19380bb2ff7SRichard Henderson             load_image_targphys(initrd_filename, initrd_base,
19480bb2ff7SRichard Henderson                                 ram_size - initrd_base);
19580bb2ff7SRichard Henderson 
19642874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x100,
19742874d3aSPeter Maydell                               initrd_base + 0xfffffc0000000000ULL,
19842874d3aSPeter Maydell                               MEMTXATTRS_UNSPECIFIED,
19942874d3aSPeter Maydell                               NULL);
20042874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x108,
20142874d3aSPeter Maydell                               initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
20280bb2ff7SRichard Henderson         }
20380bb2ff7SRichard Henderson     }
20480bb2ff7SRichard Henderson }
20580bb2ff7SRichard Henderson 
206e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
20780bb2ff7SRichard Henderson {
208e264d29dSEduardo Habkost     mc->desc = "Alpha DP264/CLIPPER";
209e264d29dSEduardo Habkost     mc->init = clipper_init;
2102059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
211e264d29dSEduardo Habkost     mc->max_cpus = 4;
212ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
213fb92da84SIgor Mammedov     mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
214b844d822SIgor Mammedov     mc->default_ram_id = "ram";
215cdd684b8SThomas Huth     mc->default_nic = "e1000";
21680bb2ff7SRichard Henderson }
21780bb2ff7SRichard Henderson 
218e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
219