Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 565d2895

History | View | Annotate | Download (28.3 kB)

1
/*
2
 * QEMU Malta board support
3
 *
4
 * Copyright (c) 2006 Aurelien Jarno
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
#include "vl.h"
26

    
27
#ifdef TARGET_WORDS_BIGENDIAN
28
#define BIOS_FILENAME "mips_bios.bin"
29
#else
30
#define BIOS_FILENAME "mipsel_bios.bin"
31
#endif
32

    
33
#ifdef TARGET_MIPS64
34
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
35
#else
36
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
37
#endif
38

    
39
#define ENVP_ADDR (int32_t)0x80002000
40
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
41

    
42
#define ENVP_NB_ENTRIES                 16
43
#define ENVP_ENTRY_SIZE                 256
44

    
45

    
46
extern FILE *logfile;
47

    
48
typedef struct {
49
    uint32_t leds;
50
    uint32_t brk;
51
    uint32_t gpout;
52
    uint32_t i2cin;
53
    uint32_t i2coe;
54
    uint32_t i2cout;
55
    uint32_t i2csel;
56
    CharDriverState *display;
57
    char display_text[9];
58
    SerialState *uart;
59
} MaltaFPGAState;
60

    
61
static PITState *pit;
62

    
63
/* Malta FPGA */
64
static void malta_fpga_update_display(void *opaque)
65
{
66
    char leds_text[9];
67
    int i;
68
    MaltaFPGAState *s = opaque;
69

    
70
    for (i = 7 ; i >= 0 ; i--) {
71
        if (s->leds & (1 << i))
72
            leds_text[i] = '#';
73
        else
74
            leds_text[i] = ' ';
75
    }
76
    leds_text[8] = '\0';
77

    
78
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
79
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
80
}
81

    
82
/*
83
 * EEPROM 24C01 / 24C02 emulation.
84
 *
85
 * Emulation for serial EEPROMs:
86
 * 24C01 - 1024 bit (128 x 8)
87
 * 24C02 - 2048 bit (256 x 8)
88
 *
89
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
90
 */
91

    
92
//~ #define DEBUG
93

    
94
#if defined(DEBUG)
95
#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
96
#else
97
#  define logout(fmt, args...) ((void)0)
98
#endif
99

    
100
struct _eeprom24c0x_t {
101
  uint8_t tick;
102
  uint8_t address;
103
  uint8_t command;
104
  uint8_t ack;
105
  uint8_t scl;
106
  uint8_t sda;
107
  uint8_t data;
108
  //~ uint16_t size;
109
  uint8_t contents[256];
110
};
111

    
112
typedef struct _eeprom24c0x_t eeprom24c0x_t;
113

    
114
static eeprom24c0x_t eeprom = {
115
    contents: {
116
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
117
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
118
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
119
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
120
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
121
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
124
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
132
    },
133
};
134

    
135
static uint8_t eeprom24c0x_read()
136
{
137
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
138
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
139
    return eeprom.sda;
140
}
141

    
142
static void eeprom24c0x_write(int scl, int sda)
143
{
144
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
145
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
146
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
147
        if (!sda) {
148
            eeprom.tick = 1;
149
            eeprom.command = 0;
150
        }
151
    } else if (eeprom.tick == 0 && !eeprom.ack) {
152
        /* Waiting for start. */
153
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
154
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
155
    } else if (!eeprom.scl && scl) {
156
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
157
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
158
        if (eeprom.ack) {
159
            logout("\ti2c ack bit = 0\n");
160
            sda = 0;
161
            eeprom.ack = 0;
162
        } else if (eeprom.sda == sda) {
163
            uint8_t bit = (sda != 0);
164
            logout("\ti2c bit = %d\n", bit);
165
            if (eeprom.tick < 9) {
166
                eeprom.command <<= 1;
167
                eeprom.command += bit;
168
                eeprom.tick++;
169
                if (eeprom.tick == 9) {
170
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
171
                    eeprom.ack = 1;
172
                }
173
            } else if (eeprom.tick < 17) {
174
                if (eeprom.command & 1) {
175
                    sda = ((eeprom.data & 0x80) != 0);
176
                }
177
                eeprom.address <<= 1;
178
                eeprom.address += bit;
179
                eeprom.tick++;
180
                eeprom.data <<= 1;
181
                if (eeprom.tick == 17) {
182
                    eeprom.data = eeprom.contents[eeprom.address];
183
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
184
                    eeprom.ack = 1;
185
                    eeprom.tick = 0;
186
                }
187
            } else if (eeprom.tick >= 17) {
188
                sda = 0;
189
            }
190
        } else {
191
            logout("\tsda changed with raising scl\n");
192
        }
193
    } else {
194
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
195
    }
