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