symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/mips_malta.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 
       
    63 typedef 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 
       
    76 static PITState *pit;
       
    77 
       
    78 static 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 */
       
    86 static 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 
       
   122 struct _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 
       
   134 typedef struct _eeprom24c0x_t eeprom24c0x_t;
       
   135 
       
   136 static 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 
       
   157 static 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 
       
   164 static 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 
       
   222 static 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 
       
   309 static 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 
       
   395 static CPUReadMemoryFunc *malta_fpga_read[] = {
       
   396    malta_fpga_readl,
       
   397    malta_fpga_readl,
       
   398    malta_fpga_readl
       
   399 };
       
   400 
       
   401 static CPUWriteMemoryFunc *malta_fpga_write[] = {
       
   402    malta_fpga_writel,
       
   403    malta_fpga_writel,
       
   404    malta_fpga_writel
       
   405 };
       
   406 
       
   407 static 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     malta_fpga_update_display(s);
       
   422 }
       
   423 
       
   424 static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
       
   425 {
       
   426     MaltaFPGAState *s;
       
   427     CharDriverState *uart_chr;
       
   428     int malta;
       
   429 
       
   430     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
       
   431 
       
   432     malta = cpu_register_io_memory(0, malta_fpga_read,
       
   433                                    malta_fpga_write, s);
       
   434 
       
   435     cpu_register_physical_memory(base, 0x900, malta);
       
   436     /* 0xa00 is less than a page, so will still get the right offsets.  */
       
   437     cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
       
   438 
       
   439     s->display = qemu_chr_open("fpga", "vc:320x200");
       
   440     qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
       
   441     qemu_chr_printf(s->display, "+--------+\r\n");
       
   442     qemu_chr_printf(s->display, "+        +\r\n");
       
   443     qemu_chr_printf(s->display, "+--------+\r\n");
       
   444     qemu_chr_printf(s->display, "\n");
       
   445     qemu_chr_printf(s->display, "Malta ASCII\r\n");
       
   446     qemu_chr_printf(s->display, "+--------+\r\n");
       
   447     qemu_chr_printf(s->display, "+        +\r\n");
       
   448     qemu_chr_printf(s->display, "+--------+\r\n");
       
   449 
       
   450     uart_chr = qemu_chr_open("cbus", "vc:80Cx24C");
       
   451     qemu_chr_printf(uart_chr, "CBUS UART\r\n");
       
   452     s->uart =
       
   453         serial_mm_init(base + 0x900, 3, env->irq[2], 230400, uart_chr, 1);
       
   454 
       
   455     malta_fpga_reset(s);
       
   456     qemu_register_reset(malta_fpga_reset, s);
       
   457 
       
   458     return s;
       
   459 }
       
   460 
       
   461 /* Audio support */
       
   462 #ifdef HAS_AUDIO
       
   463 static void audio_init (PCIBus *pci_bus)
       
   464 {
       
   465     struct soundhw *c;
       
   466     int audio_enabled = 0;
       
   467 
       
   468     for (c = soundhw; !audio_enabled && c->name; ++c) {
       
   469         audio_enabled = c->enabled;
       
   470     }
       
   471 
       
   472     if (audio_enabled) {
       
   473         AudioState *s;
       
   474 
       
   475         s = AUD_init ();
       
   476         if (s) {
       
   477             for (c = soundhw; c->name; ++c) {
       
   478                 if (c->enabled)
       
   479                     c->init.init_pci (pci_bus, s);
       
   480             }
       
   481         }
       
   482     }
       
   483 }
       
   484 #endif
       
   485 
       
   486 /* Network support */
       
   487 static void network_init (PCIBus *pci_bus)
       
   488 {
       
   489     int i;
       
   490     NICInfo *nd;
       
   491 
       
   492     for(i = 0; i < nb_nics; i++) {
       
   493         nd = &nd_table[i];
       
   494         if (!nd->model) {
       
   495             nd->model = "pcnet";
       
   496         }
       
   497         if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
       
   498             /* The malta board has a PCNet card using PCI SLOT 11 */
       
   499             pci_nic_init(pci_bus, nd, 88);
       
   500         } else {
       
   501             pci_nic_init(pci_bus, nd, -1);
       
   502         }
       
   503     }
       
   504 }
       
   505 
       
   506 /* ROM and pseudo bootloader
       
   507 
       
   508    The following code implements a very very simple bootloader. It first
       
   509    loads the registers a0 to a3 to the values expected by the OS, and
       
   510    then jump at the kernel address.
       
   511 
       
   512    The bootloader should pass the locations of the kernel arguments and
       
   513    environment variables tables. Those tables contain the 32-bit address
       
   514    of NULL terminated strings. The environment variables table should be
       
   515    terminated by a NULL address.
       
   516 
       
   517    For a simpler implementation, the number of kernel arguments is fixed
       
   518    to two (the name of the kernel and the command line), and the two
       
   519    tables are actually the same one.
       
   520 
       
   521    The registers a0 to a3 should contain the following values:
       
   522      a0 - number of kernel arguments
       
   523      a1 - 32-bit address of the kernel arguments table
       
   524      a2 - 32-bit address of the environment variables table
       
   525      a3 - RAM size in bytes
       
   526 */
       
   527 
       
   528 static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
       
   529 {
       
   530     uint32_t *p;
       
   531 
       
   532     /* Small bootloader */
       
   533     p = (uint32_t *) (phys_ram_base + bios_offset);
       
   534     stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
       
   535     stl_raw(p++, 0x00000000);                                      /* nop */
       
   536 
       
   537     /* YAMON service vector */
       
   538     stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
       
   539     stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
       
   540     stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
       
   541     stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
       
   542     stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
       
   543     stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
       
   544     stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
       
   545     stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
       
   546     stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
       
   547     stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
       
   548     stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
       
   549     stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
       
   550     stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
       
   551 
       
   552 
       
   553     /* Second part of the bootloader */
       
   554     p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
       
   555     stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
       
   556     stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
       
   557     stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
       
   558     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
       
   559     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
       
   560     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
       
   561     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
       
   562     stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
       
   563     stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
       
   564 
       
   565     /* Load BAR registers as done by YAMON */
       
   566     stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
       
   567 
       
   568 #ifdef TARGET_WORDS_BIGENDIAN
       
   569     stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
       
   570 #else
       
   571     stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
       
   572 #endif
       
   573     stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
       
   574 
       
   575     stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
       
   576 
       
   577 #ifdef TARGET_WORDS_BIGENDIAN
       
   578     stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
       
   579 #else
       
   580     stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
       
   581 #endif
       
   582     stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
       
   583 #ifdef TARGET_WORDS_BIGENDIAN
       
   584     stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
       
   585 #else
       
   586     stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
       
   587 #endif
       
   588     stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
       
   589 
       
   590 #ifdef TARGET_WORDS_BIGENDIAN
       
   591     stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
       
   592 #else
       
   593     stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
       
   594 #endif
       
   595     stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
       
   596 #ifdef TARGET_WORDS_BIGENDIAN
       
   597     stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
       
   598 #else
       
   599     stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
       
   600 #endif
       
   601     stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
       
   602 
       
   603 #ifdef TARGET_WORDS_BIGENDIAN
       
   604     stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
       
   605 #else
       
   606     stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
       
   607 #endif
       
   608     stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
       
   609 #ifdef TARGET_WORDS_BIGENDIAN
       
   610     stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
       
   611 #else
       
   612     stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
       
   613 #endif
       
   614     stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
       
   615 
       
   616     /* Jump to kernel code */
       
   617     stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
       
   618     stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
       
   619     stl_raw(p++, 0x03e00008);                                      /* jr ra */
       
   620     stl_raw(p++, 0x00000000);                                      /* nop */
       
   621 
       
   622     /* YAMON subroutines */
       
   623     p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
       
   624     stl_raw(p++, 0x03e00008);                                     /* jr ra */
       
   625     stl_raw(p++, 0x24020000);                                     /* li v0,0 */
       
   626    /* 808 YAMON print */
       
   627     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
       
   628     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
       
   629     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
       
   630     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
       
   631     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
       
   632     stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
       
   633     stl_raw(p++, 0x00000000);                                     /* nop */
       
   634     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
       
   635     stl_raw(p++, 0x00000000);                                     /* nop */
       
   636     stl_raw(p++, 0x08000205);                                     /* j 814 */
       
   637     stl_raw(p++, 0x00000000);                                     /* nop */
       
   638     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
       
   639     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
       
   640     /* 0x83c YAMON print_count */
       
   641     stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
       
   642     stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
       
   643     stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
       
   644     stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
       
   645     stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
       
   646     stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
       
   647     stl_raw(p++, 0x00000000);                                     /* nop */
       
   648     stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
       
   649     stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
       
   650     stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
       
   651     stl_raw(p++, 0x00000000);                                     /* nop */
       
   652     stl_raw(p++, 0x01a00008);                                     /* jr t5 */
       
   653     stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
       
   654     /* 0x870 */
       
   655     stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
       
   656     stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
       
   657     stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
       
   658     stl_raw(p++, 0x00000000);                                     /* nop */
       
   659     stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
       
   660     stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
       
   661     stl_raw(p++, 0x00000000);                                     /* nop */
       
   662     stl_raw(p++, 0x03e00008);                                     /* jr ra */
       
   663     stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
       
   664 
       
   665 }
       
   666 
       
   667 static void prom_set(int index, const char *string, ...)
       
   668 {
       
   669     va_list ap;
       
   670     int32_t *p;
       
   671     int32_t table_addr;
       
   672     char *s;
       
   673 
       
   674     if (index >= ENVP_NB_ENTRIES)
       
   675         return;
       
   676 
       
   677     p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
       
   678     p += index;
       
   679 
       
   680     if (string == NULL) {
       
   681         stl_raw(p, 0);
       
   682         return;
       
   683     }
       
   684 
       
   685     table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
       
   686     s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
       
   687 
       
   688     stl_raw(p, table_addr);
       
   689 
       
   690     va_start(ap, string);
       
   691     vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
       
   692     va_end(ap);
       
   693 }
       
   694 
       
   695 /* Kernel */
       
   696 static int64_t load_kernel (CPUState *env)
       
   697 {
       
   698     int64_t kernel_entry, kernel_low, kernel_high;
       
   699     int index = 0;
       
   700     long initrd_size;
       
   701     ram_addr_t initrd_offset;
       
   702 
       
   703     if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
       
   704                  (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
       
   705                  (uint64_t *)&kernel_high) < 0) {
       
   706         fprintf(stderr, "qemu: could not load kernel '%s'\n",
       
   707                 loaderparams.kernel_filename);
       
   708         exit(1);
       
   709     }
       
   710 
       
   711     /* load initrd */
       
   712     initrd_size = 0;
       
   713     initrd_offset = 0;
       
   714     if (loaderparams.initrd_filename) {
       
   715         initrd_size = get_image_size (loaderparams.initrd_filename);
       
   716         if (initrd_size > 0) {
       
   717             initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
       
   718             if (initrd_offset + initrd_size > ram_size) {
       
   719                 fprintf(stderr,
       
   720                         "qemu: memory too small for initial ram disk '%s'\n",
       
   721                         loaderparams.initrd_filename);
       
   722                 exit(1);
       
   723             }
       
   724             initrd_size = load_image(loaderparams.initrd_filename,
       
   725                                      phys_ram_base + initrd_offset);
       
   726         }
       
   727         if (initrd_size == (target_ulong) -1) {
       
   728             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
       
   729                     loaderparams.initrd_filename);
       
   730             exit(1);
       
   731         }
       
   732     }
       
   733 
       
   734     /* Store command line.  */
       
   735     prom_set(index++, loaderparams.kernel_filename);
       
   736     if (initrd_size > 0)
       
   737         prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
       
   738                  PHYS_TO_VIRT(initrd_offset), initrd_size,
       
   739                  loaderparams.kernel_cmdline);
       
   740     else
       
   741         prom_set(index++, loaderparams.kernel_cmdline);
       
   742 
       
   743     /* Setup minimum environment variables */
       
   744     prom_set(index++, "memsize");
       
   745     prom_set(index++, "%i", loaderparams.ram_size);
       
   746     prom_set(index++, "modetty0");
       
   747     prom_set(index++, "38400n8r");
       
   748     prom_set(index++, NULL);
       
   749 
       
   750     return kernel_entry;
       
   751 }
       
   752 
       
   753 static void main_cpu_reset(void *opaque)
       
   754 {
       
   755     CPUState *env = opaque;
       
   756     cpu_reset(env);
       
   757 
       
   758     /* The bootload does not need to be rewritten as it is located in a
       
   759        read only location. The kernel location and the arguments table
       
   760        location does not change. */
       
   761     if (loaderparams.kernel_filename) {
       
   762         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
       
   763         load_kernel (env);
       
   764     }
       
   765 }
       
   766 
       
   767 static
       
   768 void mips_malta_init (ram_addr_t ram_size, int vga_ram_size,
       
   769                       const char *boot_device, DisplayState *ds,
       
   770                       const char *kernel_filename, const char *kernel_cmdline,
       
   771                       const char *initrd_filename, const char *cpu_model)
       
   772 {
       
   773     char buf[1024];
       
   774     unsigned long bios_offset;
       
   775     target_long bios_size;
       
   776     int64_t kernel_entry;
       
   777     PCIBus *pci_bus;
       
   778     CPUState *env;
       
   779     RTCState *rtc_state;
       
   780     fdctrl_t *floppy_controller;
       
   781     MaltaFPGAState *malta_fpga;
       
   782     qemu_irq *i8259;
       
   783     int piix4_devfn;
       
   784     uint8_t *eeprom_buf;
       
   785     i2c_bus *smbus;
       
   786     int i;
       
   787     int index;
       
   788     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
       
   789     BlockDriverState *fd[MAX_FD];
       
   790     int fl_idx = 0;
       
   791     int fl_sectors = 0;
       
   792 
       
   793     /* init CPUs */
       
   794     if (cpu_model == NULL) {
       
   795 #ifdef TARGET_MIPS64
       
   796         cpu_model = "20Kc";
       
   797 #else
       
   798         cpu_model = "24Kf";
       
   799 #endif
       
   800     }
       
   801     env = cpu_init(cpu_model);
       
   802     if (!env) {
       
   803         fprintf(stderr, "Unable to find CPU definition\n");
       
   804         exit(1);
       
   805     }
       
   806     qemu_register_reset(main_cpu_reset, env);
       
   807 
       
   808     /* allocate RAM */
       
   809     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
       
   810 
       
   811     /* Map the bios at two physical locations, as on the real board. */
       
   812     bios_offset = ram_size + vga_ram_size;
       
   813     cpu_register_physical_memory(0x1e000000LL,
       
   814                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
       
   815     cpu_register_physical_memory(0x1fc00000LL,
       
   816                                  BIOS_SIZE, bios_offset | IO_MEM_ROM);
       
   817 
       
   818     /* FPGA */
       
   819     malta_fpga = malta_fpga_init(0x1f000000LL, env);
       
   820 
       
   821     /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
       
   822     if (kernel_filename) {
       
   823         /* Write a small bootloader to the flash location. */
       
   824         loaderparams.ram_size = ram_size;
       
   825         loaderparams.kernel_filename = kernel_filename;
       
   826         loaderparams.kernel_cmdline = kernel_cmdline;
       
   827         loaderparams.initrd_filename = initrd_filename;
       
   828         kernel_entry = load_kernel(env);
       
   829         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
       
   830         write_bootloader(env, bios_offset, kernel_entry);
       
   831     } else {
       
   832         index = drive_get_index(IF_PFLASH, 0, fl_idx);
       
   833         if (index != -1) {
       
   834             /* Load firmware from flash. */
       
   835             bios_size = 0x400000;
       
   836             fl_sectors = bios_size >> 16;
       
   837 #ifdef DEBUG_BOARD_INIT
       
   838             printf("Register parallel flash %d size " TARGET_FMT_lx " at "
       
   839                    "offset %08lx addr %08llx '%s' %x\n",
       
   840                    fl_idx, bios_size, bios_offset, 0x1e000000LL,
       
   841                    bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
       
   842 #endif
       
   843             pflash_cfi01_register(0x1e000000LL, bios_offset,
       
   844                                   drives_table[index].bdrv, 65536, fl_sectors,
       
   845                                   4, 0x0000, 0x0000, 0x0000, 0x0000);
       
   846             fl_idx++;
       
   847         } else {
       
   848             /* Load a BIOS image. */
       
   849             if (bios_name == NULL)
       
   850                 bios_name = BIOS_FILENAME;
       
   851             snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
       
   852             bios_size = load_image(buf, phys_ram_base + bios_offset);
       
   853             if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
       
   854                 fprintf(stderr,
       
   855                         "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
       
   856                         buf);
       
   857                 exit(1);
       
   858             }
       
   859         }
       
   860         /* In little endian mode the 32bit words in the bios are swapped,
       
   861            a neat trick which allows bi-endian firmware. */
       
   862 #ifndef TARGET_WORDS_BIGENDIAN
       
   863         {
       
   864             uint32_t *addr;
       
   865             for (addr = (uint32_t *)(phys_ram_base + bios_offset);
       
   866                  addr < (uint32_t *)(phys_ram_base + bios_offset + bios_size);
       
   867                  addr++) {
       
   868                 *addr = bswap32(*addr);
       
   869             }
       
   870         }
       
   871 #endif
       
   872     }
       
   873 
       
   874     /* Board ID = 0x420 (Malta Board with CoreLV)
       
   875        XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
       
   876        map to the board ID. */
       
   877     stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
       
   878 
       
   879     /* Init internal devices */
       
   880     cpu_mips_irq_init_cpu(env);
       
   881     cpu_mips_clock_init(env);
       
   882 
       
   883     /* Interrupt controller */
       
   884     /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
       
   885     i8259 = i8259_init(env->irq[2]);
       
   886 
       
   887     /* Northbridge */
       
   888     pci_bus = pci_gt64120_init(i8259);
       
   889 
       
   890     /* Southbridge */
       
   891 
       
   892     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
       
   893         fprintf(stderr, "qemu: too many IDE bus\n");
       
   894         exit(1);
       
   895     }
       
   896 
       
   897     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
       
   898         index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
       
   899         if (index != -1)
       
   900             hd[i] = drives_table[index].bdrv;
       
   901         else
       
   902             hd[i] = NULL;
       
   903     }
       
   904 
       
   905     piix4_devfn = piix4_init(pci_bus, 80);
       
   906     pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1, i8259);
       
   907     usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
       
   908     smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, i8259[9]);
       
   909     eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
       
   910     for (i = 0; i < 8; i++) {
       
   911         /* TODO: Populate SPD eeprom data.  */
       
   912         smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
       
   913     }
       
   914     pit = pit_init(0x40, i8259[0]);
       
   915     DMA_init(0);
       
   916 
       
   917     /* Super I/O */
       
   918     i8042_init(i8259[1], i8259[12], 0x60);
       
   919     rtc_state = rtc_init(0x70, i8259[8]);
       
   920     if (serial_hds[0])
       
   921         serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
       
   922     if (serial_hds[1])
       
   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     pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
       
   945                         ram_size, vga_ram_size);
       
   946 }
       
   947 
       
   948 QEMUMachine mips_malta_machine = {
       
   949     .name = "malta",
       
   950     .desc = "MIPS Malta Core LV",
       
   951     .init = mips_malta_init,
       
   952     .ram_require = VGA_RAM_SIZE + BIOS_SIZE,
       
   953     .nodisk_ok = 1,
       
   954 };