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