Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ af655b6d

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

    
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
/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
64
static void pic_irq_request(void *opaque, int level)
65
{
66
    cpu_mips_irq_request(opaque, 2, level);
67
}
68

    
69
/* Malta FPGA */
70
static void malta_fpga_update_display(void *opaque)
71
{
72
    char leds_text[9];
73
    int i;
74
    MaltaFPGAState *s = opaque;
75

    
76
    for (i = 7 ; i >= 0 ; i--) {
77
        if (s->leds & (1 << i))
78
            leds_text[i] = '#';
79
        else
80
            leds_text[i] = ' ';
81
    }
82
    leds_text[8] = '\0';
83

    
84
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
85
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
86
}
87

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

    
98
//~ #define DEBUG
99

    
100
#if defined(DEBUG)
101
#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
102
#else
103
#  define logout(fmt, args...) ((void)0)
104
#endif
105

    
106
struct _eeprom24c0x_t {
107
  uint8_t tick;
108
  uint8_t address;
109
  uint8_t command;
110
  uint8_t ack;
111
  uint8_t scl;
112
  uint8_t sda;
113
  uint8_t data;
114
  //~ uint16_t size;
115
  uint8_t contents[256];
116
};
117

    
118
typedef struct _eeprom24c0x_t eeprom24c0x_t;
119

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

    
141
static uint8_t eeprom24c0x_read()
142
{
143
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
144
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
145
    return eeprom.sda;
146
}
147

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

    
206
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
207
{
208
    MaltaFPGAState *s = opaque;
209
    uint32_t val = 0;
210
    uint32_t saddr;
211

    
212
    saddr = (addr & 0xfffff);
213

    
214
    switch (saddr) {
215

    
216
    /* SWITCH Register */
217
    case 0x00200:
218
        val = 0x00000000;                /* All switches closed */
219
        break;
220

    
221
    /* STATUS Register */
222
    case 0x00208:
223
#ifdef TARGET_WORDS_BIGENDIAN
224
        val = 0x00000012;
225
#else
226
        val = 0x00000010;
227
#endif
228
        break;
229

    
230
    /* JMPRS Register */
231
    case 0x00210:
232
        val = 0x00;
233
        break;
234

    
235
    /* LEDBAR Register */
236
    case 0x00408:
237
        val = s->leds;
238
        break;
239

    
240
    /* BRKRES Register */
241
    case 0x00508:
242
        val = s->brk;
243
        break;
244

    
245
    /* UART Registers */
246
    case 0x00900:
247
    case 0x00908:
248
    case 0x00910:
249
    case 0x00918:
250
    case 0x00920:
251
    case 0x00928:
252
    case 0x00930:
253
    case 0x00938:
254
        val = serial_mm_readb(s->uart, addr);
255
        break;
256

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

    
262
    /* XXX: implement a real I2C controller */
263

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

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

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

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

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

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

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

    
309
    saddr = (addr & 0xfffff);
310

    
311
    switch (saddr) {
312

    
313
    /* SWITCH Register */
314
    case 0x00200:
315
        break;
316

    
317
    /* JMPRS Register */
318
    case 0x00210:
319
        break;
320

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

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

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

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

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

    
357
    /* UART Registers */
358
    case 0x00900:
359
    case 0x00908:
360
    case 0x00910:
361
    case 0x00918:
362
    case 0x00920:
363
    case 0x00928:
364
    case 0x00930:
365
    case 0x00938:
366
        serial_mm_writeb(s->uart, addr, val);
367
        break;
368

    
369
    /* GPOUT Register */
370
    case 0x00a00:
371
        s->gpout = val & 0xff;
372
        break;
373

    
374
    /* I2COE Register */
375
    case 0x00b08:
376
        s->i2coe = val & 0x03;
377
        break;
378

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

    
385
    /* I2CSEL Register */
386
    case 0x00b18:
387
        s->i2csel = val & 0x01;
388
        break;
389

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

    
399
static CPUReadMemoryFunc *malta_fpga_read[] = {
400
   malta_fpga_readl,
401
   malta_fpga_readl,
402
   malta_fpga_readl
403
};
404

    
405
static CPUWriteMemoryFunc *malta_fpga_write[] = {
406
   malta_fpga_writel,
407
   malta_fpga_writel,
408
   malta_fpga_writel
409
};
410

    
411
void malta_fpga_reset(void *opaque)
412
{
413
    MaltaFPGAState *s = opaque;
414

    
415
    s->leds   = 0x00;
416
    s->brk    = 0x0a;
417
    s->gpout  = 0x00;
418
    s->i2cin  = 0x3;
419
    s->i2coe  = 0x0;
420
    s->i2cout = 0x3;
421
    s->i2csel = 0x1;
422

    
423
    s->display_text[8] = '\0';
424
    snprintf(s->display_text, 9, "        ");
425
    malta_fpga_update_display(s);
426
}
427

    
428
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
429
{
430
    MaltaFPGAState *s;
431
    CharDriverState *uart_chr;
432
    int malta;
433

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

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

    
439
    cpu_register_physical_memory(base, 0x100000, malta);
440

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

    
452
    uart_chr = qemu_chr_open("vc");
453
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
454
    s->uart = serial_mm_init(&cpu_mips_irq_request, env, base, 3, 2,
455
                             uart_chr, 0);
456

    
457
    malta_fpga_reset(s);
458
    qemu_register_reset(malta_fpga_reset, s);
459

    
460
    return s;
461
}
462

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

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

    
474
    if (audio_enabled) {
475
        AudioState *s;
476

    
477
        s = AUD_init ();
478
        if (s) {
479
            for (c = soundhw; c->name; ++c) {
480
                if (c->enabled) {
481
                    if (c->isa) {
482
                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
483
                        exit(1);
484
                    }
485
                    else {
486
                        if (pci_bus) {
487
                            c->init.init_pci (pci_bus, s);
488
                        }
489
                    }
490
                }
491
            }
492
        }
493
    }
494
}
495
#endif
496

    
497
/* Network support */
498
static void network_init (PCIBus *pci_bus)
499
{
500
    int i;
501
    NICInfo *nd;
502

    
503
    for(i = 0; i < nb_nics; i++) {
504
        nd = &nd_table[i];
505
        if (!nd->model) {
506
            nd->model = "pcnet";
507
        }
508
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
509
            /* The malta board has a PCNet card using PCI SLOT 11 */
510
            pci_nic_init(pci_bus, nd, 88);
511
        } else {
512
            pci_nic_init(pci_bus, nd, -1);
513
        }
514
    }
515
}
516

    
517
/* ROM and pseudo bootloader
518

519
   The following code implements a very very simple bootloader. It first
520
   loads the registers a0 to a3 to the values expected by the OS, and
521
   then jump at the kernel address.
522

523
   The bootloader should pass the locations of the kernel arguments and
524
   environment variables tables. Those tables contain the 32-bit address
525
   of NULL terminated strings. The environment variables table should be
526
   terminated by a NULL address.
527

528
   For a simpler implementation, the number of kernel arguments is fixed
529
   to two (the name of the kernel and the command line), and the two
530
   tables are actually the same one.
531

532
   The registers a0 to a3 should contain the following values:
533
     a0 - number of kernel arguments
534
     a1 - 32-bit address of the kernel arguments table
535
     a2 - 32-bit address of the environment variables table
536
     a3 - RAM size in bytes
537
*/
538

    
539
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
540
{
541
    uint32_t *p;
542

    
543
    /* Small bootloader */
544
    p = (uint32_t *) (phys_ram_base + bios_offset);
545
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
546
    stl_raw(p++, 0x00000000);                                      /* nop */
547

    
548
    /* Second part of the bootloader */
549
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
550
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
551
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
552
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
553
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
554
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
555
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
556
    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
557
    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
558
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
559
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
560
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
561
    stl_raw(p++, 0x00000000);                                      /* nop */
562
}
563

    
564
static void prom_set(int index, const char *string, ...)
565
{
566
    va_list ap;
567
    int32_t *p;
568
    int32_t table_addr;
569
    char *s;
570

    
571
    if (index >= ENVP_NB_ENTRIES)
572
        return;
573

    
574
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
575
    p += index;
576

    
577
    if (string == NULL) {
578
        stl_raw(p, 0);
579
        return;
580
    }
581

    
582
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
583
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
584

    
585
    stl_raw(p, table_addr);
586

    
587
    va_start(ap, string);
588
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
589
    va_end(ap);
590
}
591

    
592
/* Kernel */
593
static int64_t load_kernel (CPUState *env)
594
{
595
    int64_t kernel_entry, kernel_low, kernel_high;
596
    int index = 0;
597
    long initrd_size;
598
    ram_addr_t initrd_offset;
599

    
600
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
601
                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
602
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
603
                env->kernel_filename);
604
      exit(1);
605
    }
