Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 99a0949b

History | View | Annotate | Download (31.7 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 "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
#include "mips-bios.h"
41
#include "ide.h"
42
#include "loader.h"
43
#include "elf.h"
44

    
45
//#define DEBUG_BOARD_INIT
46

    
47
#ifdef TARGET_MIPS64
48
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
49
#else
50
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
51
#endif
52

    
53
#define ENVP_ADDR (int32_t)0x80002000
54
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
55

    
56
#define ENVP_NB_ENTRIES                 16
57
#define ENVP_ENTRY_SIZE                 256
58

    
59
#define MAX_IDE_BUS 2
60

    
61
typedef struct {
62
    uint32_t leds;
63
    uint32_t brk;
64
    uint32_t gpout;
65
    uint32_t i2cin;
66
    uint32_t i2coe;
67
    uint32_t i2cout;
68
    uint32_t i2csel;
69
    CharDriverState *display;
70
    char display_text[9];
71
    SerialState *uart;
72
} MaltaFPGAState;
73

    
74
static PITState *pit;
75

    
76
static struct _loaderparams {
77
    int ram_size;
78
    const char *kernel_filename;
79
    const char *kernel_cmdline;
80
    const char *initrd_filename;
81
} loaderparams;
82

    
83
/* Malta FPGA */
84
static void malta_fpga_update_display(void *opaque)
85
{
86
    char leds_text[9];
87
    int i;
88
    MaltaFPGAState *s = opaque;
89

    
90
    for (i = 7 ; i >= 0 ; i--) {
91
        if (s->leds & (1 << i))
92
            leds_text[i] = '#';
93
        else
94
            leds_text[i] = ' ';
95
    }
96
    leds_text[8] = '\0';
97

    
98
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
99
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
100
}
101

    
102
/*
103
 * EEPROM 24C01 / 24C02 emulation.
104
 *
105
 * Emulation for serial EEPROMs:
106
 * 24C01 - 1024 bit (128 x 8)
107
 * 24C02 - 2048 bit (256 x 8)
108
 *
109
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
110
 */
111

    
112
//~ #define DEBUG
113

    
114
#if defined(DEBUG)
115
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
116
#else
117
#  define logout(fmt, ...) ((void)0)
118
#endif
119

    
120
struct eeprom24c0x {
121
  uint8_t tick;
122
  uint8_t address;
123
  uint8_t command;
124
  uint8_t ack;
125
  uint8_t scl;
126
  uint8_t sda;
127
  uint8_t data;
128
  //~ uint16_t size;
129
  uint8_t contents[256];
130
};
131

    
132
typedef struct eeprom24c0x a_eeprom24c0x;
133

    
134
static a_eeprom24c0x eeprom = {
135
    .contents = {
136
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
137
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
138
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
139
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
140
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
141
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
144
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
152
    },
153
};
154

    
155
static uint8_t eeprom24c0x_read(void)
156
{
157
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
158
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
159
    return eeprom.sda;
160
}
161

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

    
220
static uint32_t malta_fpga_readl(void *opaque, a_target_phys_addr addr)
221
{
222
    MaltaFPGAState *s = opaque;
223
    uint32_t val = 0;
224
    uint32_t saddr;
225

    
226
    saddr = (addr & 0xfffff);
227

    
228
    switch (saddr) {
229

    
230
    /* SWITCH Register */
231
    case 0x00200:
232
        val = 0x00000000;                /* All switches closed */
233
        break;
234

    
235
    /* STATUS Register */
236
    case 0x00208:
237
#ifdef TARGET_WORDS_BIGENDIAN
238
        val = 0x00000012;
239
#else
240
        val = 0x00000010;
241
#endif
242
        break;
243

    
244
    /* JMPRS Register */
245
    case 0x00210:
246
        val = 0x00;
247
        break;
248

    
249
    /* LEDBAR Register */
250
    case 0x00408:
251
        val = s->leds;
252
        break;
253

    
254
    /* BRKRES Register */
255
    case 0x00508:
256
        val = s->brk;
257
        break;
258

    
259
    /* UART Registers are handled directly by the serial device */
260

    
261
    /* GPOUT Register */
262
    case 0x00a00:
263
        val = s->gpout;
264
        break;
265

    
266
    /* XXX: implement a real I2C controller */
267

    
268
    /* GPINP Register */
269
    case 0x00a08:
270
        /* IN = OUT until a real I2C control is implemented */
271
        if (s->i2csel)
272
            val = s->i2cout;
273
        else
274
            val = 0x00;
275
        break;
276

    
277
    /* I2CINP Register */
278
    case 0x00b00:
279
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
280
        break;
281

    
282
    /* I2COE Register */
283
    case 0x00b08:
284
        val = s->i2coe;
285
        break;
286

    
287
    /* I2COUT Register */
288
    case 0x00b10:
289
        val = s->i2cout;
290
        break;
291

    
292
    /* I2CSEL Register */
293
    case 0x00b18:
294
        val = s->i2csel;
295
        break;
296

    
297
    default:
298
#if 0
299
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
300
                addr);
301
#endif
302
        break;
303
    }
304
    return val;
305
}
306

    
307
static void malta_fpga_writel(void *opaque, a_target_phys_addr addr,
308
                              uint32_t val)