196
    eeprom.scl = scl;
197
    eeprom.sda = sda;
198
}
199

    
200
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
201
{
202
    MaltaFPGAState *s = opaque;
203
    uint32_t val = 0;
204
    uint32_t saddr;
205

    
206
    saddr = (addr & 0xfffff);
207

    
208
    switch (saddr) {
209

    
210
    /* SWITCH Register */
211
    case 0x00200:
212
        val = 0x00000000;                /* All switches closed */
213
        break;
214

    
215
    /* STATUS Register */
216
    case 0x00208:
217
#ifdef TARGET_WORDS_BIGENDIAN
218
        val = 0x00000012;
219
#else
220
        val = 0x00000010;
221
#endif
222
        break;
223

    
224
    /* JMPRS Register */
225
    case 0x00210:
226
        val = 0x00;
227
        break;
228

    
229
    /* LEDBAR Register */
230
    case 0x00408:
231
        val = s->leds;
232
        break;
233

    
234
    /* BRKRES Register */
235
    case 0x00508:
236
        val = s->brk;
237
        break;
238

    
239
    /* UART Registers */
240
    case 0x00900:
241
    case 0x00908:
242
    case 0x00910:
243
    case 0x00918:
244
    case 0x00920:
245
    case 0x00928:
246
    case 0x00930:
247
    case 0x00938:
248
        val = serial_mm_readb(s->uart, addr);
249
        break;
250

    
251
    /* GPOUT Register */
252
    case 0x00a00:
253
        val = s->gpout;
254
        break;
255

    
256
    /* XXX: implement a real I2C controller */
257

    
258
    /* GPINP Register */
259
    case 0x00a08:
260
        /* IN = OUT until a real I2C control is implemented */
261
        if (s->i2csel)
262
            val = s->i2cout;
263
        else
264
            val = 0x00;
265
        break;
266

    
267
    /* I2CINP Register */
268
    case 0x00b00:
269
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
270
        break;
271

    
272
    /* I2COE Register */
273
    case 0x00b08:
274
        val = s->i2coe;
275
        break;
276

    
277
    /* I2COUT Register */
278
    case 0x00b10:
279
        val = s->i2cout;
280
        break;
281

    
282
    /* I2CSEL Register */
283
    case 0x00b18:
284
        val = s->i2csel;
285
        break;
286

    
287
    default:
288
#if 0
289
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
290
                addr);
291
#endif
292
        break;
293
    }
294
    return val;
295
}
296

    
297
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
298
                              uint32_t val)
