Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ ceecf1d1

History | View | Annotate | Download (31.3 kB)

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

    
25
#include "hw.h"
26
#include "pc.h"
27
#include "fdc.h"
28
#include "net.h"
29
#include "boards.h"
30
#include "smbus.h"
31
#include "block.h"
32
#include "flash.h"
33
#include "mips.h"
34
#include "pci.h"
35
#include "qemu-char.h"
36
#include "sysemu.h"
37
#include "audio/audio.h"
38
#include "boards.h"
39
#include "qemu-log.h"
40

    
41
//#define DEBUG_BOARD_INIT
42

    
43
#ifdef TARGET_WORDS_BIGENDIAN
44
#define BIOS_FILENAME "mips_bios.bin"
45
#else
46
#define BIOS_FILENAME "mipsel_bios.bin"
47
#endif
48

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

    
55
#define ENVP_ADDR (int32_t)0x80002000
56
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
57

    
58
#define ENVP_NB_ENTRIES                 16
59
#define ENVP_ENTRY_SIZE                 256
60

    
61
#define MAX_IDE_BUS 2
62

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

    
76
static PITState *pit;
77

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

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

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

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

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

    
114
//~ #define DEBUG
115

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

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

    
134
typedef struct _eeprom24c0x_t eeprom24c0x_t;
135

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

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

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

    
222
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
223
{
224
    MaltaFPGAState *s = opaque;
225
    uint32_t val = 0;
226
    uint32_t saddr;
227

    
228
    saddr = (addr & 0xfffff);
229

    
230
    switch (saddr) {
231

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

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

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

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

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

    
261
    /* UART Registers are handled directly by the serial device */
262

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

    
268
    /* XXX: implement a real I2C controller */
269

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

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

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

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

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

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

    
309
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
310
                              uint32_t val)
311
{
312
    MaltaFPGAState *s = opaque;
313
    uint32_t saddr;
314

    
315
    saddr = (addr & 0xfffff);
316

    
317
    switch (saddr) {
318

    
319
    /* SWITCH Register */
320
    case 0x00200:
321
        break;
322

    
323
    /* JMPRS Register */
324
    case 0x00210:
325
        break;
326

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

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

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

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

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

    
363
    /* UART Registers are handled directly by the serial device */
364

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

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

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

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

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

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

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

    
407
static void malta_fpga_reset(void *opaque)
408
{
409
    MaltaFPGAState *s = opaque;
410

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

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

    
423
static void malta_fpga_uart_init(CharDriverState *chr)
424
{
425
    qemu_chr_printf(chr, "CBUS UART\r\n");
426
}
427

    
428
static void malta_fpga_led_init(CharDriverState *chr)
429
{
430
    qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
431
    qemu_chr_printf(chr, "+--------+\r\n");
432
    qemu_chr_printf(chr, "+        +\r\n");
433
    qemu_chr_printf(chr, "+--------+\r\n");
434
    qemu_chr_printf(chr, "\n");
435
    qemu_chr_printf(chr, "Malta ASCII\r\n");
436
    qemu_chr_printf(chr, "+--------+\r\n");
437
    qemu_chr_printf(chr, "+        +\r\n");
438
    qemu_chr_printf(chr, "+--------+\r\n");
439
}
440

    
441
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
442
{
443
    MaltaFPGAState *s;
444
    CharDriverState *uart_chr;
445
    int malta;
446

    
447
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
448

    
449
    malta = cpu_register_io_memory(0, malta_fpga_read,
450
                                   malta_fpga_write, s);
451

    
452
    cpu_register_physical_memory(base, 0x900, malta);
453
    /* 0xa00 is less than a page, so will still get the right offsets.  */
454
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
455

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

    
458
    uart_chr = qemu_chr_open("cbus", "vc:80Cx24C", malta_fpga_uart_init);
459
    s->uart =
460
        serial_mm_init(base + 0x900, 3, env->irq[2], 230400, uart_chr, 1);
461

    
462
    malta_fpga_reset(s);
463
    qemu_register_reset(malta_fpga_reset, s);
464

    
465
    return s;
466
}
467

    
468
/* Audio support */
469
#ifdef HAS_AUDIO
470
static void audio_init (PCIBus *pci_bus)
471
{
472
    struct soundhw *c;
473
    int audio_enabled = 0;
474

    
475
    for (c = soundhw; !audio_enabled && c->name; ++c) {
476
        audio_enabled = c->enabled;
477
    }
478

    
479
    if (audio_enabled) {
480
        AudioState *s;
481

    
482
        s = AUD_init ();
483
        if (s) {
484
            for (c = soundhw; c->name; ++c) {
485
                if (c->enabled)
486
                    c->init.init_pci (pci_bus, s);
487
            }
488
        }
489
    }
490
}
491
#endif
492

    
493
/* Network support */
494
static void network_init (PCIBus *pci_bus)
495
{
496
    int i;
497

    
498
    for(i = 0; i < nb_nics; i++) {
499
        NICInfo *nd = &nd_table[i];
500
        int devfn = -1;
501

    
502
        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
503
            /* The malta board has a PCNet card using PCI SLOT 11 */
504
            devfn = 88;
505

    
506
        pci_nic_init(pci_bus, nd, devfn, "pcnet");
507
    }
508
}
509

    
510
/* ROM and pseudo bootloader
511

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

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

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

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

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

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

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

    
556

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

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

    
572
#ifdef TARGET_WORDS_BIGENDIAN
573
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
574
#else
575
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
576
#endif
577
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
578

    
579
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
580

    
581
#ifdef TARGET_WORDS_BIGENDIAN
582
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
583
#else
584
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
585
#endif
586
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
587
#ifdef TARGET_WORDS_BIGENDIAN
588
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
589
#else
590
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
591
#endif
592
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
593

    
594
#ifdef TARGET_WORDS_BIGENDIAN
595
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
596
#else
597
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
598
#endif
599
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
600
#ifdef TARGET_WORDS_BIGENDIAN
601
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
602
#else
603
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
604
#endif
605
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
606

    
607
#ifdef TARGET_WORDS_BIGENDIAN
608
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
609
#else
610
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
611
#endif
612
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
613
#ifdef TARGET_WORDS_BIGENDIAN
614
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
615
#else
616
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
617
#endif
618
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
619

    
620
    /* Jump to kernel code */
621
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
622
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
623
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
624
    stl_raw(p++, 0x00000000);                                      /* nop */
625

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

    
669
}
670

    
671
static void prom_set(int index, const char *string, ...)
672
{
673
    va_list ap;
674
    int32_t *p;
675
    int32_t table_addr;
676
    char *s;
677

    
678
    if (index >= ENVP_NB_ENTRIES)
679
        return;
680

    
681
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
682
    p += index;
683

    
684
    if (string == NULL) {
685
        stl_raw(p, 0);
686
        return;
687
    }
688

    
689
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
690
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
691

    
692
    stl_raw(p, table_addr);
693

    
694
    va_start(ap, string);
695
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
696
    va_end(ap);
697
}
698

    
699
/* Kernel */
700
static int64_t load_kernel (CPUState *env)
701
{
702
    int64_t kernel_entry, kernel_low, kernel_high;
703
    int index = 0;
704
    long initrd_size;
705
    ram_addr_t initrd_offset;
706

    
707
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
708
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
709
                 (uint64_t *)&kernel_high) < 0) {
710
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
711
                loaderparams.kernel_filename);
712
        exit(1);
713
    }
714

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

    
738
    /* Store command line.  */
739
    prom_set(index++, loaderparams.kernel_filename);
740
    if (initrd_size > 0)
741
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
742
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
743
                 loaderparams.kernel_cmdline);