309
{
310
    MaltaFPGAState *s = opaque;
311
    uint32_t saddr;
312

    
313
    saddr = (addr & 0xfffff);
314

    
315
    switch (saddr) {
316

    
317
    /* SWITCH Register */
318
    case 0x00200:
319
        break;
320

    
321
    /* JMPRS Register */
322
    case 0x00210:
323
        break;
324

    
325
    /* LEDBAR Register */
326
    /* XXX: implement a 8-LED array */
327
    case 0x00408:
328
        s->leds = val & 0xff;
329
        break;
330

    
331
    /* ASCIIWORD Register */
332
    case 0x00410:
333
        snprintf(s->display_text, 9, "%08X", val);
334
        malta_fpga_update_display(s);
335
        break;
336

    
337
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
338
    case 0x00418:
339
    case 0x00420:
340
    case 0x00428:
341
    case 0x00430:
342
    case 0x00438:
343
    case 0x00440:
344
    case 0x00448:
345
    case 0x00450:
346
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
347
        malta_fpga_update_display(s);
348
        break;
349

    
350
    /* SOFTRES Register */
351
    case 0x00500:
352
        if (val == 0x42)
353
            qemu_system_reset_request ();
354
        break;
355

    
356
    /* BRKRES Register */
357
    case 0x00508:
358
        s->brk = val & 0xff;
359
        break;
360

    
361
    /* UART Registers are handled directly by the serial device */
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 * const malta_fpga_read[] = {
394
   malta_fpga_readl,
395
   malta_fpga_readl,
396
   malta_fpga_readl
397
};
398

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

    
405
static 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
}
420

    
421
static void malta_fpga_led_init(CharDriverState *chr)
422
{
423
    qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
424
    qemu_chr_printf(chr, "+--------+\r\n");
425
    qemu_chr_printf(chr, "+        +\r\n");
426
    qemu_chr_printf(chr, "+--------+\r\n");
427
    qemu_chr_printf(chr, "\n");
428
    qemu_chr_printf(chr, "Malta ASCII\r\n");
429
    qemu_chr_printf(chr, "+--------+\r\n");
430
    qemu_chr_printf(chr, "+        +\r\n");
431
    qemu_chr_printf(chr, "+--------+\r\n");
432
}
433

    
434
static MaltaFPGAState *malta_fpga_init(a_target_phys_addr base, qemu_irq uart_irq, CharDriverState *uart_chr)
435
{
436
    MaltaFPGAState *s;
437
    int malta;
438

    
439
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
440

    
441
    malta = cpu_register_io_memory(malta_fpga_read,
442
                                   malta_fpga_write, s);
443

    
444
    cpu_register_physical_memory(base, 0x900, malta);
445
    /* 0xa00 is less than a page, so will still get the right offsets.  */
446
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
447

    
448
    s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
449

    
450
    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1);
451

    
452
    malta_fpga_reset(s);
453
    qemu_register_reset(malta_fpga_reset, s);
454

    
455
    return s;
456
}
457

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

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

    
469
    if (audio_enabled) {
470
        for (c = soundhw; c->name; ++c) {
471
            if (c->enabled) {
472
                c->init.init_pci(pci_bus);
473
            }
474
        }
475
    }
