1 | /* |
2 | * QEMU Sun4m & Sun4d & Sun4c System Emulator |
3 | * |
4 | * Copyright (c) 2003-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 | |
25 | #include "qemu/osdep.h" |
26 | #include "qemu/units.h" |
27 | #include "qapi/error.h" |
28 | #include "qemu-common.h" |
29 | #include "cpu.h" |
30 | #include "hw/sysbus.h" |
31 | #include "qemu/error-report.h" |
32 | #include "qemu/timer.h" |
33 | #include "hw/sparc/sun4m_iommu.h" |
34 | #include "hw/timer/m48t59.h" |
35 | #include "migration/vmstate.h" |
36 | #include "hw/sparc/sparc32_dma.h" |
37 | #include "hw/block/fdc.h" |
38 | #include "sysemu/reset.h" |
39 | #include "sysemu/runstate.h" |
40 | #include "sysemu/sysemu.h" |
41 | #include "net/net.h" |
42 | #include "hw/boards.h" |
43 | #include "hw/scsi/esp.h" |
44 | #include "hw/nvram/sun_nvram.h" |
45 | #include "hw/qdev-properties.h" |
46 | #include "hw/nvram/chrp_nvram.h" |
47 | #include "hw/nvram/fw_cfg.h" |
48 | #include "hw/char/escc.h" |
49 | #include "hw/empty_slot.h" |
50 | #include "hw/irq.h" |
51 | #include "hw/loader.h" |
52 | #include "elf.h" |
53 | #include "trace.h" |
54 | |
55 | /* |
56 | * Sun4m architecture was used in the following machines: |
57 | * |
58 | * SPARCserver 6xxMP/xx |
59 | * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), |
60 | * SPARCclassic X (4/10) |
61 | * SPARCstation LX/ZX (4/30) |
62 | * SPARCstation Voyager |
63 | * SPARCstation 10/xx, SPARCserver 10/xx |
64 | * SPARCstation 5, SPARCserver 5 |
65 | * SPARCstation 20/xx, SPARCserver 20 |
66 | * SPARCstation 4 |
67 | * |
68 | * See for example: http://www.sunhelp.org/faq/sunref1.html |
69 | */ |
70 | |
71 | #define KERNEL_LOAD_ADDR 0x00004000 |
72 | #define CMDLINE_ADDR 0x007ff000 |
73 | #define INITRD_LOAD_ADDR 0x00800000 |
74 | #define PROM_SIZE_MAX (1 * MiB) |
75 | #define PROM_VADDR 0xffd00000 |
76 | #define PROM_FILENAME "openbios-sparc32" |
77 | #define CFG_ADDR 0xd00000510ULL |
78 | #define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00) |
79 | #define FW_CFG_SUN4M_WIDTH (FW_CFG_ARCH_LOCAL + 0x01) |
80 | #define FW_CFG_SUN4M_HEIGHT (FW_CFG_ARCH_LOCAL + 0x02) |
81 | |
82 | #define MAX_CPUS 16 |
83 | #define MAX_PILS 16 |
84 | #define MAX_VSIMMS 4 |
85 | |
86 | #define ESCC_CLOCK 4915200 |
87 | |
88 | struct sun4m_hwdef { |
89 | hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base; |
90 | hwaddr intctl_base, counter_base, nvram_base, ms_kb_base; |
91 | hwaddr serial_base, fd_base; |
92 | hwaddr afx_base, idreg_base, dma_base, esp_base, le_base; |
93 | hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base; |
94 | hwaddr bpp_base, dbri_base, sx_base; |
95 | struct { |
96 | hwaddr reg_base, vram_base; |
97 | } vsimm[MAX_VSIMMS]; |
98 | hwaddr ecc_base; |
99 | uint64_t max_mem; |
100 | uint32_t ecc_version; |
101 | uint32_t iommu_version; |
102 | uint16_t machine_id; |
103 | uint8_t nvram_machine_id; |
104 | }; |
105 | |
106 | const char *fw_cfg_arch_key_name(uint16_t key) |
107 | { |
108 | static const struct { |
109 | uint16_t key; |
110 | const char *name; |
111 | } fw_cfg_arch_wellknown_keys[] = { |
112 | {FW_CFG_SUN4M_DEPTH, "depth" }, |
113 | {FW_CFG_SUN4M_WIDTH, "width" }, |
114 | {FW_CFG_SUN4M_HEIGHT, "height" }, |
115 | }; |
116 | |
117 | for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { |
118 | if (fw_cfg_arch_wellknown_keys[i].key == key) { |
119 | return fw_cfg_arch_wellknown_keys[i].name; |
120 | } |
121 | } |
122 | return NULL; |
123 | } |
124 | |
125 | static void fw_cfg_boot_set(void *opaque, const char *boot_device, |
126 | Error **errp) |
127 | { |
128 | fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); |
129 | } |
130 | |
131 | static void nvram_init(Nvram *nvram, uint8_t *macaddr, |
132 | const char *cmdline, const char *boot_devices, |
133 | ram_addr_t RAM_size, uint32_t kernel_size, |
134 | int width, int height, int depth, |
135 | int nvram_machine_id, const char *arch) |
136 | { |
137 | unsigned int i; |
138 | int sysp_end; |
139 | uint8_t image[0x1ff0]; |
140 | NvramClass *k = NVRAM_GET_CLASS(nvram); |
141 | |
142 | memset(image, '\0', sizeof(image)); |
143 | |
144 | /* OpenBIOS nvram variables partition */ |
145 | sysp_end = chrp_nvram_create_system_partition(image, 0); |
146 | |
147 | /* Free space partition */ |
148 | chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end); |
149 | |
150 | Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, |
151 | nvram_machine_id); |
152 | |
153 | for (i = 0; i < sizeof(image); i++) { |
154 | (k->write)(nvram, i, image[i]); |
155 | } |
156 | } |
157 | |
158 | void cpu_check_irqs(CPUSPARCState *env) |
159 | { |
160 | CPUState *cs; |
161 | |
162 | /* We should be holding the BQL before we mess with IRQs */ |
163 | g_assert(qemu_mutex_iothread_locked()); |
164 | |
165 | if (env->pil_in && (env->interrupt_index == 0 || |
166 | (env->interrupt_index & ~15) == TT_EXTINT)) { |
167 | unsigned int i; |
168 | |
169 | for (i = 15; i > 0; i--) { |
170 | if (env->pil_in & (1 << i)) { |
171 | int old_interrupt = env->interrupt_index; |
172 | |
173 | env->interrupt_index = TT_EXTINT | i; |
174 | if (old_interrupt != env->interrupt_index) { |
175 | cs = env_cpu(env); |
176 | trace_sun4m_cpu_interrupt(i); |
177 | cpu_interrupt(cs, CPU_INTERRUPT_HARD); |
178 | } |
179 | break; |
180 | } |
181 | } |
182 | } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) { |
183 | cs = env_cpu(env); |
184 | trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15); |
185 | env->interrupt_index = 0; |
186 | cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); |
187 | } |
188 | } |
189 | |
190 | static void cpu_kick_irq(SPARCCPU *cpu) |
191 | { |
192 | CPUSPARCState *env = &cpu->env; |
193 | CPUState *cs = CPU(cpu); |
194 | |
195 | cs->halted = 0; |
196 | cpu_check_irqs(env); |
197 | qemu_cpu_kick(cs); |
198 | } |
199 | |
200 | static void cpu_set_irq(void *opaque, int irq, int level) |
201 | { |
202 | SPARCCPU *cpu = opaque; |
203 | CPUSPARCState *env = &cpu->env; |
204 | |
205 | if (level) { |
206 | trace_sun4m_cpu_set_irq_raise(irq); |
207 | env->pil_in |= 1 << irq; |
208 | cpu_kick_irq(cpu); |
209 | } else { |
210 | trace_sun4m_cpu_set_irq_lower(irq); |
211 | env->pil_in &= ~(1 << irq); |
212 | cpu_check_irqs(env); |
213 | } |
214 | } |
215 | |
216 | static void dummy_cpu_set_irq(void *opaque, int irq, int level) |
217 | { |
218 | } |
219 | |
220 | static void main_cpu_reset(void *opaque) |
221 | { |
222 | SPARCCPU *cpu = opaque; |
223 | CPUState *cs = CPU(cpu); |
224 | |
225 | cpu_reset(cs); |
226 | cs->halted = 0; |
227 | } |
228 | |
229 | static void secondary_cpu_reset(void *opaque) |
230 | { |
231 | SPARCCPU *cpu = opaque; |
232 | CPUState *cs = CPU(cpu); |
233 | |
234 | cpu_reset(cs); |
235 | cs->halted = 1; |
236 | } |
237 | |
238 | static void cpu_halt_signal(void *opaque, int irq, int level) |
239 | { |
240 | if (level && current_cpu) { |
241 | cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT); |
242 | } |
243 | } |
244 | |
245 | static uint64_t translate_kernel_address(void *opaque, uint64_t addr) |
246 | { |
247 | return addr - 0xf0000000ULL; |
248 | } |
249 | |
250 | static unsigned long sun4m_load_kernel(const char *kernel_filename, |
251 | const char *initrd_filename, |
252 | ram_addr_t RAM_size, |
253 | uint32_t *initrd_size) |
254 | { |
255 | int linux_boot; |
256 | unsigned int i; |
257 | long kernel_size; |
258 | uint8_t *ptr; |
259 | |
260 | linux_boot = (kernel_filename != NULL); |
261 | |
262 | kernel_size = 0; |
263 | if (linux_boot) { |
264 | int bswap_needed; |
265 | |
266 | #ifdef BSWAP_NEEDED |
267 | bswap_needed = 1; |
268 | #else |
269 | bswap_needed = 0; |
270 | #endif |
271 | kernel_size = load_elf(kernel_filename, NULL, |
272 | translate_kernel_address, NULL, |
273 | NULL, NULL, NULL, 1, EM_SPARC, 0, 0); |
274 | if (kernel_size < 0) |
275 | kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, |
276 | RAM_size - KERNEL_LOAD_ADDR, bswap_needed, |
277 | TARGET_PAGE_SIZE); |
278 | if (kernel_size < 0) |
279 | kernel_size = load_image_targphys(kernel_filename, |
280 | KERNEL_LOAD_ADDR, |
281 | RAM_size - KERNEL_LOAD_ADDR); |
282 | if (kernel_size < 0) { |
283 | error_report("could not load kernel '%s'" , kernel_filename); |
284 | exit(1); |
285 | } |
286 | |
287 | /* load initrd */ |
288 | *initrd_size = 0; |
289 | if (initrd_filename) { |
290 | *initrd_size = load_image_targphys(initrd_filename, |
291 | INITRD_LOAD_ADDR, |
292 | RAM_size - INITRD_LOAD_ADDR); |
293 | if ((int)*initrd_size < 0) { |
294 | error_report("could not load initial ram disk '%s'" , |
295 | initrd_filename); |
296 | exit(1); |
297 | } |
298 | } |
299 | if (*initrd_size > 0) { |
300 | for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) { |
301 | ptr = rom_ptr(KERNEL_LOAD_ADDR + i, 24); |
302 | if (ptr && ldl_p(ptr) == 0x48647253) { /* HdrS */ |
303 | stl_p(ptr + 16, INITRD_LOAD_ADDR); |
304 | stl_p(ptr + 20, *initrd_size); |
305 | break; |
306 | } |
307 | } |
308 | } |
309 | } |
310 | return kernel_size; |
311 | } |
312 | |
313 | static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq) |
314 | { |
315 | DeviceState *dev; |
316 | SysBusDevice *s; |
317 | |
318 | dev = qdev_create(NULL, TYPE_SUN4M_IOMMU); |
319 | qdev_prop_set_uint32(dev, "version" , version); |
320 | qdev_init_nofail(dev); |
321 | s = SYS_BUS_DEVICE(dev); |
322 | sysbus_connect_irq(s, 0, irq); |
323 | sysbus_mmio_map(s, 0, addr); |
324 | |
325 | return s; |
326 | } |
327 | |
328 | static void *sparc32_dma_init(hwaddr dma_base, |
329 | hwaddr esp_base, qemu_irq espdma_irq, |
330 | hwaddr le_base, qemu_irq ledma_irq) |
331 | { |
332 | DeviceState *dma; |
333 | ESPDMADeviceState *espdma; |
334 | LEDMADeviceState *ledma; |
335 | SysBusESPState *esp; |
336 | SysBusPCNetState *lance; |
337 | |
338 | dma = qdev_create(NULL, TYPE_SPARC32_DMA); |
339 | qdev_init_nofail(dma); |
340 | sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, dma_base); |
341 | |
342 | espdma = SPARC32_ESPDMA_DEVICE(object_resolve_path_component( |
343 | OBJECT(dma), "espdma" )); |
344 | sysbus_connect_irq(SYS_BUS_DEVICE(espdma), 0, espdma_irq); |
345 | |
346 | esp = ESP_STATE(object_resolve_path_component(OBJECT(espdma), "esp" )); |
347 | sysbus_mmio_map(SYS_BUS_DEVICE(esp), 0, esp_base); |
348 | scsi_bus_legacy_handle_cmdline(&esp->esp.bus); |
349 | |
350 | ledma = SPARC32_LEDMA_DEVICE(object_resolve_path_component( |
351 | OBJECT(dma), "ledma" )); |
352 | sysbus_connect_irq(SYS_BUS_DEVICE(ledma), 0, ledma_irq); |
353 | |
354 | lance = SYSBUS_PCNET(object_resolve_path_component( |
355 | OBJECT(ledma), "lance" )); |
356 | sysbus_mmio_map(SYS_BUS_DEVICE(lance), 0, le_base); |
357 | |
358 | return dma; |
359 | } |
360 | |
361 | static DeviceState *slavio_intctl_init(hwaddr addr, |
362 | hwaddr addrg, |
363 | qemu_irq **parent_irq) |
364 | { |
365 | DeviceState *dev; |
366 | SysBusDevice *s; |
367 | unsigned int i, j; |
368 | |
369 | dev = qdev_create(NULL, "slavio_intctl" ); |
370 | qdev_init_nofail(dev); |
371 | |
372 | s = SYS_BUS_DEVICE(dev); |
373 | |
374 | for (i = 0; i < MAX_CPUS; i++) { |
375 | for (j = 0; j < MAX_PILS; j++) { |
376 | sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]); |
377 | } |
378 | } |
379 | sysbus_mmio_map(s, 0, addrg); |
380 | for (i = 0; i < MAX_CPUS; i++) { |
381 | sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE); |
382 | } |
383 | |
384 | return dev; |
385 | } |
386 | |
387 | #define SYS_TIMER_OFFSET 0x10000ULL |
388 | #define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu) |
389 | |
390 | static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq, |
391 | qemu_irq *cpu_irqs, unsigned int num_cpus) |
392 | { |
393 | DeviceState *dev; |
394 | SysBusDevice *s; |
395 | unsigned int i; |
396 | |
397 | dev = qdev_create(NULL, "slavio_timer" ); |
398 | qdev_prop_set_uint32(dev, "num_cpus" , num_cpus); |
399 | qdev_init_nofail(dev); |
400 | s = SYS_BUS_DEVICE(dev); |
401 | sysbus_connect_irq(s, 0, master_irq); |
402 | sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET); |
403 | |
404 | for (i = 0; i < MAX_CPUS; i++) { |
405 | sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i)); |
406 | sysbus_connect_irq(s, i + 1, cpu_irqs[i]); |
407 | } |
408 | } |
409 | |
410 | static qemu_irq slavio_system_powerdown; |
411 | |
412 | static void slavio_powerdown_req(Notifier *n, void *opaque) |
413 | { |
414 | qemu_irq_raise(slavio_system_powerdown); |
415 | } |
416 | |
417 | static Notifier slavio_system_powerdown_notifier = { |
418 | .notify = slavio_powerdown_req |
419 | }; |
420 | |
421 | #define MISC_LEDS 0x01600000 |
422 | #define MISC_CFG 0x01800000 |
423 | #define MISC_DIAG 0x01a00000 |
424 | #define MISC_MDM 0x01b00000 |
425 | #define MISC_SYS 0x01f00000 |
426 | |
427 | static void slavio_misc_init(hwaddr base, |
428 | hwaddr aux1_base, |
429 | hwaddr aux2_base, qemu_irq irq, |
430 | qemu_irq fdc_tc) |
431 | { |
432 | DeviceState *dev; |
433 | SysBusDevice *s; |
434 | |
435 | dev = qdev_create(NULL, "slavio_misc" ); |
436 | qdev_init_nofail(dev); |
437 | s = SYS_BUS_DEVICE(dev); |
438 | if (base) { |
439 | /* 8 bit registers */ |
440 | /* Slavio control */ |
441 | sysbus_mmio_map(s, 0, base + MISC_CFG); |
442 | /* Diagnostics */ |
443 | sysbus_mmio_map(s, 1, base + MISC_DIAG); |
444 | /* Modem control */ |
445 | sysbus_mmio_map(s, 2, base + MISC_MDM); |
446 | /* 16 bit registers */ |
447 | /* ss600mp diag LEDs */ |
448 | sysbus_mmio_map(s, 3, base + MISC_LEDS); |
449 | /* 32 bit registers */ |
450 | /* System control */ |
451 | sysbus_mmio_map(s, 4, base + MISC_SYS); |
452 | } |
453 | if (aux1_base) { |
454 | /* AUX 1 (Misc System Functions) */ |
455 | sysbus_mmio_map(s, 5, aux1_base); |
456 | } |
457 | if (aux2_base) { |
458 | /* AUX 2 (Software Powerdown Control) */ |
459 | sysbus_mmio_map(s, 6, aux2_base); |
460 | } |
461 | sysbus_connect_irq(s, 0, irq); |
462 | sysbus_connect_irq(s, 1, fdc_tc); |
463 | slavio_system_powerdown = qdev_get_gpio_in(dev, 0); |
464 | qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier); |
465 | } |
466 | |
467 | static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version) |
468 | { |
469 | DeviceState *dev; |
470 | SysBusDevice *s; |
471 | |
472 | dev = qdev_create(NULL, "eccmemctl" ); |
473 | qdev_prop_set_uint32(dev, "version" , version); |
474 | qdev_init_nofail(dev); |
475 | s = SYS_BUS_DEVICE(dev); |
476 | sysbus_connect_irq(s, 0, irq); |
477 | sysbus_mmio_map(s, 0, base); |
478 | if (version == 0) { // SS-600MP only |
479 | sysbus_mmio_map(s, 1, base + 0x1000); |
480 | } |
481 | } |
482 | |
483 | static void apc_init(hwaddr power_base, qemu_irq cpu_halt) |
484 | { |
485 | DeviceState *dev; |
486 | SysBusDevice *s; |
487 | |
488 | dev = qdev_create(NULL, "apc" ); |
489 | qdev_init_nofail(dev); |
490 | s = SYS_BUS_DEVICE(dev); |
491 | /* Power management (APC) XXX: not a Slavio device */ |
492 | sysbus_mmio_map(s, 0, power_base); |
493 | sysbus_connect_irq(s, 0, cpu_halt); |
494 | } |
495 | |
496 | static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width, |
497 | int height, int depth) |
498 | { |
499 | DeviceState *dev; |
500 | SysBusDevice *s; |
501 | |
502 | dev = qdev_create(NULL, "SUNW,tcx" ); |
503 | qdev_prop_set_uint32(dev, "vram_size" , vram_size); |
504 | qdev_prop_set_uint16(dev, "width" , width); |
505 | qdev_prop_set_uint16(dev, "height" , height); |
506 | qdev_prop_set_uint16(dev, "depth" , depth); |
507 | qdev_init_nofail(dev); |
508 | s = SYS_BUS_DEVICE(dev); |
509 | |
510 | /* 10/ROM : FCode ROM */ |
511 | sysbus_mmio_map(s, 0, addr); |
512 | /* 2/STIP : Stipple */ |
513 | sysbus_mmio_map(s, 1, addr + 0x04000000ULL); |
514 | /* 3/BLIT : Blitter */ |
515 | sysbus_mmio_map(s, 2, addr + 0x06000000ULL); |
516 | /* 5/RSTIP : Raw Stipple */ |
517 | sysbus_mmio_map(s, 3, addr + 0x0c000000ULL); |
518 | /* 6/RBLIT : Raw Blitter */ |
519 | sysbus_mmio_map(s, 4, addr + 0x0e000000ULL); |
520 | /* 7/TEC : Transform Engine */ |
521 | sysbus_mmio_map(s, 5, addr + 0x00700000ULL); |
522 | /* 8/CMAP : DAC */ |
523 | sysbus_mmio_map(s, 6, addr + 0x00200000ULL); |
524 | /* 9/THC : */ |
525 | if (depth == 8) { |
526 | sysbus_mmio_map(s, 7, addr + 0x00300000ULL); |
527 | } else { |
528 | sysbus_mmio_map(s, 7, addr + 0x00301000ULL); |
529 | } |
530 | /* 11/DHC : */ |
531 | sysbus_mmio_map(s, 8, addr + 0x00240000ULL); |
532 | /* 12/ALT : */ |
533 | sysbus_mmio_map(s, 9, addr + 0x00280000ULL); |
534 | /* 0/DFB8 : 8-bit plane */ |
535 | sysbus_mmio_map(s, 10, addr + 0x00800000ULL); |
536 | /* 1/DFB24 : 24bit plane */ |
537 | sysbus_mmio_map(s, 11, addr + 0x02000000ULL); |
538 | /* 4/RDFB32: Raw framebuffer. Control plane */ |
539 | sysbus_mmio_map(s, 12, addr + 0x0a000000ULL); |
540 | /* 9/THC24bits : NetBSD writes here even with 8-bit display: dummy */ |
541 | if (depth == 8) { |
542 | sysbus_mmio_map(s, 13, addr + 0x00301000ULL); |
543 | } |
544 | |
545 | sysbus_connect_irq(s, 0, irq); |
546 | } |
547 | |
548 | static void cg3_init(hwaddr addr, qemu_irq irq, int vram_size, int width, |
549 | int height, int depth) |
550 | { |
551 | DeviceState *dev; |
552 | SysBusDevice *s; |
553 | |
554 | dev = qdev_create(NULL, "cgthree" ); |
555 | qdev_prop_set_uint32(dev, "vram-size" , vram_size); |
556 | qdev_prop_set_uint16(dev, "width" , width); |
557 | qdev_prop_set_uint16(dev, "height" , height); |
558 | qdev_prop_set_uint16(dev, "depth" , depth); |
559 | qdev_init_nofail(dev); |
560 | s = SYS_BUS_DEVICE(dev); |
561 | |
562 | /* FCode ROM */ |
563 | sysbus_mmio_map(s, 0, addr); |
564 | /* DAC */ |
565 | sysbus_mmio_map(s, 1, addr + 0x400000ULL); |
566 | /* 8-bit plane */ |
567 | sysbus_mmio_map(s, 2, addr + 0x800000ULL); |
568 | |
569 | sysbus_connect_irq(s, 0, irq); |
570 | } |
571 | |
572 | /* NCR89C100/MACIO Internal ID register */ |
573 | |
574 | #define TYPE_MACIO_ID_REGISTER "macio_idreg" |
575 | |
576 | static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 }; |
577 | |
578 | static void idreg_init(hwaddr addr) |
579 | { |
580 | DeviceState *dev; |
581 | SysBusDevice *s; |
582 | |
583 | dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER); |
584 | qdev_init_nofail(dev); |
585 | s = SYS_BUS_DEVICE(dev); |
586 | |
587 | sysbus_mmio_map(s, 0, addr); |
588 | address_space_write_rom(&address_space_memory, addr, |
589 | MEMTXATTRS_UNSPECIFIED, |
590 | idreg_data, sizeof(idreg_data)); |
591 | } |
592 | |
593 | #define MACIO_ID_REGISTER(obj) \ |
594 | OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER) |
595 | |
596 | typedef struct IDRegState { |
597 | SysBusDevice parent_obj; |
598 | |
599 | MemoryRegion mem; |
600 | } IDRegState; |
601 | |
602 | static void idreg_realize(DeviceState *ds, Error **errp) |
603 | { |
604 | IDRegState *s = MACIO_ID_REGISTER(ds); |
605 | SysBusDevice *dev = SYS_BUS_DEVICE(ds); |
606 | Error *local_err = NULL; |
607 | |
608 | memory_region_init_ram_nomigrate(&s->mem, OBJECT(ds), "sun4m.idreg" , |
609 | sizeof(idreg_data), &local_err); |
610 | if (local_err) { |
611 | error_propagate(errp, local_err); |
612 | return; |
613 | } |
614 | |
615 | vmstate_register_ram_global(&s->mem); |
616 | memory_region_set_readonly(&s->mem, true); |
617 | sysbus_init_mmio(dev, &s->mem); |
618 | } |
619 | |
620 | static void idreg_class_init(ObjectClass *oc, void *data) |
621 | { |
622 | DeviceClass *dc = DEVICE_CLASS(oc); |
623 | |
624 | dc->realize = idreg_realize; |
625 | } |
626 | |
627 | static const TypeInfo idreg_info = { |
628 | .name = TYPE_MACIO_ID_REGISTER, |
629 | .parent = TYPE_SYS_BUS_DEVICE, |
630 | .instance_size = sizeof(IDRegState), |
631 | .class_init = idreg_class_init, |
632 | }; |
633 | |
634 | #define TYPE_TCX_AFX "tcx_afx" |
635 | #define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX) |
636 | |
637 | typedef struct AFXState { |
638 | SysBusDevice parent_obj; |
639 | |
640 | MemoryRegion mem; |
641 | } AFXState; |
642 | |
643 | /* SS-5 TCX AFX register */ |
644 | static void afx_init(hwaddr addr) |
645 | { |
646 | DeviceState *dev; |
647 | SysBusDevice *s; |
648 | |
649 | dev = qdev_create(NULL, TYPE_TCX_AFX); |
650 | qdev_init_nofail(dev); |
651 | s = SYS_BUS_DEVICE(dev); |
652 | |
653 | sysbus_mmio_map(s, 0, addr); |
654 | } |
655 | |
656 | static void afx_realize(DeviceState *ds, Error **errp) |
657 | { |
658 | AFXState *s = TCX_AFX(ds); |
659 | SysBusDevice *dev = SYS_BUS_DEVICE(ds); |
660 | Error *local_err = NULL; |
661 | |
662 | memory_region_init_ram_nomigrate(&s->mem, OBJECT(ds), "sun4m.afx" , 4, |
663 | &local_err); |
664 | if (local_err) { |
665 | error_propagate(errp, local_err); |
666 | return; |
667 | } |
668 | |
669 | vmstate_register_ram_global(&s->mem); |
670 | sysbus_init_mmio(dev, &s->mem); |
671 | } |
672 | |
673 | static void afx_class_init(ObjectClass *oc, void *data) |
674 | { |
675 | DeviceClass *dc = DEVICE_CLASS(oc); |
676 | |
677 | dc->realize = afx_realize; |
678 | } |
679 | |
680 | static const TypeInfo afx_info = { |
681 | .name = TYPE_TCX_AFX, |
682 | .parent = TYPE_SYS_BUS_DEVICE, |
683 | .instance_size = sizeof(AFXState), |
684 | .class_init = afx_class_init, |
685 | }; |
686 | |
687 | #define TYPE_OPENPROM "openprom" |
688 | #define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM) |
689 | |
690 | typedef struct PROMState { |
691 | SysBusDevice parent_obj; |
692 | |
693 | MemoryRegion prom; |
694 | } PROMState; |
695 | |
696 | /* Boot PROM (OpenBIOS) */ |
697 | static uint64_t translate_prom_address(void *opaque, uint64_t addr) |
698 | { |
699 | hwaddr *base_addr = (hwaddr *)opaque; |
700 | return addr + *base_addr - PROM_VADDR; |
701 | } |
702 | |
703 | static void prom_init(hwaddr addr, const char *bios_name) |
704 | { |
705 | DeviceState *dev; |
706 | SysBusDevice *s; |
707 | char *filename; |
708 | int ret; |
709 | |
710 | dev = qdev_create(NULL, TYPE_OPENPROM); |
711 | qdev_init_nofail(dev); |
712 | s = SYS_BUS_DEVICE(dev); |
713 | |
714 | sysbus_mmio_map(s, 0, addr); |
715 | |
716 | /* load boot prom */ |
717 | if (bios_name == NULL) { |
718 | bios_name = PROM_FILENAME; |
719 | } |
720 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); |
721 | if (filename) { |
722 | ret = load_elf(filename, NULL, |
723 | translate_prom_address, &addr, NULL, |
724 | NULL, NULL, 1, EM_SPARC, 0, 0); |
725 | if (ret < 0 || ret > PROM_SIZE_MAX) { |
726 | ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); |
727 | } |
728 | g_free(filename); |
729 | } else { |
730 | ret = -1; |
731 | } |
732 | if (ret < 0 || ret > PROM_SIZE_MAX) { |
733 | error_report("could not load prom '%s'" , bios_name); |
734 | exit(1); |
735 | } |
736 | } |
737 | |
738 | static void prom_realize(DeviceState *ds, Error **errp) |
739 | { |
740 | PROMState *s = OPENPROM(ds); |
741 | SysBusDevice *dev = SYS_BUS_DEVICE(ds); |
742 | Error *local_err = NULL; |
743 | |
744 | memory_region_init_ram_nomigrate(&s->prom, OBJECT(ds), "sun4m.prom" , |
745 | PROM_SIZE_MAX, &local_err); |
746 | if (local_err) { |
747 | error_propagate(errp, local_err); |
748 | return; |
749 | } |
750 | |
751 | vmstate_register_ram_global(&s->prom); |
752 | memory_region_set_readonly(&s->prom, true); |
753 | sysbus_init_mmio(dev, &s->prom); |
754 | } |
755 | |
756 | static Property prom_properties[] = { |
757 | {/* end of property list */}, |
758 | }; |
759 | |
760 | static void prom_class_init(ObjectClass *klass, void *data) |
761 | { |
762 | DeviceClass *dc = DEVICE_CLASS(klass); |
763 | |
764 | dc->props = prom_properties; |
765 | dc->realize = prom_realize; |
766 | } |
767 | |
768 | static const TypeInfo prom_info = { |
769 | .name = TYPE_OPENPROM, |
770 | .parent = TYPE_SYS_BUS_DEVICE, |
771 | .instance_size = sizeof(PROMState), |
772 | .class_init = prom_class_init, |
773 | }; |
774 | |
775 | #define TYPE_SUN4M_MEMORY "memory" |
776 | #define SUN4M_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4M_MEMORY) |
777 | |
778 | typedef struct RamDevice { |
779 | SysBusDevice parent_obj; |
780 | |
781 | MemoryRegion ram; |
782 | uint64_t size; |
783 | } RamDevice; |
784 | |
785 | /* System RAM */ |
786 | static void ram_realize(DeviceState *dev, Error **errp) |
787 | { |
788 | RamDevice *d = SUN4M_RAM(dev); |
789 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev); |
790 | |
791 | memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram" , |
792 | d->size); |
793 | sysbus_init_mmio(sbd, &d->ram); |
794 | } |
795 | |
796 | static void ram_init(hwaddr addr, ram_addr_t RAM_size, |
797 | uint64_t max_mem) |
798 | { |
799 | DeviceState *dev; |
800 | SysBusDevice *s; |
801 | RamDevice *d; |
802 | |
803 | /* allocate RAM */ |
804 | if ((uint64_t)RAM_size > max_mem) { |
805 | error_report("Too much memory for this machine: %" PRId64 "," |
806 | " maximum %" PRId64, |
807 | RAM_size / MiB, max_mem / MiB); |
808 | exit(1); |
809 | } |
810 | dev = qdev_create(NULL, "memory" ); |
811 | s = SYS_BUS_DEVICE(dev); |
812 | |
813 | d = SUN4M_RAM(dev); |
814 | d->size = RAM_size; |
815 | qdev_init_nofail(dev); |
816 | |
817 | sysbus_mmio_map(s, 0, addr); |
818 | } |
819 | |
820 | static Property ram_properties[] = { |
821 | DEFINE_PROP_UINT64("size" , RamDevice, size, 0), |
822 | DEFINE_PROP_END_OF_LIST(), |
823 | }; |
824 | |
825 | static void ram_class_init(ObjectClass *klass, void *data) |
826 | { |
827 | DeviceClass *dc = DEVICE_CLASS(klass); |
828 | |
829 | dc->realize = ram_realize; |
830 | dc->props = ram_properties; |
831 | } |
832 | |
833 | static const TypeInfo ram_info = { |
834 | .name = TYPE_SUN4M_MEMORY, |
835 | .parent = TYPE_SYS_BUS_DEVICE, |
836 | .instance_size = sizeof(RamDevice), |
837 | .class_init = ram_class_init, |
838 | }; |
839 | |
840 | static void cpu_devinit(const char *cpu_type, unsigned int id, |
841 | uint64_t prom_addr, qemu_irq **cpu_irqs) |
842 | { |
843 | CPUState *cs; |
844 | SPARCCPU *cpu; |
845 | CPUSPARCState *env; |
846 | |
847 | cpu = SPARC_CPU(cpu_create(cpu_type)); |
848 | env = &cpu->env; |
849 | |
850 | cpu_sparc_set_id(env, id); |
851 | if (id == 0) { |
852 | qemu_register_reset(main_cpu_reset, cpu); |
853 | } else { |
854 | qemu_register_reset(secondary_cpu_reset, cpu); |
855 | cs = CPU(cpu); |
856 | cs->halted = 1; |
857 | } |
858 | *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS); |
859 | env->prom_addr = prom_addr; |
860 | } |
861 | |
862 | static void dummy_fdc_tc(void *opaque, int irq, int level) |
863 | { |
864 | } |
865 | |
866 | static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, |
867 | MachineState *machine) |
868 | { |
869 | DeviceState *slavio_intctl; |
870 | unsigned int i; |
871 | void *nvram; |
872 | qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS]; |
873 | qemu_irq fdc_tc; |
874 | unsigned long kernel_size; |
875 | uint32_t initrd_size; |
876 | DriveInfo *fd[MAX_FD]; |
877 | FWCfgState *fw_cfg; |
878 | DeviceState *dev; |
879 | SysBusDevice *s; |
880 | unsigned int smp_cpus = machine->smp.cpus; |
881 | unsigned int max_cpus = machine->smp.max_cpus; |
882 | |
883 | /* init CPUs */ |
884 | for(i = 0; i < smp_cpus; i++) { |
885 | cpu_devinit(machine->cpu_type, i, hwdef->slavio_base, &cpu_irqs[i]); |
886 | } |
887 | |
888 | for (i = smp_cpus; i < MAX_CPUS; i++) |
889 | cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); |
890 | |
891 | |
892 | /* set up devices */ |
893 | ram_init(0, machine->ram_size, hwdef->max_mem); |
894 | /* models without ECC don't trap when missing ram is accessed */ |
895 | if (!hwdef->ecc_base) { |
896 | empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size); |
897 | } |
898 | |
899 | prom_init(hwdef->slavio_base, bios_name); |
900 | |
901 | slavio_intctl = slavio_intctl_init(hwdef->intctl_base, |
902 | hwdef->intctl_base + 0x10000ULL, |
903 | cpu_irqs); |
904 | |
905 | for (i = 0; i < 32; i++) { |
906 | slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i); |
907 | } |
908 | for (i = 0; i < MAX_CPUS; i++) { |
909 | slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i); |
910 | } |
911 | |
912 | if (hwdef->idreg_base) { |
913 | idreg_init(hwdef->idreg_base); |
914 | } |
915 | |
916 | if (hwdef->afx_base) { |
917 | afx_init(hwdef->afx_base); |
918 | } |
919 | |
920 | iommu_init(hwdef->iommu_base, hwdef->iommu_version, slavio_irq[30]); |
921 | |
922 | if (hwdef->iommu_pad_base) { |
923 | /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased. |
924 | Software shouldn't use aliased addresses, neither should it crash |
925 | when does. Using empty_slot instead of aliasing can help with |
926 | debugging such accesses */ |
927 | empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); |
928 | } |
929 | |
930 | sparc32_dma_init(hwdef->dma_base, |
931 | hwdef->esp_base, slavio_irq[18], |
932 | hwdef->le_base, slavio_irq[16]); |
933 | |
934 | if (graphic_depth != 8 && graphic_depth != 24) { |
935 | error_report("Unsupported depth: %d" , graphic_depth); |
936 | exit (1); |
937 | } |
938 | if (vga_interface_type != VGA_NONE) { |
939 | if (vga_interface_type == VGA_CG3) { |
940 | if (graphic_depth != 8) { |
941 | error_report("Unsupported depth: %d" , graphic_depth); |
942 | exit(1); |
943 | } |
944 | |
945 | if (!(graphic_width == 1024 && graphic_height == 768) && |
946 | !(graphic_width == 1152 && graphic_height == 900)) { |
947 | error_report("Unsupported resolution: %d x %d" , graphic_width, |
948 | graphic_height); |
949 | exit(1); |
950 | } |
951 | |
952 | /* sbus irq 5 */ |
953 | cg3_init(hwdef->tcx_base, slavio_irq[11], 0x00100000, |
954 | graphic_width, graphic_height, graphic_depth); |
955 | } else { |
956 | /* If no display specified, default to TCX */ |
957 | if (graphic_depth != 8 && graphic_depth != 24) { |
958 | error_report("Unsupported depth: %d" , graphic_depth); |
959 | exit(1); |
960 | } |
961 | |
962 | if (!(graphic_width == 1024 && graphic_height == 768)) { |
963 | error_report("Unsupported resolution: %d x %d" , |
964 | graphic_width, graphic_height); |
965 | exit(1); |
966 | } |
967 | |
968 | tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000, |
969 | graphic_width, graphic_height, graphic_depth); |
970 | } |
971 | } |
972 | |
973 | for (i = 0; i < MAX_VSIMMS; i++) { |
974 | /* vsimm registers probed by OBP */ |
975 | if (hwdef->vsimm[i].reg_base) { |
976 | empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000); |
977 | } |
978 | } |
979 | |
980 | if (hwdef->sx_base) { |
981 | empty_slot_init(hwdef->sx_base, 0x2000); |
982 | } |
983 | |
984 | nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); |
985 | |
986 | slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus); |
987 | |
988 | /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device |
989 | Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ |
990 | dev = qdev_create(NULL, TYPE_ESCC); |
991 | qdev_prop_set_uint32(dev, "disabled" , !machine->enable_graphics); |
992 | qdev_prop_set_uint32(dev, "frequency" , ESCC_CLOCK); |
993 | qdev_prop_set_uint32(dev, "it_shift" , 1); |
994 | qdev_prop_set_chr(dev, "chrB" , NULL); |
995 | qdev_prop_set_chr(dev, "chrA" , NULL); |
996 | qdev_prop_set_uint32(dev, "chnBtype" , escc_mouse); |
997 | qdev_prop_set_uint32(dev, "chnAtype" , escc_kbd); |
998 | qdev_init_nofail(dev); |
999 | s = SYS_BUS_DEVICE(dev); |
1000 | sysbus_connect_irq(s, 0, slavio_irq[14]); |
1001 | sysbus_connect_irq(s, 1, slavio_irq[14]); |
1002 | sysbus_mmio_map(s, 0, hwdef->ms_kb_base); |
1003 | |
1004 | dev = qdev_create(NULL, TYPE_ESCC); |
1005 | qdev_prop_set_uint32(dev, "disabled" , 0); |
1006 | qdev_prop_set_uint32(dev, "frequency" , ESCC_CLOCK); |
1007 | qdev_prop_set_uint32(dev, "it_shift" , 1); |
1008 | qdev_prop_set_chr(dev, "chrB" , serial_hd(1)); |
1009 | qdev_prop_set_chr(dev, "chrA" , serial_hd(0)); |
1010 | qdev_prop_set_uint32(dev, "chnBtype" , escc_serial); |
1011 | qdev_prop_set_uint32(dev, "chnAtype" , escc_serial); |
1012 | qdev_init_nofail(dev); |
1013 | |
1014 | s = SYS_BUS_DEVICE(dev); |
1015 | sysbus_connect_irq(s, 0, slavio_irq[15]); |
1016 | sysbus_connect_irq(s, 1, slavio_irq[15]); |
1017 | sysbus_mmio_map(s, 0, hwdef->serial_base); |
1018 | |
1019 | if (hwdef->apc_base) { |
1020 | apc_init(hwdef->apc_base, qemu_allocate_irq(cpu_halt_signal, NULL, 0)); |
1021 | } |
1022 | |
1023 | if (hwdef->fd_base) { |
1024 | /* there is zero or one floppy drive */ |
1025 | memset(fd, 0, sizeof(fd)); |
1026 | fd[0] = drive_get(IF_FLOPPY, 0, 0); |
1027 | sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd, |
1028 | &fdc_tc); |
1029 | } else { |
1030 | fdc_tc = qemu_allocate_irq(dummy_fdc_tc, NULL, 0); |
1031 | } |
1032 | |
1033 | slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base, |
1034 | slavio_irq[30], fdc_tc); |
1035 | |
1036 | if (hwdef->cs_base) { |
1037 | sysbus_create_simple("SUNW,CS4231" , hwdef->cs_base, |
1038 | slavio_irq[5]); |
1039 | } |
1040 | |
1041 | if (hwdef->dbri_base) { |
1042 | /* ISDN chip with attached CS4215 audio codec */ |
1043 | /* prom space */ |
1044 | empty_slot_init(hwdef->dbri_base+0x1000, 0x30); |
1045 | /* reg space */ |
1046 | empty_slot_init(hwdef->dbri_base+0x10000, 0x100); |
1047 | } |
1048 | |
1049 | if (hwdef->bpp_base) { |
1050 | /* parallel port */ |
1051 | empty_slot_init(hwdef->bpp_base, 0x20); |
1052 | } |
1053 | |
1054 | initrd_size = 0; |
1055 | kernel_size = sun4m_load_kernel(machine->kernel_filename, |
1056 | machine->initrd_filename, |
1057 | machine->ram_size, &initrd_size); |
1058 | |
1059 | nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline, |
1060 | machine->boot_order, machine->ram_size, kernel_size, |
1061 | graphic_width, graphic_height, graphic_depth, |
1062 | hwdef->nvram_machine_id, "Sun4m" ); |
1063 | |
1064 | if (hwdef->ecc_base) |
1065 | ecc_init(hwdef->ecc_base, slavio_irq[28], |
1066 | hwdef->ecc_version); |
1067 | |
1068 | dev = qdev_create(NULL, TYPE_FW_CFG_MEM); |
1069 | fw_cfg = FW_CFG(dev); |
1070 | qdev_prop_set_uint32(dev, "data_width" , 1); |
1071 | qdev_prop_set_bit(dev, "dma_enabled" , false); |
1072 | object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG, |
1073 | OBJECT(fw_cfg), NULL); |
1074 | qdev_init_nofail(dev); |
1075 | s = SYS_BUS_DEVICE(dev); |
1076 | sysbus_mmio_map(s, 0, CFG_ADDR); |
1077 | sysbus_mmio_map(s, 1, CFG_ADDR + 2); |
1078 | |
1079 | fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); |
1080 | fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); |
1081 | fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); |
1082 | fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); |
1083 | fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); |
1084 | fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width); |
1085 | fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height); |
1086 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR); |
1087 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); |
1088 | if (machine->kernel_cmdline) { |
1089 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); |
1090 | pstrcpy_targphys("cmdline" , CMDLINE_ADDR, TARGET_PAGE_SIZE, |
1091 | machine->kernel_cmdline); |
1092 | fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline); |
1093 | fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, |
1094 | strlen(machine->kernel_cmdline) + 1); |
1095 | } else { |
1096 | fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); |
1097 | fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0); |
1098 | } |
1099 | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR); |
1100 | fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); |
1101 | fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]); |
1102 | qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); |
1103 | } |
1104 | |
1105 | enum { |
1106 | ss5_id = 32, |
1107 | vger_id, |
1108 | lx_id, |
1109 | ss4_id, |
1110 | scls_id, |
1111 | sbook_id, |
1112 | ss10_id = 64, |
1113 | ss20_id, |
1114 | ss600mp_id, |
1115 | }; |
1116 | |
1117 | static const struct sun4m_hwdef sun4m_hwdefs[] = { |
1118 | /* SS-5 */ |
1119 | { |
1120 | .iommu_base = 0x10000000, |
1121 | .iommu_pad_base = 0x10004000, |
1122 | .iommu_pad_len = 0x0fffb000, |
1123 | .tcx_base = 0x50000000, |
1124 | .cs_base = 0x6c000000, |
1125 | .slavio_base = 0x70000000, |
1126 | .ms_kb_base = 0x71000000, |
1127 | .serial_base = 0x71100000, |
1128 | .nvram_base = 0x71200000, |
1129 | .fd_base = 0x71400000, |
1130 | .counter_base = 0x71d00000, |
1131 | .intctl_base = 0x71e00000, |
1132 | .idreg_base = 0x78000000, |
1133 | .dma_base = 0x78400000, |
1134 | .esp_base = 0x78800000, |
1135 | .le_base = 0x78c00000, |
1136 | .apc_base = 0x6a000000, |
1137 | .afx_base = 0x6e000000, |
1138 | .aux1_base = 0x71900000, |
1139 | .aux2_base = 0x71910000, |
1140 | .nvram_machine_id = 0x80, |
1141 | .machine_id = ss5_id, |
1142 | .iommu_version = 0x05000000, |
1143 | .max_mem = 0x10000000, |
1144 | }, |
1145 | /* SS-10 */ |
1146 | { |
1147 | .iommu_base = 0xfe0000000ULL, |
1148 | .tcx_base = 0xe20000000ULL, |
1149 | .slavio_base = 0xff0000000ULL, |
1150 | .ms_kb_base = 0xff1000000ULL, |
1151 | .serial_base = 0xff1100000ULL, |
1152 | .nvram_base = 0xff1200000ULL, |
1153 | .fd_base = 0xff1700000ULL, |
1154 | .counter_base = 0xff1300000ULL, |
1155 | .intctl_base = 0xff1400000ULL, |
1156 | .idreg_base = 0xef0000000ULL, |
1157 | .dma_base = 0xef0400000ULL, |
1158 | .esp_base = 0xef0800000ULL, |
1159 | .le_base = 0xef0c00000ULL, |
1160 | .apc_base = 0xefa000000ULL, // XXX should not exist |
1161 | .aux1_base = 0xff1800000ULL, |
1162 | .aux2_base = 0xff1a01000ULL, |
1163 | .ecc_base = 0xf00000000ULL, |
1164 | .ecc_version = 0x10000000, // version 0, implementation 1 |
1165 | .nvram_machine_id = 0x72, |
1166 | .machine_id = ss10_id, |
1167 | .iommu_version = 0x03000000, |
1168 | .max_mem = 0xf00000000ULL, |
1169 | }, |
1170 | /* SS-600MP */ |
1171 | { |
1172 | .iommu_base = 0xfe0000000ULL, |
1173 | .tcx_base = 0xe20000000ULL, |
1174 | .slavio_base = 0xff0000000ULL, |
1175 | .ms_kb_base = 0xff1000000ULL, |
1176 | .serial_base = 0xff1100000ULL, |
1177 | .nvram_base = 0xff1200000ULL, |
1178 | .counter_base = 0xff1300000ULL, |
1179 | .intctl_base = 0xff1400000ULL, |
1180 | .dma_base = 0xef0081000ULL, |
1181 | .esp_base = 0xef0080000ULL, |
1182 | .le_base = 0xef0060000ULL, |
1183 | .apc_base = 0xefa000000ULL, // XXX should not exist |
1184 | .aux1_base = 0xff1800000ULL, |
1185 | .aux2_base = 0xff1a01000ULL, // XXX should not exist |
1186 | .ecc_base = 0xf00000000ULL, |
1187 | .ecc_version = 0x00000000, // version 0, implementation 0 |
1188 | .nvram_machine_id = 0x71, |
1189 | .machine_id = ss600mp_id, |
1190 | .iommu_version = 0x01000000, |
1191 | .max_mem = 0xf00000000ULL, |
1192 | }, |
1193 | /* SS-20 */ |
1194 | { |
1195 | .iommu_base = 0xfe0000000ULL, |
1196 | .tcx_base = 0xe20000000ULL, |
1197 | .slavio_base = 0xff0000000ULL, |
1198 | .ms_kb_base = 0xff1000000ULL, |
1199 | .serial_base = 0xff1100000ULL, |
1200 | .nvram_base = 0xff1200000ULL, |
1201 | .fd_base = 0xff1700000ULL, |
1202 | .counter_base = 0xff1300000ULL, |
1203 | .intctl_base = 0xff1400000ULL, |
1204 | .idreg_base = 0xef0000000ULL, |
1205 | .dma_base = 0xef0400000ULL, |
1206 | .esp_base = 0xef0800000ULL, |
1207 | .le_base = 0xef0c00000ULL, |
1208 | .bpp_base = 0xef4800000ULL, |
1209 | .apc_base = 0xefa000000ULL, // XXX should not exist |
1210 | .aux1_base = 0xff1800000ULL, |
1211 | .aux2_base = 0xff1a01000ULL, |
1212 | .dbri_base = 0xee0000000ULL, |
1213 | .sx_base = 0xf80000000ULL, |
1214 | .vsimm = { |
1215 | { |
1216 | .reg_base = 0x9c000000ULL, |
1217 | .vram_base = 0xfc000000ULL |
1218 | }, { |
1219 | .reg_base = 0x90000000ULL, |
1220 | .vram_base = 0xf0000000ULL |
1221 | }, { |
1222 | .reg_base = 0x94000000ULL |
1223 | }, { |
1224 | .reg_base = 0x98000000ULL |
1225 | } |
1226 | }, |
1227 | .ecc_base = 0xf00000000ULL, |
1228 | .ecc_version = 0x20000000, // version 0, implementation 2 |
1229 | .nvram_machine_id = 0x72, |
1230 | .machine_id = ss20_id, |
1231 | .iommu_version = 0x13000000, |
1232 | .max_mem = 0xf00000000ULL, |
1233 | }, |
1234 | /* Voyager */ |
1235 | { |
1236 | .iommu_base = 0x10000000, |
1237 | .tcx_base = 0x50000000, |
1238 | .slavio_base = 0x70000000, |
1239 | .ms_kb_base = 0x71000000, |
1240 | .serial_base = 0x71100000, |
1241 | .nvram_base = 0x71200000, |
1242 | .fd_base = 0x71400000, |
1243 | .counter_base = 0x71d00000, |
1244 | .intctl_base = 0x71e00000, |
1245 | .idreg_base = 0x78000000, |
1246 | .dma_base = 0x78400000, |
1247 | .esp_base = 0x78800000, |
1248 | .le_base = 0x78c00000, |
1249 | .apc_base = 0x71300000, // pmc |
1250 | .aux1_base = 0x71900000, |
1251 | .aux2_base = 0x71910000, |
1252 | .nvram_machine_id = 0x80, |
1253 | .machine_id = vger_id, |
1254 | .iommu_version = 0x05000000, |
1255 | .max_mem = 0x10000000, |
1256 | }, |
1257 | /* LX */ |
1258 | { |
1259 | .iommu_base = 0x10000000, |
1260 | .iommu_pad_base = 0x10004000, |
1261 | .iommu_pad_len = 0x0fffb000, |
1262 | .tcx_base = 0x50000000, |
1263 | .slavio_base = 0x70000000, |
1264 | .ms_kb_base = 0x71000000, |
1265 | .serial_base = 0x71100000, |
1266 | .nvram_base = 0x71200000, |
1267 | .fd_base = 0x71400000, |
1268 | .counter_base = 0x71d00000, |
1269 | .intctl_base = 0x71e00000, |
1270 | .idreg_base = 0x78000000, |
1271 | .dma_base = 0x78400000, |
1272 | .esp_base = 0x78800000, |
1273 | .le_base = 0x78c00000, |
1274 | .aux1_base = 0x71900000, |
1275 | .aux2_base = 0x71910000, |
1276 | .nvram_machine_id = 0x80, |
1277 | .machine_id = lx_id, |
1278 | .iommu_version = 0x04000000, |
1279 | .max_mem = 0x10000000, |
1280 | }, |
1281 | /* SS-4 */ |
1282 | { |
1283 | .iommu_base = 0x10000000, |
1284 | .tcx_base = 0x50000000, |
1285 | .cs_base = 0x6c000000, |
1286 | .slavio_base = 0x70000000, |
1287 | .ms_kb_base = 0x71000000, |
1288 | .serial_base = 0x71100000, |
1289 | .nvram_base = 0x71200000, |
1290 | .fd_base = 0x71400000, |
1291 | .counter_base = 0x71d00000, |
1292 | .intctl_base = 0x71e00000, |
1293 | .idreg_base = 0x78000000, |
1294 | .dma_base = 0x78400000, |
1295 | .esp_base = 0x78800000, |
1296 | .le_base = 0x78c00000, |
1297 | .apc_base = 0x6a000000, |
1298 | .aux1_base = 0x71900000, |
1299 | .aux2_base = 0x71910000, |
1300 | .nvram_machine_id = 0x80, |
1301 | .machine_id = ss4_id, |
1302 | .iommu_version = 0x05000000, |
1303 | .max_mem = 0x10000000, |
1304 | }, |
1305 | /* SPARCClassic */ |
1306 | { |
1307 | .iommu_base = 0x10000000, |
1308 | .tcx_base = 0x50000000, |
1309 | .slavio_base = 0x70000000, |
1310 | .ms_kb_base = 0x71000000, |
1311 | .serial_base = 0x71100000, |
1312 | .nvram_base = 0x71200000, |
1313 | .fd_base = 0x71400000, |
1314 | .counter_base = 0x71d00000, |
1315 | .intctl_base = 0x71e00000, |
1316 | .idreg_base = 0x78000000, |
1317 | .dma_base = 0x78400000, |
1318 | .esp_base = 0x78800000, |
1319 | .le_base = 0x78c00000, |
1320 | .apc_base = 0x6a000000, |
1321 | .aux1_base = 0x71900000, |
1322 | .aux2_base = 0x71910000, |
1323 | .nvram_machine_id = 0x80, |
1324 | .machine_id = scls_id, |
1325 | .iommu_version = 0x05000000, |
1326 | .max_mem = 0x10000000, |
1327 | }, |
1328 | /* SPARCbook */ |
1329 | { |
1330 | .iommu_base = 0x10000000, |
1331 | .tcx_base = 0x50000000, // XXX |
1332 | .slavio_base = 0x70000000, |
1333 | .ms_kb_base = 0x71000000, |
1334 | .serial_base = 0x71100000, |
1335 | .nvram_base = 0x71200000, |
1336 | .fd_base = 0x71400000, |
1337 | .counter_base = 0x71d00000, |
1338 | .intctl_base = 0x71e00000, |
1339 | .idreg_base = 0x78000000, |
1340 | .dma_base = 0x78400000, |
1341 | .esp_base = 0x78800000, |
1342 | .le_base = 0x78c00000, |
1343 | .apc_base = 0x6a000000, |
1344 | .aux1_base = 0x71900000, |
1345 | .aux2_base = 0x71910000, |
1346 | .nvram_machine_id = 0x80, |
1347 | .machine_id = sbook_id, |
1348 | .iommu_version = 0x05000000, |
1349 | .max_mem = 0x10000000, |
1350 | }, |
1351 | }; |
1352 | |
1353 | /* SPARCstation 5 hardware initialisation */ |
1354 | static void ss5_init(MachineState *machine) |
1355 | { |
1356 | sun4m_hw_init(&sun4m_hwdefs[0], machine); |
1357 | } |
1358 | |
1359 | /* SPARCstation 10 hardware initialisation */ |
1360 | static void ss10_init(MachineState *machine) |
1361 | { |
1362 | sun4m_hw_init(&sun4m_hwdefs[1], machine); |
1363 | } |
1364 | |
1365 | /* SPARCserver 600MP hardware initialisation */ |
1366 | static void ss600mp_init(MachineState *machine) |
1367 | { |
1368 | sun4m_hw_init(&sun4m_hwdefs[2], machine); |
1369 | } |
1370 | |
1371 | /* SPARCstation 20 hardware initialisation */ |
1372 | static void ss20_init(MachineState *machine) |
1373 | { |
1374 | sun4m_hw_init(&sun4m_hwdefs[3], machine); |
1375 | } |
1376 | |
1377 | /* SPARCstation Voyager hardware initialisation */ |
1378 | static void vger_init(MachineState *machine) |
1379 | { |
1380 | sun4m_hw_init(&sun4m_hwdefs[4], machine); |
1381 | } |
1382 | |
1383 | /* SPARCstation LX hardware initialisation */ |
1384 | static void ss_lx_init(MachineState *machine) |
1385 | { |
1386 | sun4m_hw_init(&sun4m_hwdefs[5], machine); |
1387 | } |
1388 | |
1389 | /* SPARCstation 4 hardware initialisation */ |
1390 | static void ss4_init(MachineState *machine) |
1391 | { |
1392 | sun4m_hw_init(&sun4m_hwdefs[6], machine); |
1393 | } |
1394 | |
1395 | /* SPARCClassic hardware initialisation */ |
1396 | static void scls_init(MachineState *machine) |
1397 | { |
1398 | sun4m_hw_init(&sun4m_hwdefs[7], machine); |
1399 | } |
1400 | |
1401 | /* SPARCbook hardware initialisation */ |
1402 | static void sbook_init(MachineState *machine) |
1403 | { |
1404 | sun4m_hw_init(&sun4m_hwdefs[8], machine); |
1405 | } |
1406 | |
1407 | static void ss5_class_init(ObjectClass *oc, void *data) |
1408 | { |
1409 | MachineClass *mc = MACHINE_CLASS(oc); |
1410 | |
1411 | mc->desc = "Sun4m platform, SPARCstation 5" ; |
1412 | mc->init = ss5_init; |
1413 | mc->block_default_type = IF_SCSI; |
1414 | mc->is_default = 1; |
1415 | mc->default_boot_order = "c" ; |
1416 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904" ); |
1417 | mc->default_display = "tcx" ; |
1418 | } |
1419 | |
1420 | static const TypeInfo ss5_type = { |
1421 | .name = MACHINE_TYPE_NAME("SS-5" ), |
1422 | .parent = TYPE_MACHINE, |
1423 | .class_init = ss5_class_init, |
1424 | }; |
1425 | |
1426 | static void ss10_class_init(ObjectClass *oc, void *data) |
1427 | { |
1428 | MachineClass *mc = MACHINE_CLASS(oc); |
1429 | |
1430 | mc->desc = "Sun4m platform, SPARCstation 10" ; |
1431 | mc->init = ss10_init; |
1432 | mc->block_default_type = IF_SCSI; |
1433 | mc->max_cpus = 4; |
1434 | mc->default_boot_order = "c" ; |
1435 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II" ); |
1436 | mc->default_display = "tcx" ; |
1437 | } |
1438 | |
1439 | static const TypeInfo ss10_type = { |
1440 | .name = MACHINE_TYPE_NAME("SS-10" ), |
1441 | .parent = TYPE_MACHINE, |
1442 | .class_init = ss10_class_init, |
1443 | }; |
1444 | |
1445 | static void ss600mp_class_init(ObjectClass *oc, void *data) |
1446 | { |
1447 | MachineClass *mc = MACHINE_CLASS(oc); |
1448 | |
1449 | mc->desc = "Sun4m platform, SPARCserver 600MP" ; |
1450 | mc->init = ss600mp_init; |
1451 | mc->block_default_type = IF_SCSI; |
1452 | mc->max_cpus = 4; |
1453 | mc->default_boot_order = "c" ; |
1454 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II" ); |
1455 | mc->default_display = "tcx" ; |
1456 | } |
1457 | |
1458 | static const TypeInfo ss600mp_type = { |
1459 | .name = MACHINE_TYPE_NAME("SS-600MP" ), |
1460 | .parent = TYPE_MACHINE, |
1461 | .class_init = ss600mp_class_init, |
1462 | }; |
1463 | |
1464 | static void ss20_class_init(ObjectClass *oc, void *data) |
1465 | { |
1466 | MachineClass *mc = MACHINE_CLASS(oc); |
1467 | |
1468 | mc->desc = "Sun4m platform, SPARCstation 20" ; |
1469 | mc->init = ss20_init; |
1470 | mc->block_default_type = IF_SCSI; |
1471 | mc->max_cpus = 4; |
1472 | mc->default_boot_order = "c" ; |
1473 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II" ); |
1474 | mc->default_display = "tcx" ; |
1475 | } |
1476 | |
1477 | static const TypeInfo ss20_type = { |
1478 | .name = MACHINE_TYPE_NAME("SS-20" ), |
1479 | .parent = TYPE_MACHINE, |
1480 | .class_init = ss20_class_init, |
1481 | }; |
1482 | |
1483 | static void voyager_class_init(ObjectClass *oc, void *data) |
1484 | { |
1485 | MachineClass *mc = MACHINE_CLASS(oc); |
1486 | |
1487 | mc->desc = "Sun4m platform, SPARCstation Voyager" ; |
1488 | mc->init = vger_init; |
1489 | mc->block_default_type = IF_SCSI; |
1490 | mc->default_boot_order = "c" ; |
1491 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904" ); |
1492 | mc->default_display = "tcx" ; |
1493 | } |
1494 | |
1495 | static const TypeInfo voyager_type = { |
1496 | .name = MACHINE_TYPE_NAME("Voyager" ), |
1497 | .parent = TYPE_MACHINE, |
1498 | .class_init = voyager_class_init, |
1499 | }; |
1500 | |
1501 | static void ss_lx_class_init(ObjectClass *oc, void *data) |
1502 | { |
1503 | MachineClass *mc = MACHINE_CLASS(oc); |
1504 | |
1505 | mc->desc = "Sun4m platform, SPARCstation LX" ; |
1506 | mc->init = ss_lx_init; |
1507 | mc->block_default_type = IF_SCSI; |
1508 | mc->default_boot_order = "c" ; |
1509 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I" ); |
1510 | mc->default_display = "tcx" ; |
1511 | } |
1512 | |
1513 | static const TypeInfo ss_lx_type = { |
1514 | .name = MACHINE_TYPE_NAME("LX" ), |
1515 | .parent = TYPE_MACHINE, |
1516 | .class_init = ss_lx_class_init, |
1517 | }; |
1518 | |
1519 | static void ss4_class_init(ObjectClass *oc, void *data) |
1520 | { |
1521 | MachineClass *mc = MACHINE_CLASS(oc); |
1522 | |
1523 | mc->desc = "Sun4m platform, SPARCstation 4" ; |
1524 | mc->init = ss4_init; |
1525 | mc->block_default_type = IF_SCSI; |
1526 | mc->default_boot_order = "c" ; |
1527 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904" ); |
1528 | mc->default_display = "tcx" ; |
1529 | } |
1530 | |
1531 | static const TypeInfo ss4_type = { |
1532 | .name = MACHINE_TYPE_NAME("SS-4" ), |
1533 | .parent = TYPE_MACHINE, |
1534 | .class_init = ss4_class_init, |
1535 | }; |
1536 | |
1537 | static void scls_class_init(ObjectClass *oc, void *data) |
1538 | { |
1539 | MachineClass *mc = MACHINE_CLASS(oc); |
1540 | |
1541 | mc->desc = "Sun4m platform, SPARCClassic" ; |
1542 | mc->init = scls_init; |
1543 | mc->block_default_type = IF_SCSI; |
1544 | mc->default_boot_order = "c" ; |
1545 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I" ); |
1546 | mc->default_display = "tcx" ; |
1547 | } |
1548 | |
1549 | static const TypeInfo scls_type = { |
1550 | .name = MACHINE_TYPE_NAME("SPARCClassic" ), |
1551 | .parent = TYPE_MACHINE, |
1552 | .class_init = scls_class_init, |
1553 | }; |
1554 | |
1555 | static void sbook_class_init(ObjectClass *oc, void *data) |
1556 | { |
1557 | MachineClass *mc = MACHINE_CLASS(oc); |
1558 | |
1559 | mc->desc = "Sun4m platform, SPARCbook" ; |
1560 | mc->init = sbook_init; |
1561 | mc->block_default_type = IF_SCSI; |
1562 | mc->default_boot_order = "c" ; |
1563 | mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I" ); |
1564 | mc->default_display = "tcx" ; |
1565 | } |
1566 | |
1567 | static const TypeInfo sbook_type = { |
1568 | .name = MACHINE_TYPE_NAME("SPARCbook" ), |
1569 | .parent = TYPE_MACHINE, |
1570 | .class_init = sbook_class_init, |
1571 | }; |
1572 | |
1573 | static void sun4m_register_types(void) |
1574 | { |
1575 | type_register_static(&idreg_info); |
1576 | type_register_static(&afx_info); |
1577 | type_register_static(&prom_info); |
1578 | type_register_static(&ram_info); |
1579 | |
1580 | type_register_static(&ss5_type); |
1581 | type_register_static(&ss10_type); |
1582 | type_register_static(&ss600mp_type); |
1583 | type_register_static(&ss20_type); |
1584 | type_register_static(&voyager_type); |
1585 | type_register_static(&ss_lx_type); |
1586 | type_register_static(&ss4_type); |
1587 | type_register_static(&scls_type); |
1588 | type_register_static(&sbook_type); |
1589 | } |
1590 | |
1591 | type_init(sun4m_register_types) |
1592 | |