qemu/hw/mips_malta.c
<<
>>
Prefs
   1/*
   2 * QEMU Malta board support
   3 *
   4 * Copyright (c) 2006 Aurelien Jarno
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "hw.h"
  26#include "pc.h"
  27#include "fdc.h"
  28#include "net.h"
  29#include "boards.h"
  30#include "smbus.h"
  31#include "block.h"
  32#include "flash.h"
  33#include "mips.h"
  34#include "pci.h"
  35#include "qemu-char.h"
  36#include "sysemu.h"
  37#include "audio/audio.h"
  38#include "boards.h"
  39#include "qemu-log.h"
  40#include "mips-bios.h"
  41
  42//#define DEBUG_BOARD_INIT
  43
  44#ifdef TARGET_MIPS64
  45#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
  46#else
  47#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
  48#endif
  49
  50#define ENVP_ADDR (int32_t)0x80002000
  51#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
  52
  53#define ENVP_NB_ENTRIES         16
  54#define ENVP_ENTRY_SIZE         256
  55
  56#define MAX_IDE_BUS 2
  57
  58typedef struct {
  59    uint32_t leds;
  60    uint32_t brk;
  61    uint32_t gpout;
  62    uint32_t i2cin;
  63    uint32_t i2coe;
  64    uint32_t i2cout;
  65    uint32_t i2csel;
  66    CharDriverState *display;
  67    char display_text[9];
  68    SerialState *uart;
  69} MaltaFPGAState;
  70
  71static PITState *pit;
  72
  73static struct _loaderparams {
  74    int ram_size;
  75    const char *kernel_filename;
  76    const char *kernel_cmdline;
  77    const char *initrd_filename;
  78} loaderparams;
  79
  80/* Malta FPGA */
  81static void malta_fpga_update_display(void *opaque)
  82{
  83    char leds_text[9];
  84    int i;
  85    MaltaFPGAState *s = opaque;
  86
  87    for (i = 7 ; i >= 0 ; i--) {
  88        if (s->leds & (1 << i))
  89            leds_text[i] = '#';
  90        else
  91            leds_text[i] = ' ';
  92    }
  93    leds_text[8] = '\0';
  94
  95    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
  96    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
  97}
  98
  99/*
 100 * EEPROM 24C01 / 24C02 emulation.
 101 *
 102 * Emulation for serial EEPROMs:
 103 * 24C01 - 1024 bit (128 x 8)
 104 * 24C02 - 2048 bit (256 x 8)
 105 *
 106 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
 107 */
 108
 109//~ #define DEBUG
 110
 111#if defined(DEBUG)
 112#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
 113#else
 114#  define logout(fmt, ...) ((void)0)
 115#endif
 116
 117struct _eeprom24c0x_t {
 118  uint8_t tick;
 119  uint8_t address;
 120  uint8_t command;
 121  uint8_t ack;
 122  uint8_t scl;
 123  uint8_t sda;
 124  uint8_t data;
 125  //~ uint16_t size;
 126  uint8_t contents[256];
 127};
 128
 129typedef struct _eeprom24c0x_t eeprom24c0x_t;
 130
 131static eeprom24c0x_t eeprom = {
 132    contents: {
 133        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
 134        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
 135        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
 136        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
 137        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
 138        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 139        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 140        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
 141        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 142        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 143        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 144        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 145        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 146        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 147        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 148        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
 149    },
 150};
 151
 152static uint8_t eeprom24c0x_read(void)
 153{
 154    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
 155        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
 156    return eeprom.sda;
 157}
 158
 159static void eeprom24c0x_write(int scl, int sda)
 160{
 161    if (eeprom.scl && scl && (eeprom.sda != sda)) {
 162        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
 163                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
 164        if (!sda) {
 165            eeprom.tick = 1;
 166            eeprom.command = 0;
 167        }
 168    } else if (eeprom.tick == 0 && !eeprom.ack) {
 169        /* Waiting for start. */
 170        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
 171                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 172    } else if (!eeprom.scl && scl) {
 173        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
 174                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 175        if (eeprom.ack) {
 176            logout("\ti2c ack bit = 0\n");
 177            sda = 0;
 178            eeprom.ack = 0;
 179        } else if (eeprom.sda == sda) {
 180            uint8_t bit = (sda != 0);
 181            logout("\ti2c bit = %d\n", bit);
 182            if (eeprom.tick < 9) {
 183                eeprom.command <<= 1;
 184                eeprom.command += bit;
 185                eeprom.tick++;
 186                if (eeprom.tick == 9) {
 187                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
 188                    eeprom.ack = 1;
 189                }
 190            } else if (eeprom.tick < 17) {
 191                if (eeprom.command & 1) {
 192                    sda = ((eeprom.data & 0x80) != 0);
 193                }
 194                eeprom.address <<= 1;
 195                eeprom.address += bit;
 196                eeprom.tick++;
 197                eeprom.data <<= 1;
 198                if (eeprom.tick == 17) {
 199                    eeprom.data = eeprom.contents[eeprom.address];
 200                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
 201                    eeprom.ack = 1;
 202                    eeprom.tick = 0;
 203                }
 204            } else if (eeprom.tick >= 17) {
 205                sda = 0;
 206            }
 207        } else {
 208            logout("\tsda changed with raising scl\n");
 209        }
 210    } else {
 211        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 212    }
 213    eeprom.scl = scl;
 214    eeprom.sda = sda;
 215}
 216
 217static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
 218{
 219    MaltaFPGAState *s = opaque;
 220    uint32_t val = 0;
 221    uint32_t saddr;
 222
 223    saddr = (addr & 0xfffff);
 224
 225    switch (saddr) {
 226
 227    /* SWITCH Register */
 228    case 0x00200:
 229        val = 0x00000000;               /* All switches closed */
 230        break;
 231
 232    /* STATUS Register */
 233    case 0x00208:
 234#ifdef TARGET_WORDS_BIGENDIAN
 235        val = 0x00000012;
 236#else
 237        val = 0x00000010;
 238#endif
 239        break;
 240
 241    /* JMPRS Register */
 242    case 0x00210:
 243        val = 0x00;
 244        break;
 245
 246    /* LEDBAR Register */
 247    case 0x00408:
 248        val = s->leds;
 249        break;
 250
 251    /* BRKRES Register */
 252    case 0x00508:
 253        val = s->brk;
 254        break;
 255
 256    /* UART Registers are handled directly by the serial device */
 257
 258    /* GPOUT Register */
 259    case 0x00a00:
 260        val = s->gpout;
 261        break;
 262
 263    /* XXX: implement a real I2C controller */
 264
 265    /* GPINP Register */
 266    case 0x00a08:
 267        /* IN = OUT until a real I2C control is implemented */
 268        if (s->i2csel)
 269            val = s->i2cout;
 270        else
 271            val = 0x00;
 272        break;
 273
 274    /* I2CINP Register */
 275    case 0x00b00:
 276        val = ((s->i2cin & ~1) | eeprom24c0x_read());
 277        break;
 278
 279    /* I2COE Register */
 280    case 0x00b08:
 281        val = s->i2coe;
 282        break;
 283
 284    /* I2COUT Register */
 285    case 0x00b10:
 286        val = s->i2cout;
 287        break;
 288
 289    /* I2CSEL Register */
 290    case 0x00b18:
 291        val = s->i2csel;
 292        break;
 293
 294    default:
 295#if 0
 296        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
 297                addr);
 298#endif
 299        break;
 300    }
 301    return val;
 302}
 303
 304static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
 305                              uint32_t val)
 306{
 307    MaltaFPGAState *s = opaque;
 308    uint32_t saddr;
 309
 310    saddr = (addr & 0xfffff);
 311
 312    switch (saddr) {
 313
 314    /* SWITCH Register */
 315    case 0x00200:
 316        break;
 317
 318    /* JMPRS Register */
 319    case 0x00210:
 320        break;
 321
 322    /* LEDBAR Register */
 323    /* XXX: implement a 8-LED array */
 324    case 0x00408:
 325        s->leds = val & 0xff;
 326        break;
 327
 328    /* ASCIIWORD Register */
 329    case 0x00410:
 330        snprintf(s->display_text, 9, "%08X", val);
 331        malta_fpga_update_display(s);
 332        break;
 333
 334    /* ASCIIPOS0 to ASCIIPOS7 Registers */
 335    case 0x00418:
 336    case 0x00420:
 337    case 0x00428:
 338    case 0x00430:
 339    case 0x00438:
 340    case 0x00440:
 341    case 0x00448:
 342    case 0x00450:
 343        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
 344        malta_fpga_update_display(s);
 345        break;
 346
 347    /* SOFTRES Register */
 348    case 0x00500:
 349        if (val == 0x42)
 350            qemu_system_reset_request ();
 351        break;
 352
 353    /* BRKRES Register */
 354    case 0x00508:
 355        s->brk = val & 0xff;
 356        break;
 357
 358    /* UART Registers are handled directly by the serial device */
 359
 360    /* GPOUT Register */
 361    case 0x00a00:
 362        s->gpout = val & 0xff;
 363        break;
 364
 365    /* I2COE Register */
 366    case 0x00b08:
 367        s->i2coe = val & 0x03;
 368        break;
 369
 370    /* I2COUT Register */
 371    case 0x00b10:
 372        eeprom24c0x_write(val & 0x02, val & 0x01);
 373        s->i2cout = val;
 374        break;
 375
 376    /* I2CSEL Register */
 377    case 0x00b18:
 378        s->i2csel = val & 0x01;
 379        break;
 380
 381    default:
 382#if 0
 383        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
 384                addr);
 385#endif
 386        break;
 387    }
 388}
 389
 390static CPUReadMemoryFunc *malta_fpga_read[] = {
 391   malta_fpga_readl,
 392   malta_fpga_readl,
 393   malta_fpga_readl
 394};
 395
 396static CPUWriteMemoryFunc *malta_fpga_write[] = {
 397   malta_fpga_writel,
 398   malta_fpga_writel,
 399   malta_fpga_writel
 400};
 401
 402static void malta_fpga_reset(void *opaque)
 403{
 404    MaltaFPGAState *s = opaque;
 405
 406    s->leds   = 0x00;
 407    s->brk    = 0x0a;
 408    s->gpout  = 0x00;
 409    s->i2cin  = 0x3;
 410    s->i2coe  = 0x0;
 411    s->i2cout = 0x3;
 412    s->i2csel = 0x1;
 413
 414    s->display_text[8] = '\0';
 415    snprintf(s->display_text, 9, "        ");
 416}
 417
 418static void malta_fpga_led_init(CharDriverState *chr)
 419{
 420    qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
 421    qemu_chr_printf(chr, "+--------+\r\n");
 422    qemu_chr_printf(chr, "+        +\r\n");
 423    qemu_chr_printf(chr, "+--------+\r\n");
 424    qemu_chr_printf(chr, "\n");
 425    qemu_chr_printf(chr, "Malta ASCII\r\n");
 426    qemu_chr_printf(chr, "+--------+\r\n");
 427    qemu_chr_printf(chr, "+        +\r\n");
 428    qemu_chr_printf(chr, "+--------+\r\n");
 429}
 430
 431static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
 432{
 433    MaltaFPGAState *s;
 434    int malta;
 435
 436    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
 437
 438    malta = cpu_register_io_memory(malta_fpga_read,
 439                                   malta_fpga_write, s);
 440
 441    cpu_register_physical_memory(base, 0x900, malta);
 442    /* 0xa00 is less than a page, so will still get the right offsets.  */
 443    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
 444
 445    s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
 446
 447    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1);
 448
 449    malta_fpga_reset(s);
 450    qemu_register_reset(malta_fpga_reset, s);
 451
 452    return s;
 453}
 454
 455/* Audio support */
 456#ifdef HAS_AUDIO
 457static void audio_init (PCIBus *pci_bus)
 458{
 459    struct soundhw *c;
 460    int audio_enabled = 0;
 461
 462    for (c = soundhw; !audio_enabled && c->name; ++c) {
 463        audio_enabled = c->enabled;
 464    }
 465
 466    if (audio_enabled) {
 467        for (c = soundhw; c->name; ++c) {
 468            if (c->enabled) {
 469                c->init.init_pci(pci_bus);
 470            }
 471        }
 472    }
 473}
 474#endif
 475
 476/* Network support */
 477static void network_init(void)
 478{
 479    int i;
 480
 481    for(i = 0; i < nb_nics; i++) {
 482        NICInfo *nd = &nd_table[i];
 483        const char *default_devaddr = NULL;
 484
 485        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
 486            /* The malta board has a PCNet card using PCI SLOT 11 */
 487            default_devaddr = "0b";
 488
 489        pci_nic_init(nd, "pcnet", default_devaddr);
 490    }
 491}
 492
 493/* ROM and pseudo bootloader
 494
 495   The following code implements a very very simple bootloader. It first
 496   loads the registers a0 to a3 to the values expected by the OS, and
 497   then jump at the kernel address.
 498
 499   The bootloader should pass the locations of the kernel arguments and
 500   environment variables tables. Those tables contain the 32-bit address
 501   of NULL terminated strings. The environment variables table should be
 502   terminated by a NULL address.
 503
 504   For a simpler implementation, the number of kernel arguments is fixed
 505   to two (the name of the kernel and the command line), and the two
 506   tables are actually the same one.
 507
 508   The registers a0 to a3 should contain the following values:
 509     a0 - number of kernel arguments
 510     a1 - 32-bit address of the kernel arguments table
 511     a2 - 32-bit address of the environment variables table
 512     a3 - RAM size in bytes
 513*/
 514
 515static void write_bootloader (CPUState *env, uint8_t *base,
 516                              int64_t kernel_entry)
 517{
 518    uint32_t *p;
 519
 520    /* Small bootloader */
 521    p = (uint32_t *)base;
 522    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
 523    stl_raw(p++, 0x00000000);                                      /* nop */
 524
 525    /* YAMON service vector */
 526    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
 527    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
 528    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
 529    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
 530    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
 531    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
 532    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
 533    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
 534    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
 535    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
 536    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
 537    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
 538    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
 539
 540
 541    /* Second part of the bootloader */
 542    p = (uint32_t *) (base + 0x580);
 543    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
 544    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
 545    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
 546    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 547    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
 548    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 549    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 550    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
 551    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
 552
 553    /* Load BAR registers as done by YAMON */
 554    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
 555
 556#ifdef TARGET_WORDS_BIGENDIAN
 557    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
 558#else
 559    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
 560#endif
 561    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
 562
 563    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 564
 565#ifdef TARGET_WORDS_BIGENDIAN
 566    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
 567#else
 568    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
 569#endif
 570    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
 571#ifdef TARGET_WORDS_BIGENDIAN
 572    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
 573#else
 574    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
 575#endif
 576    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
 577
 578#ifdef TARGET_WORDS_BIGENDIAN
 579    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
 580#else
 581    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
 582#endif
 583    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
 584#ifdef TARGET_WORDS_BIGENDIAN
 585    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
 586#else
 587    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
 588#endif
 589    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
 590
 591#ifdef TARGET_WORDS_BIGENDIAN
 592    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
 593#else
 594    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
 595#endif
 596    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
 597#ifdef TARGET_WORDS_BIGENDIAN
 598    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
 599#else
 600    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
 601#endif
 602    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
 603
 604    /* Jump to kernel code */
 605    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
 606    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
 607    stl_raw(p++, 0x03e00008);                                      /* jr ra */
 608    stl_raw(p++, 0x00000000);                                      /* nop */
 609
 610    /* YAMON subroutines */
 611    p = (uint32_t *) (base + 0x800);
 612    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 613    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
 614   /* 808 YAMON print */
 615    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 616    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 617    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 618    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 619    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 620    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
 621    stl_raw(p++, 0x00000000);                                     /* nop */
 622    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 623    stl_raw(p++, 0x00000000);                                     /* nop */
 624    stl_raw(p++, 0x08000205);                                     /* j 814 */
 625    stl_raw(p++, 0x00000000);                                     /* nop */
 626    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 627    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 628    /* 0x83c YAMON print_count */
 629    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 630    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 631    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 632    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
 633    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 634    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 635    stl_raw(p++, 0x00000000);                                     /* nop */
 636    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 637    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
 638    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
 639    stl_raw(p++, 0x00000000);                                     /* nop */
 640    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 641    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 642    /* 0x870 */
 643    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
 644    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
 645    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
 646    stl_raw(p++, 0x00000000);                                     /* nop */
 647    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
 648    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
 649    stl_raw(p++, 0x00000000);                                     /* nop */
 650    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 651    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
 652
 653}
 654
 655static void prom_set(int index, const char *string, ...)
 656{
 657    char buf[ENVP_ENTRY_SIZE];
 658    target_phys_addr_t p;
 659    va_list ap;
 660    int32_t table_addr;
 661
 662    if (index >= ENVP_NB_ENTRIES)
 663        return;
 664
 665    p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
 666
 667    if (string == NULL) {
 668        stl_phys(p, 0);
 669        return;
 670    }
 671
 672    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES
 673                 + index * ENVP_ENTRY_SIZE;
 674    stl_phys(p, table_addr);
 675
 676    va_start(ap, string);
 677    vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap);
 678    va_end(ap);
 679    pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf);
 680}
 681
 682/* Kernel */
 683static int64_t load_kernel (CPUState *env)
 684{
 685    int64_t kernel_entry, kernel_low, kernel_high;
 686    int index = 0;
 687    long initrd_size;
 688    ram_addr_t initrd_offset;
 689
 690    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
 691                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
 692                 (uint64_t *)&kernel_high) < 0) {
 693        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 694                loaderparams.kernel_filename);
 695        exit(1);
 696    }
 697
 698    /* load initrd */
 699    initrd_size = 0;
 700    initrd_offset = 0;
 701    if (loaderparams.initrd_filename) {
 702        initrd_size = get_image_size (loaderparams.initrd_filename);
 703        if (initrd_size > 0) {
 704            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
 705            if (initrd_offset + initrd_size > ram_size) {
 706                fprintf(stderr,
 707                        "qemu: memory too small for initial ram disk '%s'\n",
 708                        loaderparams.initrd_filename);
 709                exit(1);
 710            }
 711            initrd_size = load_image_targphys(loaderparams.initrd_filename,
 712                                              initrd_offset,
 713                                              ram_size - initrd_offset);
 714        }
 715        if (initrd_size == (target_ulong) -1) {
 716            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
 717                    loaderparams.initrd_filename);
 718            exit(1);
 719        }
 720    }
 721
 722    /* Store command line.  */
 723    prom_set(index++, loaderparams.kernel_filename);
 724    if (initrd_size > 0)
 725        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
 726                 PHYS_TO_VIRT(initrd_offset), initrd_size,
 727                 loaderparams.kernel_cmdline);
 728    else
 729        prom_set(index++, loaderparams.kernel_cmdline);
 730
 731    /* Setup minimum environment variables */
 732    prom_set(index++, "memsize");
 733    prom_set(index++, "%i", loaderparams.ram_size);
 734    prom_set(index++, "modetty0");
 735    prom_set(index++, "38400n8r");
 736    prom_set(index++, NULL);
 737
 738    return kernel_entry;
 739}
 740
 741static void main_cpu_reset(void *opaque)
 742{
 743    CPUState *env = opaque;
 744    cpu_reset(env);
 745
 746    /* The bootload does not need to be rewritten as it is located in a
 747       read only location. The kernel location and the arguments table
 748       location does not change. */
 749    if (loaderparams.kernel_filename) {
 750        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
 751        load_kernel (env);
 752    }
 753}
 754
 755static
 756void mips_malta_init (ram_addr_t ram_size,
 757                      const char *boot_device,
 758                      const char *kernel_filename, const char *kernel_cmdline,
 759                      const char *initrd_filename, const char *cpu_model)
 760{
 761    char *filename;
 762    ram_addr_t ram_offset;
 763    ram_addr_t bios_offset;
 764    target_long bios_size;
 765    int64_t kernel_entry;
 766    PCIBus *pci_bus;
 767    CPUState *env;
 768    RTCState *rtc_state;
 769    fdctrl_t *floppy_controller;
 770    MaltaFPGAState *malta_fpga;
 771    qemu_irq *i8259;
 772    int piix4_devfn;
 773    uint8_t *eeprom_buf;
 774    i2c_bus *smbus;
 775    int i;
 776    int index;
 777    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 778    BlockDriverState *fd[MAX_FD];
 779    int fl_idx = 0;
 780    int fl_sectors = 0;
 781
 782    /* init CPUs */
 783    if (cpu_model == NULL) {
 784#ifdef TARGET_MIPS64
 785        cpu_model = "20Kc";
 786#else
 787        cpu_model = "24Kf";
 788#endif
 789    }
 790    env = cpu_init(cpu_model);
 791    if (!env) {
 792        fprintf(stderr, "Unable to find CPU definition\n");
 793        exit(1);
 794    }
 795    qemu_register_reset(main_cpu_reset, env);
 796
 797    /* allocate RAM */
 798    if (ram_size > (256 << 20)) {
 799        fprintf(stderr,
 800                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
 801                ((unsigned int)ram_size / (1 << 20)));
 802        exit(1);
 803    }
 804    ram_offset = qemu_ram_alloc(ram_size);
 805    bios_offset = qemu_ram_alloc(BIOS_SIZE);
 806
 807
 808    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
 809
 810    /* Map the bios at two physical locations, as on the real board. */
 811    cpu_register_physical_memory(0x1e000000LL,
 812                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
 813    cpu_register_physical_memory(0x1fc00000LL,
 814                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
 815
 816    /* FPGA */
 817    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
 818
 819    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
 820    if (kernel_filename) {
 821        /* Write a small bootloader to the flash location. */
 822        loaderparams.ram_size = ram_size;
 823        loaderparams.kernel_filename = kernel_filename;
 824        loaderparams.kernel_cmdline = kernel_cmdline;
 825        loaderparams.initrd_filename = initrd_filename;
 826        kernel_entry = load_kernel(env);
 827        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
 828        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
 829    } else {
 830        index = drive_get_index(IF_PFLASH, 0, fl_idx);
 831        if (index != -1) {
 832            /* Load firmware from flash. */
 833            bios_size = 0x400000;
 834            fl_sectors = bios_size >> 16;
 835#ifdef DEBUG_BOARD_INIT
 836            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
 837                   "offset %08lx addr %08llx '%s' %x\n",
 838                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
 839                   bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
 840#endif
 841            pflash_cfi01_register(0x1e000000LL, bios_offset,
 842                                  drives_table[index].bdrv, 65536, fl_sectors,
 843                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
 844            fl_idx++;
 845        } else {
 846            /* Load a BIOS image. */
 847            if (bios_name == NULL)
 848                bios_name = BIOS_FILENAME;
 849            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 850            if (filename) {
 851                bios_size = load_image_targphys(filename, 0x1fc00000LL,
 852                                                BIOS_SIZE);
 853                qemu_free(filename);
 854            } else {
 855                bios_size = -1;
 856            }
 857            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
 858                fprintf(stderr,
 859                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
 860                        bios_name);
 861                exit(1);
 862            }
 863        }
 864        /* In little endian mode the 32bit words in the bios are swapped,
 865           a neat trick which allows bi-endian firmware. */
 866#ifndef TARGET_WORDS_BIGENDIAN
 867        {
 868            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
 869            uint32_t *end = addr + bios_size;
 870            while (addr < end) {
 871                bswap32s(addr);
 872            }
 873        }
 874#endif
 875    }
 876
 877    /* Board ID = 0x420 (Malta Board with CoreLV)
 878       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
 879       map to the board ID. */
 880    stl_phys(0x1fc00010LL, 0x00000420);
 881
 882    /* Init internal devices */
 883    cpu_mips_irq_init_cpu(env);
 884    cpu_mips_clock_init(env);
 885
 886    /* Interrupt controller */
 887    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
 888    i8259 = i8259_init(env->irq[2]);
 889
 890    /* Northbridge */
 891    pci_bus = pci_gt64120_init(i8259);
 892
 893    /* Southbridge */
 894
 895    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
 896        fprintf(stderr, "qemu: too many IDE bus\n");
 897        exit(1);
 898    }
 899
 900    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
 901        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
 902        if (index != -1)
 903            hd[i] = drives_table[index].bdrv;
 904        else
 905            hd[i] = NULL;
 906    }
 907
 908    piix4_devfn = piix4_init(pci_bus, 80);
 909    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
 910    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
 911    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, i8259[9]);
 912    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
 913    for (i = 0; i < 8; i++) {
 914        /* TODO: Populate SPD eeprom data.  */
 915        DeviceState *eeprom;
 916        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
 917        qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
 918        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
 919        qdev_init(eeprom);
 920    }
 921    pit = pit_init(0x40, i8259[0]);
 922    DMA_init(0);
 923
 924    /* Super I/O */
 925    i8042_init(i8259[1], i8259[12], 0x60);
 926    rtc_state = rtc_init(0x70, i8259[8], 2000);
 927    serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
 928    serial_init(0x2f8, i8259[3], 115200, serial_hds[1]);
 929    if (parallel_hds[0])
 930        parallel_init(0x378, i8259[7], parallel_hds[0]);
 931    for(i = 0; i < MAX_FD; i++) {
 932        index = drive_get_index(IF_FLOPPY, 0, i);
 933       if (index != -1)
 934           fd[i] = drives_table[index].bdrv;
 935       else
 936           fd[i] = NULL;
 937    }
 938    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 939
 940    /* Sound card */
 941#ifdef HAS_AUDIO
 942    audio_init(pci_bus);
 943#endif
 944
 945    /* Network card */
 946    network_init();
 947
 948    /* Optional PCI video card */
 949    if (cirrus_vga_enabled) {
 950        pci_cirrus_vga_init(pci_bus);
 951    } else if (vmsvga_enabled) {
 952        pci_vmsvga_init(pci_bus);
 953    } else if (std_vga_enabled) {
 954        pci_vga_init(pci_bus, 0, 0);
 955    }
 956}
 957
 958static QEMUMachine mips_malta_machine = {
 959    .name = "malta",
 960    .desc = "MIPS Malta Core LV",
 961    .init = mips_malta_init,
 962    .is_default = 1,
 963};
 964
 965static void mips_malta_machine_init(void)
 966{
 967    qemu_register_machine(&mips_malta_machine);
 968}
 969
 970machine_init(mips_malta_machine_init);
 971