744
    else
745
        prom_set(index++, loaderparams.kernel_cmdline);
746

    
747
    /* Setup minimum environment variables */
748
    prom_set(index++, "memsize");
749
    prom_set(index++, "%i", loaderparams.ram_size);
750
    prom_set(index++, "modetty0");
751
    prom_set(index++, "38400n8r");
752
    prom_set(index++, NULL);
753

    
754
    return kernel_entry;
755
}
756

    
757
static void main_cpu_reset(void *opaque)
758
{
759
    CPUState *env = opaque;
760
    cpu_reset(env);
761

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

    
771
static
772
void mips_malta_init (ram_addr_t ram_size, int vga_ram_size,
773
                      const char *boot_device,
774
                      const char *kernel_filename, const char *kernel_cmdline,
775
                      const char *initrd_filename, const char *cpu_model)
776
{
777
    char buf[1024];
778
    unsigned long bios_offset;
779
    target_long bios_size;
780
    int64_t kernel_entry;
781
    PCIBus *pci_bus;
782
    CPUState *env;
783
    RTCState *rtc_state;
784
    fdctrl_t *floppy_controller;
785
    MaltaFPGAState *malta_fpga;
786
    qemu_irq *i8259;
787
    int piix4_devfn;
788
    uint8_t *eeprom_buf;
789
    i2c_bus *smbus;
790
    int i;
791
    int index;
792
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
793
    BlockDriverState *fd[MAX_FD];
794
    int fl_idx = 0;
795
    int fl_sectors = 0;
796

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

    
812
    /* allocate RAM */
813
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
814

    
815
    /* Map the bios at two physical locations, as on the real board. */
816
    bios_offset = ram_size + vga_ram_size;
817
    cpu_register_physical_memory(0x1e000000LL,
818
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
819
    cpu_register_physical_memory(0x1fc00000LL,
820
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
821

    
822
    /* FPGA */
823
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
824

    
825
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
826
    if (kernel_filename) {
827
        /* Write a small bootloader to the flash location. */
828
        loaderparams.ram_size = ram_size;
829
        loaderparams.kernel_filename = kernel_filename;
830
        loaderparams.kernel_cmdline = kernel_cmdline;
831
        loaderparams.initrd_filename = initrd_filename;
832
        kernel_entry = load_kernel(env);
833
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
834
        write_bootloader(env, bios_offset, kernel_entry);
835
    } else {
836
        index = drive_get_index(IF_PFLASH, 0, fl_idx);
837
        if (index != -1) {
838
            /* Load firmware from flash. */
839
            bios_size = 0x400000;
840
            fl_sectors = bios_size >> 16;
841
#ifdef DEBUG_BOARD_INIT
842
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
843
                   "offset %08lx addr %08llx '%s' %x\n",
844
                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
845
                   bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
846
#endif
847
            pflash_cfi01_register(0x1e000000LL, bios_offset,
848
                                  drives_table[index].bdrv, 65536, fl_sectors,
849
                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
850
            fl_idx++;
851
        } else {
852
            /* Load a BIOS image. */
853
            if (bios_name == NULL)
854
                bios_name = BIOS_FILENAME;
855
            snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
856
            bios_size = load_image(buf, phys_ram_base + bios_offset);
857
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
858
                fprintf(stderr,
859
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
860
                        buf);
861
                exit(1);
862
            }
863
        }
864
        /* In little endian mode the 32bit words in the bios are swapped,
865
           a neat trick which allows bi-endian firmware. */
866
#ifndef TARGET_WORDS_BIGENDIAN
867
        {
868
            uint32_t *addr;
869
            for (addr = (uint32_t *)(phys_ram_base + bios_offset);
870
                 addr < (uint32_t *)(phys_ram_base + bios_offset + bios_size);
871
                 addr++) {
872
                *addr = bswap32(*addr);
873
            }
874
        }
875
#endif
876
    }
877

    
878
    /* Board ID = 0x420 (Malta Board with CoreLV)
879
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
880
       map to the board ID. */
881
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
882

    
883
    /* Init internal devices */
884
    cpu_mips_irq_init_cpu(env);
885
    cpu_mips_clock_init(env);
886

    
887
    /* Interrupt controller */
888
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
889
    i8259 = i8259_init(env->irq[2]);
890

    
891
    /* Northbridge */
892
    pci_bus = pci_gt64120_init(i8259);
893

    
894
    /* Southbridge */
895

    
896
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
897
        fprintf(stderr, "qemu: too many IDE bus\n");
898
        exit(1);
899
    }
900

    
901
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
902
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
903
        if (index != -1)
904
            hd[i] = drives_table[index].bdrv;
905
        else
906
            hd[i] = NULL;
907
    }
908

    
909
    piix4_devfn = piix4_init(pci_bus, 80);
910
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
911
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
912
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, i8259[9]);
913
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
914
    for (i = 0; i < 8; i++) {
915
        /* TODO: Populate SPD eeprom data.  */
916
        smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
917
    }
918
    pit = pit_init(0x40, i8259[0]);
919
    DMA_init(0);
920

    
921
    /* Super I/O */
922
    i8042_init(i8259[1], i8259[12], 0x60);
923
    rtc_state = rtc_init(0x70, i8259[8]);
924
    if (serial_hds[0])
925
        serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
926
    if (serial_hds[1])
927
        serial_init(0x2f8, i8259[3], 115200, serial_hds[1]);
928
    if (parallel_hds[0])
929
        parallel_init(0x378, i8259[7], parallel_hds[0]);
930
    for(i = 0; i < MAX_FD; i++) {
931
        index = drive_get_index(IF_FLOPPY, 0, i);
932
       if (index != -1)
933
           fd[i] = drives_table[index].bdrv;
934
       else
935
           fd[i] = NULL;
936
    }
937
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
938

    
939
    /* Sound card */
940
#ifdef HAS_AUDIO
941
    audio_init(pci_bus);
942
#endif
943

    
944
    /* Network card */
945
    network_init(pci_bus);
946

    
947
    /* Optional PCI video card */
948
    pci_cirrus_vga_init(pci_bus, phys_ram_base + ram_size,
949
                        ram_size, vga_ram_size);
950
}
951

    
952
QEMUMachine mips_malta_machine = {
953
    .name = "malta",
954
    .desc = "MIPS Malta Core LV",
955
    .init = mips_malta_init,
956
    .ram_require = VGA_RAM_SIZE + BIOS_SIZE,
957
    .nodisk_ok = 1,
958
};