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