Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ aaed909a

History | View | Annotate | Download (29.4 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
extern FILE *logfile;
46

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

    
60
static PITState *pit;
61

    
62
static struct _loaderparams {
63
    int ram_size;
64
    const char *kernel_filename;
65
    const char *kernel_cmdline;
66
    const char *initrd_filename;
67
} loaderparams;
68

    
69
/* Malta FPGA */
70
static void malta_fpga_update_display(void *opaque)
71
{
72
    char leds_text[9];
73
    int i;
74
    MaltaFPGAState *s = opaque;
75

    
76
    for (i = 7 ; i >= 0 ; i--) {
77
        if (s->leds & (1 << i))
78
            leds_text[i] = '#';
79
        else
80
            leds_text[i] = ' ';
81
    }
82
    leds_text[8] = '\0';
83

    
84
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
85
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
86
}
87

    
88
/*
89
 * EEPROM 24C01 / 24C02 emulation.
90
 *
91
 * Emulation for serial EEPROMs:
92
 * 24C01 - 1024 bit (128 x 8)
93
 * 24C02 - 2048 bit (256 x 8)
94
 *
95
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
96
 */
97

    
98
//~ #define DEBUG
99

    
100
#if defined(DEBUG)
101
#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
102
#else
103
#  define logout(fmt, args...) ((void)0)
104
#endif
105

    
106
struct _eeprom24c0x_t {
107
  uint8_t tick;
108
  uint8_t address;
109
  uint8_t command;
110
  uint8_t ack;
111
  uint8_t scl;
112
  uint8_t sda;
113
  uint8_t data;
114
  //~ uint16_t size;
115
  uint8_t contents[256];
116
};
117

    
118
typedef struct _eeprom24c0x_t eeprom24c0x_t;
119

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

    
141
static uint8_t eeprom24c0x_read()
142
{
143
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
144
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
145
    return eeprom.sda;
146
}
147

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

    
206
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
207
{
208
    MaltaFPGAState *s = opaque;
209
    uint32_t val = 0;
210
    uint32_t saddr;
211

    
212
    saddr = (addr & 0xfffff);
213

    
214
    switch (saddr) {
215

    
216
    /* SWITCH Register */
217
    case 0x00200:
218
        val = 0x00000000;                /* All switches closed */
219
        break;
220

    
221
    /* STATUS Register */
222
    case 0x00208:
223
#ifdef TARGET_WORDS_BIGENDIAN
224
        val = 0x00000012;
225
#else
226
        val = 0x00000010;
227
#endif
228
        break;
229

    
230
    /* JMPRS Register */
231
    case 0x00210:
232
        val = 0x00;
233
        break;
234

    
235
    /* LEDBAR Register */
236
    case 0x00408:
237
        val = s->leds;
238
        break;
239

    
240
    /* BRKRES Register */
241
    case 0x00508:
242
        val = s->brk;
243
        break;
244

    
245
    /* UART Registers are handled directly by the serial device */
246

    
247
    /* GPOUT Register */
248
    case 0x00a00:
249
        val = s->gpout;
250
        break;
251

    
252
    /* XXX: implement a real I2C controller */
253

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

    
263
    /* I2CINP Register */
264
    case 0x00b00:
265
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
266
        break;
267

    
268
    /* I2COE Register */
269
    case 0x00b08:
270
        val = s->i2coe;
271
        break;
272

    
273
    /* I2COUT Register */
274
    case 0x00b10:
275
        val = s->i2cout;
276
        break;
277

    
278
    /* I2CSEL Register */
279
    case 0x00b18:
280
        val = s->i2csel;
281
        break;
282

    
283
    default:
284
#if 0
285
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
286
                addr);
287
#endif
288
        break;
289
    }
290
    return val;
291
}
292

    
293
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
294
                              uint32_t val)
