Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 87ecb68b

History | View | Annotate | Download (29.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 "net.h"
28
#include "boards.h"
29
#include "smbus.h"
30
#include "mips.h"
31
#include "pci.h"
32
#include "qemu-char.h"
33
#include "sysemu.h"
34
#include "audio/audio.h"
35
#include "boards.h"
36

    
37
#ifdef TARGET_WORDS_BIGENDIAN
38
#define BIOS_FILENAME "mips_bios.bin"
39
#else
40
#define BIOS_FILENAME "mipsel_bios.bin"
41
#endif
42

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

    
49
#define ENVP_ADDR (int32_t)0x80002000
50
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
51

    
52
#define ENVP_NB_ENTRIES                 16
53
#define ENVP_ENTRY_SIZE                 256
54

    
55
extern FILE *logfile;
56

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

    
70
static PITState *pit;
71

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

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

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

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

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

    
108
//~ #define DEBUG
109

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

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

    
128
typedef struct _eeprom24c0x_t eeprom24c0x_t;
129

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

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

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

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

    
222
    saddr = (addr & 0xfffff);
223

    
224
    switch (saddr) {
225

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

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

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

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

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

    
255
    /* UART Registers are handled directly by the serial device */
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 are handled directly by the serial device */
358

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

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

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

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

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

    
389
static CPUReadMemoryFunc *malta_fpga_read[] = {
390
   malta_fpga_readl,
391
   malta_fpga_readl,
392
   malta_fpga_readl
393
};
394

    
395
static CPUWriteMemoryFunc *malta_fpga_write[] = {
396
   malta_fpga_writel,
397
   malta_fpga_writel,
398
   malta_fpga_writel
399
};
400

    
401
void malta_fpga_reset(void *opaque)
402
{
403
    MaltaFPGAState *s = opaque;
404

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

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

    
418
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
419
{
420
    MaltaFPGAState *s;
421
    CharDriverState *uart_chr;
422
    int malta;
423

    
424
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
425

    
426
    malta = cpu_register_io_memory(0, malta_fpga_read,
427
                                   malta_fpga_write, s);
428

    
429
    cpu_register_physical_memory(base, 0x900, malta);
430
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
431

    
432
    s->display = qemu_chr_open("vc");
433
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
434
    qemu_chr_printf(s->display, "+--------+\r\n");
435
    qemu_chr_printf(s->display, "+        +\r\n");
436
    qemu_chr_printf(s->display, "+--------+\r\n");
437
    qemu_chr_printf(s->display, "\n");
438
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
439
    qemu_chr_printf(s->display, "+--------+\r\n");
440
    qemu_chr_printf(s->display, "+        +\r\n");
441
    qemu_chr_printf(s->display, "+--------+\r\n");
442

    
443
    uart_chr = qemu_chr_open("vc");
444
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
445
    s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
446

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

    
450
    return s;
451
}
452

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

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

    
464
    if (audio_enabled) {
465
        AudioState *s;
466

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

    
478
/* Network support */
479
static void network_init (PCIBus *pci_bus)
480
{
481
    int i;
482
    NICInfo *nd;
483

    
484
    for(i = 0; i < nb_nics; i++) {
485
        nd = &nd_table[i];
486
        if (!nd->model) {
487
            nd->model = "pcnet";
488
        }
489
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
490
            /* The malta board has a PCNet card using PCI SLOT 11 */
491
            pci_nic_init(pci_bus, nd, 88);
492
        } else {
493
            pci_nic_init(pci_bus, nd, -1);
494
        }
495
    }
496
}
497

    
498
/* ROM and pseudo bootloader
499

500
   The following code implements a very very simple bootloader. It first
501
   loads the registers a0 to a3 to the values expected by the OS, and
502
   then jump at the kernel address.
503

504
   The bootloader should pass the locations of the kernel arguments and
505
   environment variables tables. Those tables contain the 32-bit address
506
   of NULL terminated strings. The environment variables table should be
507
   terminated by a NULL address.
508

509
   For a simpler implementation, the number of kernel arguments is fixed
510
   to two (the name of the kernel and the command line), and the two
511
   tables are actually the same one.
512

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

    
520
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
521
{
522
    uint32_t *p;
523

    
524
    /* Small bootloader */
525
    p = (uint32_t *) (phys_ram_base + bios_offset);
526
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
527
    stl_raw(p++, 0x00000000);                                      /* nop */
528

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

    
544

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

    
557
    /* Load BAR registers as done by YAMON */
558
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
559

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

    
567
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
568

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

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

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

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

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

    
657
}
658

    
659
static void prom_set(int index, const char *string, ...)
660
{
661
    va_list ap;
662
    int32_t *p;
663
    int32_t table_addr;
664
    char *s;
665

    
666
    if (index >= ENVP_NB_ENTRIES)
667
        return;
668

    
669
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
670
    p += index;
671

    
672
    if (string == NULL) {
673
        stl_raw(p, 0);
674
        return;
675
    }
676

    
677
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
678
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
679

    
680
    stl_raw(p, table_addr);
681

    
682
    va_start(ap, string);
683
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
684
    va_end(ap);
685
}
686

    
687
/* Kernel */
688
static int64_t load_kernel (CPUState *env)
689
{
690
    int64_t kernel_entry, kernel_low, kernel_high;
691
    int index = 0;
692
    long initrd_size;
693
    ram_addr_t initrd_offset;
694

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

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

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

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

    
741
    return kernel_entry;
742
}
743

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

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

    
758
static
759
void mips_malta_init (int ram_size, int vga_ram_size, const char *boot_device,
760
                      DisplayState *ds, const char **fd_filename, int snapshot,
761
                      const char *kernel_filename, const char *kernel_cmdline,
762
                      const char *initrd_filename, const char *cpu_model)
763
{
764
    char buf[1024];
765
    unsigned long bios_offset;
766
    int64_t kernel_entry;
767
    PCIBus *pci_bus;
768
    CPUState *env;
769
    RTCState *rtc_state;
770
    /* fdctrl_t *floppy_controller; */
771
    MaltaFPGAState *malta_fpga;
772
    int ret;
773
    qemu_irq *i8259;
774
    int piix4_devfn;
775
    uint8_t *eeprom_buf;
776
    i2c_bus *smbus;
777
    int i;
778

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

    
795
    /* allocate RAM */
796
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
797

    
798
    /* Map the bios at two physical locations, as on the real board */
799
    bios_offset = ram_size + vga_ram_size;
800
    cpu_register_physical_memory(0x1e000000LL,
801
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
802
    cpu_register_physical_memory(0x1fc00000LL,
803
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
804

    
805
    /* FPGA */
806
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
807

    
808
    /* Load a BIOS image unless a kernel image has been specified. */
809
    if (!kernel_filename) {
810
        if (bios_name == NULL)
811
            bios_name = BIOS_FILENAME;
812
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
813
        ret = load_image(buf, phys_ram_base + bios_offset);
814
        if (ret < 0 || ret > BIOS_SIZE) {
815
            fprintf(stderr,
816
                    "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
817
                    buf);
818
            exit(1);
819
        }
820
        /* In little endian mode the 32bit words in the bios are swapped,
821
           a neat trick which allows bi-endian firmware. */
822
#ifndef TARGET_WORDS_BIGENDIAN
823
        {
824
            uint32_t *addr;
825
            for (addr = (uint32_t *)(phys_ram_base + bios_offset);
826
                 addr < (uint32_t *)(phys_ram_base + bios_offset + ret);
827
                 addr++) {
828
                *addr = bswap32(*addr);
829
            }
830
        }
831
#endif
832
    }
833

    
834
    /* If a kernel image has been specified, write a small bootloader
835
       to the flash location. */
836
    if (kernel_filename) {
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(env);
842
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
843
        write_bootloader(env, bios_offset, kernel_entry);
844
    }
845

    
846
    /* Board ID = 0x420 (Malta Board with CoreLV)
847
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
848
       map to the board ID. */
849
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
850

    
851
    /* Init internal devices */
852
    cpu_mips_irq_init_cpu(env);
853
    cpu_mips_clock_init(env);
854
    cpu_mips_irqctrl_init();
855

    
856
    /* Interrupt controller */
857
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
858
    i8259 = i8259_init(env->irq[2]);
859

    
860
    /* Northbridge */
861
    pci_bus = pci_gt64120_init(i8259);
862

    
863
    /* Southbridge */
864
    piix4_devfn = piix4_init(pci_bus, 80);
865
    pci_piix4_ide_init(pci_bus, bs_table, piix4_devfn + 1, i8259);
866
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
867
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100);
868
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
869
    for (i = 0; i < 8; i++) {
870
        /* TODO: Populate SPD eeprom data.  */
871
        smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
872
    }
873
    pit = pit_init(0x40, i8259[0]);
874
    DMA_init(0);
875

    
876
    /* Super I/O */
877
    i8042_init(i8259[1], i8259[12], 0x60);
878
    rtc_state = rtc_init(0x70, i8259[8]);
879
    if (serial_hds[0])
880
        serial_init(0x3f8, i8259[4], serial_hds[0]);
881
    if (serial_hds[1])
882
        serial_init(0x2f8, i8259[3], serial_hds[1]);
883
    if (parallel_hds[0])
884
        parallel_init(0x378, i8259[7], parallel_hds[0]);
885
    /* XXX: The floppy controller does not work correctly, something is
886
       probably wrong.
887
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
888

    
889
    /* Sound card */
890
#ifdef HAS_AUDIO
891
    audio_init(pci_bus);
892
#endif
893

    
894
    /* Network card */
895
    network_init(pci_bus);
896

    
897
    /* Optional PCI video card */
898
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
899
                        ram_size, vga_ram_size);
900
}
901

    
902
QEMUMachine mips_malta_machine = {
903
    "malta",
904
    "MIPS Malta Core LV",
905
    mips_malta_init,
906
};