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 "mips_cpudevs.h"
  35#include "pci.h"
  36#include "vmware_vga.h"
  37#include "qemu-char.h"
  38#include "sysemu.h"
  39#include "arch_init.h"
  40#include "boards.h"
  41#include "qemu-log.h"
  42#include "mips-bios.h"
  43#include "ide.h"
  44#include "loader.h"
  45#include "elf.h"
  46#include "mc146818rtc.h"
  47#include "i8254.h"
  48#include "blockdev.h"
  49#include "exec-memory.h"
  50#include "sysbus.h"             /* SysBusDevice */
  51#include "vga-pci.h"
  52
  53//#define DEBUG_BOARD_INIT
  54
  55#define ENVP_ADDR               0x80002000l
  56#define ENVP_NB_ENTRIES         16
  57#define ENVP_ENTRY_SIZE         256
  58
  59/* Hardware addresses */
  60#define FLASH_ADDRESS 0x1e000000ULL
  61#define FPGA_ADDRESS  0x1f000000ULL
  62#define RESET_ADDRESS 0x1fc00000ULL
  63
  64#define FLASH_SIZE    0x400000
  65
  66#define MAX_IDE_BUS 2
  67
  68typedef struct {
  69    MemoryRegion iomem;
  70    MemoryRegion iomem_lo; /* 0 - 0x900 */
  71    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
  72    uint32_t leds;
  73    uint32_t brk;
  74    uint32_t gpout;
  75    uint32_t i2cin;
  76    uint32_t i2coe;
  77    uint32_t i2cout;
  78    uint32_t i2csel;
  79    CharDriverState *display;
  80    char display_text[9];
  81    SerialState *uart;
  82} MaltaFPGAState;
  83
  84typedef struct {
  85    SysBusDevice busdev;
  86    qemu_irq *i8259;
  87} MaltaState;
  88
  89static ISADevice *pit;
  90
  91static struct _loaderparams {
  92    int ram_size;
  93    const char *kernel_filename;
  94    const char *kernel_cmdline;
  95    const char *initrd_filename;
  96} loaderparams;
  97
  98/* Malta FPGA */
  99static void malta_fpga_update_display(void *opaque)
 100{
 101    char leds_text[9];
 102    int i;
 103    MaltaFPGAState *s = opaque;
 104
 105    for (i = 7 ; i >= 0 ; i--) {
 106        if (s->leds & (1 << i))
 107            leds_text[i] = '#';
 108        else
 109            leds_text[i] = ' ';
 110    }
 111    leds_text[8] = '\0';
 112
 113    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
 114    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
 115}
 116
 117/*
 118 * EEPROM 24C01 / 24C02 emulation.
 119 *
 120 * Emulation for serial EEPROMs:
 121 * 24C01 - 1024 bit (128 x 8)
 122 * 24C02 - 2048 bit (256 x 8)
 123 *
 124 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
 125 */
 126
 127//~ #define DEBUG
 128
 129#if defined(DEBUG)
 130#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
 131#else
 132#  define logout(fmt, ...) ((void)0)
 133#endif
 134
 135struct _eeprom24c0x_t {
 136  uint8_t tick;
 137  uint8_t address;
 138  uint8_t command;
 139  uint8_t ack;
 140  uint8_t scl;
 141  uint8_t sda;
 142  uint8_t data;
 143  //~ uint16_t size;
 144  uint8_t contents[256];
 145};
 146
 147typedef struct _eeprom24c0x_t eeprom24c0x_t;
 148
 149static eeprom24c0x_t eeprom = {
 150    .contents = {
 151        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
 152        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
 153        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
 154        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
 155        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
 156        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 157        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 158        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
 159        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 160        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 161        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 162        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 163        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 164        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 165        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 166        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
 167    },
 168};
 169
 170static uint8_t eeprom24c0x_read(void)
 171{
 172    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
 173        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
 174    return eeprom.sda;
 175}
 176
 177static void eeprom24c0x_write(int scl, int sda)
 178{
 179    if (eeprom.scl && scl && (eeprom.sda != sda)) {
 180        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
 181                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
 182        if (!sda) {
 183            eeprom.tick = 1;
 184            eeprom.command = 0;
 185        }
 186    } else if (eeprom.tick == 0 && !eeprom.ack) {
 187        /* Waiting for start. */
 188        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
 189                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 190    } else if (!eeprom.scl && scl) {
 191        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
 192                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 193        if (eeprom.ack) {
 194            logout("\ti2c ack bit = 0\n");
 195            sda = 0;
 196            eeprom.ack = 0;
 197        } else if (eeprom.sda == sda) {
 198            uint8_t bit = (sda != 0);
 199            logout("\ti2c bit = %d\n", bit);
 200            if (eeprom.tick < 9) {
 201                eeprom.command <<= 1;
 202                eeprom.command += bit;
 203                eeprom.tick++;
 204                if (eeprom.tick == 9) {
 205                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
 206                    eeprom.ack = 1;
 207                }
 208            } else if (eeprom.tick < 17) {
 209                if (eeprom.command & 1) {
 210                    sda = ((eeprom.data & 0x80) != 0);
 211                }
 212                eeprom.address <<= 1;
 213                eeprom.address += bit;
 214                eeprom.tick++;
 215                eeprom.data <<= 1;
 216                if (eeprom.tick == 17) {
 217                    eeprom.data = eeprom.contents[eeprom.address];
 218                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
 219                    eeprom.ack = 1;
 220                    eeprom.tick = 0;
 221                }
 222            } else if (eeprom.tick >= 17) {
 223                sda = 0;
 224            }
 225        } else {
 226            logout("\tsda changed with raising scl\n");
 227        }
 228    } else {
 229        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
 230    }
 231    eeprom.scl = scl;
 232    eeprom.sda = sda;
 233}
 234
 235static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr,
 236                                unsigned size)
 237{
 238    MaltaFPGAState *s = opaque;
 239    uint32_t val = 0;
 240    uint32_t saddr;
 241
 242    saddr = (addr & 0xfffff);
 243
 244    switch (saddr) {
 245
 246    /* SWITCH Register */
 247    case 0x00200:
 248        val = 0x00000000;               /* All switches closed */
 249        break;
 250
 251    /* STATUS Register */
 252    case 0x00208:
 253#ifdef TARGET_WORDS_BIGENDIAN
 254        val = 0x00000012;
 255#else
 256        val = 0x00000010;
 257#endif
 258        break;
 259
 260    /* JMPRS Register */
 261    case 0x00210:
 262        val = 0x00;
 263        break;
 264
 265    /* LEDBAR Register */
 266    case 0x00408:
 267        val = s->leds;
 268        break;
 269
 270    /* BRKRES Register */
 271    case 0x00508:
 272        val = s->brk;
 273        break;
 274
 275    /* UART Registers are handled directly by the serial device */
 276
 277    /* GPOUT Register */
 278    case 0x00a00:
 279        val = s->gpout;
 280        break;
 281
 282    /* XXX: implement a real I2C controller */
 283
 284    /* GPINP Register */
 285    case 0x00a08:
 286        /* IN = OUT until a real I2C control is implemented */
 287        if (s->i2csel)
 288            val = s->i2cout;
 289        else
 290            val = 0x00;
 291        break;
 292
 293    /* I2CINP Register */
 294    case 0x00b00:
 295        val = ((s->i2cin & ~1) | eeprom24c0x_read());
 296        break;
 297
 298    /* I2COE Register */
 299    case 0x00b08:
 300        val = s->i2coe;
 301        break;
 302
 303    /* I2COUT Register */
 304    case 0x00b10:
 305        val = s->i2cout;
 306        break;
 307
 308    /* I2CSEL Register */
 309    case 0x00b18:
 310        val = s->i2csel;
 311        break;
 312
 313    default:
 314#if 0
 315        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
 316                addr);
 317#endif
 318        break;
 319    }
 320    return val;
 321}
 322
 323static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
 324                             uint64_t val, unsigned size)
 325{
 326    MaltaFPGAState *s = opaque;
 327    uint32_t saddr;
 328
 329    saddr = (addr & 0xfffff);
 330
 331    switch (saddr) {
 332
 333    /* SWITCH Register */
 334    case 0x00200:
 335        break;
 336
 337    /* JMPRS Register */
 338    case 0x00210:
 339        break;
 340
 341    /* LEDBAR Register */
 342    case 0x00408:
 343        s->leds = val & 0xff;
 344        malta_fpga_update_display(s);
 345        break;
 346
 347    /* ASCIIWORD Register */
 348    case 0x00410:
 349        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
 350        malta_fpga_update_display(s);
 351        break;
 352
 353    /* ASCIIPOS0 to ASCIIPOS7 Registers */
 354    case 0x00418:
 355    case 0x00420:
 356    case 0x00428:
 357    case 0x00430:
 358    case 0x00438:
 359    case 0x00440:
 360    case 0x00448:
 361    case 0x00450:
 362        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
 363        malta_fpga_update_display(s);
 364        break;
 365
 366    /* SOFTRES Register */
 367    case 0x00500:
 368        if (val == 0x42)
 369            qemu_system_reset_request ();
 370        break;
 371
 372    /* BRKRES Register */
 373    case 0x00508:
 374        s->brk = val & 0xff;
 375        break;
 376
 377    /* UART Registers are handled directly by the serial device */
 378
 379    /* GPOUT Register */
 380    case 0x00a00:
 381        s->gpout = val & 0xff;
 382        break;
 383
 384    /* I2COE Register */
 385    case 0x00b08:
 386        s->i2coe = val & 0x03;
 387        break;
 388
 389    /* I2COUT Register */
 390    case 0x00b10:
 391        eeprom24c0x_write(val & 0x02, val & 0x01);
 392        s->i2cout = val;
 393        break;
 394
 395    /* I2CSEL Register */
 396    case 0x00b18:
 397        s->i2csel = val & 0x01;
 398        break;
 399
 400    default:
 401#if 0
 402        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
 403                addr);
 404#endif
 405        break;
 406    }
 407}
 408
 409static const MemoryRegionOps malta_fpga_ops = {
 410    .read = malta_fpga_read,
 411    .write = malta_fpga_write,
 412    .endianness = DEVICE_NATIVE_ENDIAN,
 413};
 414
 415static void malta_fpga_reset(void *opaque)
 416{
 417    MaltaFPGAState *s = opaque;
 418
 419    s->leds   = 0x00;
 420    s->brk    = 0x0a;
 421    s->gpout  = 0x00;
 422    s->i2cin  = 0x3;
 423    s->i2coe  = 0x0;
 424    s->i2cout = 0x3;
 425    s->i2csel = 0x1;
 426
 427    s->display_text[8] = '\0';
 428    snprintf(s->display_text, 9, "        ");
 429}
 430
 431static void malta_fpga_led_init(CharDriverState *chr)
 432{
 433    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
 434    qemu_chr_fe_printf(chr, "+--------+\r\n");
 435    qemu_chr_fe_printf(chr, "+        +\r\n");
 436    qemu_chr_fe_printf(chr, "+--------+\r\n");
 437    qemu_chr_fe_printf(chr, "\n");
 438    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
 439    qemu_chr_fe_printf(chr, "+--------+\r\n");
 440    qemu_chr_fe_printf(chr, "+        +\r\n");
 441    qemu_chr_fe_printf(chr, "+--------+\r\n");
 442}
 443
 444static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
 445         target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
 446{
 447    MaltaFPGAState *s;
 448
 449    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
 450
 451    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
 452                          "malta-fpga", 0x100000);
 453    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
 454                             &s->iomem, 0, 0x900);
 455    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
 456                             &s->iomem, 0xa00, 0x10000-0xa00);
 457
 458    memory_region_add_subregion(address_space, base, &s->iomem_lo);
 459    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
 460
 461    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
 462
 463    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
 464                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
 465
 466    malta_fpga_reset(s);
 467    qemu_register_reset(malta_fpga_reset, s);
 468
 469    return s;
 470}
 471
 472/* Network support */
 473static void network_init(void)
 474{
 475    int i;
 476
 477    for(i = 0; i < nb_nics; i++) {
 478        NICInfo *nd = &nd_table[i];
 479        const char *default_devaddr = NULL;
 480
 481        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
 482            /* The malta board has a PCNet card using PCI SLOT 11 */
 483            default_devaddr = "0b";
 484
 485        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
 486    }
 487}
 488
 489/* ROM and pseudo bootloader
 490
 491   The following code implements a very very simple bootloader. It first
 492   loads the registers a0 to a3 to the values expected by the OS, and
 493   then jump at the kernel address.
 494
 495   The bootloader should pass the locations of the kernel arguments and
 496   environment variables tables. Those tables contain the 32-bit address
 497   of NULL terminated strings. The environment variables table should be
 498   terminated by a NULL address.
 499
 500   For a simpler implementation, the number of kernel arguments is fixed
 501   to two (the name of the kernel and the command line), and the two
 502   tables are actually the same one.
 503
 504   The registers a0 to a3 should contain the following values:
 505     a0 - number of kernel arguments
 506     a1 - 32-bit address of the kernel arguments table
 507     a2 - 32-bit address of the environment variables table
 508     a3 - RAM size in bytes
 509*/
 510
 511static void write_bootloader (CPUMIPSState *env, uint8_t *base,
 512                              int64_t kernel_entry)
 513{
 514    uint32_t *p;
 515
 516    /* Small bootloader */
 517    p = (uint32_t *)base;
 518    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
 519    stl_raw(p++, 0x00000000);                                      /* nop */
 520
 521    /* YAMON service vector */
 522    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
 523    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
 524    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
 525    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
 526    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
 527    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
 528    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
 529    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
 530    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
 531    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
 532    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
 533    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
 534    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
 535
 536
 537    /* Second part of the bootloader */
 538    p = (uint32_t *) (base + 0x580);
 539    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
 540    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
 541    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
 542    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
 543    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
 544    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
 545    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
 546    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
 547    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
 548
 549    /* Load BAR registers as done by YAMON */
 550    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
 551
 552#ifdef TARGET_WORDS_BIGENDIAN
 553    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
 554#else
 555    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
 556#endif
 557    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
 558
 559    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
 560
 561#ifdef TARGET_WORDS_BIGENDIAN
 562    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
 563#else
 564    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
 565#endif
 566    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
 567#ifdef TARGET_WORDS_BIGENDIAN
 568    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
 569#else
 570    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
 571#endif
 572    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
 573
 574#ifdef TARGET_WORDS_BIGENDIAN
 575    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
 576#else
 577    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
 578#endif
 579    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
 580#ifdef TARGET_WORDS_BIGENDIAN
 581    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
 582#else
 583    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
 584#endif
 585    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
 586
 587#ifdef TARGET_WORDS_BIGENDIAN
 588    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
 589#else
 590    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
 591#endif
 592    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
 593#ifdef TARGET_WORDS_BIGENDIAN
 594    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
 595#else
 596    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
 597#endif
 598    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
 599
 600    /* Jump to kernel code */
 601    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
 602    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
 603    stl_raw(p++, 0x03e00008);                                      /* jr ra */
 604    stl_raw(p++, 0x00000000);                                      /* nop */
 605
 606    /* YAMON subroutines */
 607    p = (uint32_t *) (base + 0x800);
 608    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 609    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
 610   /* 808 YAMON print */
 611    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 612    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 613    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 614    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 615    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 616    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
 617    stl_raw(p++, 0x00000000);                                     /* nop */
 618    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 619    stl_raw(p++, 0x00000000);                                     /* nop */
 620    stl_raw(p++, 0x08000205);                                     /* j 814 */
 621    stl_raw(p++, 0x00000000);                                     /* nop */
 622    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 623    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 624    /* 0x83c YAMON print_count */
 625    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
 626    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
 627    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
 628    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
 629    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
 630    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
 631    stl_raw(p++, 0x00000000);                                     /* nop */
 632    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
 633    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
 634    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
 635    stl_raw(p++, 0x00000000);                                     /* nop */
 636    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
 637    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
 638    /* 0x870 */
 639    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
 640    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
 641    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
 642    stl_raw(p++, 0x00000000);                                     /* nop */
 643    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
 644    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
 645    stl_raw(p++, 0x00000000);                                     /* nop */
 646    stl_raw(p++, 0x03e00008);                                     /* jr ra */
 647    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
 648
 649}
 650
 651static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
 652                                        const char *string, ...)
 653{
 654    va_list ap;
 655    int32_t table_addr;
 656
 657    if (index >= ENVP_NB_ENTRIES)
 658        return;
 659
 660    if (string == NULL) {
 661        prom_buf[index] = 0;
 662        return;
 663    }
 664
 665    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
 666    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
 667
 668    va_start(ap, string);
 669    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
 670    va_end(ap);
 671}
 672
 673/* Kernel */
 674static int64_t load_kernel (void)
 675{
 676    int64_t kernel_entry, kernel_high;
 677    long initrd_size;
 678    ram_addr_t initrd_offset;
 679    int big_endian;
 680    uint32_t *prom_buf;
 681    long prom_size;
 682    int prom_index = 0;
 683
 684#ifdef TARGET_WORDS_BIGENDIAN
 685    big_endian = 1;
 686#else
 687    big_endian = 0;
 688#endif
 689
 690    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
 691                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
 692                 big_endian, ELF_MACHINE, 1) < 0) {
 693        fprintf(stderr, "qemu: could not load kernel '%s'\n",
 694                loaderparams.kernel_filename);
 695        exit(1);
 696    }
 697
 698    /* load initrd */
 699    initrd_size = 0;
 700    initrd_offset = 0;
 701    if (loaderparams.initrd_filename) {
 702        initrd_size = get_image_size (loaderparams.initrd_filename);
 703        if (initrd_size > 0) {
 704            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
 705            if (initrd_offset + initrd_size > ram_size) {
 706                fprintf(stderr,
 707                        "qemu: memory too small for initial ram disk '%s'\n",
 708                        loaderparams.initrd_filename);
 709                exit(1);
 710            }
 711            initrd_size = load_image_targphys(loaderparams.initrd_filename,
 712                                              initrd_offset,
 713                                              ram_size - initrd_offset);
 714        }
 715        if (initrd_size == (target_ulong) -1) {
 716            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
 717                    loaderparams.initrd_filename);
 718            exit(1);
 719        }
 720    }
 721
 722    /* Setup prom parameters. */
 723    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
 724    prom_buf = g_malloc(prom_size);
 725
 726    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
 727    if (initrd_size > 0) {
 728        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
 729                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
 730                 loaderparams.kernel_cmdline);
 731    } else {
 732        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
 733    }
 734
 735    prom_set(prom_buf, prom_index++, "memsize");
 736    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
 737    prom_set(prom_buf, prom_index++, "modetty0");
 738    prom_set(prom_buf, prom_index++, "38400n8r");
 739    prom_set(prom_buf, prom_index++, NULL);
 740
 741    rom_add_blob_fixed("prom", prom_buf, prom_size,
 742                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
 743
 744    return kernel_entry;
 745}
 746
 747static void malta_mips_config(CPUMIPSState *env)
 748{
 749    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
 750                         ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC);
 751}
 752
 753static void main_cpu_reset(void *opaque)
 754{
 755    MIPSCPU *cpu = opaque;
 756    CPUMIPSState *env = &cpu->env;
 757
 758    cpu_reset(CPU(cpu));
 759
 760    /* The bootloader does not need to be rewritten as it is located in a
 761       read only location. The kernel location and the arguments table
 762       location does not change. */
 763    if (loaderparams.kernel_filename) {
 764        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
 765    }
 766
 767    malta_mips_config(env);
 768}
 769
 770static void cpu_request_exit(void *opaque, int irq, int level)
 771{
 772    CPUMIPSState *env = cpu_single_env;
 773
 774    if (env && level) {
 775        cpu_exit(env);
 776    }
 777}
 778
 779static
 780void mips_malta_init (ram_addr_t ram_size,
 781                      const char *boot_device,
 782                      const char *kernel_filename, const char *kernel_cmdline,
 783                      const char *initrd_filename, const char *cpu_model)
 784{
 785    char *filename;
 786    pflash_t *fl;
 787    MemoryRegion *system_memory = get_system_memory();
 788    MemoryRegion *ram = g_new(MemoryRegion, 1);
 789    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
 790    target_long bios_size = FLASH_SIZE;
 791    int64_t kernel_entry;
 792    PCIBus *pci_bus;
 793    ISABus *isa_bus;
 794    MIPSCPU *cpu;
 795    CPUMIPSState *env;
 796    qemu_irq *isa_irq;
 797    qemu_irq *cpu_exit_irq;
 798    int piix4_devfn;
 799    i2c_bus *smbus;
 800    int i;
 801    DriveInfo *dinfo;
 802    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 803    DriveInfo *fd[MAX_FD];
 804    int fl_idx = 0;
 805    int fl_sectors = bios_size >> 16;
 806    int be;
 807
 808    DeviceState *dev = qdev_create(NULL, "mips-malta");
 809    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
 810
 811    qdev_init_nofail(dev);
 812
 813    /* Make sure the first 3 serial ports are associated with a device. */
 814    for(i = 0; i < 3; i++) {
 815        if (!serial_hds[i]) {
 816            char label[32];
 817            snprintf(label, sizeof(label), "serial%d", i);
 818            serial_hds[i] = qemu_chr_new(label, "null", NULL);
 819        }
 820    }
 821
 822    /* init CPUs */
 823    if (cpu_model == NULL) {
 824#ifdef TARGET_MIPS64
 825        cpu_model = "20Kc";
 826#else
 827        cpu_model = "24Kf";
 828#endif
 829    }
 830
 831    for (i = 0; i < smp_cpus; i++) {
 832        cpu = cpu_mips_init(cpu_model);
 833        if (cpu == NULL) {
 834            fprintf(stderr, "Unable to find CPU definition\n");
 835            exit(1);
 836        }
 837        env = &cpu->env;
 838
 839        /* Init internal devices */
 840        cpu_mips_irq_init_cpu(env);
 841        cpu_mips_clock_init(env);
 842        qemu_register_reset(main_cpu_reset, cpu);
 843    }
 844    env = first_cpu;
 845
 846    /* allocate RAM */
 847    if (ram_size > (256 << 20)) {
 848        fprintf(stderr,
 849                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
 850                ((unsigned int)ram_size / (1 << 20)));
 851        exit(1);
 852    }
 853    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
 854    vmstate_register_ram_global(ram);
 855    memory_region_add_subregion(system_memory, 0, ram);
 856
 857#ifdef TARGET_WORDS_BIGENDIAN
 858    be = 1;
 859#else
 860    be = 0;
 861#endif
 862    /* FPGA */
 863    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[2], serial_hds[2]);
 864
 865    /* Load firmware in flash / BIOS. */
 866    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
 867#ifdef DEBUG_BOARD_INIT
 868    if (dinfo) {
 869        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
 870               "addr %08llx '%s' %x\n",
 871               fl_idx, bios_size, FLASH_ADDRESS,
 872               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 873    }
 874#endif
 875    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
 876                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
 877                               65536, fl_sectors,
 878                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
 879    bios = pflash_cfi01_get_memory(fl);
 880    fl_idx++;
 881    if (kernel_filename) {
 882        /* Write a small bootloader to the flash location. */
 883        loaderparams.ram_size = ram_size;
 884        loaderparams.kernel_filename = kernel_filename;
 885        loaderparams.kernel_cmdline = kernel_cmdline;
 886        loaderparams.initrd_filename = initrd_filename;
 887        kernel_entry = load_kernel();
 888        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
 889    } else {
 890        /* Load firmware from flash. */
 891        if (!dinfo) {
 892            /* Load a BIOS image. */
 893            if (bios_name == NULL) {
 894                bios_name = BIOS_FILENAME;
 895            }
 896            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
 897            if (filename) {
 898                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
 899                                                BIOS_SIZE);
 900                g_free(filename);
 901            } else {
 902                bios_size = -1;
 903            }
 904            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
 905                fprintf(stderr,
 906                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
 907                        bios_name);
 908                exit(1);
 909            }
 910        }
 911        /* In little endian mode the 32bit words in the bios are swapped,
 912           a neat trick which allows bi-endian firmware. */
 913#ifndef TARGET_WORDS_BIGENDIAN
 914        {
 915            uint32_t *addr = memory_region_get_ram_ptr(bios);
 916            uint32_t *end = addr + bios_size;
 917            while (addr < end) {
 918                bswap32s(addr);
 919                addr++;
 920            }
 921        }
 922#endif
 923    }
 924
 925    /* Map the BIOS at a 2nd physical location, as on the real board. */
 926    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
 927    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
 928
 929    /* Board ID = 0x420 (Malta Board with CoreLV)
 930       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
 931       map to the board ID. */
 932    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
 933
 934    /* Init internal devices */
 935    cpu_mips_irq_init_cpu(env);
 936    cpu_mips_clock_init(env);
 937
 938    /*
 939     * We have a circular dependency problem: pci_bus depends on isa_irq,
 940     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
 941     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
 942     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
 943     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
 944     */
 945    isa_irq = qemu_irq_proxy(&s->i8259, 16);
 946
 947    /* Northbridge */
 948    pci_bus = gt64120_register(isa_irq);
 949
 950    /* Southbridge */
 951    ide_drive_get(hd, MAX_IDE_BUS);
 952
 953    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
 954
 955    /* Interrupt controller */
 956    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
 957    s->i8259 = i8259_init(isa_bus, env->irq[2]);
 958
 959    isa_bus_irqs(isa_bus, s->i8259);
 960    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
 961    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
 962    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
 963                          isa_get_irq(NULL, 9), NULL, 0, NULL);
 964    /* TODO: Populate SPD eeprom data.  */
 965    smbus_eeprom_init(smbus, 8, NULL, 0);
 966    pit = pit_init(isa_bus, 0x40, 0, NULL);
 967    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
 968    DMA_init(0, cpu_exit_irq);
 969
 970    /* Super I/O */
 971    isa_create_simple(isa_bus, "i8042");
 972
 973    rtc_init(isa_bus, 2000, NULL);
 974    serial_isa_init(isa_bus, 0, serial_hds[0]);
 975    serial_isa_init(isa_bus, 1, serial_hds[1]);
 976    if (parallel_hds[0])
 977        parallel_init(isa_bus, 0, parallel_hds[0]);
 978    for(i = 0; i < MAX_FD; i++) {
 979        fd[i] = drive_get(IF_FLOPPY, 0, i);
 980    }
 981    fdctrl_init_isa(isa_bus, fd);
 982
 983    /* Sound card */
 984    audio_init(isa_bus, pci_bus);
 985
 986    /* Network card */
 987    network_init();
 988
 989    /* Optional PCI video card */
 990    if (cirrus_vga_enabled) {
 991        pci_cirrus_vga_init(pci_bus);
 992    } else if (vmsvga_enabled) {
 993        pci_vmsvga_init(pci_bus);
 994    } else if (std_vga_enabled) {
 995        pci_vga_init(pci_bus);
 996    }
 997}
 998
 999static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
1000{
1001    return 0;
1002}
1003
1004static void mips_malta_class_init(ObjectClass *klass, void *data)
1005{
1006    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1007
1008    k->init = mips_malta_sysbus_device_init;
1009}
1010
1011static TypeInfo mips_malta_device = {
1012    .name          = "mips-malta",
1013    .parent        = TYPE_SYS_BUS_DEVICE,
1014    .instance_size = sizeof(MaltaState),
1015    .class_init    = mips_malta_class_init,
1016};
1017
1018static QEMUMachine mips_malta_machine = {
1019    .name = "malta",
1020    .desc = "MIPS Malta Core LV",
1021    .init = mips_malta_init,
1022    .max_cpus = 16,
1023    .is_default = 1,
1024};
1025
1026static void mips_malta_register_types(void)
1027{
1028    type_register_static(&mips_malta_device);
1029}
1030
1031static void mips_malta_machine_init(void)
1032{
1033    qemu_register_machine(&mips_malta_machine);
1034}
1035
1036type_init(mips_malta_register_types)
1037machine_init(mips_malta_machine_init);
1038