295
{
296
    MaltaFPGAState *s = opaque;
297
    uint32_t saddr;
298

    
299
    saddr = (addr & 0xfffff);
300

    
301
    switch (saddr) {
302

    
303
    /* SWITCH Register */
304
    case 0x00200:
305
        break;
306

    
307
    /* JMPRS Register */
308
    case 0x00210:
309
        break;
310

    
311
    /* LEDBAR Register */
312
    /* XXX: implement a 8-LED array */
313
    case 0x00408:
314
        s->leds = val & 0xff;
315
        break;
316

    
317
    /* ASCIIWORD Register */
318
    case 0x00410:
319
        snprintf(s->display_text, 9, "%08X", val);
320
        malta_fpga_update_display(s);
321
        break;
322

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

    
336
    /* SOFTRES Register */
337
    case 0x00500:
338
        if (val == 0x42)
339
            qemu_system_reset_request ();
340
        break;
341

    
342
    /* BRKRES Register */
343
    case 0x00508:
344
        s->brk = val & 0xff;
345
        break;
346

    
347
    /* UART Registers are handled directly by the serial device */
348

    
349
    /* GPOUT Register */
350
    case 0x00a00:
351
        s->gpout = val & 0xff;
352
        break;
353

    
354
    /* I2COE Register */
355
    case 0x00b08:
356
        s->i2coe = val & 0x03;
357
        break;
358

    
359
    /* I2COUT Register */
360
    case 0x00b10:
361
        eeprom24c0x_write(val & 0x02, val & 0x01);
362
        s->i2cout = val;
363
        break;
364

    
365
    /* I2CSEL Register */
366
    case 0x00b18:
367
        s->i2csel = val & 0x01;
368
        break;
369

    
370
    default:
371
#if 0
372
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
373
                addr);
374
#endif
375
        break;
376
    }
377
}
378

    
379
static CPUReadMemoryFunc *malta_fpga_read[] = {
380
   malta_fpga_readl,
381
   malta_fpga_readl,
382
   malta_fpga_readl
383
};
384

    
385
static CPUWriteMemoryFunc *malta_fpga_write[] = {
386
   malta_fpga_writel,
387
   malta_fpga_writel,
388
   malta_fpga_writel
389
};
390

    
391
void malta_fpga_reset(void *opaque)
392
{
393
    MaltaFPGAState *s = opaque;
394

    
395
    s->leds   = 0x00;
396
    s->brk    = 0x0a;
397
    s->gpout  = 0x00;
398
    s->i2cin  = 0x3;
399
    s->i2coe  = 0x0;
400
    s->i2cout = 0x3;
401
    s->i2csel = 0x1;
402

    
403
    s->display_text[8] = '\0';
404
    snprintf(s->display_text, 9, "        ");
405
    malta_fpga_update_display(s);
406
}
407

    
408
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
409
{
410
    MaltaFPGAState *s;
411
    CharDriverState *uart_chr;
412
    int malta;
413

    
414
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
415

    
416
    malta = cpu_register_io_memory(0, malta_fpga_read,
417
                                   malta_fpga_write, s);
418

    
419
    cpu_register_physical_memory(base, 0x900, malta);
420
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
421

    
422
    s->display = qemu_chr_open("vc");
423
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
424
    qemu_chr_printf(s->display, "+--------+\r\n");
425
    qemu_chr_printf(s->display, "+        +\r\n");
426
    qemu_chr_printf(s->display, "+--------+\r\n");
427
    qemu_chr_printf(s->display, "\n");
428
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
429
    qemu_chr_printf(s->display, "+--------+\r\n");
430
    qemu_chr_printf(s->display, "+        +\r\n");
431
    qemu_chr_printf(s->display, "+--------+\r\n");
432

    
433
    uart_chr = qemu_chr_open("vc");
434
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
435
    s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
436

    
437
    malta_fpga_reset(s);
438
    qemu_register_reset(malta_fpga_reset, s);
439

    
440
    return s;
441
}
442

    
443
/* Audio support */
444
#ifdef HAS_AUDIO
445
static void audio_init (PCIBus *pci_bus)
446
{
447
    struct soundhw *c;
448
    int audio_enabled = 0;
449

    
450
    for (c = soundhw; !audio_enabled && c->name; ++c) {
451
        audio_enabled = c->enabled;
452
    }
453

    
454
    if (audio_enabled) {
455
        AudioState *s;
456

    
457
        s = AUD_init ();
458
        if (s) {
459
            for (c = soundhw; c->name; ++c) {
460
                if (c->enabled)
461
                    c->init.init_pci (pci_bus, s);
462
            }
463
        }
464
    }
465
}
466
#endif
467

    
468
/* Network support */
469
static void network_init (PCIBus *pci_bus)
470
{
471
    int i;
472
    NICInfo *nd;
473

    
474
    for(i = 0; i < nb_nics; i++) {
475
        nd = &nd_table[i];
476
        if (!nd->model) {
477
            nd->model = "pcnet";
478
        }
479
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
480
            /* The malta board has a PCNet card using PCI SLOT 11 */
481
            pci_nic_init(pci_bus, nd, 88);
482
        } else {
483
            pci_nic_init(pci_bus, nd, -1);
484
        }
485
    }
