added cpu_model parameter to cpu_init()
[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 "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 PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
35 #else
36 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
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 extern FILE *logfile;
46
47 typedef struct {
48     uint32_t leds;
49     uint32_t brk;
50     uint32_t gpout;
51     uint32_t i2cin;
52     uint32_t i2coe;
53     uint32_t i2cout;
54     uint32_t i2csel;
55     CharDriverState *display;
56     char display_text[9];
57     SerialState *uart;
58 } MaltaFPGAState;
59
60 static PITState *pit;
61
62 static struct _loaderparams {
63     int ram_size;
64     const char *kernel_filename;
65     const char *kernel_cmdline;
66     const char *initrd_filename;
67 } loaderparams;
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 are handled directly by the serial device */
246
247     /* GPOUT Register */
248     case 0x00a00:
249         val = s->gpout;
250         break;
251
252     /* XXX: implement a real I2C controller */
253
254     /* GPINP Register */
255     case 0x00a08:
256         /* IN = OUT until a real I2C control is implemented */
257         if (s->i2csel)
258             val = s->i2cout;
259         else
260             val = 0x00;
261         break;
262
263     /* I2CINP Register */
264     case 0x00b00:
265         val = ((s->i2cin & ~1) | eeprom24c0x_read());
266         break;
267
268     /* I2COE Register */
269     case 0x00b08:
270         val = s->i2coe;
271         break;
272
273     /* I2COUT Register */
274     case 0x00b10:
275         val = s->i2cout;
276         break;
277
278     /* I2CSEL Register */
279     case 0x00b18:
280         val = s->i2csel;
281         break;
282
283     default:
284 #if 0
285         printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
286                 addr);
287 #endif
288         break;
289     }
290     return val;
291 }
292
293 static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
294                               uint32_t val)
295 {
296     MaltaFPGAState *s = opaque;
297     uint32_t saddr;
298
299     saddr = (addr & 0xfffff);
300
301     switch (saddr) {
302
303     /* SWITCH Register */
304     case 0x00200:
305         break;
306
307     /* JMPRS Register */
308     case 0x00210:
309         break;
310
311     /* LEDBAR Register */
312     /* XXX: implement a 8-LED array */
313     case 0x00408:
314         s->leds = val & 0xff;
315         break;
316
317     /* ASCIIWORD Register */
318     case 0x00410:
319         snprintf(s->display_text, 9, "%08X", val);
320         malta_fpga_update_display(s);
321         break;
322
323     /* ASCIIPOS0 to ASCIIPOS7 Registers */
324     case 0x00418:
325     case 0x00420:
326     case 0x00428:
327     case 0x00430:
328     case 0x00438:
329     case 0x00440:
330     case 0x00448:
331     case 0x00450:
332         s->display_text[(saddr - 0x00418) >> 3] = (char) val;
333         malta_fpga_update_display(s);
334         break;
335
336     /* SOFTRES Register */
337     case 0x00500:
338         if (val == 0x42)
339             qemu_system_reset_request ();
340         break;
341
342     /* BRKRES Register */
343     case 0x00508:
344         s->brk = val & 0xff;
345         break;
346
347     /* UART Registers are handled directly by the serial device */
348
349     /* GPOUT Register */
350     case 0x00a00:
351         s->gpout = val & 0xff;
352         break;
353
354     /* I2COE Register */
355     case 0x00b08:
356         s->i2coe = val & 0x03;
357         break;
358
359     /* I2COUT Register */
360     case 0x00b10:
361         eeprom24c0x_write(val & 0x02, val & 0x01);
362         s->i2cout = val;
363         break;
364
365     /* I2CSEL Register */
366     case 0x00b18:
367         s->i2csel = val & 0x01;
368         break;
369
370     default:
371 #if 0
372         printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
373                 addr);
374 #endif
375         break;
376     }
377 }
378
379 static CPUReadMemoryFunc *malta_fpga_read[] = {
380    malta_fpga_readl,
381    malta_fpga_readl,
382    malta_fpga_readl
383 };
384
385 static CPUWriteMemoryFunc *malta_fpga_write[] = {
386    malta_fpga_writel,
387    malta_fpga_writel,
388    malta_fpga_writel
389 };
390
391 void malta_fpga_reset(void *opaque)
392 {
393     MaltaFPGAState *s = opaque;
394
395     s->leds   = 0x00;
396     s->brk    = 0x0a;
397     s->gpout  = 0x00;
398     s->i2cin  = 0x3;
399     s->i2coe  = 0x0;
400     s->i2cout = 0x3;
401     s->i2csel = 0x1;
402
403     s->display_text[8] = '\0';
404     snprintf(s->display_text, 9, "        ");
405     malta_fpga_update_display(s);
406 }
407
408 MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
409 {
410     MaltaFPGAState *s;
411     CharDriverState *uart_chr;
412     int malta;
413
414     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
415
416     malta = cpu_register_io_memory(0, malta_fpga_read,
417                                    malta_fpga_write, s);
418
419     cpu_register_physical_memory(base, 0x900, malta);
420     cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
421
422     s->display = qemu_chr_open("vc");
423     qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
424     qemu_chr_printf(s->display, "+--------+\r\n");
425     qemu_chr_printf(s->display, "+        +\r\n");
426     qemu_chr_printf(s->display, "+--------+\r\n");
427     qemu_chr_printf(s->display, "\n");
428     qemu_chr_printf(s->display, "Malta ASCII\r\n");
429     qemu_chr_printf(s->display, "+--------+\r\n");
430     qemu_chr_printf(s->display, "+        +\r\n");
431     qemu_chr_printf(s->display, "+--------+\r\n");
432
433     uart_chr = qemu_chr_open("vc");
434     qemu_chr_printf(uart_chr, "CBUS UART\r\n");
435     s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
436
437     malta_fpga_reset(s);
438     qemu_register_reset(malta_fpga_reset, s);
439
440     return s;
441 }
442
443 /* Audio support */
444 #ifdef HAS_AUDIO
445 static void audio_init (PCIBus *pci_bus)
446 {
447     struct soundhw *c;
448     int audio_enabled = 0;
449
450     for (c = soundhw; !audio_enabled && c->name; ++c) {
451         audio_enabled = c->enabled;
452     }
453
454     if (audio_enabled) {
455         AudioState *s;
456
457         s = AUD_init ();
458         if (s) {
459             for (c = soundhw; c->name; ++c) {
460                 if (c->enabled)
461                     c->init.init_pci (pci_bus, s);
462             }
463         }
464     }
465 }
466 #endif
467
468 /* Network support */
469 static void network_init (PCIBus *pci_bus)
470 {
471     int i;
472     NICInfo *nd;
473
474     for(i = 0; i < nb_nics; i++) {
475         nd = &nd_table[i];
476         if (!nd->model) {
477             nd->model = "pcnet";
478         }
479         if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
480             /* The malta board has a PCNet card using PCI SLOT 11 */
481             pci_nic_init(pci_bus, nd, 88);
482         } else {
483             pci_nic_init(pci_bus, nd, -1);
484         }
485     }
486 }
487
488 /* ROM and pseudo bootloader
489
490    The following code implements a very very simple bootloader. It first
491    loads the registers a0 to a3 to the values expected by the OS, and
492    then jump at the kernel address.
493
494    The bootloader should pass the locations of the kernel arguments and
495    environment variables tables. Those tables contain the 32-bit address
496    of NULL terminated strings. The environment variables table should be
497    terminated by a NULL address.
498
499    For a simpler implementation, the number of kernel arguments is fixed
500    to two (the name of the kernel and the command line), and the two
501    tables are actually the same one.
502
503    The registers a0 to a3 should contain the following values:
504      a0 - number of kernel arguments
505      a1 - 32-bit address of the kernel arguments table
506      a2 - 32-bit address of the environment variables table
507      a3 - RAM size in bytes
508 */
509
510 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
511 {
512     uint32_t *p;
513
514     /* Small bootloader */
515     p = (uint32_t *) (phys_ram_base + bios_offset);
516     stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
517     stl_raw(p++, 0x00000000);                                      /* nop */
518
519     /* YAMON service vector */
520     stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
521     stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
522     stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
523     stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
524     stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
525     stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
526     stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
527     stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
528     stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
529     stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
530     stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
531     stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
532     stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
533
534
535     /* Second part of the bootloader */
536     p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
537     stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
538     stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
539     stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
540     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
541     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
542     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
543     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
544     stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
545     stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
546
547     /* Load BAR registers as done by YAMON */
548     stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
549
550 #ifdef TARGET_WORDS_BIGENDIAN
551     stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
552 #else
553     stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
554 #endif
555     stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
556
557     stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
558
559 #ifdef TARGET_WORDS_BIGENDIAN
560     stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
561 #else
562     stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
563 #endif
564     stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
565 #ifdef TARGET_WORDS_BIGENDIAN
566     stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
567 #else
568     stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
569 #endif
570     stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
571
572 #ifdef TARGET_WORDS_BIGENDIAN
573     stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
574 #else
575     stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
576 #endif
577     stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
578 #ifdef TARGET_WORDS_BIGENDIAN
579     stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
580 #else
581     stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
582 #endif
583     stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
584
585 #ifdef TARGET_WORDS_BIGENDIAN
586     stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
587 #else
588     stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
589 #endif
590     stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
591 #ifdef TARGET_WORDS_BIGENDIAN
592     stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
593 #else
594     stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
595 #endif
596     stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
597
598     /* Jump to kernel code */
599     stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
600     stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
601     stl_raw(p++, 0x03e00008);                                      /* jr ra */
602     stl_raw(p++, 0x00000000);                                      /* nop */
603
604     /* YAMON subroutines */
605     p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
606     stl_raw(p++, 0x03e00008);                                     /* jr ra */
607     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
608    /* 808 YAMON print */
609     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
610     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
611     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
612     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
613     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
614     stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
615     stl_raw(p++, 0x00000000);                                     /* nop */
616     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
617     stl_raw(p++, 0x00000000);                                     /* nop */
618     stl_raw(p++, 0x08000205);                                     /* j 814 */
619     stl_raw(p++, 0x00000000);                                     /* nop */
620     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
621     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
622     /* 0x83c YAMON print_count */
623     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
624     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
625     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
626     stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
627     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
628     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
629     stl_raw(p++, 0x00000000);                                     /* nop */
630     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
631     stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
632     stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
633     stl_raw(p++, 0x00000000);                                     /* nop */
634     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
635     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
636     /* 0x870 */
637     stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
638     stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
639     stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
640     stl_raw(p++, 0x00000000);                                     /* nop */
641     stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
642     stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
643     stl_raw(p++, 0x00000000);                                     /* nop */
644     stl_raw(p++, 0x03e00008);                                     /* jr ra */
645     stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
646
647 }
648
649 static void prom_set(int index, const char *string, ...)
650 {
651     va_list ap;
652     int32_t *p;
653     int32_t table_addr;
654     char *s;
655
656     if (index >= ENVP_NB_ENTRIES)
657         return;
658
659     p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
660     p += index;
661
662     if (string == NULL) {
663         stl_raw(p, 0);
664         return;
665     }
666
667     table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
668     s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
669
670     stl_raw(p, table_addr);
671
672     va_start(ap, string);
673     vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
674     va_end(ap);
675 }
676
677 /* Kernel */
678 static int64_t load_kernel (CPUState *env)
679 {
680     int64_t kernel_entry, kernel_low, kernel_high;
681     int index = 0;
682     long initrd_size;
683     ram_addr_t initrd_offset;
684
685     if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
686                  &kernel_entry, &kernel_low, &kernel_high) < 0) {
687         fprintf(stderr, "qemu: could not load kernel '%s'\n",
688                 loaderparams.kernel_filename);
689         exit(1);
690     }
691
692     /* load initrd */
693     initrd_size = 0;
694     initrd_offset = 0;
695     if (loaderparams.initrd_filename) {
696         initrd_size = get_image_size (loaderparams.initrd_filename);
697         if (initrd_size > 0) {
698             initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
699             if (initrd_offset + initrd_size > ram_size) {
700                 fprintf(stderr,
701                         "qemu: memory too small for initial ram disk '%s'\n",
702                         loaderparams.initrd_filename);
703                 exit(1);
704             }
705             initrd_size = load_image(loaderparams.initrd_filename,
706                                      phys_ram_base + initrd_offset);
707         }
708         if (initrd_size == (target_ulong) -1) {
709             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
710                     loaderparams.initrd_filename);
711             exit(1);
712         }
713     }
714
715     /* Store command line.  */
716     prom_set(index++, loaderparams.kernel_filename);
717     if (initrd_size > 0)
718         prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
719                  PHYS_TO_VIRT(initrd_offset), initrd_size,
720                  loaderparams.kernel_cmdline);
721     else
722         prom_set(index++, loaderparams.kernel_cmdline);
723
724     /* Setup minimum environment variables */
725     prom_set(index++, "memsize");
726     prom_set(index++, "%i", loaderparams.ram_size);
727     prom_set(index++, "modetty0");
728     prom_set(index++, "38400n8r");
729     prom_set(index++, NULL);
730
731     return kernel_entry;
732 }
733
734 static void main_cpu_reset(void *opaque)
735 {
736     CPUState *env = opaque;
737     cpu_reset(env);
738
739     /* The bootload does not need to be rewritten as it is located in a
740        read only location. The kernel location and the arguments table
741        location does not change. */
742     if (loaderparams.kernel_filename) {
743         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
744         load_kernel (env);
745     }
746 }
747
748 static
749 void mips_malta_init (int ram_size, int vga_ram_size, const char *boot_device,
750                       DisplayState *ds, const char **fd_filename, int snapshot,
751                       const char *kernel_filename, const char *kernel_cmdline,
752                       const char *initrd_filename, const char *cpu_model)
753 {
754     char buf[1024];
755     unsigned long bios_offset;
756     int64_t kernel_entry;
757     PCIBus *pci_bus;
758     CPUState *env;
759     RTCState *rtc_state;
760     /* fdctrl_t *floppy_controller; */
761     MaltaFPGAState *malta_fpga;
762     int ret;
763     qemu_irq *i8259;
764     int piix4_devfn;
765     uint8_t *eeprom_buf;
766     i2c_bus *smbus;
767     int i;
768
769     /* init CPUs */
770     if (cpu_model == NULL) {
771 #ifdef TARGET_MIPS64
772         cpu_model = "20Kc";
773 #else
774         cpu_model = "24Kf";
775 #endif
776     }
777     env = cpu_init(cpu_model);
778     if (!env) {
779         fprintf(stderr, "Unable to find CPU definition\n");
780         exit(1);
781     }
782     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
783     qemu_register_reset(main_cpu_reset, env);
784
785     /* allocate RAM */
786     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
787
788     /* Map the bios at two physical locations, as on the real board */
789     bios_offset = ram_size + vga_ram_size;
790     cpu_register_physical_memory(0x1e000000LL,
791                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
792     cpu_register_physical_memory(0x1fc00000LL,
793                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
794
795     /* FPGA */
796     malta_fpga = malta_fpga_init(0x1f000000LL, env);
797
798     /* Load a BIOS image unless a kernel image has been specified. */
799     if (!kernel_filename) {
800         if (bios_name == NULL)
801             bios_name = BIOS_FILENAME;
802         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
803         ret = load_image(buf, phys_ram_base + bios_offset);
804         if (ret < 0 || ret > BIOS_SIZE) {
805             fprintf(stderr,
806                     "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
807                     buf);
808             exit(1);
809         }
810         /* In little endian mode the 32bit words in the bios are swapped,
811            a neat trick which allows bi-endian firmware. */
812 #ifndef TARGET_WORDS_BIGENDIAN
813         {
814             uint32_t *addr;
815             for (addr = (uint32_t *)(phys_ram_base + bios_offset);
816                  addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
817                  addr++) {
818                 *addr = bswap32(*addr);
819             }
820         }
821 #endif
822     }
823
824     /* If a kernel image has been specified, write a small bootloader
825        to the flash location. */
826     if (kernel_filename) {
827         loaderparams.ram_size = ram_size;
828         loaderparams.kernel_filename = kernel_filename;
829         loaderparams.kernel_cmdline = kernel_cmdline;
830         loaderparams.initrd_filename = initrd_filename;
831         kernel_entry = load_kernel(env);
832         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
833         write_bootloader(env, bios_offset, kernel_entry);
834     }
835
836     /* Board ID = 0x420 (Malta Board with CoreLV)
837        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
838        map to the board ID. */
839     stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
840
841     /* Init internal devices */
842     cpu_mips_irq_init_cpu(env);
843     cpu_mips_clock_init(env);
844     cpu_mips_irqctrl_init();
845
846     /* Interrupt controller */
847     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
848     i8259 = i8259_init(env->irq[2]);
849
850     /* Northbridge */
851     pci_bus = pci_gt64120_init(i8259);
852
853     /* Southbridge */
854     piix4_devfn = piix4_init(pci_bus, 80);
855     pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, i8259);
856     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
857     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
858     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
859     for (i = 0; i < 8; i++) {
860         /* TODO: Populate SPD eeprom data.  */
861         smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
862     }
863     pit = pit_init(0x40, i8259[0]);
864     DMA_init(0);
865
866     /* Super I/O */
867     i8042_init(i8259[1], i8259[12], 0x60);
868     rtc_state = rtc_init(0x70, i8259[8]);
869     if (serial_hds[0])
870         serial_init(0x3f8, i8259[4], serial_hds[0]);
871     if (serial_hds[1])
872         serial_init(0x2f8, i8259[3], serial_hds[1]);
873     if (parallel_hds[0])
874         parallel_init(0x378, i8259[7], parallel_hds[0]);
875     /* XXX: The floppy controller does not work correctly, something is
876        probably wrong.
877     floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
878
879     /* Sound card */
880 #ifdef HAS_AUDIO
881     audio_init(pci_bus);
882 #endif
883
884     /* Network card */
885     network_init(pci_bus);
886
887     /* Optional PCI video card */
888     pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
889                         ram_size, vga_ram_size);
890 }
891
892 QEMUMachine mips_malta_machine = {
893     "malta",
894     "MIPS Malta Core LV",
895     mips_malta_init,
896 };