606

    
607
    /* load initrd */
608
    initrd_size = 0;
609
    initrd_offset = 0;
610
    if (env->initrd_filename) {
611
        initrd_size = get_image_size (env->initrd_filename);
612
        if (initrd_size > 0) {
613
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
614
            if (initrd_offset + initrd_size > env->ram_size) {
615
                fprintf(stderr,
616
                        "qemu: memory too small for initial ram disk '%s'\n",
617
                        env->initrd_filename);
618
                exit(1);
619
            }
620
            initrd_size = load_image(env->initrd_filename,
621
                                     phys_ram_base + initrd_offset);
622
        }
623
        if (initrd_size == (target_ulong) -1) {
624
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
625
                    env->initrd_filename);
626
            exit(1);
627
        }
628
    }
629

    
630
    /* Store command line.  */
631
    prom_set(index++, env->kernel_filename);
632
    if (initrd_size > 0)
633
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
634
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
635
                 env->kernel_cmdline);
636
    else
637
        prom_set(index++, env->kernel_cmdline);
638

    
639
    /* Setup minimum environment variables */
640
    prom_set(index++, "memsize");
641
    prom_set(index++, "%i", env->ram_size);
642
    prom_set(index++, "modetty0");
643
    prom_set(index++, "38400n8r");
644
    prom_set(index++, NULL);