486
}
487

    
488
/* ROM and pseudo bootloader
489

490
   The following code implements a very very simple bootloader. It first
491
   loads the registers a0 to a3 to the values expected by the OS, and
492
   then jump at the kernel address.
493

494
   The bootloader should pass the locations of the kernel arguments and
495
   environment variables tables. Those tables contain the 32-bit address
496
   of NULL terminated strings. The environment variables table should be
497
   terminated by a NULL address.
498

499
   For a simpler implementation, the number of kernel arguments is fixed
500
   to two (the name of the kernel and the command line), and the two
501
   tables are actually the same one.
502

503
   The registers a0 to a3 should contain the following values:
504
     a0 - number of kernel arguments
505
     a1 - 32-bit address of the kernel arguments table
506
     a2 - 32-bit address of the environment variables table
507
     a3 - RAM size in bytes
508
*/
509

    
510
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
511
{
512
    uint32_t *p;
513

    
514
    /* Small bootloader */
515
    p = (uint32_t *) (phys_ram_base + bios_offset);
516
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
517
    stl_raw(p++, 0x00000000);                                      /* nop */
518

    
519
    /* YAMON service vector */
520
    stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
521
    stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
522
    stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
523
    stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
524
    stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
525
    stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
526
    stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
527
    stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
528
    stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
529
    stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
530
    stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
531
    stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
532
    stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
533

    
534

    
535
    /* Second part of the bootloader */
536
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
537
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
538
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
539
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
540
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
541
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
542
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
543
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
544
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
545
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
546

    
547
    /* Load BAR registers as done by YAMON */
548
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
549

    
550
#ifdef TARGET_WORDS_BIGENDIAN
551
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
552
#else
553
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
554
#endif
555
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
556

    
557
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
558

    
559
#ifdef TARGET_WORDS_BIGENDIAN
560
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
561
#else
562
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
563
#endif
564
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
565
#ifdef TARGET_WORDS_BIGENDIAN
566
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
567
#else
568
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
569
#endif
570
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
571

    
572
#ifdef TARGET_WORDS_BIGENDIAN
573
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
574
#else
575
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
576
#endif
577
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
578
#ifdef TARGET_WORDS_BIGENDIAN
579
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
580
#else
581
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
582
#endif
583
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
584

    
585
#ifdef TARGET_WORDS_BIGENDIAN
586
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
587
#else
588
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
589
#endif
590
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
591
#ifdef TARGET_WORDS_BIGENDIAN
592
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
593
#else
594
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
595
#endif
596
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
597

    
598
    /* Jump to kernel code */
599
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
600
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
601
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
602
    stl_raw(p++, 0x00000000);                                      /* nop */
603

    
604
    /* YAMON subroutines */
605
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
606
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
607
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
608
   /* 808 YAMON print */
609
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
610
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
611
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
612
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
613
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
614
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
615
    stl_raw(p++, 0x00000000);                                     /* nop */
616
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
617
    stl_raw(p++, 0x00000000);                                     /* nop */
618
    stl_raw(p++, 0x08000205);                                     /* j 814 */
619
    stl_raw(p++, 0x00000000);                                     /* nop */
620
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
621
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
622
    /* 0x83c YAMON print_count */
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++, 0x00c06021);                                     /* move t4,a2 */
627
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
628
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
629
    stl_raw(p++, 0x00000000);                                     /* nop */
630
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
631
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
632
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
633
    stl_raw(p++, 0x00000000);                                     /* nop */
