root / hw / alpha_dp264.c @ c48c6522
History | View | Annotate | Download (5.3 kB)
1 | 80bb2ff7 | Richard Henderson | /*
|
---|---|---|---|
2 | 80bb2ff7 | Richard Henderson | * QEMU Alpha DP264/CLIPPER hardware system emulator.
|
3 | 80bb2ff7 | Richard Henderson | *
|
4 | 80bb2ff7 | Richard Henderson | * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
|
5 | 66a0a2cb | Dong Xu Wang | * variants because CLIPPER doesn't have an SMC669 SuperIO controller
|
6 | 80bb2ff7 | Richard Henderson | * that we need to emulate as well.
|
7 | 80bb2ff7 | Richard Henderson | */
|
8 | 80bb2ff7 | Richard Henderson | |
9 | 80bb2ff7 | Richard Henderson | #include "hw.h" |
10 | 80bb2ff7 | Richard Henderson | #include "elf.h" |
11 | 80bb2ff7 | Richard Henderson | #include "loader.h" |
12 | 80bb2ff7 | Richard Henderson | #include "boards.h" |
13 | 80bb2ff7 | Richard Henderson | #include "alpha_sys.h" |
14 | 80bb2ff7 | Richard Henderson | #include "sysemu.h" |
15 | 80bb2ff7 | Richard Henderson | #include "mc146818rtc.h" |
16 | 80bb2ff7 | Richard Henderson | #include "ide.h" |
17 | b1277b03 | Jan Kiszka | #include "i8254.h" |
18 | 80bb2ff7 | Richard Henderson | |
19 | 80bb2ff7 | Richard Henderson | #define MAX_IDE_BUS 2 |
20 | 80bb2ff7 | Richard Henderson | |
21 | 80bb2ff7 | Richard Henderson | static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) |
22 | 80bb2ff7 | Richard Henderson | { |
23 | 80bb2ff7 | Richard Henderson | if (((addr >> 41) & 3) == 2) { |
24 | 80bb2ff7 | Richard Henderson | addr &= 0xffffffffffull;
|
25 | 80bb2ff7 | Richard Henderson | } |
26 | 80bb2ff7 | Richard Henderson | return addr;
|
27 | 80bb2ff7 | Richard Henderson | } |
28 | 80bb2ff7 | Richard Henderson | |
29 | 80bb2ff7 | Richard Henderson | /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
|
30 | 80bb2ff7 | Richard Henderson | (0) The dev_irq_n lines into the cpu, which we totally ignore,
|
31 | 80bb2ff7 | Richard Henderson | (1) The DRIR lines in the typhoon chipset,
|
32 | 80bb2ff7 | Richard Henderson | (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
|
33 | 80bb2ff7 | Richard Henderson | (3) The interrupt number assigned by the kernel.
|
34 | 80bb2ff7 | Richard Henderson | The following function is concerned with (1) only. */
|
35 | 80bb2ff7 | Richard Henderson | |
36 | 80bb2ff7 | Richard Henderson | static int clipper_pci_map_irq(PCIDevice *d, int irq_num) |
37 | 80bb2ff7 | Richard Henderson | { |
38 | 80bb2ff7 | Richard Henderson | int slot = d->devfn >> 3; |
39 | 80bb2ff7 | Richard Henderson | |
40 | 80bb2ff7 | Richard Henderson | assert(irq_num >= 0 && irq_num <= 3); |
41 | 80bb2ff7 | Richard Henderson | |
42 | 80bb2ff7 | Richard Henderson | return (slot + 1) * 4 + irq_num; |
43 | 80bb2ff7 | Richard Henderson | } |
44 | 80bb2ff7 | Richard Henderson | |
45 | 80bb2ff7 | Richard Henderson | static void clipper_init(ram_addr_t ram_size, |
46 | 80bb2ff7 | Richard Henderson | const char *boot_device, |
47 | 80bb2ff7 | Richard Henderson | const char *kernel_filename, |
48 | 80bb2ff7 | Richard Henderson | const char *kernel_cmdline, |
49 | 80bb2ff7 | Richard Henderson | const char *initrd_filename, |
50 | 80bb2ff7 | Richard Henderson | const char *cpu_model) |
51 | 80bb2ff7 | Richard Henderson | { |
52 | 8b2aee29 | Andreas Färber | CPUAlphaState *cpus[4];
|
53 | 80bb2ff7 | Richard Henderson | PCIBus *pci_bus; |
54 | 48a18b3c | Hervé Poussineau | ISABus *isa_bus; |
55 | 80bb2ff7 | Richard Henderson | qemu_irq rtc_irq; |
56 | 80bb2ff7 | Richard Henderson | long size, i;
|
57 | 80bb2ff7 | Richard Henderson | const char *palcode_filename; |
58 | 80bb2ff7 | Richard Henderson | uint64_t palcode_entry, palcode_low, palcode_high; |
59 | 80bb2ff7 | Richard Henderson | uint64_t kernel_entry, kernel_low, kernel_high; |
60 | 80bb2ff7 | Richard Henderson | |
61 | 80bb2ff7 | Richard Henderson | /* Create up to 4 cpus. */
|
62 | 80bb2ff7 | Richard Henderson | memset(cpus, 0, sizeof(cpus)); |
63 | 80bb2ff7 | Richard Henderson | for (i = 0; i < smp_cpus; ++i) { |
64 | 80bb2ff7 | Richard Henderson | cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
65 | 80bb2ff7 | Richard Henderson | } |
66 | 80bb2ff7 | Richard Henderson | |
67 | 80bb2ff7 | Richard Henderson | cpus[0]->trap_arg0 = ram_size;
|
68 | 80bb2ff7 | Richard Henderson | cpus[0]->trap_arg1 = 0; |
69 | 80bb2ff7 | Richard Henderson | cpus[0]->trap_arg2 = smp_cpus;
|
70 | 80bb2ff7 | Richard Henderson | |
71 | 80bb2ff7 | Richard Henderson | /* Init the chipset. */
|
72 | 71baa303 | Hervé Poussineau | pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, |
73 | 71baa303 | Hervé Poussineau | clipper_pci_map_irq); |
74 | 80bb2ff7 | Richard Henderson | |
75 | 48a18b3c | Hervé Poussineau | rtc_init(isa_bus, 1980, rtc_irq);
|
76 | 319ba9f5 | Jan Kiszka | pit_init(isa_bus, 0x40, 0, NULL); |
77 | 48a18b3c | Hervé Poussineau | isa_create_simple(isa_bus, "i8042");
|
78 | 80bb2ff7 | Richard Henderson | |
79 | 80bb2ff7 | Richard Henderson | /* VGA setup. Don't bother loading the bios. */
|
80 | 80bb2ff7 | Richard Henderson | alpha_pci_vga_setup(pci_bus); |
81 | 80bb2ff7 | Richard Henderson | |
82 | 80bb2ff7 | Richard Henderson | /* Serial code setup. */
|
83 | 80bb2ff7 | Richard Henderson | for (i = 0; i < MAX_SERIAL_PORTS; ++i) { |
84 | 80bb2ff7 | Richard Henderson | if (serial_hds[i]) {
|
85 | 48a18b3c | Hervé Poussineau | serial_isa_init(isa_bus, i, serial_hds[i]); |
86 | 80bb2ff7 | Richard Henderson | } |
87 | 80bb2ff7 | Richard Henderson | } |
88 | 80bb2ff7 | Richard Henderson | |
89 | 80bb2ff7 | Richard Henderson | /* Network setup. e1000 is good enough, failing Tulip support. */
|
90 | 80bb2ff7 | Richard Henderson | for (i = 0; i < nb_nics; i++) { |
91 | 80bb2ff7 | Richard Henderson | pci_nic_init_nofail(&nd_table[i], "e1000", NULL); |
92 | 80bb2ff7 | Richard Henderson | } |
93 | 80bb2ff7 | Richard Henderson | |
94 | 80bb2ff7 | Richard Henderson | /* IDE disk setup. */
|
95 | 80bb2ff7 | Richard Henderson | { |
96 | 80bb2ff7 | Richard Henderson | DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
97 | 80bb2ff7 | Richard Henderson | ide_drive_get(hd, MAX_IDE_BUS); |
98 | 80bb2ff7 | Richard Henderson | |
99 | 80bb2ff7 | Richard Henderson | pci_cmd646_ide_init(pci_bus, hd, 0);
|
100 | 80bb2ff7 | Richard Henderson | } |
101 | 80bb2ff7 | Richard Henderson | |
102 | 80bb2ff7 | Richard Henderson | /* Load PALcode. Given that this is not "real" cpu palcode,
|
103 | 80bb2ff7 | Richard Henderson | but one explicitly written for the emulation, we might as
|
104 | 80bb2ff7 | Richard Henderson | well load it directly from and ELF image. */
|
105 | 80bb2ff7 | Richard Henderson | palcode_filename = (bios_name ? bios_name : "palcode-clipper");
|
106 | 80bb2ff7 | Richard Henderson | palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename); |
107 | 80bb2ff7 | Richard Henderson | if (palcode_filename == NULL) { |
108 | 80bb2ff7 | Richard Henderson | hw_error("no palcode provided\n");
|
109 | 80bb2ff7 | Richard Henderson | exit(1);
|
110 | 80bb2ff7 | Richard Henderson | } |
111 | 80bb2ff7 | Richard Henderson | size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, |
112 | 80bb2ff7 | Richard Henderson | NULL, &palcode_entry, &palcode_low, &palcode_high,
|
113 | 80bb2ff7 | Richard Henderson | 0, EM_ALPHA, 0); |
114 | 80bb2ff7 | Richard Henderson | if (size < 0) { |
115 | 80bb2ff7 | Richard Henderson | hw_error("could not load palcode '%s'\n", palcode_filename);
|
116 | 80bb2ff7 | Richard Henderson | exit(1);
|
117 | 80bb2ff7 | Richard Henderson | } |
118 | 80bb2ff7 | Richard Henderson | |
119 | 80bb2ff7 | Richard Henderson | /* Start all cpus at the PALcode RESET entry point. */
|
120 | 80bb2ff7 | Richard Henderson | for (i = 0; i < smp_cpus; ++i) { |
121 | 80bb2ff7 | Richard Henderson | cpus[i]->pal_mode = 1;
|
122 | 80bb2ff7 | Richard Henderson | cpus[i]->pc = palcode_entry; |
123 | 80bb2ff7 | Richard Henderson | cpus[i]->palbr = palcode_entry; |
124 | 80bb2ff7 | Richard Henderson | } |
125 | 80bb2ff7 | Richard Henderson | |
126 | 80bb2ff7 | Richard Henderson | /* Load a kernel. */
|
127 | 80bb2ff7 | Richard Henderson | if (kernel_filename) {
|
128 | 80bb2ff7 | Richard Henderson | uint64_t param_offset; |
129 | 80bb2ff7 | Richard Henderson | |
130 | 80bb2ff7 | Richard Henderson | size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, |
131 | 80bb2ff7 | Richard Henderson | NULL, &kernel_entry, &kernel_low, &kernel_high,
|
132 | 80bb2ff7 | Richard Henderson | 0, EM_ALPHA, 0); |
133 | 80bb2ff7 | Richard Henderson | if (size < 0) { |
134 | 80bb2ff7 | Richard Henderson | hw_error("could not load kernel '%s'\n", kernel_filename);
|
135 | 80bb2ff7 | Richard Henderson | exit(1);
|
136 | 80bb2ff7 | Richard Henderson | } |
137 | 80bb2ff7 | Richard Henderson | |
138 | 80bb2ff7 | Richard Henderson | cpus[0]->trap_arg1 = kernel_entry;
|
139 | 80bb2ff7 | Richard Henderson | |
140 | 80bb2ff7 | Richard Henderson | param_offset = kernel_low - 0x6000;
|
141 | 80bb2ff7 | Richard Henderson | |
142 | 80bb2ff7 | Richard Henderson | if (kernel_cmdline) {
|
143 | 80bb2ff7 | Richard Henderson | pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); |
144 | 80bb2ff7 | Richard Henderson | } |
145 | 80bb2ff7 | Richard Henderson | |
146 | 80bb2ff7 | Richard Henderson | if (initrd_filename) {
|
147 | 80bb2ff7 | Richard Henderson | long initrd_base, initrd_size;
|
148 | 80bb2ff7 | Richard Henderson | |
149 | 80bb2ff7 | Richard Henderson | initrd_size = get_image_size(initrd_filename); |
150 | 80bb2ff7 | Richard Henderson | if (initrd_size < 0) { |
151 | 80bb2ff7 | Richard Henderson | hw_error("could not load initial ram disk '%s'\n",
|
152 | 80bb2ff7 | Richard Henderson | initrd_filename); |
153 | 80bb2ff7 | Richard Henderson | exit(1);
|
154 | 80bb2ff7 | Richard Henderson | } |
155 | 80bb2ff7 | Richard Henderson | |
156 | 80bb2ff7 | Richard Henderson | /* Put the initrd image as high in memory as possible. */
|
157 | 80bb2ff7 | Richard Henderson | initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; |
158 | 80bb2ff7 | Richard Henderson | load_image_targphys(initrd_filename, initrd_base, |
159 | 80bb2ff7 | Richard Henderson | ram_size - initrd_base); |
160 | 80bb2ff7 | Richard Henderson | |
161 | 02d6516c | Stefan Weil | stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); |
162 | 80bb2ff7 | Richard Henderson | stq_phys(param_offset + 0x108, initrd_size);
|
163 | 80bb2ff7 | Richard Henderson | } |
164 | 80bb2ff7 | Richard Henderson | } |
165 | 80bb2ff7 | Richard Henderson | } |
166 | 80bb2ff7 | Richard Henderson | |
167 | 80bb2ff7 | Richard Henderson | static QEMUMachine clipper_machine = {
|
168 | 80bb2ff7 | Richard Henderson | .name = "clipper",
|
169 | 80bb2ff7 | Richard Henderson | .desc = "Alpha DP264/CLIPPER",
|
170 | 80bb2ff7 | Richard Henderson | .init = clipper_init, |
171 | 80bb2ff7 | Richard Henderson | .max_cpus = 4,
|
172 | 80bb2ff7 | Richard Henderson | .is_default = 1,
|
173 | 80bb2ff7 | Richard Henderson | }; |
174 | 80bb2ff7 | Richard Henderson | |
175 | 80bb2ff7 | Richard Henderson | static void clipper_machine_init(void) |
176 | 80bb2ff7 | Richard Henderson | { |
177 | 80bb2ff7 | Richard Henderson | qemu_register_machine(&clipper_machine); |
178 | 80bb2ff7 | Richard Henderson | } |
179 | 80bb2ff7 | Richard Henderson | |
180 | 80bb2ff7 | Richard Henderson | machine_init(clipper_machine_init); |