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