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