Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 87ee1669

History | View | Annotate | Download (28.9 kB)

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

    
25
#include "vl.h"
26

    
27
#ifdef TARGET_WORDS_BIGENDIAN
28
#define BIOS_FILENAME "mips_bios.bin"
29
#else
30
#define BIOS_FILENAME "mipsel_bios.bin"
31
#endif
32

    
33
#ifdef TARGET_MIPS64
34
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
35
#else
36
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
37
#endif
38

    
39
#define ENVP_ADDR (int32_t)0x80002000
40
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
41

    
42
#define ENVP_NB_ENTRIES                 16
43
#define ENVP_ENTRY_SIZE                 256
44

    
45
extern int nographic;
46
extern FILE *logfile;
47

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

    
61
static PITState *pit;
62

    
63
/* Malta FPGA */
64
static void malta_fpga_update_display(void *opaque)
65
{
66
    char leds_text[9];
67
    int i;
68
    MaltaFPGAState *s = opaque;
69

    
70
    if (!nographic) {
71
        for (i = 7 ; i >= 0 ; i--) {
72
            if (s->leds & (1 << i))
73
                leds_text[i] = '#';
74
            else
75
                leds_text[i] = ' ';
76
        }
77
        leds_text[8] = '\0';
78

    
79
        qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
80
        qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
81
    }
82
}
83

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

    
94
//~ #define DEBUG
95

    
96
#if defined(DEBUG)
97
#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
98
#else
99
#  define logout(fmt, args...) ((void)0)
100
#endif
101

    
102
struct _eeprom24c0x_t {
103
  uint8_t tick;
104
  uint8_t address;
105
  uint8_t command;
106
  uint8_t ack;
107
  uint8_t scl;
108
  uint8_t sda;
109
  uint8_t data;
110
  //~ uint16_t size;
111
  uint8_t contents[256];
112
};
113

    
114
typedef struct _eeprom24c0x_t eeprom24c0x_t;
115

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

    
137
static uint8_t eeprom24c0x_read()
138
{
139
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
140
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
141
    return eeprom.sda;
142
}
143

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

    
202
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
203
{
204
    MaltaFPGAState *s = opaque;
205
    uint32_t val = 0;
206
    uint32_t saddr;
207

    
208
    saddr = (addr & 0xfffff);
209

    
210
    switch (saddr) {
211

    
212
    /* SWITCH Register */
213
    case 0x00200:
214
        val = 0x00000000;                /* All switches closed */
215
        break;
216

    
217
    /* STATUS Register */
218
    case 0x00208:
219
#ifdef TARGET_WORDS_BIGENDIAN
220
        val = 0x00000012;
221
#else
222
        val = 0x00000010;
223
#endif
224
        break;
225

    
226
    /* JMPRS Register */
227
    case 0x00210:
228
        val = 0x00;
229
        break;
230

    
231
    /* LEDBAR Register */
232
    case 0x00408:
233
        val = s->leds;
234
        break;
235

    
236
    /* BRKRES Register */
237
    case 0x00508:
238
        val = s->brk;
239
        break;
240

    
241
    /* UART Registers are handled directly by the serial device */
242

    
243
    /* GPOUT Register */
244
    case 0x00a00:
245
        val = s->gpout;
246
        break;
247

    
248
    /* XXX: implement a real I2C controller */
249

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

    
259
    /* I2CINP Register */
260
    case 0x00b00:
261
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
262
        break;
263

    
264
    /* I2COE Register */
265
    case 0x00b08:
266
        val = s->i2coe;
267
        break;
268

    
269
    /* I2COUT Register */
270
    case 0x00b10:
271
        val = s->i2cout;
272
        break;
273

    
274
    /* I2CSEL Register */
275
    case 0x00b18:
276
        val = s->i2csel;
277
        break;
278

    
279
    default:
280
#if 0
281
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
282
                addr);
283
#endif
284
        break;
285
    }
286
    return val;
287
}
288

    
289
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
290
                              uint32_t val)