299
{
300
    MaltaFPGAState *s = opaque;
301
    uint32_t saddr;
302

    
303
    saddr = (addr & 0xfffff);
304

    
305
    switch (saddr) {
306

    
307
    /* SWITCH Register */
308
    case 0x00200:
309
        break;
310

    
311
    /* JMPRS Register */
312
    case 0x00210:
313
        break;
314

    
315
    /* LEDBAR Register */
316
    /* XXX: implement a 8-LED array */
317
    case 0x00408:
318
        s->leds = val & 0xff;
319
        break;
320

    
321
    /* ASCIIWORD Register */
322
    case 0x00410:
323
        snprintf(s->display_text, 9, "%08X", val);
324
        malta_fpga_update_display(s);
325
        break;
326

    
327
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
328
    case 0x00418:
329
    case 0x00420:
330
    case 0x00428:
331
    case 0x00430:
332
    case 0x00438:
333
    case 0x00440:
334
    case 0x00448:
335
    case 0x00450:
336
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
337
        malta_fpga_update_display(s);
338
        break;
339

    
340
    /* SOFTRES Register */
341
    case 0x00500:
342
        if (val == 0x42)
343
            qemu_system_reset_request ();
344
        break;
345

    
346
    /* BRKRES Register */
347
    case 0x00508:
348
        s->brk = val & 0xff;
349
        break;
350

    
351
    /* UART Registers */
352
    case 0x00900:
353
    case 0x00908:
354
    case 0x00910:
355
    case 0x00918:
356
    case 0x00920:
357
    case 0x00928:
358
    case 0x00930:
359
    case 0x00938:
360
        serial_mm_writeb(s->uart, addr, val);
361
        break;
362

    
363
    /* GPOUT Register */
364
    case 0x00a00:
365
        s->gpout = val & 0xff;
366
        break;
367

    
368
    /* I2COE Register */
369
    case 0x00b08:
370
        s->i2coe = val & 0x03;
371
        break;
372

    
373
    /* I2COUT Register */
374
    case 0x00b10:
375
        eeprom24c0x_write(val & 0x02, val & 0x01);
376
        s->i2cout = val;
377
        break;
378

    
379
    /* I2CSEL Register */
380
    case 0x00b18:
381
        s->i2csel = val & 0x01;
382
        break;
383

    
384
    default:
385
#if 0
386
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
387
                addr);
388
#endif
389
        break;
390
    }
391
}
392

    
393
static CPUReadMemoryFunc *malta_fpga_read[] = {
394
   malta_fpga_readl,
395
   malta_fpga_readl,
396
   malta_fpga_readl
397
};
398

    
399
static CPUWriteMemoryFunc *malta_fpga_write[] = {
400
   malta_fpga_writel,
401
   malta_fpga_writel,
402
   malta_fpga_writel
403
};
404

    
405
void malta_fpga_reset(void *opaque)
406
{
407
    MaltaFPGAState *s = opaque;
408

    
409
    s->leds   = 0x00;
410
    s->brk    = 0x0a;
411
    s->gpout  = 0x00;
412
    s->i2cin  = 0x3;
413
    s->i2coe  = 0x0;
414
    s->i2cout = 0x3;
415
    s->i2csel = 0x1;
416

    
417
    s->display_text[8] = '\0';
418
    snprintf(s->display_text, 9, "        ");
419
    malta_fpga_update_display(s);
420
}
421

    
422
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
423
{
424
    MaltaFPGAState *s;
425
    CharDriverState *uart_chr;
426
    int malta;
427

    
428
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
429

    
430
    malta = cpu_register_io_memory(0, malta_fpga_read,
431
                                   malta_fpga_write, s);
432

    
433
    cpu_register_physical_memory(base, 0x100000, malta);
434

    
435
    s->display = qemu_chr_open("vc");
436
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
437
    qemu_chr_printf(s->display, "+--------+\r\n");
438
    qemu_chr_printf(s->display, "+        +\r\n");
439
    qemu_chr_printf(s->display, "+--------+\r\n");
440
    qemu_chr_printf(s->display, "\n");
441
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
442
    qemu_chr_printf(s->display, "+--------+\r\n");
443
    qemu_chr_printf(s->display, "+        +\r\n");
444
    qemu_chr_printf(s->display, "+--------+\r\n");
445

    
446
    uart_chr = qemu_chr_open("vc");
447
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
448
    s->uart = serial_mm_init(base, 3, env->irq[2], uart_chr, 0);
449

    
450
    malta_fpga_reset(s);
451
    qemu_register_reset(malta_fpga_reset, s);
452

    
453
    return s;
454
}
455

    
456
/* Audio support */
457
#ifdef HAS_AUDIO
458
static void audio_init (PCIBus *pci_bus)
459
{
460
    struct soundhw *c;
461
    int audio_enabled = 0;
462

    
463
    for (c = soundhw; !audio_enabled && c->name; ++c) {
464
        audio_enabled = c->enabled;
465
    }
466

    
467
    if (audio_enabled) {
468
        AudioState *s;
469

    
470
        s = AUD_init ();
471
        if (s) {
472
            for (c = soundhw; c->name; ++c) {
473
                if (c->enabled) {
474
                    if (c->isa) {
475
                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
476
                        exit(1);
477
                    }
478
                    else {
479
                        if (pci_bus) {
480
                            c->init.init_pci (pci_bus, s);
481
                        }
482
                    }
483
                }
484
            }
485
        }
486
    }
487
}
488
#endif
489

    
490
/* Network support */
491
static void network_init (PCIBus *pci_bus)
492
{
493
    int i;
494
    NICInfo *nd;
495

    
496
    for(i = 0; i < nb_nics; i++) {
497
        nd = &nd_table[i];
498
        if (!nd->model) {
499
            nd->model = "pcnet";
500
        }
501
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
502
            /* The malta board has a PCNet card using PCI SLOT 11 */
503
            pci_nic_init(pci_bus, nd, 88);
504
        } else {
505
            pci_nic_init(pci_bus, nd, -1);
506
        }
507
    }
