]> Git Repo - qemu.git/blob - hw/mips_malta.c
Clean up VGA ram allocation.
[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 "pci.h"
35 #include "qemu-char.h"
36 #include "sysemu.h"
37 #include "audio/audio.h"
38 #include "boards.h"
39 #include "qemu-log.h"
40
41 //#define DEBUG_BOARD_INIT
42
43 #ifdef TARGET_WORDS_BIGENDIAN
44 #define BIOS_FILENAME "mips_bios.bin"
45 #else
46 #define BIOS_FILENAME "mipsel_bios.bin"
47 #endif
48
49 #ifdef TARGET_MIPS64
50 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
51 #else
52 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
53 #endif
54
55 #define ENVP_ADDR (int32_t)0x80002000
56 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
57
58 #define ENVP_NB_ENTRIES         16
59 #define ENVP_ENTRY_SIZE         256
60
61 #define MAX_IDE_BUS 2
62
63 typedef struct {
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 static PITState *pit;
77
78 static struct _loaderparams {
79     int ram_size;
80     const char *kernel_filename;
81     const char *kernel_cmdline;
82     const char *initrd_filename;
83 } loaderparams;
84
85 /* Malta FPGA */
86 static void malta_fpga_update_display(void *opaque)
87 {
88     char leds_text[9];
89     int i;
90     MaltaFPGAState *s = opaque;
91
92     for (i = 7 ; i >= 0 ; i--) {
93         if (s->leds & (1 << i))
94             leds_text[i] = '#';
95         else
96             leds_text[i] = ' ';
97     }
98     leds_text[8] = '\0';
99
100     qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
101     qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
102 }
103
104 /*
105  * EEPROM 24C01 / 24C02 emulation.
106  *
107  * Emulation for serial EEPROMs:
108  * 24C01 - 1024 bit (128 x 8)
109  * 24C02 - 2048 bit (256 x 8)
110  *
111  * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
112  */
113
114 //~ #define DEBUG
115
116 #if defined(DEBUG)
117 #  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
118 #else
119 #  define logout(fmt, args...) ((void)0)
120 #endif
121
122 struct _eeprom24c0x_t {
123   uint8_t tick;
124   uint8_t address;
125   uint8_t command;
126   uint8_t ack;
127   uint8_t scl;
128   uint8_t sda;
129   uint8_t data;
130   //~ uint16_t size;
131   uint8_t contents[256];
132 };
133
134 typedef struct _eeprom24c0x_t eeprom24c0x_t;
135
136 static eeprom24c0x_t eeprom = {
137     contents: {
138         /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
139         /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
140         /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
141         /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
142         /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
143         /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144         /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145         /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
146         /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147         /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148         /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149         /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150         /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151         /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
152         /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
153         /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
154     },
155 };
156
157 static uint8_t eeprom24c0x_read(void)
158 {
159     logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
160         eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
161     return eeprom.sda;
162 }
163
164 static void eeprom24c0x_write(int scl, int sda)
165 {
166     if (eeprom.scl && scl && (eeprom.sda != sda)) {
167         logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
168                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
169         if (!sda) {
170             eeprom.tick = 1;
171             eeprom.command = 0;
172         }
173     } else if (eeprom.tick == 0 && !eeprom.ack) {
174         /* Waiting for start. */
175         logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
176                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
177     } else if (!eeprom.scl && scl) {
178         logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
179                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
180         if (eeprom.ack) {
181             logout("\ti2c ack bit = 0\n");
182             sda = 0;
183             eeprom.ack = 0;
184         } else if (eeprom.sda == sda) {
185             uint8_t bit = (sda != 0);
186             logout("\ti2c bit = %d\n", bit);
187             if (eeprom.tick < 9) {
188                 eeprom.command <<= 1;
189                 eeprom.command += bit;
190                 eeprom.tick++;
191                 if (eeprom.tick == 9) {
192                     logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
193                     eeprom.ack = 1;
194                 }
195             } else if (eeprom.tick < 17) {
196                 if (eeprom.command & 1) {
197                     sda = ((eeprom.data & 0x80) != 0);
198                 }
199                 eeprom.address <<= 1;
200                 eeprom.address += bit;
201                 eeprom.tick++;
202                 eeprom.data <<= 1;
203                 if (eeprom.tick == 17) {
204                     eeprom.data = eeprom.contents[eeprom.address];
205                     logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
206                     eeprom.ack = 1;
207                     eeprom.tick = 0;
208                 }
209             } else if (eeprom.tick >= 17) {
210                 sda = 0;
211             }
212         } else {
213             logout("\tsda changed with raising scl\n");
214         }
215     } else {
216         logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
217     }
218     eeprom.scl = scl;
219     eeprom.sda = sda;
220 }
221
222 static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
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_writel(void *opaque, target_phys_addr_t addr,
310                               uint32_t val)
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", 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 CPUReadMemoryFunc *malta_fpga_read[] = {
396    malta_fpga_readl,
397    malta_fpga_readl,
398    malta_fpga_readl
399 };
400
401 static CPUWriteMemoryFunc *malta_fpga_write[] = {
402    malta_fpga_writel,
403    malta_fpga_writel,
404    malta_fpga_writel
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_printf(chr, "\e[HMalta LEDBAR\r\n");
426     qemu_chr_printf(chr, "+--------+\r\n");
427     qemu_chr_printf(chr, "+        +\r\n");
428     qemu_chr_printf(chr, "+--------+\r\n");
429     qemu_chr_printf(chr, "\n");
430     qemu_chr_printf(chr, "Malta ASCII\r\n");
431     qemu_chr_printf(chr, "+--------+\r\n");
432     qemu_chr_printf(chr, "+        +\r\n");
433     qemu_chr_printf(chr, "+--------+\r\n");
434 }
435
436 static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
437 {
438     MaltaFPGAState *s;
439     int malta;
440
441     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
442
443     malta = cpu_register_io_memory(0, malta_fpga_read,
444                                    malta_fpga_write, s);
445
446     cpu_register_physical_memory(base, 0x900, malta);
447     /* 0xa00 is less than a page, so will still get the right offsets.  */
448     cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
449
450     s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
451
452     s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, 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
490     for(i = 0; i < nb_nics; i++) {
491         NICInfo *nd = &nd_table[i];
492         int devfn = -1;
493
494         if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
495             /* The malta board has a PCNet card using PCI SLOT 11 */
496             devfn = 88;
497
498         pci_nic_init(pci_bus, nd, devfn, "pcnet");
499     }
500 }
501
502 /* ROM and pseudo bootloader
503
504    The following code implements a very very simple bootloader. It first
505    loads the registers a0 to a3 to the values expected by the OS, and
506    then jump at the kernel address.
507
508    The bootloader should pass the locations of the kernel arguments and
509    environment variables tables. Those tables contain the 32-bit address
510    of NULL terminated strings. The environment variables table should be
511    terminated by a NULL address.
512
513    For a simpler implementation, the number of kernel arguments is fixed
514    to two (the name of the kernel and the command line), and the two
515    tables are actually the same one.
516
517    The registers a0 to a3 should contain the following values:
518      a0 - number of kernel arguments
519      a1 - 32-bit address of the kernel arguments table
520      a2 - 32-bit address of the environment variables table
521      a3 - RAM size in bytes
522 */
523
524 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
525 {
526     uint32_t *p;
527
528     /* Small bootloader */
529     p = (uint32_t *) (phys_ram_base + bios_offset);
530     stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
531     stl_raw(p++, 0x00000000);                                      /* nop */
532
533     /* YAMON service vector */
534     stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
535     stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
536     stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
537     stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
538     stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
539     stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
540     stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
541     stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
542     stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
543     stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
544     stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
545     stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
546     stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
547
548
549     /* Second part of the bootloader */
550     p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
551     stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
552     stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
553     stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
554     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
555     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
556     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
557     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
558     stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
559     stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
560
561     /* Load BAR registers as done by YAMON */
562     stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
563
564 #ifdef TARGET_WORDS_BIGENDIAN
565     stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
566 #else
567     stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
568 #endif
569     stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
570
571     stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
572
573 #ifdef TARGET_WORDS_BIGENDIAN
574     stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
575 #else
576     stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
577 #endif
578     stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
579 #ifdef TARGET_WORDS_BIGENDIAN
580     stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
581 #else
582     stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
583 #endif
584     stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
585
586 #ifdef TARGET_WORDS_BIGENDIAN
587     stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
588 #else
589     stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
590 #endif
591     stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
592 #ifdef TARGET_WORDS_BIGENDIAN
593     stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
594 #else
595     stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
596 #endif
597     stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
598
599 #ifdef TARGET_WORDS_BIGENDIAN
600     stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
601 #else
602     stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
603 #endif
604     stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
605 #ifdef TARGET_WORDS_BIGENDIAN
606     stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
607 #else
608     stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
609 #endif
610     stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
611
612     /* Jump to kernel code */
613     stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
614     stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
615     stl_raw(p++, 0x03e00008);                                      /* jr ra */
616     stl_raw(p++, 0x00000000);                                      /* nop */
617
618     /* YAMON subroutines */
619     p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
620     stl_raw(p++, 0x03e00008);                                     /* jr ra */
621     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
622    /* 808 YAMON print */
623     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
624     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
625     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
626     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
627     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
628     stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
629     stl_raw(p++, 0x00000000);                                     /* nop */
630     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
631     stl_raw(p++, 0x00000000);                                     /* nop */
632     stl_raw(p++, 0x08000205);                                     /* j 814 */
633     stl_raw(p++, 0x00000000);                                     /* nop */
634     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
635     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
636     /* 0x83c YAMON print_count */
637     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
638     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
639     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
640     stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
641     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
642     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
643     stl_raw(p++, 0x00000000);                                     /* nop */
644     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
645     stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
646     stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
647     stl_raw(p++, 0x00000000);                                     /* nop */
648     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
649     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
650     /* 0x870 */
651     stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
652     stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
653     stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
654     stl_raw(p++, 0x00000000);                                     /* nop */
655     stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
656     stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
657     stl_raw(p++, 0x00000000);                                     /* nop */
658     stl_raw(p++, 0x03e00008);                                     /* jr ra */
659     stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
660
661 }
662
663 static void prom_set(int index, const char *string, ...)
664 {
665     va_list ap;
666     int32_t *p;
667     int32_t table_addr;
668     char *s;
669
670     if (index >= ENVP_NB_ENTRIES)
671         return;
672
673     p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
674     p += index;
675
676     if (string == NULL) {
677         stl_raw(p, 0);
678         return;
679     }
680
681     table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
682     s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
683
684     stl_raw(p, table_addr);
685
686     va_start(ap, string);
687     vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
688     va_end(ap);
689 }
690
691 /* Kernel */
692 static int64_t load_kernel (CPUState *env)
693 {
694     int64_t kernel_entry, kernel_low, kernel_high;
695     int index = 0;
696     long initrd_size;
697     ram_addr_t initrd_offset;
698
699     if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
700                  (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
701                  (uint64_t *)&kernel_high) < 0) {
702         fprintf(stderr, "qemu: could not load kernel '%s'\n",
703                 loaderparams.kernel_filename);
704         exit(1);
705     }
706
707     /* load initrd */
708     initrd_size = 0;
709     initrd_offset = 0;
710     if (loaderparams.initrd_filename) {
711         initrd_size = get_image_size (loaderparams.initrd_filename);
712         if (initrd_size > 0) {
713             initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
714             if (initrd_offset + initrd_size > ram_size) {
715                 fprintf(stderr,
716                         "qemu: memory too small for initial ram disk '%s'\n",
717                         loaderparams.initrd_filename);
718                 exit(1);
719             }
720             initrd_size = load_image_targphys(loaderparams.initrd_filename,
721                                               initrd_offset,
722                                               ram_size - initrd_offset);
723         }
724         if (initrd_size == (target_ulong) -1) {
725             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
726                     loaderparams.initrd_filename);
727             exit(1);
728         }
729     }
730
731     /* Store command line.  */
732     prom_set(index++, loaderparams.kernel_filename);
733     if (initrd_size > 0)
734         prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
735                  PHYS_TO_VIRT(initrd_offset), initrd_size,
736                  loaderparams.kernel_cmdline);
737     else
738         prom_set(index++, loaderparams.kernel_cmdline);
739
740     /* Setup minimum environment variables */
741     prom_set(index++, "memsize");
742     prom_set(index++, "%i", loaderparams.ram_size);
743     prom_set(index++, "modetty0");
744     prom_set(index++, "38400n8r");
745     prom_set(index++, NULL);
746
747     return kernel_entry;
748 }
749
750 static void main_cpu_reset(void *opaque)
751 {
752     CPUState *env = opaque;
753     cpu_reset(env);
754
755     /* The bootload does not need to be rewritten as it is located in a
756        read only location. The kernel location and the arguments table
757        location does not change. */
758     if (loaderparams.kernel_filename) {
759         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
760         load_kernel (env);
761     }
762 }
763
764 static
765 void mips_malta_init (ram_addr_t ram_size, int vga_ram_size,
766                       const char *boot_device,
767                       const char *kernel_filename, const char *kernel_cmdline,
768                       const char *initrd_filename, const char *cpu_model)
769 {
770     char buf[1024];
771     ram_addr_t ram_offset;
772     ram_addr_t 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     qemu_register_reset(main_cpu_reset, env);
805
806     /* allocate RAM */
807     if (ram_size > (256 << 20)) {
808         fprintf(stderr,
809                 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
810                 ((unsigned int)ram_size / (1 << 20)));
811         exit(1);
812     }
813     ram_offset = qemu_ram_alloc(ram_size);
814     bios_offset = qemu_ram_alloc(BIOS_SIZE);
815
816
817     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
818
819     /* Map the bios at two physical locations, as on the real board. */
820     cpu_register_physical_memory(0x1e000000LL,
821                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
822     cpu_register_physical_memory(0x1fc00000LL,
823                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
824
825     /* FPGA */
826     malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
827
828     /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
829     if (kernel_filename) {
830         /* Write a small bootloader to the flash location. */
831         loaderparams.ram_size = ram_size;
832         loaderparams.kernel_filename = kernel_filename;
833         loaderparams.kernel_cmdline = kernel_cmdline;
834         loaderparams.initrd_filename = initrd_filename;
835         kernel_entry = load_kernel(env);
836         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
837         write_bootloader(env, bios_offset, kernel_entry);
838     } else {
839         index = drive_get_index(IF_PFLASH, 0, fl_idx);
840         if (index != -1) {
841             /* Load firmware from flash. */
842             bios_size = 0x400000;
843             fl_sectors = bios_size >> 16;
844 #ifdef DEBUG_BOARD_INIT
845             printf("Register parallel flash %d size " TARGET_FMT_lx " at "
846                    "offset %08lx addr %08llx '%s' %x\n",
847                    fl_idx, bios_size, bios_offset, 0x1e000000LL,
848                    bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
849 #endif
850             pflash_cfi01_register(0x1e000000LL, bios_offset,
851                                   drives_table[index].bdrv, 65536, fl_sectors,
852                                   4, 0x0000, 0x0000, 0x0000, 0x0000);
853             fl_idx++;
854         } else {
855             /* Load a BIOS image. */
856             if (bios_name == NULL)
857                 bios_name = BIOS_FILENAME;
858             snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
859             bios_size = load_image_targphys(buf, 0x1fc00000LL, BIOS_SIZE);
860             if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
861                 fprintf(stderr,
862                         "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
863                         buf);
864                 exit(1);
865             }
866         }
867         /* In little endian mode the 32bit words in the bios are swapped,
868            a neat trick which allows bi-endian firmware. */
869 #ifndef TARGET_WORDS_BIGENDIAN
870         {
871             uint32_t *addr;
872             for (addr = (uint32_t *)(phys_ram_base + bios_offset);
873                  addr < (uint32_t *)(phys_ram_base + bios_offset + bios_size);
874                  addr++) {
875                 *addr = bswap32(*addr);
876             }
877         }
878 #endif
879     }
880
881     /* Board ID = 0x420 (Malta Board with CoreLV)
882        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
883        map to the board ID. */
884     stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
885
886     /* Init internal devices */
887     cpu_mips_irq_init_cpu(env);
888     cpu_mips_clock_init(env);
889
890     /* Interrupt controller */
891     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
892     i8259 = i8259_init(env->irq[2]);
893
894     /* Northbridge */
895     pci_bus = pci_gt64120_init(i8259);
896
897     /* Southbridge */
898
899     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
900         fprintf(stderr, "qemu: too many IDE bus\n");
901         exit(1);
902     }
903
904     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
905         index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
906         if (index != -1)
907             hd[i] = drives_table[index].bdrv;
908         else
909             hd[i] = NULL;
910     }
911
912     piix4_devfn = piix4_init(pci_bus, 80);
913     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
914     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
915     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, i8259[9]);
916     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
917     for (i = 0; i < 8; i++) {
918         /* TODO: Populate SPD eeprom data.  */
919         smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
920     }
921     pit = pit_init(0x40, i8259[0]);
922     DMA_init(0);
923
924     /* Super I/O */
925     i8042_init(i8259[1], i8259[12], 0x60);
926     rtc_state = rtc_init(0x70, i8259[8], 2000);
927     serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
928     serial_init(0x2f8, i8259[3], 115200, serial_hds[1]);
929     if (parallel_hds[0])
930         parallel_init(0x378, i8259[7], parallel_hds[0]);
931     for(i = 0; i < MAX_FD; i++) {
932         index = drive_get_index(IF_FLOPPY, 0, i);
933        if (index != -1)
934            fd[i] = drives_table[index].bdrv;
935        else
936            fd[i] = NULL;
937     }
938     floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
939
940     /* Sound card */
941 #ifdef HAS_AUDIO
942     audio_init(pci_bus);
943 #endif
944
945     /* Network card */
946     network_init(pci_bus);
947
948     /* Optional PCI video card */
949     if (cirrus_vga_enabled) {
950         pci_cirrus_vga_init(pci_bus, vga_ram_size);
951     } else if (vmsvga_enabled) {
952         pci_vmsvga_init(pci_bus, vga_ram_size);
953     } else if (std_vga_enabled) {
954         pci_vga_init(pci_bus, vga_ram_size, 0, 0);
955     }
956 }
957
958 QEMUMachine mips_malta_machine = {
959     .name = "malta",
960     .desc = "MIPS Malta Core LV",
961     .init = mips_malta_init,
962     .ram_require = VGA_RAM_SIZE + BIOS_SIZE,
963 };
This page took 0.080596 seconds and 4 git commands to generate.