|
1 /* |
|
2 * QEMU Sun4u/Sun4v System Emulator |
|
3 * |
|
4 * Copyright (c) 2005 Fabrice Bellard |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 #include "hw.h" |
|
25 #include "pci.h" |
|
26 #include "pc.h" |
|
27 #include "nvram.h" |
|
28 #include "fdc.h" |
|
29 #include "net.h" |
|
30 #include "qemu-timer.h" |
|
31 #include "sysemu.h" |
|
32 #include "boards.h" |
|
33 #include "firmware_abi.h" |
|
34 #include "fw_cfg.h" |
|
35 |
|
36 //#define DEBUG_IRQ |
|
37 |
|
38 #ifdef DEBUG_IRQ |
|
39 #define DPRINTF(fmt, args...) \ |
|
40 do { printf("CPUIRQ: " fmt , ##args); } while (0) |
|
41 #else |
|
42 #define DPRINTF(fmt, args...) |
|
43 #endif |
|
44 |
|
45 #define KERNEL_LOAD_ADDR 0x00404000 |
|
46 #define CMDLINE_ADDR 0x003ff000 |
|
47 #define INITRD_LOAD_ADDR 0x00300000 |
|
48 #define PROM_SIZE_MAX (4 * 1024 * 1024) |
|
49 #define PROM_VADDR 0x000ffd00000ULL |
|
50 #define APB_SPECIAL_BASE 0x1fe00000000ULL |
|
51 #define APB_MEM_BASE 0x1ff00000000ULL |
|
52 #define VGA_BASE (APB_MEM_BASE + 0x400000ULL) |
|
53 #define PROM_FILENAME "openbios-sparc64" |
|
54 #define NVRAM_SIZE 0x2000 |
|
55 #define MAX_IDE_BUS 2 |
|
56 #define BIOS_CFG_IOPORT 0x510 |
|
57 |
|
58 #define MAX_PILS 16 |
|
59 |
|
60 #define TICK_INT_DIS 0x8000000000000000ULL |
|
61 #define TICK_MAX 0x7fffffffffffffffULL |
|
62 |
|
63 struct hwdef { |
|
64 const char * const default_cpu_model; |
|
65 uint16_t machine_id; |
|
66 uint64_t prom_addr; |
|
67 uint64_t console_serial_base; |
|
68 }; |
|
69 |
|
70 int DMA_get_channel_mode (int nchan) |
|
71 { |
|
72 return 0; |
|
73 } |
|
74 int DMA_read_memory (int nchan, void *buf, int pos, int size) |
|
75 { |
|
76 return 0; |
|
77 } |
|
78 int DMA_write_memory (int nchan, void *buf, int pos, int size) |
|
79 { |
|
80 return 0; |
|
81 } |
|
82 void DMA_hold_DREQ (int nchan) {} |
|
83 void DMA_release_DREQ (int nchan) {} |
|
84 void DMA_schedule(int nchan) {} |
|
85 void DMA_init (int high_page_enable) {} |
|
86 void DMA_register_channel (int nchan, |
|
87 DMA_transfer_handler transfer_handler, |
|
88 void *opaque) |
|
89 { |
|
90 } |
|
91 |
|
92 static int nvram_boot_set(void *opaque, const char *boot_device) |
|
93 { |
|
94 unsigned int i; |
|
95 uint8_t image[sizeof(ohwcfg_v3_t)]; |
|
96 ohwcfg_v3_t *header = (ohwcfg_v3_t *)ℑ |
|
97 m48t59_t *nvram = (m48t59_t *)opaque; |
|
98 |
|
99 for (i = 0; i < sizeof(image); i++) |
|
100 image[i] = m48t59_read(nvram, i) & 0xff; |
|
101 |
|
102 pstrcpy((char *)header->boot_devices, sizeof(header->boot_devices), |
|
103 boot_device); |
|
104 header->nboot_devices = strlen(boot_device) & 0xff; |
|
105 header->crc = cpu_to_be16(OHW_compute_crc(header, 0x00, 0xF8)); |
|
106 |
|
107 for (i = 0; i < sizeof(image); i++) |
|
108 m48t59_write(nvram, i, image[i]); |
|
109 |
|
110 return 0; |
|
111 } |
|
112 |
|
113 static int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, |
|
114 const char *arch, |
|
115 ram_addr_t RAM_size, |
|
116 const char *boot_devices, |
|
117 uint32_t kernel_image, uint32_t kernel_size, |
|
118 const char *cmdline, |
|
119 uint32_t initrd_image, uint32_t initrd_size, |
|
120 uint32_t NVRAM_image, |
|
121 int width, int height, int depth, |
|
122 const uint8_t *macaddr) |
|
123 { |
|
124 unsigned int i; |
|
125 uint32_t start, end; |
|
126 uint8_t image[0x1ff0]; |
|
127 ohwcfg_v3_t *header = (ohwcfg_v3_t *)ℑ |
|
128 struct sparc_arch_cfg *sparc_header; |
|
129 struct OpenBIOS_nvpart_v1 *part_header; |
|
130 |
|
131 memset(image, '\0', sizeof(image)); |
|
132 |
|
133 // Try to match PPC NVRAM |
|
134 pstrcpy((char *)header->struct_ident, sizeof(header->struct_ident), |
|
135 "QEMU_BIOS"); |
|
136 header->struct_version = cpu_to_be32(3); /* structure v3 */ |
|
137 |
|
138 header->nvram_size = cpu_to_be16(NVRAM_size); |
|
139 header->nvram_arch_ptr = cpu_to_be16(sizeof(ohwcfg_v3_t)); |
|
140 header->nvram_arch_size = cpu_to_be16(sizeof(struct sparc_arch_cfg)); |
|
141 pstrcpy((char *)header->arch, sizeof(header->arch), arch); |
|
142 header->nb_cpus = smp_cpus & 0xff; |
|
143 header->RAM0_base = 0; |
|
144 header->RAM0_size = cpu_to_be64((uint64_t)RAM_size); |
|
145 pstrcpy((char *)header->boot_devices, sizeof(header->boot_devices), |
|
146 boot_devices); |
|
147 header->nboot_devices = strlen(boot_devices) & 0xff; |
|
148 header->kernel_image = cpu_to_be64((uint64_t)kernel_image); |
|
149 header->kernel_size = cpu_to_be64((uint64_t)kernel_size); |
|
150 if (cmdline) { |
|
151 pstrcpy_targphys(CMDLINE_ADDR, TARGET_PAGE_SIZE, cmdline); |
|
152 header->cmdline = cpu_to_be64((uint64_t)CMDLINE_ADDR); |
|
153 header->cmdline_size = cpu_to_be64((uint64_t)strlen(cmdline)); |
|
154 } |
|
155 header->initrd_image = cpu_to_be64((uint64_t)initrd_image); |
|
156 header->initrd_size = cpu_to_be64((uint64_t)initrd_size); |
|
157 header->NVRAM_image = cpu_to_be64((uint64_t)NVRAM_image); |
|
158 |
|
159 header->width = cpu_to_be16(width); |
|
160 header->height = cpu_to_be16(height); |
|
161 header->depth = cpu_to_be16(depth); |
|
162 if (nographic) |
|
163 header->graphic_flags = cpu_to_be16(OHW_GF_NOGRAPHICS); |
|
164 |
|
165 header->crc = cpu_to_be16(OHW_compute_crc(header, 0x00, 0xF8)); |
|
166 |
|
167 // Architecture specific header |
|
168 start = sizeof(ohwcfg_v3_t); |
|
169 sparc_header = (struct sparc_arch_cfg *)&image[start]; |
|
170 sparc_header->valid = 0; |
|
171 start += sizeof(struct sparc_arch_cfg); |
|
172 |
|
173 // OpenBIOS nvram variables |
|
174 // Variable partition |
|
175 part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
|
176 part_header->signature = OPENBIOS_PART_SYSTEM; |
|
177 pstrcpy(part_header->name, sizeof(part_header->name), "system"); |
|
178 |
|
179 end = start + sizeof(struct OpenBIOS_nvpart_v1); |
|
180 for (i = 0; i < nb_prom_envs; i++) |
|
181 end = OpenBIOS_set_var(image, end, prom_envs[i]); |
|
182 |
|
183 // End marker |
|
184 image[end++] = '\0'; |
|
185 |
|
186 end = start + ((end - start + 15) & ~15); |
|
187 OpenBIOS_finish_partition(part_header, end - start); |
|
188 |
|
189 // free partition |
|
190 start = end; |
|
191 part_header = (struct OpenBIOS_nvpart_v1 *)&image[start]; |
|
192 part_header->signature = OPENBIOS_PART_FREE; |
|
193 pstrcpy(part_header->name, sizeof(part_header->name), "free"); |
|
194 |
|
195 end = 0x1fd0; |
|
196 OpenBIOS_finish_partition(part_header, end - start); |
|
197 |
|
198 Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80); |
|
199 |
|
200 for (i = 0; i < sizeof(image); i++) |
|
201 m48t59_write(nvram, i, image[i]); |
|
202 |
|
203 qemu_register_boot_set(nvram_boot_set, nvram); |
|
204 |
|
205 return 0; |
|
206 } |
|
207 |
|
208 void pic_info(void) |
|
209 { |
|
210 } |
|
211 |
|
212 void irq_info(void) |
|
213 { |
|
214 } |
|
215 |
|
216 void cpu_check_irqs(CPUState *env) |
|
217 { |
|
218 uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) | |
|
219 ((env->softint & SOFTINT_TIMER) << 14); |
|
220 |
|
221 if (pil && (env->interrupt_index == 0 || |
|
222 (env->interrupt_index & ~15) == TT_EXTINT)) { |
|
223 unsigned int i; |
|
224 |
|
225 for (i = 15; i > 0; i--) { |
|
226 if (pil & (1 << i)) { |
|
227 int old_interrupt = env->interrupt_index; |
|
228 |
|
229 env->interrupt_index = TT_EXTINT | i; |
|
230 if (old_interrupt != env->interrupt_index) { |
|
231 DPRINTF("Set CPU IRQ %d\n", i); |
|
232 cpu_interrupt(env, CPU_INTERRUPT_HARD); |
|
233 } |
|
234 break; |
|
235 } |
|
236 } |
|
237 } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) { |
|
238 DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); |
|
239 env->interrupt_index = 0; |
|
240 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
|
241 } |
|
242 } |
|
243 |
|
244 static void cpu_set_irq(void *opaque, int irq, int level) |
|
245 { |
|
246 CPUState *env = opaque; |
|
247 |
|
248 if (level) { |
|
249 DPRINTF("Raise CPU IRQ %d\n", irq); |
|
250 env->halted = 0; |
|
251 env->pil_in |= 1 << irq; |
|
252 cpu_check_irqs(env); |
|
253 } else { |
|
254 DPRINTF("Lower CPU IRQ %d\n", irq); |
|
255 env->pil_in &= ~(1 << irq); |
|
256 cpu_check_irqs(env); |
|
257 } |
|
258 } |
|
259 |
|
260 void qemu_system_powerdown(void) |
|
261 { |
|
262 } |
|
263 |
|
264 typedef struct ResetData { |
|
265 CPUState *env; |
|
266 uint64_t reset_addr; |
|
267 } ResetData; |
|
268 |
|
269 static void main_cpu_reset(void *opaque) |
|
270 { |
|
271 ResetData *s = (ResetData *)opaque; |
|
272 CPUState *env = s->env; |
|
273 |
|
274 cpu_reset(env); |
|
275 env->tick_cmpr = TICK_INT_DIS | 0; |
|
276 ptimer_set_limit(env->tick, TICK_MAX, 1); |
|
277 ptimer_run(env->tick, 0); |
|
278 env->stick_cmpr = TICK_INT_DIS | 0; |
|
279 ptimer_set_limit(env->stick, TICK_MAX, 1); |
|
280 ptimer_run(env->stick, 0); |
|
281 env->hstick_cmpr = TICK_INT_DIS | 0; |
|
282 ptimer_set_limit(env->hstick, TICK_MAX, 1); |
|
283 ptimer_run(env->hstick, 0); |
|
284 env->gregs[1] = 0; // Memory start |
|
285 env->gregs[2] = ram_size; // Memory size |
|
286 env->gregs[3] = 0; // Machine description XXX |
|
287 env->pc = s->reset_addr; |
|
288 env->npc = env->pc + 4; |
|
289 } |
|
290 |
|
291 static void tick_irq(void *opaque) |
|
292 { |
|
293 CPUState *env = opaque; |
|
294 |
|
295 if (!(env->tick_cmpr & TICK_INT_DIS)) { |
|
296 env->softint |= SOFTINT_TIMER; |
|
297 cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
|
298 } |
|
299 } |
|
300 |
|
301 static void stick_irq(void *opaque) |
|
302 { |
|
303 CPUState *env = opaque; |
|
304 |
|
305 if (!(env->stick_cmpr & TICK_INT_DIS)) { |
|
306 env->softint |= SOFTINT_STIMER; |
|
307 cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
|
308 } |
|
309 } |
|
310 |
|
311 static void hstick_irq(void *opaque) |
|
312 { |
|
313 CPUState *env = opaque; |
|
314 |
|
315 if (!(env->hstick_cmpr & TICK_INT_DIS)) { |
|
316 cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
|
317 } |
|
318 } |
|
319 |
|
320 void cpu_tick_set_count(void *opaque, uint64_t count) |
|
321 { |
|
322 ptimer_set_count(opaque, -count); |
|
323 } |
|
324 |
|
325 uint64_t cpu_tick_get_count(void *opaque) |
|
326 { |
|
327 return -ptimer_get_count(opaque); |
|
328 } |
|
329 |
|
330 void cpu_tick_set_limit(void *opaque, uint64_t limit) |
|
331 { |
|
332 ptimer_set_limit(opaque, -limit, 0); |
|
333 } |
|
334 |
|
335 static const int ide_iobase[2] = { 0x1f0, 0x170 }; |
|
336 static const int ide_iobase2[2] = { 0x3f6, 0x376 }; |
|
337 static const int ide_irq[2] = { 14, 15 }; |
|
338 |
|
339 static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; |
|
340 static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; |
|
341 |
|
342 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; |
|
343 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; |
|
344 |
|
345 static fdctrl_t *floppy_controller; |
|
346 |
|
347 static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, |
|
348 const char *boot_devices, DisplayState *ds, |
|
349 const char *kernel_filename, const char *kernel_cmdline, |
|
350 const char *initrd_filename, const char *cpu_model, |
|
351 const struct hwdef *hwdef) |
|
352 { |
|
353 CPUState *env; |
|
354 char buf[1024]; |
|
355 m48t59_t *nvram; |
|
356 int ret, linux_boot; |
|
357 unsigned int i; |
|
358 ram_addr_t ram_offset, prom_offset, vga_ram_offset; |
|
359 long initrd_size, kernel_size; |
|
360 PCIBus *pci_bus; |
|
361 QEMUBH *bh; |
|
362 qemu_irq *irq; |
|
363 int drive_index; |
|
364 BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; |
|
365 BlockDriverState *fd[MAX_FD]; |
|
366 void *fw_cfg; |
|
367 ResetData *reset_info; |
|
368 |
|
369 linux_boot = (kernel_filename != NULL); |
|
370 |
|
371 /* init CPUs */ |
|
372 if (!cpu_model) |
|
373 cpu_model = hwdef->default_cpu_model; |
|
374 |
|
375 env = cpu_init(cpu_model); |
|
376 if (!env) { |
|
377 fprintf(stderr, "Unable to find Sparc CPU definition\n"); |
|
378 exit(1); |
|
379 } |
|
380 bh = qemu_bh_new(tick_irq, env); |
|
381 env->tick = ptimer_init(bh); |
|
382 ptimer_set_period(env->tick, 1ULL); |
|
383 |
|
384 bh = qemu_bh_new(stick_irq, env); |
|
385 env->stick = ptimer_init(bh); |
|
386 ptimer_set_period(env->stick, 1ULL); |
|
387 |
|
388 bh = qemu_bh_new(hstick_irq, env); |
|
389 env->hstick = ptimer_init(bh); |
|
390 ptimer_set_period(env->hstick, 1ULL); |
|
391 |
|
392 reset_info = qemu_mallocz(sizeof(ResetData)); |
|
393 reset_info->env = env; |
|
394 reset_info->reset_addr = hwdef->prom_addr + 0x40ULL; |
|
395 qemu_register_reset(main_cpu_reset, reset_info); |
|
396 main_cpu_reset(reset_info); |
|
397 // Override warm reset address with cold start address |
|
398 env->pc = hwdef->prom_addr + 0x20ULL; |
|
399 env->npc = env->pc + 4; |
|
400 |
|
401 /* allocate RAM */ |
|
402 ram_offset = qemu_ram_alloc(RAM_size); |
|
403 cpu_register_physical_memory(0, RAM_size, ram_offset); |
|
404 |
|
405 prom_offset = qemu_ram_alloc(PROM_SIZE_MAX); |
|
406 cpu_register_physical_memory(hwdef->prom_addr, |
|
407 (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & |
|
408 TARGET_PAGE_MASK, |
|
409 prom_offset | IO_MEM_ROM); |
|
410 |
|
411 if (bios_name == NULL) |
|
412 bios_name = PROM_FILENAME; |
|
413 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); |
|
414 ret = load_elf(buf, hwdef->prom_addr - PROM_VADDR, NULL, NULL, NULL); |
|
415 if (ret < 0) { |
|
416 ret = load_image_targphys(buf, hwdef->prom_addr, |
|
417 (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & |
|
418 TARGET_PAGE_MASK); |
|
419 if (ret < 0) { |
|
420 fprintf(stderr, "qemu: could not load prom '%s'\n", |
|
421 buf); |
|
422 exit(1); |
|
423 } |
|
424 } |
|
425 |
|
426 kernel_size = 0; |
|
427 initrd_size = 0; |
|
428 if (linux_boot) { |
|
429 /* XXX: put correct offset */ |
|
430 kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL); |
|
431 if (kernel_size < 0) |
|
432 kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, |
|
433 ram_size - KERNEL_LOAD_ADDR); |
|
434 if (kernel_size < 0) |
|
435 kernel_size = load_image_targphys(kernel_filename, |
|
436 KERNEL_LOAD_ADDR, |
|
437 ram_size - KERNEL_LOAD_ADDR); |
|
438 if (kernel_size < 0) { |
|
439 fprintf(stderr, "qemu: could not load kernel '%s'\n", |
|
440 kernel_filename); |
|
441 exit(1); |
|
442 } |
|
443 |
|
444 /* load initrd */ |
|
445 if (initrd_filename) { |
|
446 initrd_size = load_image_targphys(initrd_filename, |
|
447 INITRD_LOAD_ADDR, |
|
448 ram_size - INITRD_LOAD_ADDR); |
|
449 if (initrd_size < 0) { |
|
450 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |
|
451 initrd_filename); |
|
452 exit(1); |
|
453 } |
|
454 } |
|
455 if (initrd_size > 0) { |
|
456 for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) { |
|
457 if (ldl_phys(KERNEL_LOAD_ADDR + i) == 0x48647253) { // HdrS |
|
458 stl_phys(KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR); |
|
459 stl_phys(KERNEL_LOAD_ADDR + i + 20, initrd_size); |
|
460 break; |
|
461 } |
|
462 } |
|
463 } |
|
464 } |
|
465 pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL); |
|
466 isa_mem_base = VGA_BASE; |
|
467 vga_ram_offset = qemu_ram_alloc(vga_ram_size); |
|
468 pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + vga_ram_offset, |
|
469 vga_ram_offset, vga_ram_size); |
|
470 |
|
471 i = 0; |
|
472 if (hwdef->console_serial_base) { |
|
473 serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200, |
|
474 serial_hds[i], 1); |
|
475 i++; |
|
476 } |
|
477 for(; i < MAX_SERIAL_PORTS; i++) { |
|
478 if (serial_hds[i]) { |
|
479 serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200, |
|
480 serial_hds[i]); |
|
481 } |
|
482 } |
|
483 |
|
484 for(i = 0; i < MAX_PARALLEL_PORTS; i++) { |
|
485 if (parallel_hds[i]) { |
|
486 parallel_init(parallel_io[i], NULL/*parallel_irq[i]*/, |
|
487 parallel_hds[i]); |
|
488 } |
|
489 } |
|
490 |
|
491 for(i = 0; i < nb_nics; i++) { |
|
492 if (!nd_table[i].model) |
|
493 nd_table[i].model = "ne2k_pci"; |
|
494 pci_nic_init(pci_bus, &nd_table[i], -1); |
|
495 } |
|
496 |
|
497 irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); |
|
498 if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { |
|
499 fprintf(stderr, "qemu: too many IDE bus\n"); |
|
500 exit(1); |
|
501 } |
|
502 for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { |
|
503 drive_index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, |
|
504 i % MAX_IDE_DEVS); |
|
505 if (drive_index != -1) |
|
506 hd[i] = drives_table[drive_index].bdrv; |
|
507 else |
|
508 hd[i] = NULL; |
|
509 } |
|
510 |
|
511 // XXX pci_cmd646_ide_init(pci_bus, hd, 1); |
|
512 pci_piix3_ide_init(pci_bus, hd, -1, irq); |
|
513 /* FIXME: wire up interrupts. */ |
|
514 i8042_init(NULL/*1*/, NULL/*12*/, 0x60); |
|
515 for(i = 0; i < MAX_FD; i++) { |
|
516 drive_index = drive_get_index(IF_FLOPPY, 0, i); |
|
517 if (drive_index != -1) |
|
518 fd[i] = drives_table[drive_index].bdrv; |
|
519 else |
|
520 fd[i] = NULL; |
|
521 } |
|
522 floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd); |
|
523 nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59); |
|
524 sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices, |
|
525 KERNEL_LOAD_ADDR, kernel_size, |
|
526 kernel_cmdline, |
|
527 INITRD_LOAD_ADDR, initrd_size, |
|
528 /* XXX: need an option to load a NVRAM image */ |
|
529 0, |
|
530 graphic_width, graphic_height, graphic_depth, |
|
531 (uint8_t *)&nd_table[0].macaddr); |
|
532 |
|
533 fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); |
|
534 fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); |
|
535 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); |
|
536 fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); |
|
537 } |
|
538 |
|
539 enum { |
|
540 sun4u_id = 0, |
|
541 sun4v_id = 64, |
|
542 niagara_id, |
|
543 }; |
|
544 |
|
545 static const struct hwdef hwdefs[] = { |
|
546 /* Sun4u generic PC-like machine */ |
|
547 { |
|
548 .default_cpu_model = "TI UltraSparc II", |
|
549 .machine_id = sun4u_id, |
|
550 .prom_addr = 0x1fff0000000ULL, |
|
551 .console_serial_base = 0, |
|
552 }, |
|
553 /* Sun4v generic PC-like machine */ |
|
554 { |
|
555 .default_cpu_model = "Sun UltraSparc T1", |
|
556 .machine_id = sun4v_id, |
|
557 .prom_addr = 0x1fff0000000ULL, |
|
558 .console_serial_base = 0, |
|
559 }, |
|
560 /* Sun4v generic Niagara machine */ |
|
561 { |
|
562 .default_cpu_model = "Sun UltraSparc T1", |
|
563 .machine_id = niagara_id, |
|
564 .prom_addr = 0xfff0000000ULL, |
|
565 .console_serial_base = 0xfff0c2c000ULL, |
|
566 }, |
|
567 }; |
|
568 |
|
569 /* Sun4u hardware initialisation */ |
|
570 static void sun4u_init(ram_addr_t RAM_size, int vga_ram_size, |
|
571 const char *boot_devices, DisplayState *ds, |
|
572 const char *kernel_filename, const char *kernel_cmdline, |
|
573 const char *initrd_filename, const char *cpu_model) |
|
574 { |
|
575 sun4uv_init(RAM_size, vga_ram_size, boot_devices, ds, kernel_filename, |
|
576 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]); |
|
577 } |
|
578 |
|
579 /* Sun4v hardware initialisation */ |
|
580 static void sun4v_init(ram_addr_t RAM_size, int vga_ram_size, |
|
581 const char *boot_devices, DisplayState *ds, |
|
582 const char *kernel_filename, const char *kernel_cmdline, |
|
583 const char *initrd_filename, const char *cpu_model) |
|
584 { |
|
585 sun4uv_init(RAM_size, vga_ram_size, boot_devices, ds, kernel_filename, |
|
586 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]); |
|
587 } |
|
588 |
|
589 /* Niagara hardware initialisation */ |
|
590 static void niagara_init(ram_addr_t RAM_size, int vga_ram_size, |
|
591 const char *boot_devices, DisplayState *ds, |
|
592 const char *kernel_filename, const char *kernel_cmdline, |
|
593 const char *initrd_filename, const char *cpu_model) |
|
594 { |
|
595 sun4uv_init(RAM_size, vga_ram_size, boot_devices, ds, kernel_filename, |
|
596 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]); |
|
597 } |
|
598 |
|
599 QEMUMachine sun4u_machine = { |
|
600 .name = "sun4u", |
|
601 .desc = "Sun4u platform", |
|
602 .init = sun4u_init, |
|
603 .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE, |
|
604 .nodisk_ok = 1, |
|
605 .max_cpus = 1, // XXX for now |
|
606 }; |
|
607 |
|
608 QEMUMachine sun4v_machine = { |
|
609 .name = "sun4v", |
|
610 .desc = "Sun4v platform", |
|
611 .init = sun4v_init, |
|
612 .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE, |
|
613 .nodisk_ok = 1, |
|
614 .max_cpus = 1, // XXX for now |
|
615 }; |
|
616 |
|
617 QEMUMachine niagara_machine = { |
|
618 .name = "Niagara", |
|
619 .desc = "Sun4v platform, Niagara", |
|
620 .init = niagara_init, |
|
621 .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE, |
|
622 .nodisk_ok = 1, |
|
623 .max_cpus = 1, // XXX for now |
|
624 }; |