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