Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 977e1244

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
#include "mips-bios.h"
41
#include "ide.h"
42

    
43
//#define DEBUG_BOARD_INIT
44

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

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

    
54
#define ENVP_NB_ENTRIES                 16
55
#define ENVP_ENTRY_SIZE                 256
56

    
57
#define MAX_IDE_BUS 2
58

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

    
72
static PITState *pit;
73

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

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

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

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

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

    
110
//~ #define DEBUG
111

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

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

    
130
typedef struct _eeprom24c0x_t eeprom24c0x_t;
131

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

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

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

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

    
224
    saddr = (addr & 0xfffff);
225

    
226
    switch (saddr) {
227

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
311
    saddr = (addr & 0xfffff);
312

    
313
    switch (saddr) {
314

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
432
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
433
{
434
    MaltaFPGAState *s;
435
    int malta;
436

    
437
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
438

    
439
    malta = cpu_register_io_memory(malta_fpga_read,
440
                                   malta_fpga_write, s);
441

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

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

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

    
450
    malta_fpga_reset(s);
451
    qemu_register_reset(malta_fpga_reset, s);
452

    
453
    return s;
454
}
455

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

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

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

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

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

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

    
490
        pci_nic_init(nd, "pcnet", default_devaddr);
491
    }
492
}
493

    
494
/* ROM and pseudo bootloader
495

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

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

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

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

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

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

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

    
541

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

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

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

    
564
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
565

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

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

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

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

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

    
654
}
655

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

    
663
    if (index >= ENVP_NB_ENTRIES)
664
        return;
665

    
666
    p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
667

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

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

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

    
683
/* Kernel */
684
static int64_t load_kernel (CPUState *env)
685
{
686
    int64_t kernel_entry, kernel_low, kernel_high;
687
    int index = 0;
688
    long initrd_size;
689
    ram_addr_t initrd_offset;
690

    
691
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
692
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
693
                 (uint64_t *)&kernel_high) < 0) {
694
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
695
                loaderparams.kernel_filename);
696
        exit(1);
697
    }
698

    
699
    /* load initrd */
700
    initrd_size = 0;
701
    initrd_offset = 0;
702
    if (loaderparams.initrd_filename) {
703
        initrd_size = get_image_size (loaderparams.initrd_filename);
704
        if (initrd_size > 0) {
705
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
706
            if (initrd_offset + initrd_size > ram_size) {
707
                fprintf(stderr,
708
                        "qemu: memory too small for initial ram disk '%s'\n",
709
                        loaderparams.initrd_filename);
710
                exit(1);
711
            }
712
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
713
                                              initrd_offset,
714
                                              ram_size - initrd_offset);
715
        }
716
        if (initrd_size == (target_ulong) -1) {
717
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
718
                    loaderparams.initrd_filename);
719
            exit(1);
720
        }
721
    }
722

    
723
    /* Store command line.  */
724
    prom_set(index++, loaderparams.kernel_filename);
725
    if (initrd_size > 0)
726
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
727
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
728
                 loaderparams.kernel_cmdline);
729
    else
730
        prom_set(index++, loaderparams.kernel_cmdline);
731

    
732
    /* Setup minimum environment variables */
733
    prom_set(index++, "memsize");
734
    prom_set(index++, "%i", loaderparams.ram_size);
735
    prom_set(index++, "modetty0");
736
    prom_set(index++, "38400n8r");
737
    prom_set(index++, NULL);
738

    
739
    return kernel_entry;
740
}
741

    
742
static void main_cpu_reset(void *opaque)
743
{
744
    CPUState *env = opaque;
745
    cpu_reset(env);
746

    
747
    /* The bootload does not need to be rewritten as it is located in a
748
       read only location. The kernel location and the arguments table
749
       location does not change. */
750
    if (loaderparams.kernel_filename) {
751
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
752
        load_kernel (env);
753
    }
754
}
755

    
756
static
757
void mips_malta_init (ram_addr_t ram_size,
758
                      const char *boot_device,
759
                      const char *kernel_filename, const char *kernel_cmdline,
760
                      const char *initrd_filename, const char *cpu_model)
