Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ b3c7724c

History | View | Annotate | Download (31.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 "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

    
40
//#define DEBUG_BOARD_INIT
41

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

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

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

    
57
#define ENVP_NB_ENTRIES                 16
58
#define ENVP_ENTRY_SIZE                 256
59

    
60
#define MAX_IDE_BUS 2
61

    
62
extern FILE *logfile;
63

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

    
77
static PITState *pit;
78

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

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

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

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

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

    
115
//~ #define DEBUG
116

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

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

    
135
typedef struct _eeprom24c0x_t eeprom24c0x_t;
136

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

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

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

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

    
229
    saddr = (addr & 0xfffff);
230

    
231
    switch (saddr) {
232

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
316
    saddr = (addr & 0xfffff);
317

    
318
    switch (saddr) {
319

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
425
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
426
{
427
    MaltaFPGAState *s;
428
    CharDriverState *uart_chr;
429
    int malta;
430

    
431
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
432

    
433
    malta = cpu_register_io_memory(0, malta_fpga_read,
434
                                   malta_fpga_write, s);
435

    
436
    cpu_register_physical_memory(base, 0x900, malta);
437
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
438

    
439
    s->display = qemu_chr_open("vc:320x200");
440
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
441
    qemu_chr_printf(s->display, "+--------+\r\n");
442
    qemu_chr_printf(s->display, "+        +\r\n");
443
    qemu_chr_printf(s->display, "+--------+\r\n");
444
    qemu_chr_printf(s->display, "\n");
445
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
446
    qemu_chr_printf(s->display, "+--------+\r\n");
447
    qemu_chr_printf(s->display, "+        +\r\n");
448
    qemu_chr_printf(s->display, "+--------+\r\n");
449

    
450
    uart_chr = qemu_chr_open("vc:80Cx24C");
451
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
452
    s->uart =
453
        serial_mm_init(base + 0x900, 3, env->irq[2], 230400, uart_chr, 1);
454

    
455
    malta_fpga_reset(s);
456
    qemu_register_reset(malta_fpga_reset, s);
457

    
458
    return s;
459
}
460

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

    
468
    for (c = soundhw; !audio_enabled && c->name; ++c) {
469
        audio_enabled = c->enabled;
470
    }
471

    
472
    if (audio_enabled) {
473
        AudioState *s;
474

    
475
        s = AUD_init ();
476
        if (s) {
477
            for (c = soundhw; c->name; ++c) {
478
                if (c->enabled)
479
                    c->init.init_pci (pci_bus, s);
480
            }
481
        }
482
    }
483
}
484
#endif
485

    
486
/* Network support */
487
static void network_init (PCIBus *pci_bus)
488
{
489
    int i;
490
    NICInfo *nd;
491

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

    
506
/* ROM and pseudo bootloader
507

508
   The following code implements a very very simple bootloader. It first
509
   loads the registers a0 to a3 to the values expected by the OS, and
510
   then jump at the kernel address.
511

512
   The bootloader should pass the locations of the kernel arguments and
513
   environment variables tables. Those tables contain the 32-bit address
514
   of NULL terminated strings. The environment variables table should be
515
   terminated by a NULL address.
516

517
   For a simpler implementation, the number of kernel arguments is fixed
518
   to two (the name of the kernel and the command line), and the two
519
   tables are actually the same one.
520

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

    
528
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
529
{
530
    uint32_t *p;
531

    
532
    /* Small bootloader */
533
    p = (uint32_t *) (phys_ram_base + bios_offset);
534
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
535
    stl_raw(p++, 0x00000000);                                      /* nop */
536

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

    
552

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

    
565
    /* Load BAR registers as done by YAMON */
566
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
567

    
568
#ifdef TARGET_WORDS_BIGENDIAN
569
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
570
#else
571
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
572
#endif
573
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
574

    
575
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
576

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

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

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

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

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

    
665
}
666

    
667
static void prom_set(int index, const char *string, ...)
668
{
669
    va_list ap;
670
    int32_t *p;
671
    int32_t table_addr;
672
    char *s;
673

    
674
    if (index >= ENVP_NB_ENTRIES)
675
        return;
676

    
677
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
678
    p += index;
679

    
680
    if (string == NULL) {
681
        stl_raw(p, 0);
682
        return;
683
    }
684

    
685
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
686
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
687

    
688
    stl_raw(p, table_addr);
689

    
690
    va_start(ap, string);
691
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
692
    va_end(ap);
693
}
694

    
695
/* Kernel */
696
static int64_t load_kernel (CPUState *env)
697
{
698
    int64_t kernel_entry, kernel_low, kernel_high;
699
    int index = 0;
700
    long initrd_size;
701
    ram_addr_t initrd_offset;
702

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

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

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

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

    
749
    return kernel_entry;
750
}
751

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

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

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

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

    
807
    /* allocate RAM */
808
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
809

    
810
    /* Map the bios at two physical locations, as on the real board. */
811
    bios_offset = ram_size + vga_ram_size;
812
    cpu_register_physical_memory(0x1e000000LL,
813
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
814
    cpu_register_physical_memory(0x1fc00000LL,
815
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
816

    
817
    /* FPGA */
818
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
819

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

    
873
    /* Board ID = 0x420 (Malta Board with CoreLV)
874
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
875
       map to the board ID. */
876
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
877

    
878
    /* Init internal devices */
879
    cpu_mips_irq_init_cpu(env);
880
    cpu_mips_clock_init(env);
881
    cpu_mips_irqctrl_init();
882

    
883
    /* Interrupt controller */
884
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
885
    i8259 = i8259_init(env->irq[2]);
886

    
887
    /* Northbridge */
888
    pci_bus = pci_gt64120_init(i8259);
889

    
890
    /* Southbridge */
891

    
892
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
893
        fprintf(stderr, "qemu: too many IDE bus\n");
894
        exit(1);
895
    }
896

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

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

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

    
935
    /* Sound card */
936
#ifdef HAS_AUDIO
937
    audio_init(pci_bus);
938
#endif
939

    
940
    /* Network card */
941
    network_init(pci_bus);
942

    
943
    /* Optional PCI video card */
944
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
945
                        ram_size, vga_ram_size);
946
}
947

    
948
QEMUMachine mips_malta_machine = {
949
    "malta",
950
    "MIPS Malta Core LV",
951
    mips_malta_init,
952
    VGA_RAM_SIZE + BIOS_SIZE,
953
};