2 * QEMU Malta board support
4 * Copyright (c) 2006 Aurelien Jarno
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
27 #define BIOS_FILENAME "mips_bios.bin"
28 #ifdef MIPS_HAS_MIPS64
29 #define INITRD_LOAD_ADDR (uint64_t)0x80800000
30 #define ENVP_ADDR (uint64_t)0x80002000
32 #define INITRD_LOAD_ADDR (uint32_t)0x80800000
33 #define ENVP_ADDR (uint32_t)0x80002000
36 #define VIRT_TO_PHYS_ADDEND (-((uint64_t)(uint32_t)0x80000000))
38 #define ENVP_NB_ENTRIES 16
39 #define ENVP_ENTRY_SIZE 256
51 CharDriverState *display;
57 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
58 static void pic_irq_request(void *opaque, int level)
60 cpu_mips_irq_request(opaque, 2, level);
64 static void malta_fpga_update_display(void *opaque)
68 MaltaFPGAState *s = opaque;
70 for (i = 7 ; i >= 0 ; i--) {
71 if (s->leds & (1 << i))
78 qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
79 qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
82 static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
84 MaltaFPGAState *s = opaque;
88 saddr = (addr & 0xfffff);
94 val = 0x00000000; /* All switches closed */
99 #ifdef TARGET_WORDS_BIGENDIAN
111 /* LEDBAR Register */
116 /* BRKRES Register */
126 /* XXX: implement a real I2C controller */
130 /* IN = OUT until a real I2C control is implemented */
137 /* I2CINP Register */
147 /* I2COUT Register */
152 /* I2CSEL Register */
159 printf ("malta_fpga_read: Bad register offset 0x%x\n", (int)addr);
166 static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
169 MaltaFPGAState *s = opaque;
172 saddr = (addr & 0xfffff);
176 /* SWITCH Register */
184 /* LEDBAR Register */
185 /* XXX: implement a 8-LED array */
187 s->leds = val & 0xff;
190 /* ASCIIWORD Register */
192 snprintf(s->display_text, 9, "%08X", val);
193 malta_fpga_update_display(s);
196 /* ASCIIPOS0 to ASCIIPOS7 Registers */
205 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
206 malta_fpga_update_display(s);
209 /* SOFTRES Register */
212 qemu_system_reset_request ();
215 /* BRKRES Register */
222 s->gpout = val & 0xff;
227 s->i2coe = val & 0x03;
230 /* I2COUT Register */
232 s->i2cout = val & 0x03;
235 /* I2CSEL Register */
237 s->i2cout = val & 0x01;
242 printf ("malta_fpga_write: Bad register offset 0x%x\n", (int)addr);
248 static CPUReadMemoryFunc *malta_fpga_read[] = {
254 static CPUWriteMemoryFunc *malta_fpga_write[] = {
260 void malta_fpga_reset(void *opaque)
262 MaltaFPGAState *s = opaque;
271 s->display_text[8] = '\0';
272 snprintf(s->display_text, 9, " ");
273 malta_fpga_update_display(s);
276 MaltaFPGAState *malta_fpga_init(target_phys_addr_t base)
281 s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
283 malta = cpu_register_io_memory(0, malta_fpga_read,
284 malta_fpga_write, s);
285 cpu_register_physical_memory(base, 0x100000, malta);
287 s->display = qemu_chr_open("vc");
288 qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
289 qemu_chr_printf(s->display, "+--------+\r\n");
290 qemu_chr_printf(s->display, "+ +\r\n");
291 qemu_chr_printf(s->display, "+--------+\r\n");
292 qemu_chr_printf(s->display, "\n");
293 qemu_chr_printf(s->display, "Malta ASCII\r\n");
294 qemu_chr_printf(s->display, "+--------+\r\n");
295 qemu_chr_printf(s->display, "+ +\r\n");
296 qemu_chr_printf(s->display, "+--------+\r\n");
299 qemu_register_reset(malta_fpga_reset, s);
306 static void audio_init (PCIBus *pci_bus)
309 int audio_enabled = 0;
311 for (c = soundhw; !audio_enabled && c->name; ++c) {
312 audio_enabled = c->enabled;
320 for (c = soundhw; c->name; ++c) {
323 fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
328 c->init.init_pci (pci_bus, s);
338 /* Network support */
339 static void network_init (PCIBus *pci_bus)
344 for(i = 0; i < nb_nics; i++) {
349 if (i == 0 && strcmp(nd->model, "pcnet") == 0) {
350 /* The malta board has a PCNet card using PCI SLOT 11 */
351 pci_nic_init(pci_bus, nd, 88);
353 pci_nic_init(pci_bus, nd, -1);
358 /* ROM and pseudo bootloader
360 The following code implements a very very simple bootloader. It first
361 loads the registers a0 to a3 to the values expected by the OS, and
362 then jump at the kernel address.
364 The bootloader should pass the locations of the kernel arguments and
365 environment variables tables. Those tables contain the 32-bit address
366 of NULL terminated strings. The environment variables table should be
367 terminated by a NULL address.
369 For a simpler implementation, the number of kernel arguments is fixed
370 to two (the name of the kernel and the command line), and the two
371 tables are actually the same one.
373 The registers a0 to a3 should contain the following values:
374 a0 - number of kernel arguments
375 a1 - 32-bit address of the kernel arguments table
376 a2 - 32-bit address of the environment variables table
377 a3 - RAM size in bytes
380 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
384 /* Small bootloader */
385 p = (uint32_t *) (phys_ram_base + bios_offset);
386 stl_raw(p++, 0x0bf00010); /* j 0x1fc00040 */
387 stl_raw(p++, 0x00000000); /* nop */
389 /* Second part of the bootloader */
390 p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
391 stl_raw(p++, 0x3c040000); /* lui a0, 0 */
392 stl_raw(p++, 0x34840002); /* ori a0, a0, 2 */
393 stl_raw(p++, 0x3c050000 | ((ENVP_ADDR) >> 16)); /* lui a1, high(ENVP_ADDR) */
394 stl_raw(p++, 0x34a50000 | ((ENVP_ADDR) & 0xffff)); /* ori a1, a0, low(ENVP_ADDR) */
395 stl_raw(p++, 0x3c060000 | ((ENVP_ADDR + 8) >> 16)); /* lui a2, high(ENVP_ADDR + 8) */
396 stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
397 stl_raw(p++, 0x3c070000 | ((env->ram_size) >> 16)); /* lui a3, high(env->ram_size) */
398 stl_raw(p++, 0x34e70000 | ((env->ram_size) & 0xffff)); /* ori a3, a3, low(env->ram_size) */
399 stl_raw(p++, 0x3c1f0000 | ((kernel_addr) >> 16)); /* lui ra, high(kernel_addr) */;
400 stl_raw(p++, 0x37ff0000 | ((kernel_addr) & 0xffff)); /* ori ra, ra, low(kernel_addr) */
401 stl_raw(p++, 0x03e00008); /* jr ra */
402 stl_raw(p++, 0x00000000); /* nop */
405 static void prom_set(int index, const char *string, ...)
412 if (index >= ENVP_NB_ENTRIES)
415 p = (uint32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
418 if (string == NULL) {
423 table_addr = ENVP_ADDR + sizeof(uint32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
424 s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
426 stl_raw(p, table_addr);
428 va_start(ap, string);
429 vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
434 static int64_t load_kernel (CPUState *env)
436 int64_t kernel_addr = 0;
440 if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
441 fprintf(stderr, "qemu: could not load kernel '%s'\n",
442 env->kernel_filename);
448 if (env->initrd_filename) {
449 initrd_size = load_image(env->initrd_filename,
450 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
451 if (initrd_size == (target_ulong) -1) {
452 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
453 env->initrd_filename);
458 /* Store command line. */
459 prom_set(index++, env->kernel_filename);
461 prom_set(index++, "rd_start=0x%08x rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
463 prom_set(index++, env->kernel_cmdline);
465 /* Setup minimum environment variables */
466 prom_set(index++, "memsize");
467 prom_set(index++, "%i", env->ram_size);
468 prom_set(index++, "modetty0");
469 prom_set(index++, "38400n8r");
470 prom_set(index++, NULL);
475 static void main_cpu_reset(void *opaque)
477 CPUState *env = opaque;
480 /* The bootload does not need to be rewritten as it is located in a
481 read only location. The kernel location and the arguments table
482 location does not change. */
483 if (env->kernel_filename)
487 void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
488 DisplayState *ds, const char **fd_filename, int snapshot,
489 const char *kernel_filename, const char *kernel_cmdline,
490 const char *initrd_filename)
493 unsigned long bios_offset;
498 /* fdctrl_t *floppy_controller; */
499 MaltaFPGAState *malta_fpga;
503 register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
504 qemu_register_reset(main_cpu_reset, env);
507 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
509 /* Map the bios at two physical locations, as on the real board */
510 bios_offset = ram_size + vga_ram_size;
511 cpu_register_physical_memory(0x1e000000LL,
512 BIOS_SIZE, bios_offset | IO_MEM_ROM);
513 cpu_register_physical_memory(0x1fc00000LL,
514 BIOS_SIZE, bios_offset | IO_MEM_ROM);
516 /* Load a BIOS image except if a kernel image has been specified. In
517 the later case, just write a small bootloader to the flash
519 if (kernel_filename) {
520 env->ram_size = ram_size;
521 env->kernel_filename = kernel_filename;
522 env->kernel_cmdline = kernel_cmdline;
523 env->initrd_filename = initrd_filename;
524 kernel_addr = load_kernel(env);
525 write_bootloader(env, bios_offset, kernel_addr);
527 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
528 ret = load_image(buf, phys_ram_base + bios_offset);
529 if (ret != BIOS_SIZE) {
530 fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
536 /* Board ID = 0x420 (Malta Board with CoreLV)
537 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
538 map to the board ID. */
539 stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
541 /* Init internal devices */
542 cpu_mips_clock_init(env);
543 cpu_mips_irqctrl_init();
546 malta_fpga = malta_fpga_init(0x1f000000LL);
548 /* Interrupt controller */
549 isa_pic = pic_init(pic_irq_request, env);
552 pci_bus = pci_gt64120_init(isa_pic);
555 piix4_init(pci_bus, 80);
556 pci_piix3_ide_init(pci_bus, bs_table, 81);
557 usb_uhci_init(pci_bus, 82);
558 piix4_pm_init(pci_bus, 83);
559 pit = pit_init(0x40, 0);
564 rtc_state = rtc_init(0x70, 8);
565 serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
566 parallel_init(0x378, 7, parallel_hds[0]);
567 /* XXX: The floppy controller does not work correctly, something is
569 floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
577 network_init(pci_bus);
580 QEMUMachine mips_malta_machine = {
582 "MIPS Malta Core LV",