Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 089b7c0a

History | View | Annotate | Download (30.1 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 "mips.h"
32
#include "pci.h"
33
#include "qemu-char.h"
34
#include "sysemu.h"
35
#include "audio/audio.h"
36
#include "boards.h"
37

    
38
#ifdef TARGET_WORDS_BIGENDIAN
39
#define BIOS_FILENAME "mips_bios.bin"
40
#else
41
#define BIOS_FILENAME "mipsel_bios.bin"
42
#endif
43

    
44
#ifdef TARGET_MIPS64
45
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
46
#else
47
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
48
#endif
49

    
50
#define ENVP_ADDR (int32_t)0x80002000
51
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
52

    
53
#define ENVP_NB_ENTRIES                 16
54
#define ENVP_ENTRY_SIZE                 256
55

    
56
#define MAX_IDE_BUS 2
57

    
58
extern FILE *logfile;
59

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

    
73
static PITState *pit;
74

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

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

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

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

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

    
111
//~ #define DEBUG
112

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

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

    
131
typedef struct _eeprom24c0x_t eeprom24c0x_t;
132

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

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

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

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

    
225
    saddr = (addr & 0xfffff);
226

    
227
    switch (saddr) {
228

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
312
    saddr = (addr & 0xfffff);
313

    
314
    switch (saddr) {
315

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

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

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

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

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

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

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

    
360
    /* UART Registers are handled directly by the serial device */
361

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

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

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

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

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

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

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

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

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

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

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

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

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

    
432
    cpu_register_physical_memory(base, 0x900, malta);
433
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, 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 + 0x900, 3, env->irq[2], uart_chr, 1);
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
                    c->init.init_pci (pci_bus, s);
475
            }
476
        }
477
    }
478
}
479
#endif
480

    
481
/* Network support */
482
static void network_init (PCIBus *pci_bus)
483
{
484
    int i;
485
    NICInfo *nd;
486

    
487
    for(i = 0; i < nb_nics; i++) {
488
        nd = &nd_table[i];
489
        if (!nd->model) {
490
            nd->model = "pcnet";
491
        }
492
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
493
            /* The malta board has a PCNet card using PCI SLOT 11 */
494
            pci_nic_init(pci_bus, nd, 88);
495
        } else {
496
            pci_nic_init(pci_bus, nd, -1);
497
        }
498
    }
499
}
500

    
501
/* ROM and pseudo bootloader
502

503
   The following code implements a very very simple bootloader. It first
504
   loads the registers a0 to a3 to the values expected by the OS, and
505
   then jump at the kernel address.
506

507
   The bootloader should pass the locations of the kernel arguments and
508
   environment variables tables. Those tables contain the 32-bit address
509
   of NULL terminated strings. The environment variables table should be
510
   terminated by a NULL address.
511

512
   For a simpler implementation, the number of kernel arguments is fixed
513
   to two (the name of the kernel and the command line), and the two
514
   tables are actually the same one.
515

516
   The registers a0 to a3 should contain the following values:
517
     a0 - number of kernel arguments
518
     a1 - 32-bit address of the kernel arguments table
519
     a2 - 32-bit address of the environment variables table
520
     a3 - RAM size in bytes
521
*/
522

    
523
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
524
{
525
    uint32_t *p;
526

    
527
    /* Small bootloader */
528
    p = (uint32_t *) (phys_ram_base + bios_offset);
529
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
530
    stl_raw(p++, 0x00000000);                                      /* nop */
531

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

    
547

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

    
560
    /* Load BAR registers as done by YAMON */
561
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
562

    
563
#ifdef TARGET_WORDS_BIGENDIAN
564
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
565
#else
566
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
567
#endif
568
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
569

    
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(loaderparams.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
                loaderparams.kernel_filename);
702
        exit(1);
703
    }
704

    
705
    /* load initrd */
706
    initrd_size = 0;
707
    initrd_offset = 0;
708
    if (loaderparams.initrd_filename) {
709
        initrd_size = get_image_size (loaderparams.initrd_filename);
710
        if (initrd_size > 0) {
711
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
712
            if (initrd_offset + initrd_size > ram_size) {
713
                fprintf(stderr,
714
                        "qemu: memory too small for initial ram disk '%s'\n",
715
                        loaderparams.initrd_filename);
716
                exit(1);
717
            }
718
            initrd_size = load_image(loaderparams.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
                    loaderparams.initrd_filename);
724
            exit(1);
725
        }
726
    }
727

    
728
    /* Store command line.  */
729
    prom_set(index++, loaderparams.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
                 loaderparams.kernel_cmdline);
734
    else
735
        prom_set(index++, loaderparams.kernel_cmdline);
736

    
737
    /* Setup minimum environment variables */
738
    prom_set(index++, "memsize");