291
{
292
    MaltaFPGAState *s = opaque;
293
    uint32_t saddr;
294

    
295
    saddr = (addr & 0xfffff);
296

    
297
    switch (saddr) {
298

    
299
    /* SWITCH Register */
300
    case 0x00200:
301
        break;
302

    
303
    /* JMPRS Register */
304
    case 0x00210:
305
        break;
306

    
307
    /* LEDBAR Register */
308
    /* XXX: implement a 8-LED array */
309
    case 0x00408:
310
        s->leds = val & 0xff;
311
        break;
312

    
313
    /* ASCIIWORD Register */
314
    case 0x00410:
315
        snprintf(s->display_text, 9, "%08X", val);
316
        malta_fpga_update_display(s);
317
        break;
318

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

    
332
    /* SOFTRES Register */
333
    case 0x00500:
334
        if (val == 0x42)
335
            qemu_system_reset_request ();
336
        break;
337

    
338
    /* BRKRES Register */
339
    case 0x00508:
340
        s->brk = val & 0xff;
341
        break;
342

    
343
    /* UART Registers are handled directly by the serial device */
344

    
345
    /* GPOUT Register */
346
    case 0x00a00:
347
        s->gpout = val & 0xff;
348
        break;
349

    
350
    /* I2COE Register */
351
    case 0x00b08:
352
        s->i2coe = val & 0x03;
353
        break;
354

    
355
    /* I2COUT Register */
356
    case 0x00b10:
357
        eeprom24c0x_write(val & 0x02, val & 0x01);
358
        s->i2cout = val;
359
        break;
360

    
361
    /* I2CSEL Register */
362
    case 0x00b18:
363
        s->i2csel = val & 0x01;
364
        break;
365

    
366
    default:
367
#if 0
368
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
369
                addr);
370
#endif
371
        break;
372
    }
373
}
374

    
375
static CPUReadMemoryFunc *malta_fpga_read[] = {
376
   malta_fpga_readl,
377
   malta_fpga_readl,
378
   malta_fpga_readl
379
};
380

    
381
static CPUWriteMemoryFunc *malta_fpga_write[] = {
382
   malta_fpga_writel,
383
   malta_fpga_writel,
384
   malta_fpga_writel
385
};
386

    
387
void malta_fpga_reset(void *opaque)
388
{
389
    MaltaFPGAState *s = opaque;
390

    
391
    s->leds   = 0x00;
392
    s->brk    = 0x0a;
393
    s->gpout  = 0x00;
394
    s->i2cin  = 0x3;
395
    s->i2coe  = 0x0;
396
    s->i2cout = 0x3;
397
    s->i2csel = 0x1;
398

    
399
    s->display_text[8] = '\0';
400
    snprintf(s->display_text, 9, "        ");
401
    malta_fpga_update_display(s);
402
}
403

    
404
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
405
{
406
    MaltaFPGAState *s;
407
    CharDriverState *uart_chr;
408
    int malta;
409

    
410
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
411

    
412
    malta = cpu_register_io_memory(0, malta_fpga_read,
413
                                   malta_fpga_write, s);
414

    
415
    cpu_register_physical_memory(base, 0x900, malta);
416
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
417

    
418
    if (!nographic) {
419
        s->display = qemu_chr_open("vc");
420
        qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
421
        qemu_chr_printf(s->display, "+--------+\r\n");
422
        qemu_chr_printf(s->display, "+        +\r\n");
423
        qemu_chr_printf(s->display, "+--------+\r\n");
424
        qemu_chr_printf(s->display, "\n");
425
        qemu_chr_printf(s->display, "Malta ASCII\r\n");
426
        qemu_chr_printf(s->display, "+--------+\r\n");
427
        qemu_chr_printf(s->display, "+        +\r\n");
428
        qemu_chr_printf(s->display, "+--------+\r\n");
429

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

    
435
    malta_fpga_reset(s);
436
    qemu_register_reset(malta_fpga_reset, s);
437

    
438
    return s;
439
}
440

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

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

    
452
    if (audio_enabled) {
453
        AudioState *s;
454

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

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

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

    
486
/* ROM and pseudo bootloader
487

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

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

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

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

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

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

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

    
532

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

    
545
    /* Load BAR registers as done by YAMON */
546
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
547

    
548
#ifdef TARGET_WORDS_BIGENDIAN
549
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
550
#else
551
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
552
#endif
553
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
554
#ifdef TARGET_WORDS_BIGENDIAN
555
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
556
#else
557
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
558
#endif
559
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
560

    
561
#ifdef TARGET_WORDS_BIGENDIAN
562
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
563
#else
564
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
565
#endif
566
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
567
#ifdef TARGET_WORDS_BIGENDIAN
568
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
569
#else
570
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
571
#endif
572
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
573

    
574
#ifdef TARGET_WORDS_BIGENDIAN
575
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
576
#else
577
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
578
#endif
579
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
580
#ifdef TARGET_WORDS_BIGENDIAN
581
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
582
#else
583
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
584
#endif
585
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
586

    
587
    /* Jump to kernel code */
588
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
589
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
590
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
591
    stl_raw(p++, 0x00000000);                                      /* nop */
592

    
593
    /* YAMON subroutines */
594
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
595
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
596
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
597
   /* 808 YAMON print */
598
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
599
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
600
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
601
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
602
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
603
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
604
    stl_raw(p++, 0x00000000);                                     /* nop */
605
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
606
    stl_raw(p++, 0x00000000);                                     /* nop */
607
    stl_raw(p++, 0x08000205);                                     /* j 814 */
608
    stl_raw(p++, 0x00000000);                                     /* nop */
609
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
610
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
611
    /* 0x83c YAMON print_count */
612
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
613
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
614
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
615
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
616
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
617
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
618
    stl_raw(p++, 0x00000000);                                     /* nop */
619
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
620
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
621
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
622
    stl_raw(p++, 0x00000000);                                     /* nop */
623
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
624
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
625
    /* 0x870 */
626
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
627
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
628
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
629
    stl_raw(p++, 0x00000000);                                     /* nop */
630
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
631
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
632
    stl_raw(p++, 0x00000000);                                     /* nop */
633
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
634
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
635

    
636
}
637

    
638
static void prom_set(int index, const char *string, ...)
639
{
640
    va_list ap;
641
    int32_t *p;
642
    int32_t table_addr;
643
    char *s;
644

    
645
    if (index >= ENVP_NB_ENTRIES)
646
        return;
647

    
648
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
649
    p += index;
650

    
651
    if (string == NULL) {
652
        stl_raw(p, 0);
653
        return;
654
    }
655

    
656
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
657
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
658

    
659
    stl_raw(p, table_addr);
660

    
661
    va_start(ap, string);
662
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
663
    va_end(ap);
664
}
665

    
666
/* Kernel */
667
static int64_t load_kernel (CPUState *env)
668
{
669
    int64_t kernel_entry, kernel_low, kernel_high;
670
    int index = 0;
671
    long initrd_size;
672
    ram_addr_t initrd_offset;
673

    
674
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
675
                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
676
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
677
                env->kernel_filename);
678
        exit(1);
679
    }