634
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
635
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
636
    /* 0x870 */
637
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
638
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
639
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
640
    stl_raw(p++, 0x00000000);                                     /* nop */
641
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
642
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
643
    stl_raw(p++, 0x00000000);                                     /* nop */
644
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
645
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
646

    
647
}
648

    
649
static void prom_set(int index, const char *string, ...)
650
{
651
    va_list ap;
652
    int32_t *p;
653
    int32_t table_addr;
654
    char *s;
655

    
656
    if (index >= ENVP_NB_ENTRIES)
657
        return;
658

    
659
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
660
    p += index;
661

    
662
    if (string == NULL) {
663
        stl_raw(p, 0);
664
        return;
665
    }
666

    
667
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
668
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
669

    
670
    stl_raw(p, table_addr);
671

    
672
    va_start(ap, string);
673
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
674
    va_end(ap);
675
}
676

    
677
/* Kernel */
678
static int64_t load_kernel (CPUState *env)
679
{
680
    int64_t kernel_entry, kernel_low, kernel_high;
681
    int index = 0;
682
    long initrd_size;
683
    ram_addr_t initrd_offset;
684

    
685
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
686
                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
687
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
688
                loaderparams.kernel_filename);
689
        exit(1);
690
    }
691

    
692
    /* load initrd */
693
    initrd_size = 0;
694
    initrd_offset = 0;
695
    if (loaderparams.initrd_filename) {
696
        initrd_size = get_image_size (loaderparams.initrd_filename);
697
        if (initrd_size > 0) {
698
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
699
            if (initrd_offset + initrd_size > ram_size) {
700
                fprintf(stderr,
701
                        "qemu: memory too small for initial ram disk '%s'\n",
702
                        loaderparams.initrd_filename);
703
                exit(1);
704
            }
705
            initrd_size = load_image(loaderparams.initrd_filename,
706
                                     phys_ram_base + initrd_offset);
707
        }
708
        if (initrd_size == (target_ulong) -1) {
709
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
710
                    loaderparams.initrd_filename);
711
            exit(1);
712
        }
713
    }
714

    
715
    /* Store command line.  */
716
    prom_set(index++, loaderparams.kernel_filename);
717
    if (initrd_size > 0)
718
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
719
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
720
                 loaderparams.kernel_cmdline);
721
    else
722
        prom_set(index++, loaderparams.kernel_cmdline);
723

    
724
    /* Setup minimum environment variables */
725
    prom_set(index++, "memsize");
726
    prom_set(index++, "%i", loaderparams.ram_size);
727
    prom_set(index++, "modetty0");
728
    prom_set(index++, "38400n8r");
729
    prom_set(index++, NULL);
730

    
731
    return kernel_entry;
732
}
733

    
734
static void main_cpu_reset(void *opaque)
735
{
736
    CPUState *env = opaque;
737
    cpu_reset(env);
738

    
739
    /* The bootload does not need to be rewritten as it is located in a
740
       read only location. The kernel location and the arguments table
741
       location does not change. */
742
    if (loaderparams.kernel_filename) {
743
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
744
        load_kernel (env);
745
    }
746
}
747

    
748
static
749
void mips_malta_init (int ram_size, int vga_ram_size, const char *boot_device,
750
                      DisplayState *ds, const char **fd_filename, int snapshot,
751
                      const char *kernel_filename, const char *kernel_cmdline,
752
                      const char *initrd_filename, const char *cpu_model)
