Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 5fafdf24

History | View | Annotate | Download (29.1 kB)

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

    
25
#include "vl.h"
26

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

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

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

    
42
#define ENVP_NB_ENTRIES                 16
43
#define ENVP_ENTRY_SIZE                 256
44

    
45
extern FILE *logfile;
46

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

    
60
static PITState *pit;
61

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

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

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

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

    
91
//~ #define DEBUG
92

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

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

    
111
typedef struct _eeprom24c0x_t eeprom24c0x_t;
112

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

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

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

    
199
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
200
{
201
    MaltaFPGAState *s = opaque;
202
    uint32_t val = 0;
203
    uint32_t saddr;
204

    
205
    saddr = (addr & 0xfffff);
206

    
207
    switch (saddr) {
208

    
209
    /* SWITCH Register */
210
    case 0x00200:
211
        val = 0x00000000;                /* All switches closed */
212
        break;
213

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

    
223
    /* JMPRS Register */
224
    case 0x00210:
225
        val = 0x00;
226
        break;
227

    
228
    /* LEDBAR Register */
229
    case 0x00408:
230
        val = s->leds;
231
        break;
232

    
233
    /* BRKRES Register */
234
    case 0x00508:
235
        val = s->brk;
236
        break;
237

    
238
    /* UART Registers are handled directly by the serial device */
239

    
240
    /* GPOUT Register */
241
    case 0x00a00:
242
        val = s->gpout;
243
        break;
244

    
245
    /* XXX: implement a real I2C controller */
246

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

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

    
261
    /* I2COE Register */
262
    case 0x00b08:
263
        val = s->i2coe;
264
        break;
265

    
266
    /* I2COUT Register */
267
    case 0x00b10:
268
        val = s->i2cout;
269
        break;
270

    
271
    /* I2CSEL Register */
272
    case 0x00b18:
273
        val = s->i2csel;
274
        break;
275

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

    
286
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
287
                              uint32_t val)
288
{
289
    MaltaFPGAState *s = opaque;
290
    uint32_t saddr;
291

    
292
    saddr = (addr & 0xfffff);
293

    
294
    switch (saddr) {
295

    
296
    /* SWITCH Register */
297
    case 0x00200:
298
        break;
299

    
300
    /* JMPRS Register */
301
    case 0x00210:
302
        break;
303

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

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

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

    
329
    /* SOFTRES Register */
330
    case 0x00500:
331
        if (val == 0x42)
332
            qemu_system_reset_request ();
333
        break;
334

    
335
    /* BRKRES Register */
336
    case 0x00508:
337
        s->brk = val & 0xff;
338
        break;
339

    
340
    /* UART Registers are handled directly by the serial device */
341

    
342
    /* GPOUT Register */
343
    case 0x00a00:
344
        s->gpout = val & 0xff;
345
        break;
346

    
347
    /* I2COE Register */
348
    case 0x00b08:
349
        s->i2coe = val & 0x03;
350
        break;
351

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

    
358
    /* I2CSEL Register */
359
    case 0x00b18:
360
        s->i2csel = val & 0x01;
361
        break;
362

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

    
372
static CPUReadMemoryFunc *malta_fpga_read[] = {
373
   malta_fpga_readl,
374
   malta_fpga_readl,
375
   malta_fpga_readl
376
};
377

    
378
static CPUWriteMemoryFunc *malta_fpga_write[] = {
379
   malta_fpga_writel,
380
   malta_fpga_writel,
381
   malta_fpga_writel
382
};
383

    
384
void malta_fpga_reset(void *opaque)
385
{
386
    MaltaFPGAState *s = opaque;
387

    
388
    s->leds   = 0x00;
389
    s->brk    = 0x0a;
390
    s->gpout  = 0x00;
391
    s->i2cin  = 0x3;
392
    s->i2coe  = 0x0;
393
    s->i2cout = 0x3;
394
    s->i2csel = 0x1;
395

    
396
    s->display_text[8] = '\0';
397
    snprintf(s->display_text, 9, "        ");
398
    malta_fpga_update_display(s);
399
}
400

    
401
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
402
{
403
    MaltaFPGAState *s;
404
    CharDriverState *uart_chr;
405
    int malta;
406

    
407
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
408

    
409
    malta = cpu_register_io_memory(0, malta_fpga_read,
410
                                   malta_fpga_write, s);
411

    
412
    cpu_register_physical_memory(base, 0x900, malta);
413
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
414

    
415
    s->display = qemu_chr_open("vc");
416
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
417
    qemu_chr_printf(s->display, "+--------+\r\n");
418
    qemu_chr_printf(s->display, "+        +\r\n");
419
    qemu_chr_printf(s->display, "+--------+\r\n");
420
    qemu_chr_printf(s->display, "\n");
421
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
422
    qemu_chr_printf(s->display, "+--------+\r\n");
423
    qemu_chr_printf(s->display, "+        +\r\n");
424
    qemu_chr_printf(s->display, "+--------+\r\n");
425

    
426
    uart_chr = qemu_chr_open("vc");
427
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
428
    s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
429

    
430
    malta_fpga_reset(s);
431
    qemu_register_reset(malta_fpga_reset, s);
432

    
433
    return s;
434
}
435

    
436
/* Audio support */
437
#ifdef HAS_AUDIO
438
static void audio_init (PCIBus *pci_bus)
439
{
440
    struct soundhw *c;
441
    int audio_enabled = 0;
442

    
443
    for (c = soundhw; !audio_enabled && c->name; ++c) {
444
        audio_enabled = c->enabled;
445
    }
446

    
447
    if (audio_enabled) {
448
        AudioState *s;
449

    
450
        s = AUD_init ();
451
        if (s) {
452
            for (c = soundhw; c->name; ++c) {
453
                if (c->enabled)
454
                    c->init.init_pci (pci_bus, s);
455
            }
456
        }
457
    }
458
}
459
#endif
460

    
461
/* Network support */
462
static void network_init (PCIBus *pci_bus)
463
{
464
    int i;
465
    NICInfo *nd;
466

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

    
481
/* ROM and pseudo bootloader
482

483
   The following code implements a very very simple bootloader. It first
484
   loads the registers a0 to a3 to the values expected by the OS, and
485
   then jump at the kernel address.
486

487
   The bootloader should pass the locations of the kernel arguments and
488
   environment variables tables. Those tables contain the 32-bit address
489
   of NULL terminated strings. The environment variables table should be
490
   terminated by a NULL address.
491

492
   For a simpler implementation, the number of kernel arguments is fixed
493
   to two (the name of the kernel and the command line), and the two
494
   tables are actually the same one.
495

496
   The registers a0 to a3 should contain the following values:
497
     a0 - number of kernel arguments
498
     a1 - 32-bit address of the kernel arguments table
499
     a2 - 32-bit address of the environment variables table
500
     a3 - RAM size in bytes
501
*/
502

    
503
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
504
{
505
    uint32_t *p;
506

    
507
    /* Small bootloader */
508
    p = (uint32_t *) (phys_ram_base + bios_offset);
509
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
510
    stl_raw(p++, 0x00000000);                                      /* nop */
511

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

    
527

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

    
540
    /* Load BAR registers as done by YAMON */
541
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
542

    
543
#ifdef TARGET_WORDS_BIGENDIAN
544
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
545
#else
546
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
547
#endif
548
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
549

    
550
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
551

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

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

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

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

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

    
640
}
641

    
642
static void prom_set(int index, const char *string, ...)
643
{
644
    va_list ap;
645
    int32_t *p;
646
    int32_t table_addr;
647
    char *s;
648

    
649
    if (index >= ENVP_NB_ENTRIES)
650
        return;
651

    
652
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
653
    p += index;
654

    
655
    if (string == NULL) {
656
        stl_raw(p, 0);
657
        return;
658
    }
659

    
660
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
661
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
662

    
663
    stl_raw(p, table_addr);
664

    
665
    va_start(ap, string);
666
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
667
    va_end(ap);
668
}
669

    
670
/* Kernel */
671
static int64_t load_kernel (CPUState *env)
672
{
673
    int64_t kernel_entry, kernel_low, kernel_high;
674
    int index = 0;
675
    long initrd_size;
676
    ram_addr_t initrd_offset;
677

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

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

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

    
717
    /* Setup minimum environment variables */
718
    prom_set(index++, "memsize");
719
    prom_set(index++, "%i", env->ram_size);
720
    prom_set(index++, "modetty0");
721
    prom_set(index++, "38400n8r");
722
    prom_set(index++, NULL);
723

    
724
    return kernel_entry;
725
}
726

    
727
static void main_cpu_reset(void *opaque)
728
{
729
    CPUState *env = opaque;
730
    cpu_reset(env);
731
    cpu_mips_register(env, NULL);
732

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

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

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

    
779
    /* allocate RAM */
780
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
781

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

    
789
    /* FPGA */
790
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
791

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

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

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

    
833
    /* Init internal devices */
834
    cpu_mips_irq_init_cpu(env);
835
    cpu_mips_clock_init(env);
836
    cpu_mips_irqctrl_init();
837

    
838
    /* Interrupt controller */
839
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
840
    i8259 = i8259_init(env->irq[2]);
841

    
842
    /* Northbridge */
843
    pci_bus = pci_gt64120_init(i8259);
844

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

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

    
871
    /* Sound card */
872
#ifdef HAS_AUDIO
873
    audio_init(pci_bus);
874
#endif
875

    
876
    /* Network card */
877
    network_init(pci_bus);
878

    
879
    /* Optional PCI video card */
880
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
881
                        ram_size, vga_ram_size);
882
}
883

    
884
QEMUMachine mips_malta_machine = {
885
    "malta",
886
    "MIPS Malta Core LV",
887
    mips_malta_init,
888
};