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 #ifdef TARGET_WORDS_BIGENDIAN
28 #define BIOS_FILENAME "mips_bios.bin"
30 #define BIOS_FILENAME "mipsel_bios.bin"
34 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
36 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
39 #define ENVP_ADDR (int32_t)0x80002000
40 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
42 #define ENVP_NB_ENTRIES 16
43 #define ENVP_ENTRY_SIZE 256
56 CharDriverState
*display
;
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
);
83 * EEPROM 24C01 / 24C02 emulation.
85 * Emulation for serial EEPROMs:
86 * 24C01 - 1024 bit (128 x 8)
87 * 24C02 - 2048 bit (256 x 8)
89 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
95 # define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
97 # define logout(fmt, args...) ((void)0)
100 struct _eeprom24c0x_t
{
109 uint8_t contents
[256];
112 typedef struct _eeprom24c0x_t eeprom24c0x_t
;
114 static eeprom24c0x_t eeprom
= {
116 /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
117 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
118 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
119 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
120 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
121 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
124 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
135 static uint8_t eeprom24c0x_read()
137 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
138 eeprom
.tick
, eeprom
.scl
, eeprom
.sda
, eeprom
.data
);
142 static void eeprom24c0x_write(int scl
, int sda
)
144 if (eeprom
.scl
&& scl
&& (eeprom
.sda
!= sda
)) {
145 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
146 eeprom
.tick
, eeprom
.scl
, scl
, eeprom
.sda
, sda
, sda
? "stop" : "start");
151 } else if (eeprom
.tick
== 0 && !eeprom
.ack
) {
152 /* Waiting for start. */
153 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
154 eeprom
.tick
, eeprom
.scl
, scl
, eeprom
.sda
, sda
);
155 } else if (!eeprom
.scl
&& scl
) {
156 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
157 eeprom
.tick
, eeprom
.scl
, scl
, eeprom
.sda
, sda
);
159 logout("\ti2c ack bit = 0\n");
162 } else if (eeprom
.sda
== sda
) {
163 uint8_t bit
= (sda
!= 0);
164 logout("\ti2c bit = %d\n", bit
);
165 if (eeprom
.tick
< 9) {
166 eeprom
.command
<<= 1;
167 eeprom
.command
+= bit
;
169 if (eeprom
.tick
== 9) {
170 logout("\tcommand 0x%04x, %s\n", eeprom
.command
, bit
? "read" : "write");
173 } else if (eeprom
.tick
< 17) {
174 if (eeprom
.command
& 1) {
175 sda
= ((eeprom
.data
& 0x80) != 0);
177 eeprom
.address
<<= 1;
178 eeprom
.address
+= bit
;
181 if (eeprom
.tick
== 17) {
182 eeprom
.data
= eeprom
.contents
[eeprom
.address
];
183 logout("\taddress 0x%04x, data 0x%02x\n", eeprom
.address
, eeprom
.data
);
187 } else if (eeprom
.tick
>= 17) {
191 logout("\tsda changed with raising scl\n");
194 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom
.tick
, eeprom
.scl
, scl
, eeprom
.sda
, sda
);
200 static uint32_t malta_fpga_readl(void *opaque
, target_phys_addr_t addr
)
202 MaltaFPGAState
*s
= opaque
;
206 saddr
= (addr
& 0xfffff);
210 /* SWITCH Register */
212 val
= 0x00000000; /* All switches closed */
215 /* STATUS Register */
217 #ifdef TARGET_WORDS_BIGENDIAN
229 /* LEDBAR Register */
234 /* BRKRES Register */
239 /* UART Registers are handled directly by the serial device */
246 /* XXX: implement a real I2C controller */
250 /* IN = OUT until a real I2C control is implemented */
257 /* I2CINP Register */
259 val
= ((s
->i2cin
& ~1) | eeprom24c0x_read());
267 /* I2COUT Register */
272 /* I2CSEL Register */
279 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx
"\n",
287 static void malta_fpga_writel(void *opaque
, target_phys_addr_t addr
,
290 MaltaFPGAState
*s
= opaque
;
293 saddr
= (addr
& 0xfffff);
297 /* SWITCH Register */
305 /* LEDBAR Register */
306 /* XXX: implement a 8-LED array */
308 s
->leds
= val
& 0xff;
311 /* ASCIIWORD Register */
313 snprintf(s
->display_text
, 9, "%08X", val
);
314 malta_fpga_update_display(s
);
317 /* ASCIIPOS0 to ASCIIPOS7 Registers */
326 s
->display_text
[(saddr
- 0x00418) >> 3] = (char) val
;
327 malta_fpga_update_display(s
);
330 /* SOFTRES Register */
333 qemu_system_reset_request ();
336 /* BRKRES Register */
341 /* UART Registers are handled directly by the serial device */
345 s
->gpout
= val
& 0xff;
350 s
->i2coe
= val
& 0x03;
353 /* I2COUT Register */
355 eeprom24c0x_write(val
& 0x02, val
& 0x01);
359 /* I2CSEL Register */
361 s
->i2csel
= val
& 0x01;
366 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx
"\n",
373 static CPUReadMemoryFunc
*malta_fpga_read
[] = {
379 static CPUWriteMemoryFunc
*malta_fpga_write
[] = {
385 void malta_fpga_reset(void *opaque
)
387 MaltaFPGAState
*s
= opaque
;
397 s
->display_text
[8] = '\0';
398 snprintf(s
->display_text
, 9, " ");
399 malta_fpga_update_display(s
);
402 MaltaFPGAState
*malta_fpga_init(target_phys_addr_t base
, CPUState
*env
)
405 CharDriverState
*uart_chr
;
408 s
= (MaltaFPGAState
*)qemu_mallocz(sizeof(MaltaFPGAState
));
410 malta
= cpu_register_io_memory(0, malta_fpga_read
,
411 malta_fpga_write
, s
);
413 cpu_register_physical_memory(base
, 0x900, malta
);
414 cpu_register_physical_memory(base
+ 0xa00, 0x100000 - 0xa00, malta
);
416 s
->display
= qemu_chr_open("vc");
417 qemu_chr_printf(s
->display
, "\e[HMalta LEDBAR\r\n");
418 qemu_chr_printf(s
->display
, "+--------+\r\n");
419 qemu_chr_printf(s
->display
, "+ +\r\n");
420 qemu_chr_printf(s
->display
, "+--------+\r\n");
421 qemu_chr_printf(s
->display
, "\n");
422 qemu_chr_printf(s
->display
, "Malta ASCII\r\n");
423 qemu_chr_printf(s
->display
, "+--------+\r\n");
424 qemu_chr_printf(s
->display
, "+ +\r\n");
425 qemu_chr_printf(s
->display
, "+--------+\r\n");
427 uart_chr
= qemu_chr_open("vc");
428 qemu_chr_printf(uart_chr
, "CBUS UART\r\n");
429 s
->uart
= serial_mm_init(base
+ 0x900, 3, env
->irq
[2], uart_chr
, 1);
432 qemu_register_reset(malta_fpga_reset
, s
);
439 static void audio_init (PCIBus
*pci_bus
)
442 int audio_enabled
= 0;
444 for (c
= soundhw
; !audio_enabled
&& c
->name
; ++c
) {
445 audio_enabled
= c
->enabled
;
453 for (c
= soundhw
; c
->name
; ++c
) {
456 fprintf(stderr
, "qemu: Unsupported Sound Card: %s\n", c
->name
);
461 c
->init
.init_pci (pci_bus
, s
);
471 /* Network support */
472 static void network_init (PCIBus
*pci_bus
)
477 for(i
= 0; i
< nb_nics
; i
++) {
482 if (i
== 0 && strcmp(nd
->model
, "pcnet") == 0) {
483 /* The malta board has a PCNet card using PCI SLOT 11 */
484 pci_nic_init(pci_bus
, nd
, 88);
486 pci_nic_init(pci_bus
, nd
, -1);
491 /* ROM and pseudo bootloader
493 The following code implements a very very simple bootloader. It first
494 loads the registers a0 to a3 to the values expected by the OS, and
495 then jump at the kernel address.
497 The bootloader should pass the locations of the kernel arguments and
498 environment variables tables. Those tables contain the 32-bit address
499 of NULL terminated strings. The environment variables table should be
500 terminated by a NULL address.
502 For a simpler implementation, the number of kernel arguments is fixed
503 to two (the name of the kernel and the command line), and the two
504 tables are actually the same one.
506 The registers a0 to a3 should contain the following values:
507 a0 - number of kernel arguments
508 a1 - 32-bit address of the kernel arguments table
509 a2 - 32-bit address of the environment variables table
510 a3 - RAM size in bytes
513 static void write_bootloader (CPUState
*env
, unsigned long bios_offset
, int64_t kernel_entry
)
517 /* Small bootloader */
518 p
= (uint32_t *) (phys_ram_base
+ bios_offset
);
519 stl_raw(p
++, 0x0bf00160); /* j 0x1fc00580 */
520 stl_raw(p
++, 0x00000000); /* nop */
522 /* YAMON service vector */
523 stl_raw(phys_ram_base
+ bios_offset
+ 0x500, 0xbfc00580); /* start: */
524 stl_raw(phys_ram_base
+ bios_offset
+ 0x504, 0xbfc0083c); /* print_count: */
525 stl_raw(phys_ram_base
+ bios_offset
+ 0x520, 0xbfc00580); /* start: */
526 stl_raw(phys_ram_base
+ bios_offset
+ 0x52c, 0xbfc00800); /* flush_cache: */
527 stl_raw(phys_ram_base
+ bios_offset
+ 0x534, 0xbfc00808); /* print: */
528 stl_raw(phys_ram_base
+ bios_offset
+ 0x538, 0xbfc00800); /* reg_cpu_isr: */
529 stl_raw(phys_ram_base
+ bios_offset
+ 0x53c, 0xbfc00800); /* unred_cpu_isr: */
530 stl_raw(phys_ram_base
+ bios_offset
+ 0x540, 0xbfc00800); /* reg_ic_isr: */
531 stl_raw(phys_ram_base
+ bios_offset
+ 0x544, 0xbfc00800); /* unred_ic_isr: */
532 stl_raw(phys_ram_base
+ bios_offset
+ 0x548, 0xbfc00800); /* reg_esr: */
533 stl_raw(phys_ram_base
+ bios_offset
+ 0x54c, 0xbfc00800); /* unreg_esr: */
534 stl_raw(phys_ram_base
+ bios_offset
+ 0x550, 0xbfc00800); /* getchar: */
535 stl_raw(phys_ram_base
+ bios_offset
+ 0x554, 0xbfc00800); /* syscon_read: */
538 /* Second part of the bootloader */
539 p
= (uint32_t *) (phys_ram_base
+ bios_offset
+ 0x580);
540 stl_raw(p
++, 0x24040002); /* addiu a0, zero, 2 */
541 stl_raw(p
++, 0x3c1d0000 | (((ENVP_ADDR
- 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
542 stl_raw(p
++, 0x37bd0000 | ((ENVP_ADDR
- 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
543 stl_raw(p
++, 0x3c050000 | ((ENVP_ADDR
>> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
544 stl_raw(p
++, 0x34a50000 | (ENVP_ADDR
& 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
545 stl_raw(p
++, 0x3c060000 | (((ENVP_ADDR
+ 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
546 stl_raw(p
++, 0x34c60000 | ((ENVP_ADDR
+ 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
547 stl_raw(p
++, 0x3c070000 | (env
->ram_size
>> 16)); /* lui a3, high(env->ram_size) */
548 stl_raw(p
++, 0x34e70000 | (env
->ram_size
& 0xffff)); /* ori a3, a3, low(env->ram_size) */
550 /* Load BAR registers as done by YAMON */
551 stl_raw(p
++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
553 #ifdef TARGET_WORDS_BIGENDIAN
554 stl_raw(p
++, 0x3c08c000); /* lui t0, 0xc000 */
556 stl_raw(p
++, 0x340800c0); /* ori t0, r0, 0x00c0 */
558 stl_raw(p
++, 0xad280048); /* sw t0, 0x0048(t1) */
559 #ifdef TARGET_WORDS_BIGENDIAN
560 stl_raw(p
++, 0x3c084000); /* lui t0, 0x4000 */
562 stl_raw(p
++, 0x34080040); /* ori t0, r0, 0x0040 */
564 stl_raw(p
++, 0xad280050); /* sw t0, 0x0050(t1) */
566 #ifdef TARGET_WORDS_BIGENDIAN
567 stl_raw(p
++, 0x3c088000); /* lui t0, 0x8000 */
569 stl_raw(p
++, 0x34080080); /* ori t0, r0, 0x0080 */
571 stl_raw(p
++, 0xad280058); /* sw t0, 0x0058(t1) */
572 #ifdef TARGET_WORDS_BIGENDIAN
573 stl_raw(p
++, 0x3c083f00); /* lui t0, 0x3f00 */
575 stl_raw(p
++, 0x3408003f); /* ori t0, r0, 0x003f */
577 stl_raw(p
++, 0xad280060); /* sw t0, 0x0060(t1) */
579 #ifdef TARGET_WORDS_BIGENDIAN
580 stl_raw(p
++, 0x3c08c100); /* lui t0, 0xc100 */
582 stl_raw(p
++, 0x340800c1); /* ori t0, r0, 0x00c1 */
584 stl_raw(p
++, 0xad280080); /* sw t0, 0x0080(t1) */
585 #ifdef TARGET_WORDS_BIGENDIAN
586 stl_raw(p
++, 0x3c085e00); /* lui t0, 0x5e00 */
588 stl_raw(p
++, 0x3408005e); /* ori t0, r0, 0x005e */
590 stl_raw(p
++, 0xad280088); /* sw t0, 0x0088(t1) */
592 /* Jump to kernel code */
593 stl_raw(p
++, 0x3c1f0000 | ((kernel_entry
>> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
594 stl_raw(p
++, 0x37ff0000 | (kernel_entry
& 0xffff)); /* ori ra, ra, low(kernel_entry) */
595 stl_raw(p
++, 0x03e00008); /* jr ra */
596 stl_raw(p
++, 0x00000000); /* nop */
598 /* YAMON subroutines */
599 p
= (uint32_t *) (phys_ram_base
+ bios_offset
+ 0x800);
600 stl_raw(p
++, 0x03e00008); /* jr ra */
601 stl_raw(p
++, 0x24020000); /* li v0,0 */
602 /* 808 YAMON print */
603 stl_raw(p
++, 0x03e06821); /* move t5,ra */
604 stl_raw(p
++, 0x00805821); /* move t3,a0 */
605 stl_raw(p
++, 0x00a05021); /* move t2,a1 */
606 stl_raw(p
++, 0x91440000); /* lbu a0,0(t2) */
607 stl_raw(p
++, 0x254a0001); /* addiu t2,t2,1 */
608 stl_raw(p
++, 0x10800005); /* beqz a0,834 */
609 stl_raw(p
++, 0x00000000); /* nop */
610 stl_raw(p
++, 0x0ff0021c); /* jal 870 */
611 stl_raw(p
++, 0x00000000); /* nop */
612 stl_raw(p
++, 0x08000205); /* j 814 */
613 stl_raw(p
++, 0x00000000); /* nop */
614 stl_raw(p
++, 0x01a00008); /* jr t5 */
615 stl_raw(p
++, 0x01602021); /* move a0,t3 */
616 /* 0x83c YAMON print_count */
617 stl_raw(p
++, 0x03e06821); /* move t5,ra */
618 stl_raw(p
++, 0x00805821); /* move t3,a0 */
619 stl_raw(p
++, 0x00a05021); /* move t2,a1 */
620 stl_raw(p
++, 0x00c06021); /* move t4,a2 */
621 stl_raw(p
++, 0x91440000); /* lbu a0,0(t2) */
622 stl_raw(p
++, 0x0ff0021c); /* jal 870 */
623 stl_raw(p
++, 0x00000000); /* nop */
624 stl_raw(p
++, 0x254a0001); /* addiu t2,t2,1 */
625 stl_raw(p
++, 0x258cffff); /* addiu t4,t4,-1 */
626 stl_raw(p
++, 0x1580fffa); /* bnez t4,84c */
627 stl_raw(p
++, 0x00000000); /* nop */
628 stl_raw(p
++, 0x01a00008); /* jr t5 */
629 stl_raw(p
++, 0x01602021); /* move a0,t3 */
631 stl_raw(p
++, 0x3c08b800); /* lui t0,0xb400 */
632 stl_raw(p
++, 0x350803f8); /* ori t0,t0,0x3f8 */
633 stl_raw(p
++, 0x91090005); /* lbu t1,5(t0) */
634 stl_raw(p
++, 0x00000000); /* nop */
635 stl_raw(p
++, 0x31290040); /* andi t1,t1,0x40 */
636 stl_raw(p
++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
637 stl_raw(p
++, 0x00000000); /* nop */
638 stl_raw(p
++, 0x03e00008); /* jr ra */
639 stl_raw(p
++, 0xa1040000); /* sb a0,0(t0) */
643 static void prom_set(int index
, const char *string
, ...)
650 if (index
>= ENVP_NB_ENTRIES
)
653 p
= (int32_t *) (phys_ram_base
+ ENVP_ADDR
+ VIRT_TO_PHYS_ADDEND
);
656 if (string
== NULL
) {
661 table_addr
= ENVP_ADDR
+ sizeof(int32_t) * ENVP_NB_ENTRIES
+ index
* ENVP_ENTRY_SIZE
;
662 s
= (char *) (phys_ram_base
+ VIRT_TO_PHYS_ADDEND
+ table_addr
);
664 stl_raw(p
, table_addr
);
666 va_start(ap
, string
);
667 vsnprintf (s
, ENVP_ENTRY_SIZE
, string
, ap
);
672 static int64_t load_kernel (CPUState
*env
)
674 int64_t kernel_entry
, kernel_low
, kernel_high
;
677 ram_addr_t initrd_offset
;
679 if (load_elf(env
->kernel_filename
, VIRT_TO_PHYS_ADDEND
,
680 &kernel_entry
, &kernel_low
, &kernel_high
) < 0) {
681 fprintf(stderr
, "qemu: could not load kernel '%s'\n",
682 env
->kernel_filename
);
689 if (env
->initrd_filename
) {
690 initrd_size
= get_image_size (env
->initrd_filename
);
691 if (initrd_size
> 0) {
692 initrd_offset
= (kernel_high
+ ~TARGET_PAGE_MASK
) & TARGET_PAGE_MASK
;
693 if (initrd_offset
+ initrd_size
> env
->ram_size
) {
695 "qemu: memory too small for initial ram disk '%s'\n",
696 env
->initrd_filename
);
699 initrd_size
= load_image(env
->initrd_filename
,
700 phys_ram_base
+ initrd_offset
);
702 if (initrd_size
== (target_ulong
) -1) {
703 fprintf(stderr
, "qemu: could not load initial ram disk '%s'\n",
704 env
->initrd_filename
);
709 /* Store command line. */
710 prom_set(index
++, env
->kernel_filename
);
712 prom_set(index
++, "rd_start=0x" TARGET_FMT_lx
" rd_size=%li %s",
713 PHYS_TO_VIRT(initrd_offset
), initrd_size
,
714 env
->kernel_cmdline
);
716 prom_set(index
++, env
->kernel_cmdline
);
718 /* Setup minimum environment variables */
719 prom_set(index
++, "memsize");
720 prom_set(index
++, "%i", env
->ram_size
);
721 prom_set(index
++, "modetty0");
722 prom_set(index
++, "38400n8r");
723 prom_set(index
++, NULL
);
728 static void main_cpu_reset(void *opaque
)
730 CPUState
*env
= opaque
;
732 cpu_mips_register(env
, NULL
);
734 /* The bootload does not need to be rewritten as it is located in a
735 read only location. The kernel location and the arguments table
736 location does not change. */
737 if (env
->kernel_filename
) {
738 env
->CP0_Status
&= ~((1 << CP0St_BEV
) | (1 << CP0St_ERL
));
744 void mips_malta_init (int ram_size
, int vga_ram_size
, int boot_device
,
745 DisplayState
*ds
, const char **fd_filename
, int snapshot
,
746 const char *kernel_filename
, const char *kernel_cmdline
,
747 const char *initrd_filename
, const char *cpu_model
)
750 unsigned long bios_offset
;
751 int64_t kernel_entry
;
755 /* fdctrl_t *floppy_controller; */
756 MaltaFPGAState
*malta_fpga
;
766 if (cpu_model
== NULL
) {
773 if (mips_find_by_name(cpu_model
, &def
) != 0)
776 cpu_mips_register(env
, def
);
777 register_savevm("cpu", 0, 3, cpu_save
, cpu_load
, env
);
778 qemu_register_reset(main_cpu_reset
, env
);
781 cpu_register_physical_memory(0, ram_size
, IO_MEM_RAM
);
783 /* Map the bios at two physical locations, as on the real board */
784 bios_offset
= ram_size
+ vga_ram_size
;
785 cpu_register_physical_memory(0x1e000000LL
,
786 BIOS_SIZE
, bios_offset
| IO_MEM_ROM
);
787 cpu_register_physical_memory(0x1fc00000LL
,
788 BIOS_SIZE
, bios_offset
| IO_MEM_ROM
);
790 /* Load a BIOS image except if a kernel image has been specified. In
791 the later case, just write a small bootloader to the flash
793 if (kernel_filename
) {
794 env
->ram_size
= ram_size
;
795 env
->kernel_filename
= kernel_filename
;
796 env
->kernel_cmdline
= kernel_cmdline
;
797 env
->initrd_filename
= initrd_filename
;
798 kernel_entry
= load_kernel(env
);
799 env
->CP0_Status
&= ~((1 << CP0St_BEV
) | (1 << CP0St_ERL
));
800 write_bootloader(env
, bios_offset
, kernel_entry
);
802 snprintf(buf
, sizeof(buf
), "%s/%s", bios_dir
, BIOS_FILENAME
);
803 ret
= load_image(buf
, phys_ram_base
+ bios_offset
);
804 if (ret
< 0 || ret
> BIOS_SIZE
) {
805 fprintf(stderr
, "qemu: Warning, could not load MIPS bios '%s'\n",
811 /* Board ID = 0x420 (Malta Board with CoreLV)
812 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
813 map to the board ID. */
814 stl_raw(phys_ram_base
+ bios_offset
+ 0x10, 0x00000420);
816 /* Init internal devices */
817 cpu_mips_irq_init_cpu(env
);
818 cpu_mips_clock_init(env
);
819 cpu_mips_irqctrl_init();
822 malta_fpga
= malta_fpga_init(0x1f000000LL
, env
);
824 /* Interrupt controller */
825 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
826 i8259
= i8259_init(env
->irq
[2]);
829 pci_bus
= pci_gt64120_init(i8259
);
832 piix4_devfn
= piix4_init(pci_bus
, 80);
833 pci_piix3_ide_init(pci_bus
, bs_table
, piix4_devfn
+ 1, i8259
);
834 usb_uhci_init(pci_bus
, piix4_devfn
+ 2);
835 smbus
= piix4_pm_init(pci_bus
, piix4_devfn
+ 3, 0x1100);
836 eeprom_buf
= qemu_mallocz(8 * 256); /* XXX: make this persistent */
837 for (i
= 0; i
< 8; i
++) {
838 /* TODO: Populate SPD eeprom data. */
839 smbus_eeprom_device_init(smbus
, 0x50 + i
, eeprom_buf
+ (i
* 256));
841 pit
= pit_init(0x40, i8259
[0]);
845 i8042_init(i8259
[1], i8259
[12], 0x60);
846 rtc_state
= rtc_init(0x70, i8259
[8]);
848 serial_init(0x3f8, i8259
[4], serial_hds
[0]);
850 serial_init(0x2f8, i8259
[3], serial_hds
[1]);
852 parallel_init(0x378, i8259
[7], parallel_hds
[0]);
853 /* XXX: The floppy controller does not work correctly, something is
855 floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
863 network_init(pci_bus
);
865 /* Optional PCI video card */
866 pci_cirrus_vga_init(pci_bus
, ds
, phys_ram_base
+ ram_size
,
867 ram_size
, vga_ram_size
);
870 QEMUMachine mips_malta_machine
= {
872 "MIPS Malta Core LV",