753
{
754
    char buf[1024];
755
    unsigned long bios_offset;
756
    int64_t kernel_entry;
757
    PCIBus *pci_bus;
758
    CPUState *env;
759
    RTCState *rtc_state;
760
    /* fdctrl_t *floppy_controller; */
761
    MaltaFPGAState *malta_fpga;
762
    int ret;
763
    qemu_irq *i8259;
764
    int piix4_devfn;
765
    uint8_t *eeprom_buf;
766
    i2c_bus *smbus;
767
    int i;
768

    
769
    /* init CPUs */
770
    if (cpu_model == NULL) {
771
#ifdef TARGET_MIPS64
772
        cpu_model = "20Kc";
773
#else
774
        cpu_model = "24Kf";
775
#endif
776
    }
777
    env = cpu_init(cpu_model);
778
    if (!env) {
779
        fprintf(stderr, "Unable to find CPU definition\n");
780
        exit(1);
781
    }
782
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
783
    qemu_register_reset(main_cpu_reset, env);
784

    
785
    /* allocate RAM */
786
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
787

    
788
    /* Map the bios at two physical locations, as on the real board */
789
    bios_offset = ram_size + vga_ram_size;
790
    cpu_register_physical_memory(0x1e000000LL,
791
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
792
    cpu_register_physical_memory(0x1fc00000LL,
793
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
794

    
795
    /* FPGA */
796
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
797

    
798
    /* Load a BIOS image unless a kernel image has been specified. */
799
    if (!kernel_filename) {
800
        if (bios_name == NULL)
801
            bios_name = BIOS_FILENAME;
802
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
803
        ret = load_image(buf, phys_ram_base + bios_offset);
804
        if (ret < 0 || ret > BIOS_SIZE) {
805
            fprintf(stderr,
806
                    "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
807
                    buf);
808
            exit(1);
809
        }
810
        /* In little endian mode the 32bit words in the bios are swapped,
811
           a neat trick which allows bi-endian firmware. */
812
#ifndef TARGET_WORDS_BIGENDIAN
813
        {
814
            uint32_t *addr;
815
            for (addr = (uint32_t *)(phys_ram_base + bios_offset);
816
                 addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
817
                 addr++) {
818
                *addr = bswap32(*addr);
819
            }
820
        }
821
#endif
822
    }
823

    
824
    /* If a kernel image has been specified, write a small bootloader
825
       to the flash location. */
826
    if (kernel_filename) {
827
        loaderparams.ram_size = ram_size;
828
        loaderparams.kernel_filename = kernel_filename;
829
        loaderparams.kernel_cmdline = kernel_cmdline;
830
        loaderparams.initrd_filename = initrd_filename;
831
        kernel_entry = load_kernel(env);
832
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
833
        write_bootloader(env, bios_offset, kernel_entry);
834
    }
835

    
836
    /* Board ID = 0x420 (Malta Board with CoreLV)
837
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
838
       map to the board ID. */
839
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
840

    
841
    /* Init internal devices */
842
    cpu_mips_irq_init_cpu(env);
843
    cpu_mips_clock_init(env);
844
    cpu_mips_irqctrl_init();
845

    
846
    /* Interrupt controller */
847
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
848
    i8259 = i8259_init(env->irq[2]);
849

    
850
    /* Northbridge */
851
    pci_bus = pci_gt64120_init(i8259);
852

    
853
    /* Southbridge */
854
    piix4_devfn = piix4_init(pci_bus, 80);
855
    pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, i8259);
856
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
857
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
858
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
859
    for (i = 0; i < 8; i++) {
860
        /* TODO: Populate SPD eeprom data.  */
861
        smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
862
    }
863
    pit = pit_init(0x40, i8259[0]);
864
    DMA_init(0);
865

    
866
    /* Super I/O */
867
    i8042_init(i8259[1], i8259[12], 0x60);
868
    rtc_state = rtc_init(0x70, i8259[8]);
869
    if (serial_hds[0])
870
        serial_init(0x3f8, i8259[4], serial_hds[0]);
871
    if (serial_hds[1])
872
        serial_init(0x2f8, i8259[3], serial_hds[1]);
873
    if (parallel_hds[0])
874
        parallel_init(0x378, i8259[7], parallel_hds[0]);
875
    /* XXX: The floppy controller does not work correctly, something is
876
       probably wrong.
877
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
878

    
879
    /* Sound card */
880
#ifdef HAS_AUDIO
881
    audio_init(pci_bus);
882
#endif
883

    
884
    /* Network card */
885
    network_init(pci_bus);
886

    
887
    /* Optional PCI video card */
888
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
889
                        ram_size, vga_ram_size);
890
}
891

    
892
QEMUMachine mips_malta_machine = {
893
    "malta",
894
    "MIPS Malta Core LV",
895
    mips_malta_init,
896
};