739
    prom_set(index++, "%i", loaderparams.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 (loaderparams.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,
763
                      const char *boot_device, DisplayState *ds,
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
    qemu_irq *i8259;
777
    int piix4_devfn;
778
    uint8_t *eeprom_buf;
779
    i2c_bus *smbus;
780
    int i;
781
    int index;
782
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
783
    BlockDriverState *fd[MAX_FD];
784

    
785
    /* init CPUs */
786
    if (cpu_model == NULL) {
787
#ifdef TARGET_MIPS64
788
        cpu_model = "20Kc";
789
#else
790
        cpu_model = "24Kf";
791
#endif
792
    }
793
    env = cpu_init(cpu_model);
794
    if (!env) {
795
        fprintf(stderr, "Unable to find CPU definition\n");
796
        exit(1);
797
    }
798
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
799
    qemu_register_reset(main_cpu_reset, env);
800

    
801
    /* allocate RAM */
802
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
803

    
804
    /* Map the bios at two physical locations, as on the real board */
805
    bios_offset = ram_size + vga_ram_size;
806
    cpu_register_physical_memory(0x1e000000LL,
807
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
808
    cpu_register_physical_memory(0x1fc00000LL,
809
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
810

    
811
    /* FPGA */
812
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
813

    
814
    /* Load a BIOS image unless a kernel image has been specified. */
815
    if (!kernel_filename) {
816
        if (bios_name == NULL)
817
            bios_name = BIOS_FILENAME;
818
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
819
        ret = load_image(buf, phys_ram_base + bios_offset);
820
        if (ret < 0 || ret > BIOS_SIZE) {
821
            fprintf(stderr,
822
                    "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
823
                    buf);
824
            exit(1);
825
        }
826
        /* In little endian mode the 32bit words in the bios are swapped,
827
           a neat trick which allows bi-endian firmware. */
828
#ifndef TARGET_WORDS_BIGENDIAN
829
        {
830
            uint32_t *addr;
831
            for (addr = (uint32_t *)(phys_ram_base + bios_offset);
832
                 addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
833
                 addr++) {
834
                *addr = bswap32(*addr);
835
            }
836
        }
837
#endif
838
    }
839

    
840
    /* If a kernel image has been specified, write a small bootloader
841
       to the flash location. */
842
    if (kernel_filename) {
843
        loaderparams.ram_size = ram_size;
844
        loaderparams.kernel_filename = kernel_filename;
845
        loaderparams.kernel_cmdline = kernel_cmdline;
846
        loaderparams.initrd_filename = initrd_filename;
847
        kernel_entry = load_kernel(env);
848
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
849
        write_bootloader(env, bios_offset, kernel_entry);
850
    }
851

    
852
    /* Board ID = 0x420 (Malta Board with CoreLV)
853
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
854
       map to the board ID. */
855
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
856

    
857
    /* Init internal devices */
858
    cpu_mips_irq_init_cpu(env);
859
    cpu_mips_clock_init(env);
860
    cpu_mips_irqctrl_init();
861

    
862
    /* Interrupt controller */
863
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
864
    i8259 = i8259_init(env->irq[2]);
865

    
866
    /* Northbridge */
867
    pci_bus = pci_gt64120_init(i8259);
868

    
869
    /* Southbridge */
870

    
871
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
872
        fprintf(stderr, "qemu: too many IDE bus\n");
873
        exit(1);
874
    }
875

    
876
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
877
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
878
        if (index != -1)
879
            hd[i] = drives_table[index].bdrv;
880
        else
881
            hd[i] = NULL;
882
    }
883

    
884
    piix4_devfn = piix4_init(pci_bus, 80);
885
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
886
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
887
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
888
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
889
    for (i = 0; i < 8; i++) {
890
        /* TODO: Populate SPD eeprom data.  */
891
        smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
892
    }
893
    pit = pit_init(0x40, i8259[0]);
894
    DMA_init(0);
895

    
896
    /* Super I/O */
897
    i8042_init(i8259[1], i8259[12], 0x60);
898
    rtc_state = rtc_init(0x70, i8259[8]);
899
    if (serial_hds[0])
900
        serial_init(0x3f8, i8259[4], serial_hds[0]);
901
    if (serial_hds[1])
902
        serial_init(0x2f8, i8259[3], serial_hds[1]);
903
    if (parallel_hds[0])
904
        parallel_init(0x378, i8259[7], parallel_hds[0]);
905
    for(i = 0; i < MAX_FD; i++) {
906
        index = drive_get_index(IF_FLOPPY, 0, i);
907
       if (index != -1)
908
           fd[i] = drives_table[index].bdrv;
909
       else
910
           fd[i] = NULL;
911
    }
912
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
913

    
914
    /* Sound card */
915
#ifdef HAS_AUDIO
916
    audio_init(pci_bus);
917
#endif
918

    
919
    /* Network card */
920
    network_init(pci_bus);
921

    
922
    /* Optional PCI video card */
923
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
924
                        ram_size, vga_ram_size);
925
}
926

    
927
QEMUMachine mips_malta_machine = {
928
    "malta",
929
    "MIPS Malta Core LV",
930
    mips_malta_init,
931
};