508
}
509

    
510
/* ROM and pseudo bootloader
511

512
   The following code implements a very very simple bootloader. It first
513
   loads the registers a0 to a3 to the values expected by the OS, and
514
   then jump at the kernel address.
515

516
   The bootloader should pass the locations of the kernel arguments and
517
   environment variables tables. Those tables contain the 32-bit address
518
   of NULL terminated strings. The environment variables table should be
519
   terminated by a NULL address.
520

521
   For a simpler implementation, the number of kernel arguments is fixed
522
   to two (the name of the kernel and the command line), and the two
523
   tables are actually the same one.
524

525
   The registers a0 to a3 should contain the following values:
526
     a0 - number of kernel arguments
527
     a1 - 32-bit address of the kernel arguments table
528
     a2 - 32-bit address of the environment variables table
529
     a3 - RAM size in bytes
530
*/
531

    
532
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
533
{
534
    uint32_t *p;
535

    
536
    /* Small bootloader */
537
    p = (uint32_t *) (phys_ram_base + bios_offset);
538
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
539
    stl_raw(p++, 0x00000000);                                      /* nop */
540

    
541
    /* YAMON service vector */
542
    stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */                                        
543
    stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
544
    stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */                                        
545
    stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
546
    stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
547
    stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
548
    stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
549
    stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
550
    stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
551
    stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
552
    stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
553
    stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
554
    stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
555

    
556

    
557
    /* Second part of the bootloader */
558
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
559
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
560
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
561
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, a0, low(ENVP_ADDR) */
562
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
563
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
564
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
565
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
566
    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
567
    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
568

    
569
    /* Load BAR registers as done by YAMON */
570
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
571

    
572
#ifdef TARGET_WORDS_BIGENDIAN
573
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
574
#else
575
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
576
#endif
577
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
578
#ifdef TARGET_WORDS_BIGENDIAN
579
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
580
#else
581
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
582
#endif
583
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
584

    
585
#ifdef TARGET_WORDS_BIGENDIAN
586
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
587
#else
588
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
589
#endif
590
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
591
#ifdef TARGET_WORDS_BIGENDIAN
592
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
593
#else
594
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
595
#endif
596
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
597

    
598
#ifdef TARGET_WORDS_BIGENDIAN
599
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
600
#else
601
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
602
#endif
603
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
604
#ifdef TARGET_WORDS_BIGENDIAN
605
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
606
#else
607
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
608
#endif
609
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
610

    
611
    /* Jump to kernel code */
612
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
613
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
614
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
615
    stl_raw(p++, 0x00000000);                                      /* nop */
616

    
617
    /* YAMON subroutines */
618
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
619
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
620
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
621
   /* 808 YAMON print */
622
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
623
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
624
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
625
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
626
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
627
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
628
    stl_raw(p++, 0x00000000);                                     /* nop */
629
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
630
    stl_raw(p++, 0x00000000);                                     /* nop */
631
    stl_raw(p++, 0x08000205);                                     /* j 814 */
632
    stl_raw(p++, 0x00000000);                                     /* nop */
633
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
634
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
635
    /* 0x83c YAMON print_count */
636
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
637
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
638
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
639
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
640
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
641
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
642
    stl_raw(p++, 0x00000000);                                     /* nop */
643
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
644
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
645
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
646
    stl_raw(p++, 0x00000000);                                     /* nop */
647
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
648
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
649
    /* 0x870 */
650
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
651
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
652
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
653
    stl_raw(p++, 0x00000000);                                     /* nop */
654
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
655
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
656
    stl_raw(p++, 0x00000000);                                     /* nop */
657
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
658
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
659

    
660
}
661

    
662
static void prom_set(int index, const char *string, ...)
663
{
664
    va_list ap;
665
    int32_t *p;
666
    int32_t table_addr;
667
    char *s;
668

    
669
    if (index >= ENVP_NB_ENTRIES)
670
        return;
671

    
672
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
673
    p += index;
674

    
675
    if (string == NULL) {
676
        stl_raw(p, 0);
677
        return;
678
    }
679

    
680
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
681
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
682

    
683
    stl_raw(p, table_addr);
684

    
685
    va_start(ap, string);
686
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
687
    va_end(ap);
688
}
689

    
690
/* Kernel */
691
static int64_t load_kernel (CPUState *env)
692
{
693
    int64_t kernel_entry, kernel_low, kernel_high;
694
    int index = 0;
695
    long initrd_size;
696
    ram_addr_t initrd_offset;
697

    
698
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
699
                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
700
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
701
                env->kernel_filename);
