Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 409dbce5

History | View | Annotate | Download (31.6 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 "usb-uhci.h"
36
#include "vmware_vga.h"
37
#include "qemu-char.h"
38
#include "sysemu.h"
39
#include "audio/audio.h"
40
#include "boards.h"
41
#include "qemu-log.h"
42
#include "mips-bios.h"
43
#include "ide.h"
44
#include "loader.h"
45
#include "elf.h"
46

    
47
//#define DEBUG_BOARD_INIT
48

    
49
#define ENVP_ADDR                0x80002000l
50
#define ENVP_NB_ENTRIES                 16
51
#define ENVP_ENTRY_SIZE                 256
52

    
53
#define MAX_IDE_BUS 2
54

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

    
68
static PITState *pit;
69

    
70
static struct _loaderparams {
71
    int ram_size;
72
    const char *kernel_filename;
73
    const char *kernel_cmdline;
74
    const char *initrd_filename;
75
} loaderparams;
76

    
77
/* Malta FPGA */
78
static void malta_fpga_update_display(void *opaque)
79
{
80
    char leds_text[9];
81
    int i;
82
    MaltaFPGAState *s = opaque;
83

    
84
    for (i = 7 ; i >= 0 ; i--) {
85
        if (s->leds & (1 << i))
86
            leds_text[i] = '#';
87
        else
88
            leds_text[i] = ' ';
89
    }
90
    leds_text[8] = '\0';
91

    
92
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
93
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
94
}
95

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

    
106
//~ #define DEBUG
107

    
108
#if defined(DEBUG)
109
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
110
#else
111
#  define logout(fmt, ...) ((void)0)
112
#endif
113

    
114
struct _eeprom24c0x_t {
115
  uint8_t tick;
116
  uint8_t address;
117
  uint8_t command;
118
  uint8_t ack;
119
  uint8_t scl;
120
  uint8_t sda;
121
  uint8_t data;
122
  //~ uint16_t size;
123
  uint8_t contents[256];
124
};
125

    
126
typedef struct _eeprom24c0x_t eeprom24c0x_t;
127

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

    
149
static uint8_t eeprom24c0x_read(void)
150
{
151
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
152
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
153
    return eeprom.sda;
154
}
155

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

    
214
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
215
{
216
    MaltaFPGAState *s = opaque;
217
    uint32_t val = 0;
218
    uint32_t saddr;
219

    
220
    saddr = (addr & 0xfffff);
221

    
222
    switch (saddr) {
223

    
224
    /* SWITCH Register */
225
    case 0x00200:
226
        val = 0x00000000;                /* All switches closed */
227
        break;
228

    
229
    /* STATUS Register */
230
    case 0x00208:
231
#ifdef TARGET_WORDS_BIGENDIAN
232
        val = 0x00000012;
233
#else
234
        val = 0x00000010;
235
#endif
236
        break;
237

    
238
    /* JMPRS Register */
239
    case 0x00210:
240
        val = 0x00;
241
        break;
242

    
243
    /* LEDBAR Register */
244
    case 0x00408:
245
        val = s->leds;
246
        break;
247

    
248
    /* BRKRES Register */
249
    case 0x00508:
250
        val = s->brk;
251
        break;
252

    
253
    /* UART Registers are handled directly by the serial device */
254

    
255
    /* GPOUT Register */
256
    case 0x00a00:
257
        val = s->gpout;
258
        break;
259

    
260
    /* XXX: implement a real I2C controller */
261

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

    
271
    /* I2CINP Register */
272
    case 0x00b00:
273
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
274
        break;
275

    
276
    /* I2COE Register */
277
    case 0x00b08:
278
        val = s->i2coe;
279
        break;
280

    
281
    /* I2COUT Register */
282
    case 0x00b10:
283
        val = s->i2cout;
284
        break;
285

    
286
    /* I2CSEL Register */
287
    case 0x00b18:
288
        val = s->i2csel;
289
        break;
290

    
291
    default:
292
#if 0
293
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
294
                addr);
295
#endif
296
        break;
297
    }
298
    return val;
299
}
300

    
301
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
302
                              uint32_t val)
