2 * QEMU Sun4m System Emulator
4 * Copyright (c) 2003-2005 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
28 * Sun4m architecture was used in the following machines:
30 * SPARCserver 6xxMP/xx
31 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), SPARCclassic X (4/10)
32 * SPARCstation LX/ZX (4/30)
33 * SPARCstation Voyager
34 * SPARCstation 10/xx, SPARCserver 10/xx
35 * SPARCstation 5, SPARCserver 5
36 * SPARCstation 20/xx, SPARCserver 20
39 * See for example: http://www.sunhelp.org/faq/sunref1.html
43 #define DPRINTF(fmt, args...) \
44 do { printf("CPUIRQ: " fmt , ##args); } while (0)
46 #define DPRINTF(fmt, args...)
49 #define KERNEL_LOAD_ADDR 0x00004000
50 #define CMDLINE_ADDR 0x007ff000
51 #define INITRD_LOAD_ADDR 0x00800000
52 #define PROM_SIZE_MAX (256 * 1024)
53 #define PROM_ADDR 0xffd00000
54 #define PROM_FILENAME "openbios-sparc32"
60 target_phys_addr_t iommu_base
, slavio_base
;
61 target_phys_addr_t intctl_base
, counter_base
, nvram_base
, ms_kb_base
;
62 target_phys_addr_t serial_base
, fd_base
;
63 target_phys_addr_t dma_base
, esp_base
, le_base
;
64 target_phys_addr_t tcx_base
, cs_base
, power_base
;
65 long vram_size
, nvram_size
;
66 // IRQ numbers are not PIL ones, but master interrupt controller register
68 int intctl_g_intr
, esp_irq
, le_irq
, clock_irq
, clock1_irq
;
69 int ser_irq
, ms_kb_irq
, fd_irq
, me_irq
, cs_irq
;
70 int machine_id
; // For NVRAM
71 uint32_t intbit_to_level
[32];
76 uint64_t cpu_get_tsc()
78 return qemu_get_clock(vm_clock
);
81 int DMA_get_channel_mode (int nchan
)
85 int DMA_read_memory (int nchan
, void *buf
, int pos
, int size
)
89 int DMA_write_memory (int nchan
, void *buf
, int pos
, int size
)
93 void DMA_hold_DREQ (int nchan
) {}
94 void DMA_release_DREQ (int nchan
) {}
95 void DMA_schedule(int nchan
) {}
96 void DMA_run (void) {}
97 void DMA_init (int high_page_enable
) {}
98 void DMA_register_channel (int nchan
,
99 DMA_transfer_handler transfer_handler
,
104 static void nvram_set_word (m48t59_t
*nvram
, uint32_t addr
, uint16_t value
)
106 m48t59_write(nvram
, addr
++, (value
>> 8) & 0xff);
107 m48t59_write(nvram
, addr
++, value
& 0xff);
110 static void nvram_set_lword (m48t59_t
*nvram
, uint32_t addr
, uint32_t value
)
112 m48t59_write(nvram
, addr
++, value
>> 24);
113 m48t59_write(nvram
, addr
++, (value
>> 16) & 0xff);
114 m48t59_write(nvram
, addr
++, (value
>> 8) & 0xff);
115 m48t59_write(nvram
, addr
++, value
& 0xff);
118 static void nvram_set_string (m48t59_t
*nvram
, uint32_t addr
,
119 const unsigned char *str
, uint32_t max
)
123 for (i
= 0; i
< max
&& str
[i
] != '\0'; i
++) {
124 m48t59_write(nvram
, addr
+ i
, str
[i
]);
126 m48t59_write(nvram
, addr
+ max
- 1, '\0');
129 static uint32_t nvram_set_var (m48t59_t
*nvram
, uint32_t addr
,
130 const unsigned char *str
)
134 len
= strlen(str
) + 1;
135 nvram_set_string(nvram
, addr
, str
, len
);
140 static void nvram_finish_partition (m48t59_t
*nvram
, uint32_t start
,
145 // Length divided by 16
146 m48t59_write(nvram
, start
+ 2, ((end
- start
) >> 12) & 0xff);
147 m48t59_write(nvram
, start
+ 3, ((end
- start
) >> 4) & 0xff);
149 sum
= m48t59_read(nvram
, start
);
150 for (i
= 0; i
< 14; i
++) {
151 sum
+= m48t59_read(nvram
, start
+ 2 + i
);
152 sum
= (sum
+ ((sum
& 0xff00) >> 8)) & 0xff;
154 m48t59_write(nvram
, start
+ 1, sum
& 0xff);
157 static m48t59_t
*nvram
;
159 extern int nographic
;
161 static void nvram_init(m48t59_t
*nvram
, uint8_t *macaddr
, const char *cmdline
,
162 int boot_device
, uint32_t RAM_size
,
163 uint32_t kernel_size
,
164 int width
, int height
, int depth
,
167 unsigned char tmp
= 0;
171 // Try to match PPC NVRAM
172 nvram_set_string(nvram
, 0x00, "QEMU_BIOS", 16);
173 nvram_set_lword(nvram
, 0x10, 0x00000001); /* structure v1 */
174 // NVRAM_size, arch not applicable
175 m48t59_write(nvram
, 0x2D, smp_cpus
& 0xff);
176 m48t59_write(nvram
, 0x2E, 0);
177 m48t59_write(nvram
, 0x2F, nographic
& 0xff);
178 nvram_set_lword(nvram
, 0x30, RAM_size
);
179 m48t59_write(nvram
, 0x34, boot_device
& 0xff);
180 nvram_set_lword(nvram
, 0x38, KERNEL_LOAD_ADDR
);
181 nvram_set_lword(nvram
, 0x3C, kernel_size
);
183 strcpy(phys_ram_base
+ CMDLINE_ADDR
, cmdline
);
184 nvram_set_lword(nvram
, 0x40, CMDLINE_ADDR
);
185 nvram_set_lword(nvram
, 0x44, strlen(cmdline
));
187 // initrd_image, initrd_size passed differently
188 nvram_set_word(nvram
, 0x54, width
);
189 nvram_set_word(nvram
, 0x56, height
);
190 nvram_set_word(nvram
, 0x58, depth
);
192 // OpenBIOS nvram variables
193 // Variable partition
195 m48t59_write(nvram
, start
, 0x70);
196 nvram_set_string(nvram
, start
+ 4, "system", 12);
199 for (i
= 0; i
< nb_prom_envs
; i
++)
200 end
= nvram_set_var(nvram
, end
, prom_envs
[i
]);
202 m48t59_write(nvram
, end
++ , 0);
203 end
= start
+ ((end
- start
+ 15) & ~15);
204 nvram_finish_partition(nvram
, start
, end
);
208 m48t59_write(nvram
, start
, 0x7f);
209 nvram_set_string(nvram
, start
+ 4, "free", 12);
212 nvram_finish_partition(nvram
, start
, end
);
214 // Sun4m specific use
216 m48t59_write(nvram
, i
++, 0x01);
217 m48t59_write(nvram
, i
++, machine_id
);
219 m48t59_write(nvram
, i
++, macaddr
[j
++]);
220 m48t59_write(nvram
, i
++, macaddr
[j
++]);
221 m48t59_write(nvram
, i
++, macaddr
[j
++]);
222 m48t59_write(nvram
, i
++, macaddr
[j
++]);
223 m48t59_write(nvram
, i
++, macaddr
[j
++]);
224 m48t59_write(nvram
, i
, macaddr
[j
]);
226 /* Calculate checksum */
227 for (i
= start
; i
< start
+ 15; i
++) {
228 tmp
^= m48t59_read(nvram
, i
);
230 m48t59_write(nvram
, start
+ 15, tmp
);
233 static void *slavio_intctl
;
237 slavio_pic_info(slavio_intctl
);
242 slavio_irq_info(slavio_intctl
);
245 static void cpu_set_irq(void *opaque
, int irq
, int level
)
247 CPUState
*env
= opaque
;
250 DPRINTF("Raise CPU IRQ %d\n", irq
);
254 if (env
->interrupt_index
== 0 ||
255 ((env
->interrupt_index
& ~15) == TT_EXTINT
&&
256 (env
->interrupt_index
& 15) < irq
)) {
257 env
->interrupt_index
= TT_EXTINT
| irq
;
258 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
260 DPRINTF("Not triggered, pending exception %d\n",
261 env
->interrupt_index
);
264 DPRINTF("Lower CPU IRQ %d\n", irq
);
268 static void dummy_cpu_set_irq(void *opaque
, int irq
, int level
)
272 static void *slavio_misc
;
274 void qemu_system_powerdown(void)
276 slavio_set_power_fail(slavio_misc
, 1);
279 static void main_cpu_reset(void *opaque
)
281 CPUState
*env
= opaque
;
287 static void secondary_cpu_reset(void *opaque
)
289 CPUState
*env
= opaque
;
295 static void sun4m_hw_init(const struct hwdef
*hwdef
, int ram_size
,
296 DisplayState
*ds
, const char *cpu_model
)
299 CPUState
*env
, *envs
[MAX_CPUS
];
301 void *iommu
, *espdma
, *ledma
, *main_esp
;
302 const sparc_def_t
*def
;
303 qemu_irq
*cpu_irqs
[MAX_CPUS
], *slavio_irq
, *slavio_cpu_irq
,
304 *espdma_irq
, *ledma_irq
;
307 sparc_find_by_name(cpu_model
, &def
);
309 fprintf(stderr
, "Unable to find Sparc CPU definition\n");
313 for(i
= 0; i
< smp_cpus
; i
++) {
315 cpu_sparc_register(env
, def
);
318 qemu_register_reset(main_cpu_reset
, env
);
320 qemu_register_reset(secondary_cpu_reset
, env
);
323 register_savevm("cpu", i
, 3, cpu_save
, cpu_load
, env
);
324 cpu_irqs
[i
] = qemu_allocate_irqs(cpu_set_irq
, envs
[i
], MAX_PILS
);
327 for (i
= smp_cpus
; i
< MAX_CPUS
; i
++)
328 cpu_irqs
[i
] = qemu_allocate_irqs(dummy_cpu_set_irq
, NULL
, MAX_PILS
);
331 cpu_register_physical_memory(0, ram_size
, 0);
333 iommu
= iommu_init(hwdef
->iommu_base
);
334 slavio_intctl
= slavio_intctl_init(hwdef
->intctl_base
,
335 hwdef
->intctl_base
+ 0x10000ULL
,
336 &hwdef
->intbit_to_level
[0],
337 &slavio_irq
, &slavio_cpu_irq
,
341 espdma
= sparc32_dma_init(hwdef
->dma_base
, slavio_irq
[hwdef
->esp_irq
],
343 ledma
= sparc32_dma_init(hwdef
->dma_base
+ 16ULL,
344 slavio_irq
[hwdef
->le_irq
], iommu
, &ledma_irq
);
346 if (graphic_depth
!= 8 && graphic_depth
!= 24) {
347 fprintf(stderr
, "qemu: Unsupported depth: %d\n", graphic_depth
);
350 tcx_init(ds
, hwdef
->tcx_base
, phys_ram_base
+ ram_size
, ram_size
,
351 hwdef
->vram_size
, graphic_width
, graphic_height
, graphic_depth
);
352 if (nd_table
[0].vlan
) {
353 if (nd_table
[0].model
== NULL
354 || strcmp(nd_table
[0].model
, "lance") == 0) {
355 lance_init(&nd_table
[0], hwdef
->le_base
, ledma
, *ledma_irq
);
357 fprintf(stderr
, "qemu: Unsupported NIC: %s\n", nd_table
[0].model
);
361 nvram
= m48t59_init(slavio_irq
[0], hwdef
->nvram_base
, 0,
362 hwdef
->nvram_size
, 8);
363 for (i
= 0; i
< MAX_CPUS
; i
++) {
364 slavio_timer_init(hwdef
->counter_base
+
365 (target_phys_addr_t
)(i
* TARGET_PAGE_SIZE
),
366 slavio_cpu_irq
[i
], 0);
368 slavio_timer_init(hwdef
->counter_base
+ 0x10000ULL
,
369 slavio_irq
[hwdef
->clock1_irq
], 2);
370 slavio_serial_ms_kbd_init(hwdef
->ms_kb_base
, slavio_irq
[hwdef
->ms_kb_irq
]);
371 // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
372 // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
373 slavio_serial_init(hwdef
->serial_base
, slavio_irq
[hwdef
->ser_irq
],
374 serial_hds
[1], serial_hds
[0]);
375 fdctrl_init(slavio_irq
[hwdef
->fd_irq
], 0, 1, hwdef
->fd_base
, fd_table
);
376 main_esp
= esp_init(bs_table
, hwdef
->esp_base
, espdma
, *espdma_irq
);
378 for (i
= 0; i
< MAX_DISKS
; i
++) {
380 esp_scsi_attach(main_esp
, bs_table
[i
], i
);
384 slavio_misc
= slavio_misc_init(hwdef
->slavio_base
, hwdef
->power_base
,
385 slavio_irq
[hwdef
->me_irq
]);
386 if (hwdef
->cs_base
!= (target_phys_addr_t
)-1)
387 cs_init(hwdef
->cs_base
, hwdef
->cs_irq
, slavio_intctl
);
390 static void sun4m_load_kernel(long vram_size
, int ram_size
, int boot_device
,
391 const char *kernel_filename
,
392 const char *kernel_cmdline
,
393 const char *initrd_filename
,
399 long prom_offset
, initrd_size
, kernel_size
;
401 linux_boot
= (kernel_filename
!= NULL
);
403 prom_offset
= ram_size
+ vram_size
;
404 cpu_register_physical_memory(PROM_ADDR
,
405 (PROM_SIZE_MAX
+ TARGET_PAGE_SIZE
- 1) & TARGET_PAGE_MASK
,
406 prom_offset
| IO_MEM_ROM
);
408 snprintf(buf
, sizeof(buf
), "%s/%s", bios_dir
, PROM_FILENAME
);
409 ret
= load_elf(buf
, 0, NULL
, NULL
, NULL
);
411 fprintf(stderr
, "qemu: could not load prom '%s'\n",
418 kernel_size
= load_elf(kernel_filename
, -0xf0000000, NULL
, NULL
, NULL
);
420 kernel_size
= load_aout(kernel_filename
, phys_ram_base
+ KERNEL_LOAD_ADDR
);
422 kernel_size
= load_image(kernel_filename
, phys_ram_base
+ KERNEL_LOAD_ADDR
);
423 if (kernel_size
< 0) {
424 fprintf(stderr
, "qemu: could not load kernel '%s'\n",
431 if (initrd_filename
) {
432 initrd_size
= load_image(initrd_filename
, phys_ram_base
+ INITRD_LOAD_ADDR
);
433 if (initrd_size
< 0) {
434 fprintf(stderr
, "qemu: could not load initial ram disk '%s'\n",
439 if (initrd_size
> 0) {
440 for (i
= 0; i
< 64 * TARGET_PAGE_SIZE
; i
+= TARGET_PAGE_SIZE
) {
441 if (ldl_raw(phys_ram_base
+ KERNEL_LOAD_ADDR
+ i
)
442 == 0x48647253) { // HdrS
443 stl_raw(phys_ram_base
+ KERNEL_LOAD_ADDR
+ i
+ 16, INITRD_LOAD_ADDR
);
444 stl_raw(phys_ram_base
+ KERNEL_LOAD_ADDR
+ i
+ 20, initrd_size
);
450 nvram_init(nvram
, (uint8_t *)&nd_table
[0].macaddr
, kernel_cmdline
,
451 boot_device
, ram_size
, kernel_size
, graphic_width
,
452 graphic_height
, graphic_depth
, machine_id
);
455 static const struct hwdef hwdefs
[] = {
458 .iommu_base
= 0x10000000,
459 .tcx_base
= 0x50000000,
460 .cs_base
= 0x6c000000,
461 .slavio_base
= 0x70000000,
462 .ms_kb_base
= 0x71000000,
463 .serial_base
= 0x71100000,
464 .nvram_base
= 0x71200000,
465 .fd_base
= 0x71400000,
466 .counter_base
= 0x71d00000,
467 .intctl_base
= 0x71e00000,
468 .dma_base
= 0x78400000,
469 .esp_base
= 0x78800000,
470 .le_base
= 0x78c00000,
471 .power_base
= 0x7a000000,
472 .vram_size
= 0x00100000,
473 .nvram_size
= 0x2000,
485 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
486 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
491 .iommu_base
= 0xfe0000000ULL
,
492 .tcx_base
= 0xe20000000ULL
,
494 .slavio_base
= 0xff0000000ULL
,
495 .ms_kb_base
= 0xff1000000ULL
,
496 .serial_base
= 0xff1100000ULL
,
497 .nvram_base
= 0xff1200000ULL
,
498 .fd_base
= 0xff1700000ULL
,
499 .counter_base
= 0xff1300000ULL
,
500 .intctl_base
= 0xff1400000ULL
,
501 .dma_base
= 0xef0400000ULL
,
502 .esp_base
= 0xef0800000ULL
,
503 .le_base
= 0xef0c00000ULL
,
504 .power_base
= 0xefa000000ULL
,
505 .vram_size
= 0x00100000,
506 .nvram_size
= 0x2000,
518 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
519 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
524 static void sun4m_common_init(int ram_size
, int boot_device
, DisplayState
*ds
,
525 const char *kernel_filename
, const char *kernel_cmdline
,
526 const char *initrd_filename
, const char *cpu_model
,
527 unsigned int machine
, int max_ram
)
529 if ((unsigned int)ram_size
> (unsigned int)max_ram
) {
530 fprintf(stderr
, "qemu: Too much memory for this machine: %d, maximum %d\n",
531 (unsigned int)ram_size
/ (1024 * 1024),
532 (unsigned int)max_ram
/ (1024 * 1024));
535 sun4m_hw_init(&hwdefs
[machine
], ram_size
, ds
, cpu_model
);
537 sun4m_load_kernel(hwdefs
[machine
].vram_size
, ram_size
, boot_device
,
538 kernel_filename
, kernel_cmdline
, initrd_filename
,
539 hwdefs
[machine
].machine_id
);
542 /* SPARCstation 5 hardware initialisation */
543 static void ss5_init(int ram_size
, int vga_ram_size
, int boot_device
,
544 DisplayState
*ds
, const char **fd_filename
, int snapshot
,
545 const char *kernel_filename
, const char *kernel_cmdline
,
546 const char *initrd_filename
, const char *cpu_model
)
548 if (cpu_model
== NULL
)
549 cpu_model
= "Fujitsu MB86904";
550 sun4m_common_init(ram_size
, boot_device
, ds
, kernel_filename
,
551 kernel_cmdline
, initrd_filename
, cpu_model
,
555 /* SPARCstation 10 hardware initialisation */
556 static void ss10_init(int ram_size
, int vga_ram_size
, int boot_device
,
557 DisplayState
*ds
, const char **fd_filename
, int snapshot
,
558 const char *kernel_filename
, const char *kernel_cmdline
,
559 const char *initrd_filename
, const char *cpu_model
)
561 if (cpu_model
== NULL
)
562 cpu_model
= "TI SuperSparc II";
563 sun4m_common_init(ram_size
, boot_device
, ds
, kernel_filename
,
564 kernel_cmdline
, initrd_filename
, cpu_model
,
565 1, PROM_ADDR
); // XXX prom overlap, actually first 4GB ok
568 QEMUMachine ss5_machine
= {
570 "Sun4m platform, SPARCstation 5",
574 QEMUMachine ss10_machine
= {
576 "Sun4m platform, SPARCstation 10",