761
{
762
    char *filename;
763
    ram_addr_t ram_offset;
764
    ram_addr_t bios_offset;
765
    target_long bios_size;
766
    int64_t kernel_entry;
767
    PCIBus *pci_bus;
768
    CPUState *env;
769
    RTCState *rtc_state;
770
    fdctrl_t *floppy_controller;
771
    MaltaFPGAState *malta_fpga;
772
    qemu_irq *i8259;
773
    int piix4_devfn;
774
    uint8_t *eeprom_buf;
775
    i2c_bus *smbus;
776
    int i;
777
    DriveInfo *dinfo;
778
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
779
    BlockDriverState *fd[MAX_FD];
780
    int fl_idx = 0;
781
    int fl_sectors = 0;
782

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

    
798
    /* allocate RAM */
799
    if (ram_size > (256 << 20)) {
800
        fprintf(stderr,
801
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
802
                ((unsigned int)ram_size / (1 << 20)));
803
        exit(1);
804
    }
805
    ram_offset = qemu_ram_alloc(ram_size);
806
    bios_offset = qemu_ram_alloc(BIOS_SIZE);
807

    
808

    
809
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
810

    
811
    /* Map the bios at two physical locations, as on the real board. */
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->irq[2], serial_hds[2]);
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, qemu_get_ram_ptr(bios_offset), kernel_entry);
830
    } else {
831
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
832
        if (dinfo) {
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(dinfo->bdrv), fl_sectors);
841
#endif
842
            pflash_cfi01_register(0x1e000000LL, bios_offset,
843
                                  dinfo->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
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
851
            if (filename) {
852
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
853
                                                BIOS_SIZE);
854
                qemu_free(filename);
855
            } else {
856
                bios_size = -1;
857
            }
858
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
859
                fprintf(stderr,
860
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
861
                        bios_name);
862
                exit(1);
863
            }
864
        }
865
        /* In little endian mode the 32bit words in the bios are swapped,
866
           a neat trick which allows bi-endian firmware. */
867
#ifndef TARGET_WORDS_BIGENDIAN
868
        {
869
            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
870
            uint32_t *end = addr + bios_size;
871
            while (addr < end) {
872
                bswap32s(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_phys(0x1fc00010LL, 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
        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
903
        hd[i] = dinfo ? dinfo->bdrv : NULL;
904
    }
905

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

    
922
    /* Super I/O */
923
    i8042_init(i8259[1], i8259[12], 0x60);
924
    rtc_state = rtc_init(0x70, i8259[8], 2000);
925
    serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
926
    serial_init(0x2f8, i8259[3], 115200, serial_hds[1]);
927
    if (parallel_hds[0])
928
        parallel_init(0x378, i8259[7], parallel_hds[0]);
929
    for(i = 0; i < MAX_FD; i++) {
930
        dinfo = drive_get(IF_FLOPPY, 0, i);
931
        fd[i] = dinfo ? dinfo->bdrv : NULL;
932
    }
933
    floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd);
934

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

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

    
943
    /* Optional PCI video card */
944
    if (cirrus_vga_enabled) {
945
        pci_cirrus_vga_init(pci_bus);
946
    } else if (vmsvga_enabled) {
947
        pci_vmsvga_init(pci_bus);
948
    } else if (std_vga_enabled) {
949
        pci_vga_init(pci_bus, 0, 0);
950
    }
951
}
952

    
953
static QEMUMachine mips_malta_machine = {
954
    .name = "malta",
955
    .desc = "MIPS Malta Core LV",
956
    .init = mips_malta_init,
957
    .is_default = 1,
958
};
959

    
960
static void mips_malta_machine_init(void)
961
{
962
    qemu_register_machine(&mips_malta_machine);
963
}
964

    
965
machine_init(mips_malta_machine_init);