476
}
477
#endif
478

    
479
/* Network support */
480
static void network_init(void)
481
{
482
    int i;
483

    
484
    for(i = 0; i < nb_nics; i++) {
485
        NICInfo *nd = &nd_table[i];
486
        const char *default_devaddr = NULL;
487

    
488
        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
489
            /* The malta board has a PCNet card using PCI SLOT 11 */
490
            default_devaddr = "0b";
491

    
492
        pci_nic_init(nd, "pcnet", default_devaddr);
493
    }
494
}
495

    
496
/* ROM and pseudo bootloader
497

498
   The following code implements a very very simple bootloader. It first
499
   loads the registers a0 to a3 to the values expected by the OS, and
500
   then jump at the kernel address.
501

502
   The bootloader should pass the locations of the kernel arguments and
503
   environment variables tables. Those tables contain the 32-bit address
504
   of NULL terminated strings. The environment variables table should be
505
   terminated by a NULL address.
506

507
   For a simpler implementation, the number of kernel arguments is fixed
508
   to two (the name of the kernel and the command line), and the two
509
   tables are actually the same one.
510

511
   The registers a0 to a3 should contain the following values:
512
     a0 - number of kernel arguments
513
     a1 - 32-bit address of the kernel arguments table
514
     a2 - 32-bit address of the environment variables table
515
     a3 - RAM size in bytes
516
*/
517

    
518
static void write_bootloader (CPUState *env, uint8_t *base,
519
                              int64_t kernel_entry)
520
{
521
    uint32_t *p;
522

    
523
    /* Small bootloader */
524
    p = (uint32_t *)base;
525
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
526
    stl_raw(p++, 0x00000000);                                      /* nop */
527

    
528
    /* YAMON service vector */
529
    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
530
    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
531
    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
532
    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
533
    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
534
    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
535
    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
536
    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
537
    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
538
    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
539
    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
540
    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
541
    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
542

    
543

    
544
    /* Second part of the bootloader */
545
    p = (uint32_t *) (base + 0x580);
546
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
547
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
548
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
549
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
550
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
551
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
552
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
553
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
554
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
555

    
556
    /* Load BAR registers as done by YAMON */
557
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
558

    
559
#ifdef TARGET_WORDS_BIGENDIAN
560
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
561
#else
562
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
563
#endif
564
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
565

    
566
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
567

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

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

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

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

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

    
656
}
657

    
658
static void prom_set(int index, const char *string, ...)
659
{
660
    char buf[ENVP_ENTRY_SIZE];
661
    a_target_phys_addr p;
662
    va_list ap;
663
    int32_t table_addr;
664

    
665
    if (index >= ENVP_NB_ENTRIES)
666
        return;
667

    
668
    p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
669

    
670
    if (string == NULL) {
671
        stl_phys(p, 0);
672
        return;
673
    }
674

    
675
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES
676
                 + index * ENVP_ENTRY_SIZE;
677
    stl_phys(p, table_addr);
678

    
679
    va_start(ap, string);
680
    vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap);
681
    va_end(ap);
682
    pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf);
683
}
684

    
685
/* Kernel */
686
static int64_t load_kernel (CPUState *env)
687
{
688
    int64_t kernel_entry, kernel_low, kernel_high;
689
    int index = 0;
690
    long initrd_size;
691
    a_ram_addr initrd_offset;
692
    int big_endian;
693

    
694
#ifdef TARGET_WORDS_BIGENDIAN
695
    big_endian = 1;
696
#else
697
    big_endian = 0;
698
#endif
699

    
700
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
701
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
702
                 (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
703
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
704
                loaderparams.kernel_filename);
705
        exit(1);
706
    }