702
      exit(1);
703
    }
704

    
705
    /* load initrd */
706
    initrd_size = 0;
707
    initrd_offset = 0;
708
    if (env->initrd_filename) {
709
        initrd_size = get_image_size (env->initrd_filename);
710
        if (initrd_size > 0) {
711
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
712
            if (initrd_offset + initrd_size > env->ram_size) {
713
                fprintf(stderr,
714
                        "qemu: memory too small for initial ram disk '%s'\n",
715
                        env->initrd_filename);
716
                exit(1);
717
            }
718
            initrd_size = load_image(env->initrd_filename,
719
                                     phys_ram_base + initrd_offset);
720
        }
721
        if (initrd_size == (target_ulong) -1) {
722
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
723
                    env->initrd_filename);
724
            exit(1);
725
        }
726
    }
727

    
728
    /* Store command line.  */
729
    prom_set(index++, env->kernel_filename);
730
    if (initrd_size > 0)
731
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
732
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
733
                 env->kernel_cmdline);
734
    else
735
        prom_set(index++, env->kernel_cmdline);
736

    
737
    /* Setup minimum environment variables */
738
    prom_set(index++, "memsize");
739
    prom_set(index++, "%i", env->ram_size);
740
    prom_set(index++, "modetty0");
741
    prom_set(index++, "38400n8r");
742
    prom_set(index++, NULL);
743

    
744
    return kernel_entry;
745
}
746

    
747
static void main_cpu_reset(void *opaque)
748
{
749
    CPUState *env = opaque;
750
    cpu_reset(env);
751

    
752
    /* The bootload does not need to be rewritten as it is located in a
753
       read only location. The kernel location and the arguments table
754
       location does not change. */
755
    if (env->kernel_filename) {
756
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
757
        load_kernel (env);
758
    }
759
}
760

    
761
static
762
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
763
                      DisplayState *ds, const char **fd_filename, int snapshot,
764
                      const char *kernel_filename, const char *kernel_cmdline,
765
                      const char *initrd_filename, const char *cpu_model)
