]> git.proxmox.com Git - qemu.git/blob - hw/mips_malta.c
Actually enable 64bit configuration.
[qemu.git] / hw / mips_malta.c
1 /*
2 * QEMU Malta board support
3 *
4 * Copyright (c) 2006 Aurelien Jarno
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 "vl.h"
26
27 #ifdef TARGET_WORDS_BIGENDIAN
28 #define BIOS_FILENAME "mips_bios.bin"
29 #else
30 #define BIOS_FILENAME "mipsel_bios.bin"
31 #endif
32
33 #ifdef TARGET_MIPS64
34 #define INITRD_LOAD_ADDR (int64_t)0x80800000
35 #else
36 #define INITRD_LOAD_ADDR (int32_t)0x80800000
37 #endif
38
39 #define ENVP_ADDR (int32_t)0x80002000
40 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
41
42 #define ENVP_NB_ENTRIES 16
43 #define ENVP_ENTRY_SIZE 256
44
45
46 extern FILE *logfile;
47
48 typedef struct {
49 uint32_t leds;
50 uint32_t brk;
51 uint32_t gpout;
52 uint32_t i2cin;
53 uint32_t i2coe;
54 uint32_t i2cout;
55 uint32_t i2csel;
56 CharDriverState *display;
57 char display_text[9];
58 SerialState *uart;
59 } MaltaFPGAState;
60
61 static PITState *pit;
62
63 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
64 static void pic_irq_request(void *opaque, int level)
65 {
66 cpu_mips_irq_request(opaque, 2, level);
67 }
68
69 /* Malta FPGA */
70 static void malta_fpga_update_display(void *opaque)
71 {
72 char leds_text[9];
73 int i;
74 MaltaFPGAState *s = opaque;
75
76 for (i = 7 ; i >= 0 ; i--) {
77 if (s->leds & (1 << i))
78 leds_text[i] = '#';
79 else
80 leds_text[i] = ' ';
81 }
82 leds_text[8] = '\0';
83
84 qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
85 qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
86 }
87
88 /*
89 * EEPROM 24C01 / 24C02 emulation.
90 *
91 * Emulation for serial EEPROMs:
92 * 24C01 - 1024 bit (128 x 8)
93 * 24C02 - 2048 bit (256 x 8)
94 *
95 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
96 */
97
98 //~ #define DEBUG
99
100 #if defined(DEBUG)
101 # define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
102 #else
103 # define logout(fmt, args...) ((void)0)
104 #endif
105
106 struct _eeprom24c0x_t {
107 uint8_t tick;
108 uint8_t address;
109 uint8_t command;
110 uint8_t ack;
111 uint8_t scl;
112 uint8_t sda;
113 uint8_t data;
114 //~ uint16_t size;
115 uint8_t contents[256];
116 };
117
118 typedef struct _eeprom24c0x_t eeprom24c0x_t;
119
120 static eeprom24c0x_t eeprom = {
121 contents: {
122 /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
123 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
124 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
125 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
126 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
127 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
130 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
137 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
138 },
139 };
140
141 static uint8_t eeprom24c0x_read()
142 {
143 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
144 eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
145 return eeprom.sda;
146 }
147
148 static void eeprom24c0x_write(int scl, int sda)
149 {
150 if (eeprom.scl && scl && (eeprom.sda != sda)) {
151 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
152 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
153 if (!sda) {
154 eeprom.tick = 1;
155 eeprom.command = 0;
156 }
157 } else if (eeprom.tick == 0 && !eeprom.ack) {
158 /* Waiting for start. */
159 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
160 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
161 } else if (!eeprom.scl && scl) {
162 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
163 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
164 if (eeprom.ack) {
165 logout("\ti2c ack bit = 0\n");
166 sda = 0;
167 eeprom.ack = 0;
168 } else if (eeprom.sda == sda) {
169 uint8_t bit = (sda != 0);
170 logout("\ti2c bit = %d\n", bit);
171 if (eeprom.tick < 9) {
172 eeprom.command <<= 1;
173 eeprom.command += bit;
174 eeprom.tick++;
175 if (eeprom.tick == 9) {
176 logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
177 eeprom.ack = 1;
178 }
179 } else if (eeprom.tick < 17) {
180 if (eeprom.command & 1) {
181 sda = ((eeprom.data & 0x80) != 0);
182 }
183 eeprom.address <<= 1;
184 eeprom.address += bit;
185 eeprom.tick++;
186 eeprom.data <<= 1;
187 if (eeprom.tick == 17) {
188 eeprom.data = eeprom.contents[eeprom.address];
189 logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
190 eeprom.ack = 1;
191 eeprom.tick = 0;
192 }
193 } else if (eeprom.tick >= 17) {
194 sda = 0;
195 }
196 } else {
197 logout("\tsda changed with raising scl\n");
198 }
199 } else {
200 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
201 }
202 eeprom.scl = scl;
203 eeprom.sda = sda;
204 }
205
206 static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
207 {
208 MaltaFPGAState *s = opaque;
209 uint32_t val = 0;
210 uint32_t saddr;
211
212 saddr = (addr & 0xfffff);
213
214 switch (saddr) {
215
216 /* SWITCH Register */
217 case 0x00200:
218 val = 0x00000000; /* All switches closed */
219 break;
220
221 /* STATUS Register */
222 case 0x00208:
223 #ifdef TARGET_WORDS_BIGENDIAN
224 val = 0x00000012;
225 #else
226 val = 0x00000010;
227 #endif
228 break;
229
230 /* JMPRS Register */
231 case 0x00210:
232 val = 0x00;
233 break;
234
235 /* LEDBAR Register */
236 case 0x00408:
237 val = s->leds;
238 break;
239
240 /* BRKRES Register */
241 case 0x00508:
242 val = s->brk;
243 break;
244
245 /* UART Registers */
246 case 0x00900:
247 case 0x00904:
248 case 0x00908:
249 case 0x0090c:
250 case 0x00910:
251 case 0x00914:
252 case 0x00918:
253 case 0x0091c:
254 val = serial_mm_readl(s->uart, addr);
255 break;
256
257 /* GPOUT Register */
258 case 0x00a00:
259 val = s->gpout;
260 break;
261
262 /* XXX: implement a real I2C controller */
263
264 /* GPINP Register */
265 case 0x00a08:
266 /* IN = OUT until a real I2C control is implemented */
267 if (s->i2csel)
268 val = s->i2cout;
269 else
270 val = 0x00;
271 break;
272
273 /* I2CINP Register */
274 case 0x00b00:
275 val = ((s->i2cin & ~1) | eeprom24c0x_read());
276 break;
277
278 /* I2COE Register */
279 case 0x00b08:
280 val = s->i2coe;
281 break;
282
283 /* I2COUT Register */
284 case 0x00b10:
285 val = s->i2cout;
286 break;
287
288 /* I2CSEL Register */
289 case 0x00b18:
290 val = s->i2csel;
291 break;
292
293 default:
294 #if 0
295 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
296 addr);
297 #endif
298 break;
299 }
300 return val;
301 }
302
303 static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
304 uint32_t val)
305 {
306 MaltaFPGAState *s = opaque;
307 uint32_t saddr;
308
309 saddr = (addr & 0xfffff);
310
311 switch (saddr) {
312
313 /* SWITCH Register */
314 case 0x00200:
315 break;
316
317 /* JMPRS Register */
318 case 0x00210:
319 break;
320
321 /* LEDBAR Register */
322 /* XXX: implement a 8-LED array */
323 case 0x00408:
324 s->leds = val & 0xff;
325 break;
326
327 /* ASCIIWORD Register */
328 case 0x00410:
329 snprintf(s->display_text, 9, "%08X", val);
330 malta_fpga_update_display(s);
331 break;
332
333 /* ASCIIPOS0 to ASCIIPOS7 Registers */
334 case 0x00418:
335 case 0x00420:
336 case 0x00428:
337 case 0x00430:
338 case 0x00438:
339 case 0x00440:
340 case 0x00448:
341 case 0x00450:
342 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
343 malta_fpga_update_display(s);
344 break;
345
346 /* SOFTRES Register */
347 case 0x00500:
348 if (val == 0x42)
349 qemu_system_reset_request ();
350 break;
351
352 /* BRKRES Register */
353 case 0x00508:
354 s->brk = val & 0xff;
355 break;
356
357 /* UART Registers */
358 case 0x00900:
359 case 0x00904:
360 case 0x00908:
361 case 0x0090c:
362 case 0x00910:
363 case 0x00914:
364 case 0x00918:
365 case 0x0091c:
366 serial_mm_writel(s->uart, addr, val);
367 break;
368
369 /* GPOUT Register */
370 case 0x00a00:
371 s->gpout = val & 0xff;
372 break;
373
374 /* I2COE Register */
375 case 0x00b08:
376 s->i2coe = val & 0x03;
377 break;
378
379 /* I2COUT Register */
380 case 0x00b10:
381 eeprom24c0x_write(val & 0x02, val & 0x01);
382 s->i2cout = val;
383 break;
384
385 /* I2CSEL Register */
386 case 0x00b18:
387 s->i2csel = val & 0x01;
388 break;
389
390 default:
391 #if 0
392 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
393 addr);
394 #endif
395 break;
396 }
397 }
398
399 static CPUReadMemoryFunc *malta_fpga_read[] = {
400 malta_fpga_readl,
401 malta_fpga_readl,
402 malta_fpga_readl
403 };
404
405 static CPUWriteMemoryFunc *malta_fpga_write[] = {
406 malta_fpga_writel,
407 malta_fpga_writel,
408 malta_fpga_writel
409 };
410
411 void malta_fpga_reset(void *opaque)
412 {
413 MaltaFPGAState *s = opaque;
414
415 s->leds = 0x00;
416 s->brk = 0x0a;
417 s->gpout = 0x00;
418 s->i2cin = 0x3;
419 s->i2coe = 0x0;
420 s->i2cout = 0x3;
421 s->i2csel = 0x1;
422
423 s->display_text[8] = '\0';
424 snprintf(s->display_text, 9, " ");
425 malta_fpga_update_display(s);
426 }
427
428 MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
429 {
430 MaltaFPGAState *s;
431 CharDriverState *uart_chr;
432 int malta;
433
434 s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
435
436 malta = cpu_register_io_memory(0, malta_fpga_read,
437 malta_fpga_write, s);
438
439 cpu_register_physical_memory(base, 0x100000, malta);
440
441 s->display = qemu_chr_open("vc");
442 qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
443 qemu_chr_printf(s->display, "+--------+\r\n");
444 qemu_chr_printf(s->display, "+ +\r\n");
445 qemu_chr_printf(s->display, "+--------+\r\n");
446 qemu_chr_printf(s->display, "\n");
447 qemu_chr_printf(s->display, "Malta ASCII\r\n");
448 qemu_chr_printf(s->display, "+--------+\r\n");
449 qemu_chr_printf(s->display, "+ +\r\n");
450 qemu_chr_printf(s->display, "+--------+\r\n");
451
452 uart_chr = qemu_chr_open("vc");
453 qemu_chr_printf(uart_chr, "CBUS UART\r\n");
454 s->uart = serial_mm_init(&cpu_mips_irq_request, env, base, 3, 2,
455 uart_chr, 0);
456
457 malta_fpga_reset(s);
458 qemu_register_reset(malta_fpga_reset, s);
459
460 return s;
461 }
462
463 /* Audio support */
464 #ifdef HAS_AUDIO
465 static void audio_init (PCIBus *pci_bus)
466 {
467 struct soundhw *c;
468 int audio_enabled = 0;
469
470 for (c = soundhw; !audio_enabled && c->name; ++c) {
471 audio_enabled = c->enabled;
472 }
473
474 if (audio_enabled) {
475 AudioState *s;
476
477 s = AUD_init ();
478 if (s) {
479 for (c = soundhw; c->name; ++c) {
480 if (c->enabled) {
481 if (c->isa) {
482 fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
483 exit(1);
484 }
485 else {
486 if (pci_bus) {
487 c->init.init_pci (pci_bus, s);
488 }
489 }
490 }
491 }
492 }
493 }
494 }
495 #endif
496
497 /* Network support */
498 static void network_init (PCIBus *pci_bus)
499 {
500 int i;
501 NICInfo *nd;
502
503 for(i = 0; i < nb_nics; i++) {
504 nd = &nd_table[i];
505 if (!nd->model) {
506 nd->model = "pcnet";
507 }
508 if (i == 0 && strcmp(nd->model, "pcnet") == 0) {
509 /* The malta board has a PCNet card using PCI SLOT 11 */
510 pci_nic_init(pci_bus, nd, 88);
511 } else {
512 pci_nic_init(pci_bus, nd, -1);
513 }
514 }
515 }
516
517 /* ROM and pseudo bootloader
518
519 The following code implements a very very simple bootloader. It first
520 loads the registers a0 to a3 to the values expected by the OS, and
521 then jump at the kernel address.
522
523 The bootloader should pass the locations of the kernel arguments and
524 environment variables tables. Those tables contain the 32-bit address
525 of NULL terminated strings. The environment variables table should be
526 terminated by a NULL address.
527
528 For a simpler implementation, the number of kernel arguments is fixed
529 to two (the name of the kernel and the command line), and the two
530 tables are actually the same one.
531
532 The registers a0 to a3 should contain the following values:
533 a0 - number of kernel arguments
534 a1 - 32-bit address of the kernel arguments table
535 a2 - 32-bit address of the environment variables table
536 a3 - RAM size in bytes
537 */
538
539 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
540 {
541 uint32_t *p;
542
543 /* Small bootloader */
544 p = (uint32_t *) (phys_ram_base + bios_offset);
545 stl_raw(p++, 0x0bf00010); /* j 0x1fc00040 */
546 stl_raw(p++, 0x00000000); /* nop */
547
548 /* Second part of the bootloader */
549 p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
550 stl_raw(p++, 0x3c040000); /* lui a0, 0 */
551 stl_raw(p++, 0x34840002); /* ori a0, a0, 2 */
552 stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
553 stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a0, low(ENVP_ADDR) */
554 stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
555 stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
556 stl_raw(p++, 0x3c070000 | (env->ram_size >> 16)); /* lui a3, high(env->ram_size) */
557 stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff)); /* ori a3, a3, low(env->ram_size) */
558 stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff)); /* lui ra, high(kernel_addr) */;
559 stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff)); /* ori ra, ra, low(kernel_addr) */
560 stl_raw(p++, 0x03e00008); /* jr ra */
561 stl_raw(p++, 0x00000000); /* nop */
562 }
563
564 static void prom_set(int index, const char *string, ...)
565 {
566 va_list ap;
567 int32_t *p;
568 int32_t table_addr;
569 char *s;
570
571 if (index >= ENVP_NB_ENTRIES)
572 return;
573
574 p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
575 p += index;
576
577 if (string == NULL) {
578 stl_raw(p, 0);
579 return;
580 }
581
582 table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
583 s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
584
585 stl_raw(p, table_addr);
586
587 va_start(ap, string);
588 vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
589 va_end(ap);
590 }
591
592 /* Kernel */
593 static int64_t load_kernel (CPUState *env)
594 {
595 int64_t kernel_addr = 0;
596 int index = 0;
597 long initrd_size;
598
599 if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
600 fprintf(stderr, "qemu: could not load kernel '%s'\n",
601 env->kernel_filename);
602 exit(1);
603 }
604
605 /* load initrd */
606 initrd_size = 0;
607 if (env->initrd_filename) {
608 initrd_size = load_image(env->initrd_filename,
609 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
610 if (initrd_size == (target_ulong) -1) {
611 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
612 env->initrd_filename);
613 exit(1);
614 }
615 }
616
617 /* Store command line. */
618 prom_set(index++, env->kernel_filename);
619 if (initrd_size > 0)
620 prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
621 else
622 prom_set(index++, env->kernel_cmdline);
623
624 /* Setup minimum environment variables */
625 prom_set(index++, "memsize");
626 prom_set(index++, "%i", env->ram_size);
627 prom_set(index++, "modetty0");
628 prom_set(index++, "38400n8r");
629 prom_set(index++, NULL);
630
631 return kernel_addr;
632 }
633
634 static void main_cpu_reset(void *opaque)
635 {
636 CPUState *env = opaque;
637 cpu_reset(env);
638
639 /* The bootload does not need to be rewritten as it is located in a
640 read only location. The kernel location and the arguments table
641 location does not change. */
642 if (env->kernel_filename)
643 load_kernel (env);
644 }
645
646 static
647 void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
648 DisplayState *ds, const char **fd_filename, int snapshot,
649 const char *kernel_filename, const char *kernel_cmdline,
650 const char *initrd_filename, const char *cpu_model)
651 {
652 char buf[1024];
653 unsigned long bios_offset;
654 int64_t kernel_addr;
655 PCIBus *pci_bus;
656 CPUState *env;
657 RTCState *rtc_state;
658 /* fdctrl_t *floppy_controller; */
659 MaltaFPGAState *malta_fpga;
660 int ret;
661 mips_def_t *def;
662
663 /* init CPUs */
664 if (cpu_model == NULL) {
665 #ifdef TARGET_MIPS64
666 cpu_model = "R4000";
667 #else
668 cpu_model = "4KEc";
669 #endif
670 }
671 if (mips_find_by_name(cpu_model, &def) != 0)
672 def = NULL;
673 env = cpu_init();
674 cpu_mips_register(env, def);
675 register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
676 qemu_register_reset(main_cpu_reset, env);
677
678 /* allocate RAM */
679 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
680
681 /* Map the bios at two physical locations, as on the real board */
682 bios_offset = ram_size + vga_ram_size;
683 cpu_register_physical_memory(0x1e000000LL,
684 BIOS_SIZE, bios_offset | IO_MEM_ROM);
685 cpu_register_physical_memory(0x1fc00000LL,
686 BIOS_SIZE, bios_offset | IO_MEM_ROM);
687
688 /* Load a BIOS image except if a kernel image has been specified. In
689 the later case, just write a small bootloader to the flash
690 location. */
691 if (kernel_filename) {
692 env->ram_size = ram_size;
693 env->kernel_filename = kernel_filename;
694 env->kernel_cmdline = kernel_cmdline;
695 env->initrd_filename = initrd_filename;
696 kernel_addr = load_kernel(env);
697 write_bootloader(env, bios_offset, kernel_addr);
698 } else {
699 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
700 ret = load_image(buf, phys_ram_base + bios_offset);
701 if (ret < 0 || ret > BIOS_SIZE) {
702 fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
703 buf);
704 exit(1);
705 }
706 }
707
708 /* Board ID = 0x420 (Malta Board with CoreLV)
709 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
710 map to the board ID. */
711 stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
712
713 /* Init internal devices */
714 cpu_mips_clock_init(env);
715 cpu_mips_irqctrl_init();
716
717 /* FPGA */
718 malta_fpga = malta_fpga_init(0x1f000000LL, env);
719
720 /* Interrupt controller */
721 isa_pic = pic_init(pic_irq_request, env);
722
723 /* Northbridge */
724 pci_bus = pci_gt64120_init(isa_pic);
725
726 /* Southbridge */
727 piix4_init(pci_bus, 80);
728 pci_piix3_ide_init(pci_bus, bs_table, 81);
729 usb_uhci_init(pci_bus, 82);
730 piix4_pm_init(pci_bus, 83);
731 pit = pit_init(0x40, 0);
732 DMA_init(0);
733
734 /* Super I/O */
735 kbd_init();
736 rtc_state = rtc_init(0x70, 8);
737 if (serial_hds[0])
738 serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
739 if (serial_hds[1])
740 serial_init(&pic_set_irq_new, isa_pic, 0x2f8, 3, serial_hds[1]);
741 if (parallel_hds[0])
742 parallel_init(0x378, 7, parallel_hds[0]);
743 /* XXX: The floppy controller does not work correctly, something is
744 probably wrong.
745 floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
746
747 /* Sound card */
748 #ifdef HAS_AUDIO
749 audio_init(pci_bus);
750 #endif
751
752 /* Network card */
753 network_init(pci_bus);
754
755 /* Optional PCI video card */
756 pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
757 ram_size, vga_ram_size);
758 }
759
760 QEMUMachine mips_malta_machine = {
761 "malta",
762 "MIPS Malta Core LV",
763 mips_malta_init,
764 };