707

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

    
732
    /* Store command line.  */
733
    prom_set(index++, loaderparams.kernel_filename);
734
    if (initrd_size > 0)
735
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
736
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
737
                 loaderparams.kernel_cmdline);
738
    else
739
        prom_set(index++, loaderparams.kernel_cmdline);
740

    
741
    /* Setup minimum environment variables */
742
    prom_set(index++, "memsize");
743
    prom_set(index++, "%i", loaderparams.ram_size);
744
    prom_set(index++, "modetty0");
745
    prom_set(index++, "38400n8r");
746
    prom_set(index++, NULL);
747

    
748
    return kernel_entry;
749
}
750

    
751
static void main_cpu_reset(void *opaque)
752
{
753
    CPUState *env = opaque;
754
    cpu_reset(env);
755

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

    
765
static
766
void mips_malta_init (a_ram_addr ram_size,
767
                      const char *boot_device,
768
                      const char *kernel_filename, const char *kernel_cmdline,
769
                      const char *initrd_filename, const char *cpu_model)
770
{
771
    char *filename;
772
    a_ram_addr ram_offset;
773
    a_ram_addr bios_offset;
774
    target_long bios_size;
775
    int64_t kernel_entry;
776
    PCIBus *pci_bus;
777
    ISADevice *isa_dev;
778
    CPUState *env;
779
    RTCState *rtc_state;
780
    a_fdctrl *floppy_controller;
781
    MaltaFPGAState *malta_fpga;
782
    qemu_irq *i8259;
783
    int piix4_devfn;
784
    uint8_t *eeprom_buf;
785
    i2c_bus *smbus;
786
    int i;
787
    DriveInfo *dinfo;
788
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
789
    BlockDriverState *fd[MAX_FD];
790
    int fl_idx = 0;
791
    int fl_sectors = 0;
792

    
793
    /* Make sure the first 3 serial ports are associated with a device. */
794
    for(i = 0; i < 3; i++) {
795
        if (!serial_hds[i]) {
796
            char label[32];
797
            snprintf(label, sizeof(label), "serial%d", i);
798
            serial_hds[i] = qemu_chr_open(label, "null", NULL);
799
        }
800
    }
801

    
802
    /* init CPUs */
803
    if (cpu_model == NULL) {
804
#ifdef TARGET_MIPS64
805
        cpu_model = "20Kc";
806
#else
807
        cpu_model = "24Kf";
808
#endif
809
    }
810
    env = cpu_init(cpu_model);
811
    if (!env) {
812
        fprintf(stderr, "Unable to find CPU definition\n");
813
        exit(1);
814
    }
815
    qemu_register_reset(main_cpu_reset, env);
816

    
817
    /* allocate RAM */
818
    if (ram_size > (256 << 20)) {
819
        fprintf(stderr,
820
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
821
                ((unsigned int)ram_size / (1 << 20)));
822
        exit(1);
823
    }
824
    ram_offset = qemu_ram_alloc(ram_size);
825
    bios_offset = qemu_ram_alloc(BIOS_SIZE);
826

    
827

    
828
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
829

    
830
    /* Map the bios at two physical locations, as on the real board. */
831
    cpu_register_physical_memory(0x1e000000LL,
832
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
833
    cpu_register_physical_memory(0x1fc00000LL,
834
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
835

    
836
    /* FPGA */
837
    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
838

    
839
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
840
    if (kernel_filename) {
841
        /* Write a small bootloader to the flash location. */
842
        loaderparams.ram_size = ram_size;
843
        loaderparams.kernel_filename = kernel_filename;
844
        loaderparams.kernel_cmdline = kernel_cmdline;
845
        loaderparams.initrd_filename = initrd_filename;
846
        kernel_entry = load_kernel(env);
847
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
848
        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
849
    } else {
850
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
851
        if (dinfo) {
852
            /* Load firmware from flash. */
853
            bios_size = 0x400000;
854
            fl_sectors = bios_size >> 16;
855
#ifdef DEBUG_BOARD_INIT
856
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
857
                   "offset %08lx addr %08llx '%s' %x\n",
858
                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
859
                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
860
#endif
861
            pflash_cfi01_register(0x1e000000LL, bios_offset,
862
                                  dinfo->bdrv, 65536, fl_sectors,
863
                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
864
            fl_idx++;
865
        } else {
866
            /* Load a BIOS image. */
867
            if (bios_name == NULL)
868
                bios_name = BIOS_FILENAME;
869
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
870
            if (filename) {
871
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
872
                                                BIOS_SIZE);
873
                qemu_free(filename);
874
            } else {
875
                bios_size = -1;
876
            }
877
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
878
                fprintf(stderr,
879
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
880
                        bios_name);
881
                exit(1);
882
            }
883
        }
884
        /* In little endian mode the 32bit words in the bios are swapped,
885
           a neat trick which allows bi-endian firmware. */
886
#ifndef TARGET_WORDS_BIGENDIAN
887
        {
888
            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
889
            uint32_t *end = addr + bios_size;
890
            while (addr < end) {
891
                bswap32s(addr);
892
            }
893
        }
894
#endif
895
    }
896

    
897
    /* Board ID = 0x420 (Malta Board with CoreLV)
898
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
899
       map to the board ID. */
900
    stl_phys(0x1fc00010LL, 0x00000420);
901

    
902
    /* Init internal devices */
903
    cpu_mips_irq_init_cpu(env);
904
    cpu_mips_clock_init(env);
905

    
906
    /* Interrupt controller */
907
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
908
    i8259 = i8259_init(env->irq[2]);
909

    
910
    /* Northbridge */
911
    pci_bus = pci_gt64120_init(i8259);
912

    
913
    /* Southbridge */
914

    
915
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
916
        fprintf(stderr, "qemu: too many IDE bus\n");
917
        exit(1);
918
    }
919

    
920
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
921
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
922
    }
923

    
924
    piix4_devfn = piix4_init(pci_bus, 80);
925
    isa_bus_irqs(i8259);
926
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
927
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
928
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9));
929
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
930
    for (i = 0; i < 8; i++) {
931
        /* TODO: Populate SPD eeprom data.  */
932
        DeviceState *eeprom;
933
        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
934
        qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
935
        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
936
        qdev_init(eeprom);
937
    }