766
{
767
    char buf[1024];
768
    unsigned long bios_offset;
769
    int64_t kernel_entry;
770
    PCIBus *pci_bus;
771
    CPUState *env;
772
    RTCState *rtc_state;
773
    /* fdctrl_t *floppy_controller; */
774
    MaltaFPGAState *malta_fpga;
775
    int ret;
776
    mips_def_t *def;
777
    qemu_irq *i8259;
778

    
779
    /* init CPUs */
780
    if (cpu_model == NULL) {
781
#ifdef TARGET_MIPS64
782
        cpu_model = "R4000";
783
#else
784
        cpu_model = "24Kf";
785
#endif
786
    }
787
    if (mips_find_by_name(cpu_model, &def) != 0)
788
        def = NULL;
789
    env = cpu_init();
790
    cpu_mips_register(env, def);
791
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
792
    qemu_register_reset(main_cpu_reset, env);
793

    
794
    /* allocate RAM */
795
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
796

    
797
    /* Map the bios at two physical locations, as on the real board */
798
    bios_offset = ram_size + vga_ram_size;
799
    cpu_register_physical_memory(0x1e000000LL,
800
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
801
    cpu_register_physical_memory(0x1fc00000LL,
802
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
803

    
804
    /* Load a BIOS image except if a kernel image has been specified. In
805
       the later case, just write a small bootloader to the flash
806
       location. */
807
    if (kernel_filename) {
808
        env->ram_size = ram_size;
809
        env->kernel_filename = kernel_filename;
810
        env->kernel_cmdline = kernel_cmdline;
811
        env->initrd_filename = initrd_filename;
812
        kernel_entry = load_kernel(env);
813
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
814
        write_bootloader(env, bios_offset, kernel_entry);
815
    } else {
816
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
817
        ret = load_image(buf, phys_ram_base + bios_offset);
818
        if (ret < 0 || ret > BIOS_SIZE) {
819
            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
820
                    buf);
821
            exit(1);
822
        }
823
    }
824

    
825
    /* Board ID = 0x420 (Malta Board with CoreLV)
826
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
827
       map to the board ID. */
828
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
829

    
830
    /* Init internal devices */
831
    cpu_mips_irq_init_cpu(env);
832
    cpu_mips_clock_init(env);
833
    cpu_mips_irqctrl_init();
834

    
835
    /* FPGA */
836
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
837

    
838
    /* Interrupt controller */
839
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
840
    i8259 = i8259_init(env->irq[2]);
841

    
842
    /* Northbridge */
843
    pci_bus = pci_gt64120_init(i8259);
844

    
845
    /* Southbridge */
846
    piix4_init(pci_bus, 80);
847
    pci_piix3_ide_init(pci_bus, bs_table, 81, i8259);
848
    usb_uhci_init(pci_bus, 82);
849
    piix4_pm_init(pci_bus, 83);
850
    pit = pit_init(0x40, i8259[0]);
851
    DMA_init(0);
852

    
853
    /* Super I/O */
854
    i8042_init(i8259[1], i8259[12], 0x60);
855
    rtc_state = rtc_init(0x70, i8259[8]);
856
    if (serial_hds[0])
857
        serial_init(0x3f8, i8259[4], serial_hds[0]);
858
    if (serial_hds[1])
859
        serial_init(0x2f8, i8259[3], serial_hds[1]);
860
    if (parallel_hds[0])
861
        parallel_init(0x378, i8259[7], parallel_hds[0]);
862
    /* XXX: The floppy controller does not work correctly, something is
863
       probably wrong.
864
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
865

    
866
    /* Sound card */
867
#ifdef HAS_AUDIO
868
    audio_init(pci_bus);
869
#endif
870

    
871
    /* Network card */
872
    network_init(pci_bus);
873

    
874
    /* Optional PCI video card */
875
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
876
                        ram_size, vga_ram_size);
877
}
878

    
879
QEMUMachine mips_malta_machine = {
880
    "malta",
881
    "MIPS Malta Core LV",
882
    mips_malta_init,
883
};