303
{
304
    MaltaFPGAState *s = opaque;
305
    uint32_t saddr;
306

    
307
    saddr = (addr & 0xfffff);
308

    
309
    switch (saddr) {
310

    
311
    /* SWITCH Register */
312
    case 0x00200:
313
        break;
314

    
315
    /* JMPRS Register */
316
    case 0x00210:
317
        break;
318

    
319
    /* LEDBAR Register */
320
    /* XXX: implement a 8-LED array */
321
    case 0x00408:
322
        s->leds = val & 0xff;
323
        break;
324

    
325
    /* ASCIIWORD Register */
326
    case 0x00410:
327
        snprintf(s->display_text, 9, "%08X", val);
328
        malta_fpga_update_display(s);
329
        break;
330

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

    
344
    /* SOFTRES Register */
345
    case 0x00500:
346
        if (val == 0x42)
347
            qemu_system_reset_request ();
348
        break;
349

    
350
    /* BRKRES Register */
351
    case 0x00508:
352
        s->brk = val & 0xff;
353
        break;
354

    
355
    /* UART Registers are handled directly by the serial device */
356

    
357
    /* GPOUT Register */
358
    case 0x00a00:
359
        s->gpout = val & 0xff;
360
        break;
361

    
362
    /* I2COE Register */
363
    case 0x00b08:
364
        s->i2coe = val & 0x03;
365
        break;
366

    
367
    /* I2COUT Register */
368
    case 0x00b10:
369
        eeprom24c0x_write(val & 0x02, val & 0x01);
370
        s->i2cout = val;
371
        break;
372

    
373
    /* I2CSEL Register */
374
    case 0x00b18:
375
        s->i2csel = val & 0x01;
376
        break;
377

    
378
    default:
379
#if 0
380
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
381
                addr);
382
#endif
383
        break;
384
    }
385
}
386

    
387
static CPUReadMemoryFunc * const malta_fpga_read[] = {
388
   malta_fpga_readl,
389
   malta_fpga_readl,
390
   malta_fpga_readl
391
};
392

    
393
static CPUWriteMemoryFunc * const malta_fpga_write[] = {
394
   malta_fpga_writel,
395
   malta_fpga_writel,
396
   malta_fpga_writel
397
};
398

    
399
static void malta_fpga_reset(void *opaque)
400
{
401
    MaltaFPGAState *s = opaque;
402

    
403
    s->leds   = 0x00;
404
    s->brk    = 0x0a;
405
    s->gpout  = 0x00;
406
    s->i2cin  = 0x3;
407
    s->i2coe  = 0x0;
408
    s->i2cout = 0x3;
409
    s->i2csel = 0x1;
410

    
411
    s->display_text[8] = '\0';
412
    snprintf(s->display_text, 9, "        ");
413
}
414

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

    
428
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
429
{
430
    MaltaFPGAState *s;
431
    int malta;
432

    
433
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
434

    
435
    malta = cpu_register_io_memory(malta_fpga_read,
436
                                   malta_fpga_write, s);
437

    
438
    cpu_register_physical_memory(base, 0x900, malta);
439
    /* 0xa00 is less than a page, so will still get the right offsets.  */
440
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
441

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

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

    
446
    malta_fpga_reset(s);
447
    qemu_register_reset(malta_fpga_reset, s);
448

    
449
    return s;
450
}
451

    
452
/* Audio support */
453
#ifdef HAS_AUDIO
454
static void audio_init (PCIBus *pci_bus)
455
{
456
    struct soundhw *c;
457
    int audio_enabled = 0;
458

    
459
    for (c = soundhw; !audio_enabled && c->name; ++c) {
460
        audio_enabled = c->enabled;
461
    }
462

    
463
    if (audio_enabled) {
464
        for (c = soundhw; c->name; ++c) {
465
            if (c->enabled) {
466
                c->init.init_pci(pci_bus);
467
            }
468
        }
469
    }
470
}
471
#endif
472

    
473
/* Network support */
474
static void network_init(void)
475
{
476
    int i;
477

    
478
    for(i = 0; i < nb_nics; i++) {
479
        NICInfo *nd = &nd_table[i];
480
        const char *default_devaddr = NULL;
481

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

    
486
        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
487
    }
488
}
489

    
490
/* ROM and pseudo bootloader
491

492
   The following code implements a very very simple bootloader. It first
493
   loads the registers a0 to a3 to the values expected by the OS, and
494
   then jump at the kernel address.
495

496
   The bootloader should pass the locations of the kernel arguments and
497
   environment variables tables. Those tables contain the 32-bit address
498
   of NULL terminated strings. The environment variables table should be
499
   terminated by a NULL address.
500

501
   For a simpler implementation, the number of kernel arguments is fixed
502
   to two (the name of the kernel and the command line), and the two
503
   tables are actually the same one.
504

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

    
512
static void write_bootloader (CPUState *env, uint8_t *base,
513
                              int64_t kernel_entry)
514
{
515
    uint32_t *p;
516

    
517
    /* Small bootloader */