938
    pit = pit_init(0x40, isa_reserve_irq(0));
939
    DMA_init(0);
940

    
941
    /* Super I/O */
942
    isa_dev = isa_create_simple("i8042");
943
 
944
    rtc_state = rtc_init(2000);
945
    serial_init(0x3f8, isa_reserve_irq(4), 115200, serial_hds[0]);
946
    serial_init(0x2f8, isa_reserve_irq(3), 115200, serial_hds[1]);
947
    if (parallel_hds[0])
948
        parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]);
949
    for(i = 0; i < MAX_FD; i++) {
950
        dinfo = drive_get(IF_FLOPPY, 0, i);
951
        fd[i] = dinfo ? dinfo->bdrv : NULL;
952
    }
953
    floppy_controller = fdctrl_init_isa(fd);
954

    
955
    /* Sound card */
956
#ifdef HAS_AUDIO
957
    audio_init(pci_bus);
958
#endif
959

    
960
    /* Network card */
961
    network_init();
962

    
963
    /* Optional PCI video card */
964
    if (cirrus_vga_enabled) {
965
        pci_cirrus_vga_init(pci_bus);
966
    } else if (vmsvga_enabled) {
967
        pci_vmsvga_init(pci_bus);
968
    } else if (std_vga_enabled) {
969
        pci_vga_init(pci_bus, 0, 0);
970
    }
971
}
972

    
973
static QEMUMachine mips_malta_machine = {
974
    .name = "malta",
975
    .desc = "MIPS Malta Core LV",
976
    .init = mips_malta_init,
977
    .is_default = 1,
978
};
979

    
980
static void mips_malta_machine_init(void)
981
{
982
    qemu_register_machine(&mips_malta_machine);
983
}
984

    
985
machine_init(mips_malta_machine_init);