645

    
646
    return kernel_entry;
647
}
648

    
649
static void main_cpu_reset(void *opaque)
650
{
651
    CPUState *env = opaque;
652
    cpu_reset(env);
653

    
654
    /* The bootload does not need to be rewritten as it is located in a
655
       read only location. The kernel location and the arguments table
656
       location does not change. */
657
    if (env->kernel_filename)
658
        load_kernel (env);
659
}
660

    
661
static
662
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
663
                      DisplayState *ds, const char **fd_filename, int snapshot,
664
                      const char *kernel_filename, const char *kernel_cmdline,
665
                      const char *initrd_filename, const char *cpu_model)
666
{
667
    char buf[1024];
668
    unsigned long bios_offset;
669
    int64_t kernel_entry;
670
    PCIBus *pci_bus;
671
    CPUState *env;
672
    RTCState *rtc_state;
673
    /* fdctrl_t *floppy_controller; */
674
    MaltaFPGAState *malta_fpga;
675
    int ret;
676
    mips_def_t *def;
677

    
678
    /* init CPUs */
679
    if (cpu_model == NULL) {
680
#ifdef TARGET_MIPS64
681
        cpu_model = "R4000";
682
#else
683
        cpu_model = "4KEc";
684
#endif
685
    }
686
    if (mips_find_by_name(cpu_model, &def) != 0)
687
        def = NULL;
688
    env = cpu_init();
689
    cpu_mips_register(env, def);
690
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
691
    qemu_register_reset(main_cpu_reset, env);
692

    
693
    /* allocate RAM */
694
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
695

    
696
    /* Map the bios at two physical locations, as on the real board */
697
    bios_offset = ram_size + vga_ram_size;
698
    cpu_register_physical_memory(0x1e000000LL,
699
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
700
    cpu_register_physical_memory(0x1fc00000LL,
701
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
702

    
703
    /* Load a BIOS image except if a kernel image has been specified. In
704
       the later case, just write a small bootloader to the flash
705
       location. */
706
    if (kernel_filename) {
707
        env->ram_size = ram_size;
708
        env->kernel_filename = kernel_filename;
709
        env->kernel_cmdline = kernel_cmdline;
710
        env->initrd_filename = initrd_filename;
711
        kernel_entry = load_kernel(env);
712
        write_bootloader(env, bios_offset, kernel_entry);
713
    } else {
714
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
715
        ret = load_image(buf, phys_ram_base + bios_offset);
716
        if (ret < 0 || ret > BIOS_SIZE) {
717
            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
718
                    buf);
719
            exit(1);
720
        }
721
    }
722

    
723
    /* Board ID = 0x420 (Malta Board with CoreLV)
724
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
725
       map to the board ID. */
726
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
727

    
728
    /* Init internal devices */
729
    cpu_mips_clock_init(env);
730
    cpu_mips_irqctrl_init();
731

    
732
    /* FPGA */
733
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
734

    
735
    /* Interrupt controller */
736
    isa_pic = pic_init(pic_irq_request, env);
737

    
738
    /* Northbridge */
739
    pci_bus = pci_gt64120_init(isa_pic);
740

    
741
    /* Southbridge */
742
    piix4_init(pci_bus, 80);
743
    pci_piix3_ide_init(pci_bus, bs_table, 81);
744
    usb_uhci_init(pci_bus, 82);
745
    piix4_pm_init(pci_bus, 83);
746
    pit = pit_init(0x40, 0);
747
    DMA_init(0);
748

    
749
    /* Super I/O */
750
    kbd_init();
751
    rtc_state = rtc_init(0x70, 8);
752
    if (serial_hds[0])
753
        serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
754
    if (serial_hds[1])
755
        serial_init(&pic_set_irq_new, isa_pic, 0x2f8, 3, serial_hds[1]);
756
    if (parallel_hds[0])
757
        parallel_init(0x378, 7, parallel_hds[0]);
758
    /* XXX: The floppy controller does not work correctly, something is
759
       probably wrong.
760
    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
761

    
762
    /* Sound card */
763
#ifdef HAS_AUDIO
764
    audio_init(pci_bus);
765
#endif
766

    
767
    /* Network card */
768
    network_init(pci_bus);
769

    
770
    /* Optional PCI video card */
771
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
772
                        ram_size, vga_ram_size);
773
}
774

    
775
QEMUMachine mips_malta_machine = {
776
    "malta",
777
    "MIPS Malta Core LV",
778
    mips_malta_init,
779
};