518
    p = (uint32_t *)base;
519
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
520
    stl_raw(p++, 0x00000000);                                      /* nop */
521

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

    
537

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

    
550
    /* Load BAR registers as done by YAMON */
551
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
552

    
553
#ifdef TARGET_WORDS_BIGENDIAN
554
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
555
#else
556
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
557
#endif
558
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
559

    
560
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
561

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

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

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

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

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

    
650
}
651

    
652
static void prom_set(uint32_t* prom_buf, int index, const char *string, ...)
653
{
654
    va_list ap;
655
    int32_t table_addr;
656

    
657
    if (index >= ENVP_NB_ENTRIES)
658
        return;
659

    
660
    if (string == NULL) {
661
        prom_buf[index] = 0;
662
        return;
663
    }
664

    
665
    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
666
    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
667

    
668
    va_start(ap, string);
669
    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
670
    va_end(ap);
671
}
672

    
673
/* Kernel */
674
static int64_t load_kernel (void)
675
{
676
    int64_t kernel_entry, kernel_high;
677
    long initrd_size;
678
    ram_addr_t initrd_offset;
679
    int big_endian;
680
    uint32_t *prom_buf;
681
    long prom_size;
682
    int prom_index = 0;
683

    
684
#ifdef TARGET_WORDS_BIGENDIAN
685
    big_endian = 1;
686
#else
687
    big_endian = 0;
688
#endif
689

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

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

    
722
    /* Setup prom parameters. */
723
    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
724
    prom_buf = qemu_malloc(prom_size);
725

    
726
    prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
727
    if (initrd_size > 0) {
728
        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
729
                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
730
                 loaderparams.kernel_cmdline);
731
    } else {
732
        prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
733
    }
734

    
735
    prom_set(prom_buf, prom_index++, "memsize");
736
    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
737
    prom_set(prom_buf, prom_index++, "modetty0");
738
    prom_set(prom_buf, prom_index++, "38400n8r");
739
    prom_set(prom_buf, prom_index++, NULL);
