]> git.proxmox.com Git - mirror_qemu.git/blame - hw/mips_malta.c
MIPS64 configurations.
[mirror_qemu.git] / hw / mips_malta.c
CommitLineData
5856de80
TS
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
44cbbf18
TS
27#ifdef TARGET_WORDS_BIGENDIAN
28#define BIOS_FILENAME "mips_bios.bin"
29#else
30#define BIOS_FILENAME "mipsel_bios.bin"
31#endif
32
5856de80 33#ifdef MIPS_HAS_MIPS64
44cbbf18 34#define INITRD_LOAD_ADDR (int64_t)0x80800000
5856de80 35#else
44cbbf18 36#define INITRD_LOAD_ADDR (int32_t)0x80800000
5856de80
TS
37#endif
38
3ddd0065 39#define ENVP_ADDR (int32_t)0x80002000
44cbbf18 40#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
5856de80
TS
41
42#define ENVP_NB_ENTRIES 16
43#define ENVP_ENTRY_SIZE 256
44
45
46extern FILE *logfile;
47
48typedef struct {
49 uint32_t leds;
50 uint32_t brk;
51 uint32_t gpout;
130751ee 52 uint32_t i2cin;
5856de80
TS
53 uint32_t i2coe;
54 uint32_t i2cout;
55 uint32_t i2csel;
56 CharDriverState *display;
57 char display_text[9];
a4bc3afc 58 SerialState *uart;
5856de80
TS
59} MaltaFPGAState;
60
61static PITState *pit;
62
4de9b249 63/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
5856de80
TS
64static void pic_irq_request(void *opaque, int level)
65{
4de9b249 66 cpu_mips_irq_request(opaque, 2, level);
5856de80
TS
67}
68
69/* Malta FPGA */
70static 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
472c5273
TS
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);
5856de80
TS
86}
87
130751ee
TS
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
106struct _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
118typedef struct _eeprom24c0x_t eeprom24c0x_t;
119
120static 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
141static 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
148static 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
5856de80
TS
206static 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
a4bc3afc
TS
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
5856de80
TS
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:
130751ee 275 val = ((s->i2cin & ~1) | eeprom24c0x_read());
5856de80
TS
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:
130751ee 290 val = s->i2csel;
5856de80
TS
291 break;
292
293 default:
294#if 0
3594c774 295 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
44cbbf18 296 addr);
5856de80
TS
297#endif
298 break;
299 }
300 return val;
301}
302
303static 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
a4bc3afc
TS
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
5856de80
TS
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:
130751ee
TS
381 eeprom24c0x_write(val & 0x02, val & 0x01);
382 s->i2cout = val;
5856de80
TS
383 break;
384
385 /* I2CSEL Register */
386 case 0x00b18:
130751ee 387 s->i2csel = val & 0x01;
5856de80
TS
388 break;
389
390 default:
391#if 0
3594c774 392 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
44cbbf18 393 addr);
5856de80
TS
394#endif
395 break;
396 }
397}
398
399static CPUReadMemoryFunc *malta_fpga_read[] = {
400 malta_fpga_readl,
401 malta_fpga_readl,
402 malta_fpga_readl
403};
404
405static CPUWriteMemoryFunc *malta_fpga_write[] = {
406 malta_fpga_writel,
407 malta_fpga_writel,
408 malta_fpga_writel
409};
410
411void malta_fpga_reset(void *opaque)
412{
413 MaltaFPGAState *s = opaque;
414
415 s->leds = 0x00;
416 s->brk = 0x0a;
417 s->gpout = 0x00;
130751ee 418 s->i2cin = 0x3;
5856de80
TS
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
a4bc3afc 428MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
5856de80
TS
429{
430 MaltaFPGAState *s;
a4bc3afc 431 CharDriverState *uart_chr;
5856de80
TS
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);
a4bc3afc 438
5856de80
TS
439 cpu_register_physical_memory(base, 0x100000, malta);
440
441 s->display = qemu_chr_open("vc");
af23902b 442 qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
5856de80
TS
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
a4bc3afc
TS
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
5856de80
TS
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
465static 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 */
498static 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
539static 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);
3ddd0065
TS
545 stl_raw(p++, 0x0bf00010); /* j 0x1fc00040 */
546 stl_raw(p++, 0x00000000); /* nop */
5856de80
TS
547
548 /* Second part of the bootloader */
549 p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
3ddd0065
TS
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 */
5856de80
TS
562}
563
564static void prom_set(int index, const char *string, ...)
565{
566 va_list ap;
3ddd0065
TS
567 int32_t *p;
568 int32_t table_addr;
5856de80
TS
569 char *s;
570
571 if (index >= ENVP_NB_ENTRIES)
572 return;
573
3ddd0065 574 p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
5856de80
TS
575 p += index;
576
577 if (string == NULL) {
578 stl_raw(p, 0);
579 return;
580 }
581
3ddd0065 582 table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
5856de80
TS
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 */
593static 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)
3594c774 620 prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
5856de80
TS
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
634static 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
70705261 646static
5856de80
TS
647void 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,
94fc95cd 650 const char *initrd_filename, const char *cpu_model)
5856de80
TS
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;
f1770b3e 658 /* fdctrl_t *floppy_controller; */
5856de80
TS
659 MaltaFPGAState *malta_fpga;
660 int ret;
33d68b5f 661 mips_def_t *def;
5856de80 662
33d68b5f
TS
663 /* init CPUs */
664 if (cpu_model == NULL) {
665#ifdef MIPS_HAS_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;
5856de80 673 env = cpu_init();
33d68b5f 674 cpu_mips_register(env, def);
5856de80
TS
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);
331ad6f4 701 if (ret < 0 || ret > BIOS_SIZE) {
5856de80
TS
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 */
a4bc3afc 718 malta_fpga = malta_fpga_init(0x1f000000LL, env);
5856de80
TS
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);
7bcc17dc
TS
737 if (serial_hds[0])
738 serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
739 if (serial_hds[1])
c05ac0cd 740 serial_init(&pic_set_irq_new, isa_pic, 0x2f8, 3, serial_hds[1]);
7bcc17dc
TS
741 if (parallel_hds[0])
742 parallel_init(0x378, 7, parallel_hds[0]);
5856de80 743 /* XXX: The floppy controller does not work correctly, something is
f1770b3e
TS
744 probably wrong.
745 floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
5856de80
TS
746
747 /* Sound card */
748#ifdef HAS_AUDIO
749 audio_init(pci_bus);
750#endif
751
752 /* Network card */
753 network_init(pci_bus);
11f29511
TS
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);
5856de80
TS
758}
759
760QEMUMachine mips_malta_machine = {
761 "malta",
762 "MIPS Malta Core LV",
763 mips_malta_init,
764};