680

    
681
    /* load initrd */
682
    initrd_size = 0;
683
    initrd_offset = 0;
684
    if (env->initrd_filename) {
685
        initrd_size = get_image_size (env->initrd_filename);
686
        if (initrd_size > 0) {
687
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
688
            if (initrd_offset + initrd_size > env->ram_size) {
689
                fprintf(stderr,
690
                        "qemu: memory too small for initial ram disk '%s'\n",
691
                        env->initrd_filename);
692
                exit(1);
693
            }
694
            initrd_size = load_image(env->initrd_filename,
695
                                     phys_ram_base + initrd_offset);
696
        }
697
        if (initrd_size == (target_ulong) -1) {
698
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
699
                    env->initrd_filename);
700
            exit(1);
701
        }
702
    }
703

    
704
    /* Store command line.  */
705
    prom_set(index++, env->kernel_filename);
706
    if (initrd_size > 0)
707
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
708
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
709
                 env->kernel_cmdline);
710
    else
711
        prom_set(index++, env->kernel_cmdline);
712

    
713
    /* Setup minimum environment variables */
714
    prom_set(index++, "memsize");
715
    prom_set(index++, "%i", env->ram_size);
716
    prom_set(index++, "modetty0");
717
    prom_set(index++, "38400n8r");
718
    prom_set(index++, NULL);
719

    
720
    return kernel_entry;
721
}
722

    
723
static void main_cpu_reset(void *opaque)
724
{
725
    CPUState *env = opaque;
726
    cpu_reset(env);
727
    cpu_mips_register(env, NULL);
728

    
729
    /* The bootload does not need to be rewritten as it is located in a
730
       read only location. The kernel location and the arguments table
731
       location does not change. */
732
    if (env->kernel_filename) {
733
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
734
        load_kernel (env);
735
    }
736
}
737

    
738
static
739
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
740
                      DisplayState *ds, const char **fd_filename, int snapshot,
