Add -drive parameter, by Laurent Vivier.
[qemu] / 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 "hw.h"
26 #include "pc.h"
27 #include "fdc.h"
28 #include "net.h"
29 #include "boards.h"
30 #include "smbus.h"
31 #include "mips.h"
32 #include "pci.h"
33 #include "qemu-char.h"
34 #include "sysemu.h"
35 #include "audio/audio.h"
36 #include "boards.h"
37
38 #ifdef TARGET_WORDS_BIGENDIAN
39 #define BIOS_FILENAME "mips_bios.bin"
40 #else
41 #define BIOS_FILENAME "mipsel_bios.bin"
42 #endif
43
44 #ifdef TARGET_MIPS64
45 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
46 #else
47 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
48 #endif
49
50 #define ENVP_ADDR (int32_t)0x80002000
51 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
52
53 #define ENVP_NB_ENTRIES         16
54 #define ENVP_ENTRY_SIZE         256
55
56 #define MAX_IDE_BUS 2
57
58 extern FILE *logfile;
59
60 typedef struct {
61     uint32_t leds;
62     uint32_t brk;
63     uint32_t gpout;
64     uint32_t i2cin;
65     uint32_t i2coe;
66     uint32_t i2cout;
67     uint32_t i2csel;
68     CharDriverState *display;
69     char display_text[9];
70     SerialState *uart;
71 } MaltaFPGAState;
72
73 static PITState *pit;
74
75 static struct _loaderparams {
76     int ram_size;
77     const char *kernel_filename;
78     const char *kernel_cmdline;
79     const char *initrd_filename;
80 } loaderparams;
81
82 /* Malta FPGA */
83 static void malta_fpga_update_display(void *opaque)
84 {
85     char leds_text[9];
86     int i;
87     MaltaFPGAState *s = opaque;
88
89     for (i = 7 ; i >= 0 ; i--) {
90         if (s->leds & (1 << i))
91             leds_text[i] = '#';
92         else
93             leds_text[i] = ' ';
94     }
95     leds_text[8] = '\0';
96
97     qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
98     qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
99 }
100
101 /*
102  * EEPROM 24C01 / 24C02 emulation.
103  *
104  * Emulation for serial EEPROMs:
105  * 24C01 - 1024 bit (128 x 8)
106  * 24C02 - 2048 bit (256 x 8)
107  *
108  * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
109  */
110
111 //~ #define DEBUG
112
113 #if defined(DEBUG)
114 #  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
115 #else
116 #  define logout(fmt, args...) ((void)0)
117 #endif
118
119 struct _eeprom24c0x_t {
120   uint8_t tick;
121   uint8_t address;
122   uint8_t command;
123   uint8_t ack;
124   uint8_t scl;
125   uint8_t sda;
126   uint8_t data;
127   //~ uint16_t size;
128   uint8_t contents[256];
129 };
130
131 typedef struct _eeprom24c0x_t eeprom24c0x_t;
132
133 static eeprom24c0x_t eeprom = {
134     contents: {
135         /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
136         /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
137         /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
138         /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
139         /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
140         /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141         /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142         /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
143         /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144         /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145         /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146         /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147         /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148         /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149         /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150         /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
151     },
152 };
153
154 static uint8_t eeprom24c0x_read()
155 {
156     logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
157         eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
158     return eeprom.sda;
159 }
160
161 static void eeprom24c0x_write(int scl, int sda)
162 {
163     if (eeprom.scl && scl && (eeprom.sda != sda)) {
164         logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
165                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
166         if (!sda) {
167             eeprom.tick = 1;
168             eeprom.command = 0;
169         }
170     } else if (eeprom.tick == 0 && !eeprom.ack) {
171         /* Waiting for start. */
172         logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
173                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
174     } else if (!eeprom.scl && scl) {
175         logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
176                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
177         if (eeprom.ack) {
178             logout("\ti2c ack bit = 0\n");
179             sda = 0;
180             eeprom.ack = 0;
181         } else if (eeprom.sda == sda) {
182             uint8_t bit = (sda != 0);
183             logout("\ti2c bit = %d\n", bit);
184             if (eeprom.tick < 9) {
185                 eeprom.command <<= 1;
186                 eeprom.command += bit;
187                 eeprom.tick++;
188                 if (eeprom.tick == 9) {
189                     logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
190                     eeprom.ack = 1;
191                 }
192             } else if (eeprom.tick < 17) {
193                 if (eeprom.command & 1) {
194                     sda = ((eeprom.data & 0x80) != 0);
195                 }
196                 eeprom.address <<= 1;
197                 eeprom.address += bit;
198                 eeprom.tick++;
199                 eeprom.data <<= 1;
200                 if (eeprom.tick == 17) {
201                     eeprom.data = eeprom.contents[eeprom.address];
202                     logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
203                     eeprom.ack = 1;
204                     eeprom.tick = 0;
205                 }
206             } else if (eeprom.tick >= 17) {
207                 sda = 0;
208             }
209         } else {
210             logout("\tsda changed with raising scl\n");
211         }
212     } else {
213         logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
214     }
215     eeprom.scl = scl;
216     eeprom.sda = sda;
217 }
218
219 static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
220 {
221     MaltaFPGAState *s = opaque;
222     uint32_t val = 0;
223     uint32_t saddr;
224
225     saddr = (addr & 0xfffff);
226
227     switch (saddr) {
228
229     /* SWITCH Register */
230     case 0x00200:
231         val = 0x00000000;               /* All switches closed */
232         break;
233
234     /* STATUS Register */
235     case 0x00208:
236 #ifdef TARGET_WORDS_BIGENDIAN
237         val = 0x00000012;
238 #else
239         val = 0x00000010;
240 #endif
241         break;
242
243     /* JMPRS Register */
244     case 0x00210:
245         val = 0x00;
246         break;
247
248     /* LEDBAR Register */
249     case 0x00408:
250         val = s->leds;
251         break;
252
253     /* BRKRES Register */
254     case 0x00508:
255         val = s->brk;
256         break;
257
258     /* UART Registers are handled directly by the serial device */
259
260     /* GPOUT Register */
261     case 0x00a00:
262         val = s->gpout;
263         break;
264
265     /* XXX: implement a real I2C controller */
266
267     /* GPINP Register */
268     case 0x00a08:
269         /* IN = OUT until a real I2C control is implemented */
270         if (s->i2csel)
271             val = s->i2cout;
272         else
273             val = 0x00;
274         break;
275
276     /* I2CINP Register */
277     case 0x00b00:
278         val = ((s->i2cin & ~1) | eeprom24c0x_read());
279         break;
280
281     /* I2COE Register */
282     case 0x00b08:
283         val = s->i2coe;
284         break;
285
286     /* I2COUT Register */
287     case 0x00b10:
288         val = s->i2cout;
289         break;
290
291     /* I2CSEL Register */
292     case 0x00b18:
293         val = s->i2csel;
294         break;
295
296     default:
297 #if 0
298         printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
299                 addr);
300 #endif
301         break;
302     }
303     return val;
304 }
305
306 static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
307                               uint32_t val)
308 {
309     MaltaFPGAState *s = opaque;
310     uint32_t saddr;
311
312     saddr = (addr & 0xfffff);
313
314     switch (saddr) {
315
316     /* SWITCH Register */
317     case 0x00200:
318         break;
319
320     /* JMPRS Register */
321     case 0x00210:
322         break;
323
324     /* LEDBAR Register */
325     /* XXX: implement a 8-LED array */
326     case 0x00408:
327         s->leds = val & 0xff;
328         break;
329
330     /* ASCIIWORD Register */
331     case 0x00410:
332         snprintf(s->display_text, 9, "%08X", val);
333         malta_fpga_update_display(s);
334         break;
335
336     /* ASCIIPOS0 to ASCIIPOS7 Registers */
337     case 0x00418:
338     case 0x00420:
339     case 0x00428:
340     case 0x00430:
341     case 0x00438:
342     case 0x00440:
343     case 0x00448:
344     case 0x00450:
345         s->display_text[(saddr - 0x00418) >> 3] = (char) val;
346         malta_fpga_update_display(s);
347         break;
348
349     /* SOFTRES Register */
350     case 0x00500:
351         if (val == 0x42)
352             qemu_system_reset_request ();
353         break;
354
355     /* BRKRES Register */
356     case 0x00508:
357         s->brk = val & 0xff;
358         break;
359
360     /* UART Registers are handled directly by the serial device */
361
362     /* GPOUT Register */
363     case 0x00a00:
364         s->gpout = val & 0xff;
365         break;
366
367     /* I2COE Register */
368     case 0x00b08:
369         s->i2coe = val & 0x03;
370         break;
371
372     /* I2COUT Register */
373     case 0x00b10:
374         eeprom24c0x_write(val & 0x02, val & 0x01);
375         s->i2cout = val;
376         break;
377
378     /* I2CSEL Register */
379     case 0x00b18:
380         s->i2csel = val & 0x01;
381         break;
382
383     default:
384 #if 0
385         printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
386                 addr);
387 #endif
388         break;
389     }
390 }
391
392 static CPUReadMemoryFunc *malta_fpga_read[] = {
393    malta_fpga_readl,
394    malta_fpga_readl,
395    malta_fpga_readl
396 };
397
398 static CPUWriteMemoryFunc *malta_fpga_write[] = {
399    malta_fpga_writel,
400    malta_fpga_writel,
401    malta_fpga_writel
402 };
403
404 static void malta_fpga_reset(void *opaque)
405 {
406     MaltaFPGAState *s = opaque;
407
408     s->leds   = 0x00;
409     s->brk    = 0x0a;
410     s->gpout  = 0x00;
411     s->i2cin  = 0x3;
412     s->i2coe  = 0x0;
413     s->i2cout = 0x3;
414     s->i2csel = 0x1;
415
416     s->display_text[8] = '\0';
417     snprintf(s->display_text, 9, "        ");
418     malta_fpga_update_display(s);
419 }
420
421 static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
422 {
423     MaltaFPGAState *s;
424     CharDriverState *uart_chr;
425     int malta;
426
427     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
428
429     malta = cpu_register_io_memory(0, malta_fpga_read,
430                                    malta_fpga_write, s);
431
432     cpu_register_physical_memory(base, 0x900, malta);
433     cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
434
435     s->display = qemu_chr_open("vc");
436     qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
437     qemu_chr_printf(s->display, "+--------+\r\n");
438     qemu_chr_printf(s->display, "+        +\r\n");
439     qemu_chr_printf(s->display, "+--------+\r\n");
440     qemu_chr_printf(s->display, "\n");
441     qemu_chr_printf(s->display, "Malta ASCII\r\n");
442     qemu_chr_printf(s->display, "+--------+\r\n");
443     qemu_chr_printf(s->display, "+        +\r\n");
444     qemu_chr_printf(s->display, "+--------+\r\n");
445
446     uart_chr = qemu_chr_open("vc");
447     qemu_chr_printf(uart_chr, "CBUS UART\r\n");
448     s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
449
450     malta_fpga_reset(s);
451     qemu_register_reset(malta_fpga_reset, s);
452
453     return s;
454 }
455
456 /* Audio support */
457 #ifdef HAS_AUDIO
458 static void audio_init (PCIBus *pci_bus)
459 {
460     struct soundhw *c;
461     int audio_enabled = 0;
462
463     for (c = soundhw; !audio_enabled && c->name; ++c) {
464         audio_enabled = c->enabled;
465     }
466
467     if (audio_enabled) {
468         AudioState *s;
469
470         s = AUD_init ();
471         if (s) {
472             for (c = soundhw; c->name; ++c) {
473                 if (c->enabled)
474                     c->init.init_pci (pci_bus, s);
475             }
476         }
477     }
478 }
479 #endif
480
481 /* Network support */
482 static void network_init (PCIBus *pci_bus)
483 {
484     int i;
485     NICInfo *nd;
486
487     for(i = 0; i < nb_nics; i++) {
488         nd = &nd_table[i];
489         if (!nd->model) {
490             nd->model = "pcnet";
491         }
492         if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
493             /* The malta board has a PCNet card using PCI SLOT 11 */
494             pci_nic_init(pci_bus, nd, 88);
495         } else {
496             pci_nic_init(pci_bus, nd, -1);
497         }
498     }
499 }
500
501 /* ROM and pseudo bootloader
502
503    The following code implements a very very simple bootloader. It first
504    loads the registers a0 to a3 to the values expected by the OS, and
505    then jump at the kernel address.
506
507    The bootloader should pass the locations of the kernel arguments and
508    environment variables tables. Those tables contain the 32-bit address
509    of NULL terminated strings. The environment variables table should be
510    terminated by a NULL address.
511
512    For a simpler implementation, the number of kernel arguments is fixed
513    to two (the name of the kernel and the command line), and the two
514    tables are actually the same one.
515
516    The registers a0 to a3 should contain the following values:
517      a0 - number of kernel arguments
518      a1 - 32-bit address of the kernel arguments table
519      a2 - 32-bit address of the environment variables table
520      a3 - RAM size in bytes
521 */
522
523 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
524 {
525     uint32_t *p;
526
527     /* Small bootloader */
528     p = (uint32_t *) (phys_ram_base + bios_offset);
529     stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
530     stl_raw(p++, 0x00000000);                                      /* nop */
531
532     /* YAMON service vector */
533     stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
534     stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
535     stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
536     stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
537     stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
538     stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
539     stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
540     stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
541     stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
542     stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
543     stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
544     stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
545     stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
546
547
548     /* Second part of the bootloader */
549     p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
550     stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
551     stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
552     stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
553     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
554     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
555     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
556     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
557     stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
558     stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
559
560     /* Load BAR registers as done by YAMON */
561     stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
562
563 #ifdef TARGET_WORDS_BIGENDIAN
564     stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
565 #else
566     stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
567 #endif
568     stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
569
570     stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
571
572 #ifdef TARGET_WORDS_BIGENDIAN
573     stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
574 #else
575     stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
576 #endif
577     stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
578 #ifdef TARGET_WORDS_BIGENDIAN
579     stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
580 #else
581     stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
582 #endif
583     stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
584
585 #ifdef TARGET_WORDS_BIGENDIAN
586     stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
587 #else
588     stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
589 #endif
590     stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
591 #ifdef TARGET_WORDS_BIGENDIAN
592     stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
593 #else
594     stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
595 #endif
596     stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
597
598 #ifdef TARGET_WORDS_BIGENDIAN
599     stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
600 #else
601     stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
602 #endif
603     stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
604 #ifdef TARGET_WORDS_BIGENDIAN
605     stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
606 #else
607     stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
608 #endif
609     stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
610
611     /* Jump to kernel code */
612     stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
613     stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
614     stl_raw(p++, 0x03e00008);                                      /* jr ra */
615     stl_raw(p++, 0x00000000);                                      /* nop */
616
617     /* YAMON subroutines */
618     p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
619     stl_raw(p++, 0x03e00008);                                     /* jr ra */
620     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
621    /* 808 YAMON print */
622     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
623     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
624     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
625     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
626     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
627     stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
628     stl_raw(p++, 0x00000000);                                     /* nop */
629     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
630     stl_raw(p++, 0x00000000);                                     /* nop */
631     stl_raw(p++, 0x08000205);                                     /* j 814 */
632     stl_raw(p++, 0x00000000);                                     /* nop */
633     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
634     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
635     /* 0x83c YAMON print_count */
636     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
637     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
638     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
639     stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
640     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
641     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
642     stl_raw(p++, 0x00000000);                                     /* nop */
643     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
644     stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
645     stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
646     stl_raw(p++, 0x00000000);                                     /* nop */
647     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
648     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
649     /* 0x870 */
650     stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
651     stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
652     stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
653     stl_raw(p++, 0x00000000);                                     /* nop */
654     stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
655     stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
656     stl_raw(p++, 0x00000000);                                     /* nop */
657     stl_raw(p++, 0x03e00008);                                     /* jr ra */
658     stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
659
660 }
661
662 static void prom_set(int index, const char *string, ...)
663 {
664     va_list ap;
665     int32_t *p;
666     int32_t table_addr;
667     char *s;
668
669     if (index >= ENVP_NB_ENTRIES)
670         return;
671
672     p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
673     p += index;
674
675     if (string == NULL) {
676         stl_raw(p, 0);
677         return;
678     }
679
680     table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
681     s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
682
683     stl_raw(p, table_addr);
684
685     va_start(ap, string);
686     vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
687     va_end(ap);
688 }
689
690 /* Kernel */
691 static int64_t load_kernel (CPUState *env)
692 {
693     int64_t kernel_entry, kernel_low, kernel_high;
694     int index = 0;
695     long initrd_size;
696     ram_addr_t initrd_offset;
697
698     if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
699                  &kernel_entry, &kernel_low, &kernel_high) < 0) {
700         fprintf(stderr, "qemu: could not load kernel '%s'\n",
701                 loaderparams.kernel_filename);
702         exit(1);
703     }
704
705     /* load initrd */
706     initrd_size = 0;
707     initrd_offset = 0;
708     if (loaderparams.initrd_filename) {
709         initrd_size = get_image_size (loaderparams.initrd_filename);
710         if (initrd_size > 0) {
711             initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
712             if (initrd_offset + initrd_size > ram_size) {
713                 fprintf(stderr,
714                         "qemu: memory too small for initial ram disk '%s'\n",
715                         loaderparams.initrd_filename);
716                 exit(1);
717             }
718             initrd_size = load_image(loaderparams.initrd_filename,
719                                      phys_ram_base + initrd_offset);
720         }
721         if (initrd_size == (target_ulong) -1) {
722             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
723                     loaderparams.initrd_filename);
724             exit(1);
725         }
726     }
727
728     /* Store command line.  */
729     prom_set(index++, loaderparams.kernel_filename);
730     if (initrd_size > 0)
731         prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
732                  PHYS_TO_VIRT(initrd_offset), initrd_size,
733                  loaderparams.kernel_cmdline);
734     else
735         prom_set(index++, loaderparams.kernel_cmdline);
736
737     /* Setup minimum environment variables */
738     prom_set(index++, "memsize");
739     prom_set(index++, "%i", loaderparams.ram_size);
740     prom_set(index++, "modetty0");
741     prom_set(index++, "38400n8r");
742     prom_set(index++, NULL);
743
744     return kernel_entry;
745 }
746
747 static void main_cpu_reset(void *opaque)
748 {
749     CPUState *env = opaque;
750     cpu_reset(env);
751
752     /* The bootload does not need to be rewritten as it is located in a
753        read only location. The kernel location and the arguments table
754        location does not change. */
755     if (loaderparams.kernel_filename) {
756         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
757         load_kernel (env);
758     }
759 }
760
761 static
762 void mips_malta_init (int ram_size, int vga_ram_size,
763                       const char *boot_device, DisplayState *ds,
764                       const char *kernel_filename, const char *kernel_cmdline,
765                       const char *initrd_filename, const char *cpu_model)
766 {
767     char buf[1024];
768     unsigned long bios_offset;
769     int64_t kernel_entry;
770     PCIBus *pci_bus;
771     CPUState *env;
772     RTCState *rtc_state;
773     fdctrl_t *floppy_controller;
774     MaltaFPGAState *malta_fpga;
775     int ret;
776     qemu_irq *i8259;
777     int piix4_devfn;
778     uint8_t *eeprom_buf;
779     i2c_bus *smbus;
780     int i;
781     int index;
782     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
783     BlockDriverState *fd[MAX_FD];
784
785     /* init CPUs */
786     if (cpu_model == NULL) {
787 #ifdef TARGET_MIPS64
788         cpu_model = "20Kc";
789 #else
790         cpu_model = "24Kf";
791 #endif
792     }
793     env = cpu_init(cpu_model);
794     if (!env) {
795         fprintf(stderr, "Unable to find CPU definition\n");
796         exit(1);
797     }
798     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
799     qemu_register_reset(main_cpu_reset, env);
800
801     /* allocate RAM */
802     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
803
804     /* Map the bios at two physical locations, as on the real board */
805     bios_offset = ram_size + vga_ram_size;
806     cpu_register_physical_memory(0x1e000000LL,
807                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
808     cpu_register_physical_memory(0x1fc00000LL,
809                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
810
811     /* FPGA */
812     malta_fpga = malta_fpga_init(0x1f000000LL, env);
813
814     /* Load a BIOS image unless a kernel image has been specified. */
815     if (!kernel_filename) {
816         if (bios_name == NULL)
817             bios_name = BIOS_FILENAME;
818         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
819         ret = load_image(buf, phys_ram_base + bios_offset);
820         if (ret < 0 || ret > BIOS_SIZE) {
821             fprintf(stderr,
822                     "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
823                     buf);
824             exit(1);
825         }
826         /* In little endian mode the 32bit words in the bios are swapped,
827            a neat trick which allows bi-endian firmware. */
828 #ifndef TARGET_WORDS_BIGENDIAN
829         {
830             uint32_t *addr;
831             for (addr = (uint32_t *)(phys_ram_base + bios_offset);
832                  addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
833                  addr++) {
834                 *addr = bswap32(*addr);
835             }
836         }
837 #endif
838     }
839
840     /* If a kernel image has been specified, write a small bootloader
841        to the flash location. */
842     if (kernel_filename) {
843         loaderparams.ram_size = ram_size;
844         loaderparams.kernel_filename = kernel_filename;
845         loaderparams.kernel_cmdline = kernel_cmdline;
846         loaderparams.initrd_filename = initrd_filename;
847         kernel_entry = load_kernel(env);
848         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
849         write_bootloader(env, bios_offset, kernel_entry);
850     }
851
852     /* Board ID = 0x420 (Malta Board with CoreLV)
853        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
854        map to the board ID. */
855     stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
856
857     /* Init internal devices */
858     cpu_mips_irq_init_cpu(env);
859     cpu_mips_clock_init(env);
860     cpu_mips_irqctrl_init();
861
862     /* Interrupt controller */
863     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
864     i8259 = i8259_init(env->irq[2]);
865
866     /* Northbridge */
867     pci_bus = pci_gt64120_init(i8259);
868
869     /* Southbridge */
870
871     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
872         fprintf(stderr, "qemu: too many IDE bus\n");
873         exit(1);
874     }
875
876     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
877         index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
878         if (index != -1)
879             hd[i] = drives_table[index].bdrv;
880         else
881             hd[i] = NULL;
882     }
883
884     piix4_devfn = piix4_init(pci_bus, 80);
885     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
886     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
887     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
888     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
889     for (i = 0; i < 8; i++) {
890         /* TODO: Populate SPD eeprom data.  */
891         smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
892     }
893     pit = pit_init(0x40, i8259[0]);
894     DMA_init(0);
895
896     /* Super I/O */
897     i8042_init(i8259[1], i8259[12], 0x60);
898     rtc_state = rtc_init(0x70, i8259[8]);
899     if (serial_hds[0])
900         serial_init(0x3f8, i8259[4], serial_hds[0]);
901     if (serial_hds[1])
902         serial_init(0x2f8, i8259[3], serial_hds[1]);
903     if (parallel_hds[0])
904         parallel_init(0x378, i8259[7], parallel_hds[0]);
905     for(i = 0; i < MAX_FD; i++) {
906         index = drive_get_index(IF_FLOPPY, 0, i);
907        if (index != -1)
908            fd[i] = drives_table[index].bdrv;
909        else
910            fd[i] = NULL;
911     }
912     floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
913
914     /* Sound card */
915 #ifdef HAS_AUDIO
916     audio_init(pci_bus);
917 #endif
918
919     /* Network card */
920     network_init(pci_bus);
921
922     /* Optional PCI video card */
923     pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
924                         ram_size, vga_ram_size);
925 }
926
927 QEMUMachine mips_malta_machine = {
928     "malta",
929     "MIPS Malta Core LV",
930     mips_malta_init,
931 };