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