741
                      const char *kernel_filename, const char *kernel_cmdline,
742
                      const char *initrd_filename, const char *cpu_model)
743
{
744
    char buf[1024];
745
    unsigned long bios_offset;
746
    int64_t kernel_entry;
747
    PCIBus *pci_bus;
748
    CPUState *env;
749
    RTCState *rtc_state;
750
    /* fdctrl_t *floppy_controller; */
751
    MaltaFPGAState *malta_fpga;
752
    int ret;
753
    mips_def_t *def;
754
    qemu_irq *i8259;
755
    int piix4_devfn;
756
    uint8_t *eeprom_buf;
757
    i2c_bus *smbus;
758
    int i;
759

    
760
    /* init CPUs */
761
    if (cpu_model == NULL) {
762
#ifdef TARGET_MIPS64
763
        cpu_model = "20Kc";
764
#else
765
        cpu_model = "24Kf";
766
#endif
767
    }
768
    if (mips_find_by_name(cpu_model, &def) != 0)
769
        def = NULL;
770
    env = cpu_init();
771
    cpu_mips_register(env, def);
772
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
773
    qemu_register_reset(main_cpu_reset, env);
774

    
775
    /* allocate RAM */
776
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
777

    
778
    /* Map the bios at two physical locations, as on the real board */
779
    bios_offset = ram_size + vga_ram_size;
780
    cpu_register_physical_memory(0x1e000000LL,
781
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
782
    cpu_register_physical_memory(0x1fc00000LL,
783
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
784

    
785
    /* FPGA */
786
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
787

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

    
812
    /* If a kernel image has been specified, write a small bootloader
813
       to the flash location. */
814
    if (kernel_filename) {
815
        env->ram_size = ram_size;
816
        env->kernel_filename = kernel_filename;
817
        env->kernel_cmdline = kernel_cmdline;
818
        env->initrd_filename = initrd_filename;
819
        kernel_entry = load_kernel(env);
820
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
821
        write_bootloader(env, bios_offset, kernel_entry);
822
    }
823

    
824
    /* Board ID = 0x420 (Malta Board with CoreLV)
825
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
826
       map to the board ID. */
827
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
828

    
829
    /* Init internal devices */
830
    cpu_mips_irq_init_cpu(env);
831
    cpu_mips_clock_init(env);
832
    cpu_mips_irqctrl_init();
833

    
834
    /* Interrupt controller */
835
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
836
    i8259 = i8259_init(env->irq[2]);
837

    
838
    /* Northbridge */
839
    pci_bus = pci_gt64120_init(i8259);
840

    
841
    /* Southbridge */
842
    piix4_devfn = piix4_init(pci_bus, 80);
843
    pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, i8259);
844
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
845
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
846
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
847
    for (i = 0; i < 8; i++) {
848
        /* TODO: Populate SPD eeprom data.  */
849
        smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
850
    }
851
    pit = pit_init(0x40, i8259[0]);
852
    DMA_init(0);
853

    
854
    /* Super I/O */
855
    i8042_init(i8259[1], i8259[12], 0x60);
856
    rtc_state = rtc_init(0x70, i8259[8]);
857
    if (serial_hds[0])
858
        serial_init(0x3f8, i8259[4], serial_hds[0]);
859
    if (serial_hds[1])
860
        serial_init(0x2f8, i8259[3], serial_hds[1]);
861
    if (parallel_hds[0])
862
        parallel_init(0x378, i8259[7], parallel_hds[0]);
863
    /* XXX: The floppy controller does not work correctly, something is
864
       probably wrong.
865
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
866

    
867
    /* Sound card */
868
#ifdef HAS_AUDIO
869
    audio_init(pci_bus);
870
#endif
871

    
872
    /* Network card */
873
    network_init(pci_bus);
874

    
875
    /* Optional PCI video card */
876
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
877
                        ram_size, vga_ram_size);
878
}
879

    
880
QEMUMachine mips_malta_machine = {
881
    "malta",
882
    "MIPS Malta Core LV",
883
    mips_malta_init,
884
};