740

    
741
    rom_add_blob_fixed("prom", prom_buf, prom_size,
742
                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
743

    
744
    return kernel_entry;
745
}
746

    
747
static void main_cpu_reset(void *opaque)
748
{
749
    CPUState *env = opaque;
750
    cpu_reset(env);
751

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

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

    
788
    /* Make sure the first 3 serial ports are associated with a device. */
789
    for(i = 0; i < 3; i++) {
790
        if (!serial_hds[i]) {
791
            char label[32];
792
            snprintf(label, sizeof(label), "serial%d", i);
793
            serial_hds[i] = qemu_chr_open(label, "null", NULL);
794
        }
795
    }
796

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

    
812
    /* allocate RAM */
813
    if (ram_size > (256 << 20)) {
814
        fprintf(stderr,
815
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
816
                ((unsigned int)ram_size / (1 << 20)));
817
        exit(1);
818
    }
819
    ram_offset = qemu_ram_alloc(ram_size);
820
    bios_offset = qemu_ram_alloc(BIOS_SIZE);
821

    
822

    
823
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
824

    
825
    /* Map the bios at two physical locations, as on the real board. */
826
    cpu_register_physical_memory(0x1e000000LL,
827
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
828
    cpu_register_physical_memory(0x1fc00000LL,
829
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
830

    
831
    /* FPGA */
832
    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
833

    
834
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
835
    if (kernel_filename) {
836
        /* Write a small bootloader to the flash location. */
837
        loaderparams.ram_size = ram_size;
838
        loaderparams.kernel_filename = kernel_filename;
839
        loaderparams.kernel_cmdline = kernel_cmdline;
840
        loaderparams.initrd_filename = initrd_filename;
841
        kernel_entry = load_kernel();
842
        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
843
    } else {
844
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
845
        if (dinfo) {
846
            /* Load firmware from flash. */
847
            bios_size = 0x400000;
848
            fl_sectors = bios_size >> 16;
849
#ifdef DEBUG_BOARD_INIT
850
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
851
                   "offset %08lx addr %08llx '%s' %x\n",
852
                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
853
                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
854
#endif
855
            pflash_cfi01_register(0x1e000000LL, bios_offset,
856
                                  dinfo->bdrv, 65536, fl_sectors,
857
                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
858
            fl_idx++;
859
        } else {
860
            /* Load a BIOS image. */
861
            if (bios_name == NULL)
862
                bios_name = BIOS_FILENAME;
863
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
864
            if (filename) {
865
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
866
                                                BIOS_SIZE);
867
                qemu_free(filename);
868
            } else {
869
                bios_size = -1;
870
            }
871
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
872
                fprintf(stderr,
873
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
874
                        bios_name);
875
                exit(1);
876
            }
877
        }
878
        /* In little endian mode the 32bit words in the bios are swapped,
879
           a neat trick which allows bi-endian firmware. */
880
#ifndef TARGET_WORDS_BIGENDIAN
881
        {
882
            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
883
            uint32_t *end = addr + bios_size;
884
            while (addr < end) {
885
                bswap32s(addr);
886
            }
887
        }
888
#endif
889
    }
890

    
891
    /* Board ID = 0x420 (Malta Board with CoreLV)
892
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
893
       map to the board ID. */
894
    stl_phys(0x1fc00010LL, 0x00000420);
895

    
896
    /* Init internal devices */
897
    cpu_mips_irq_init_cpu(env);
898
    cpu_mips_clock_init(env);
899

    
900
    /* Interrupt controller */
901
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
902
    i8259 = i8259_init(env->irq[2]);
903

    
904
    /* Northbridge */
905
    pci_bus = pci_gt64120_init(i8259);
906

    
907
    /* Southbridge */
908

    
909
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
910
        fprintf(stderr, "qemu: too many IDE bus\n");
911
        exit(1);
912
    }
913

    
914
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
915
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
916
    }
917

    
918
    piix4_devfn = piix4_init(pci_bus, 80);
919
    isa_bus_irqs(i8259);
920
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
921
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
922
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9));
923
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
924
    for (i = 0; i < 8; i++) {
925
        /* TODO: Populate SPD eeprom data.  */
926
        DeviceState *eeprom;
927
        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
928
        qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
929
        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
930
        qdev_init_nofail(eeprom);
931
    }
932
    pit = pit_init(0x40, isa_reserve_irq(0));
933
    DMA_init(0);
934

    
935
    /* Super I/O */
936
    isa_dev = isa_create_simple("i8042");
937
 
938
    rtc_state = rtc_init(2000);
939
    serial_isa_init(0, serial_hds[0]);
940
    serial_isa_init(1, serial_hds[1]);
941
    if (parallel_hds[0])
942
        parallel_init(0, parallel_hds[0]);
943
    for(i = 0; i < MAX_FD; i++) {
944
        fd[i] = drive_get(IF_FLOPPY, 0, i);
945
    }
946
    floppy_controller = fdctrl_init_isa(fd);
947

    
948
    /* Sound card */
949
#ifdef HAS_AUDIO
950
    audio_init(pci_bus);
951
#endif
952

    
953
    /* Network card */
954
    network_init();
955

    
956
    /* Optional PCI video card */
957
    if (cirrus_vga_enabled) {
958
        pci_cirrus_vga_init(pci_bus);
959
    } else if (vmsvga_enabled) {
960
        pci_vmsvga_init(pci_bus);
961
    } else if (std_vga_enabled) {
962
        pci_vga_init(pci_bus, 0, 0);
963
    }
964
}
965

    
966
static QEMUMachine mips_malta_machine = {
967
    .name = "malta",
968
    .desc = "MIPS Malta Core LV",
969
    .init = mips_malta_init,
970
    .is_default = 1,
971
};
972

    
973
static void mips_malta_machine_init(void)
974
{
975
    qemu_register_machine(&mips_malta_machine);
976
}
977

    
978
machine_init(mips_malta_machine_init);