Statistics
| Branch: | Revision:

root / hw / mips / mips_malta.c @ 05318a85

History | View | Annotate | Download (33.6 kB)

1 5856de80 ths
/*
2 5856de80 ths
 * QEMU Malta board support
3 5856de80 ths
 *
4 5856de80 ths
 * Copyright (c) 2006 Aurelien Jarno
5 5856de80 ths
 *
6 5856de80 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 5856de80 ths
 * of this software and associated documentation files (the "Software"), to deal
8 5856de80 ths
 * in the Software without restriction, including without limitation the rights
9 5856de80 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 5856de80 ths
 * copies of the Software, and to permit persons to whom the Software is
11 5856de80 ths
 * furnished to do so, subject to the following conditions:
12 5856de80 ths
 *
13 5856de80 ths
 * The above copyright notice and this permission notice shall be included in
14 5856de80 ths
 * all copies or substantial portions of the Software.
15 5856de80 ths
 *
16 5856de80 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 5856de80 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 5856de80 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 5856de80 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 5856de80 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 5856de80 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 5856de80 ths
 * THE SOFTWARE.
23 5856de80 ths
 */
24 5856de80 ths
25 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
26 0d09e41a Paolo Bonzini
#include "hw/i386/pc.h"
27 0d09e41a Paolo Bonzini
#include "hw/char/serial.h"
28 0d09e41a Paolo Bonzini
#include "hw/block/fdc.h"
29 1422e32d Paolo Bonzini
#include "net/net.h"
30 83c9f4ca Paolo Bonzini
#include "hw/boards.h"
31 0d09e41a Paolo Bonzini
#include "hw/i2c/smbus.h"
32 737e150e Paolo Bonzini
#include "block/block.h"
33 0d09e41a Paolo Bonzini
#include "hw/block/flash.h"
34 0d09e41a Paolo Bonzini
#include "hw/mips/mips.h"
35 0d09e41a Paolo Bonzini
#include "hw/mips/cpudevs.h"
36 83c9f4ca Paolo Bonzini
#include "hw/pci/pci.h"
37 dccfcd0e Paolo Bonzini
#include "sysemu/char.h"
38 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
39 9c17d615 Paolo Bonzini
#include "sysemu/arch_init.h"
40 1de7afc9 Paolo Bonzini
#include "qemu/log.h"
41 0d09e41a Paolo Bonzini
#include "hw/mips/bios.h"
42 83c9f4ca Paolo Bonzini
#include "hw/ide.h"
43 83c9f4ca Paolo Bonzini
#include "hw/loader.h"
44 ca20cf32 Blue Swirl
#include "elf.h"
45 0d09e41a Paolo Bonzini
#include "hw/timer/mc146818rtc.h"
46 0d09e41a Paolo Bonzini
#include "hw/timer/i8254.h"
47 9c17d615 Paolo Bonzini
#include "sysemu/blockdev.h"
48 022c62cb Paolo Bonzini
#include "exec/address-spaces.h"
49 83c9f4ca Paolo Bonzini
#include "hw/sysbus.h"             /* SysBusDevice */
50 5856de80 ths
51 c8b153d7 ths
//#define DEBUG_BOARD_INIT
52 c8b153d7 ths
53 409dbce5 Aurelien Jarno
#define ENVP_ADDR                0x80002000l
54 5856de80 ths
#define ENVP_NB_ENTRIES                 16
55 5856de80 ths
#define ENVP_ENTRY_SIZE                 256
56 5856de80 ths
57 03a1a8e1 Stefan Weil
/* Hardware addresses */
58 03a1a8e1 Stefan Weil
#define FLASH_ADDRESS 0x1e000000ULL
59 03a1a8e1 Stefan Weil
#define FPGA_ADDRESS  0x1f000000ULL
60 03a1a8e1 Stefan Weil
#define RESET_ADDRESS 0x1fc00000ULL
61 03a1a8e1 Stefan Weil
62 03a1a8e1 Stefan Weil
#define FLASH_SIZE    0x400000
63 03a1a8e1 Stefan Weil
64 e4bcb14c ths
#define MAX_IDE_BUS 2
65 e4bcb14c ths
66 5856de80 ths
typedef struct {
67 ea85df72 Avi Kivity
    MemoryRegion iomem;
68 ea85df72 Avi Kivity
    MemoryRegion iomem_lo; /* 0 - 0x900 */
69 ea85df72 Avi Kivity
    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
70 5856de80 ths
    uint32_t leds;
71 5856de80 ths
    uint32_t brk;
72 5856de80 ths
    uint32_t gpout;
73 130751ee ths
    uint32_t i2cin;
74 5856de80 ths
    uint32_t i2coe;
75 5856de80 ths
    uint32_t i2cout;
76 5856de80 ths
    uint32_t i2csel;
77 5856de80 ths
    CharDriverState *display;
78 5856de80 ths
    char display_text[9];
79 a4bc3afc ths
    SerialState *uart;
80 5856de80 ths
} MaltaFPGAState;
81 5856de80 ths
82 e9b40fd3 Stefan Weil
typedef struct {
83 e9b40fd3 Stefan Weil
    SysBusDevice busdev;
84 e9b40fd3 Stefan Weil
    qemu_irq *i8259;
85 e9b40fd3 Stefan Weil
} MaltaState;
86 e9b40fd3 Stefan Weil
87 64d7e9a4 Blue Swirl
static ISADevice *pit;
88 5856de80 ths
89 7df526e3 ths
static struct _loaderparams {
90 7df526e3 ths
    int ram_size;
91 7df526e3 ths
    const char *kernel_filename;
92 7df526e3 ths
    const char *kernel_cmdline;
93 7df526e3 ths
    const char *initrd_filename;
94 7df526e3 ths
} loaderparams;
95 7df526e3 ths
96 5856de80 ths
/* Malta FPGA */
97 5856de80 ths
static void malta_fpga_update_display(void *opaque)
98 5856de80 ths
{
99 5856de80 ths
    char leds_text[9];
100 5856de80 ths
    int i;
101 5856de80 ths
    MaltaFPGAState *s = opaque;
102 5856de80 ths
103 07cf0ba0 ths
    for (i = 7 ; i >= 0 ; i--) {
104 07cf0ba0 ths
        if (s->leds & (1 << i))
105 07cf0ba0 ths
            leds_text[i] = '#';
106 07cf0ba0 ths
        else
107 07cf0ba0 ths
            leds_text[i] = ' ';
108 87ee1669 ths
    }
109 07cf0ba0 ths
    leds_text[8] = '\0';
110 07cf0ba0 ths
111 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
112 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
113 5856de80 ths
}
114 5856de80 ths
115 130751ee ths
/*
116 130751ee ths
 * EEPROM 24C01 / 24C02 emulation.
117 130751ee ths
 *
118 130751ee ths
 * Emulation for serial EEPROMs:
119 130751ee ths
 * 24C01 - 1024 bit (128 x 8)
120 130751ee ths
 * 24C02 - 2048 bit (256 x 8)
121 130751ee ths
 *
122 130751ee ths
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
123 130751ee ths
 */
124 130751ee ths
125 130751ee ths
//~ #define DEBUG
126 130751ee ths
127 130751ee ths
#if defined(DEBUG)
128 001faf32 Blue Swirl
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
129 130751ee ths
#else
130 001faf32 Blue Swirl
#  define logout(fmt, ...) ((void)0)
131 130751ee ths
#endif
132 130751ee ths
133 c227f099 Anthony Liguori
struct _eeprom24c0x_t {
134 130751ee ths
  uint8_t tick;
135 130751ee ths
  uint8_t address;
136 130751ee ths
  uint8_t command;
137 130751ee ths
  uint8_t ack;
138 130751ee ths
  uint8_t scl;
139 130751ee ths
  uint8_t sda;
140 130751ee ths
  uint8_t data;
141 130751ee ths
  //~ uint16_t size;
142 130751ee ths
  uint8_t contents[256];
143 130751ee ths
};
144 130751ee ths
145 c227f099 Anthony Liguori
typedef struct _eeprom24c0x_t eeprom24c0x_t;
146 130751ee ths
147 c227f099 Anthony Liguori
static eeprom24c0x_t eeprom = {
148 284b08f1 Blue Swirl
    .contents = {
149 130751ee ths
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
150 130751ee ths
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
151 130751ee ths
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
152 130751ee ths
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
153 130751ee ths
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
154 130751ee ths
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
155 130751ee ths
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
156 130751ee ths
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
157 130751ee ths
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
158 130751ee ths
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
159 130751ee ths
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160 130751ee ths
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
161 130751ee ths
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
162 130751ee ths
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
163 130751ee ths
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
164 130751ee ths
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
165 130751ee ths
    },
166 130751ee ths
};
167 130751ee ths
168 a5f1b965 blueswir1
static uint8_t eeprom24c0x_read(void)
169 130751ee ths
{
170 130751ee ths
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
171 130751ee ths
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
172 130751ee ths
    return eeprom.sda;
173 130751ee ths
}
174 130751ee ths
175 130751ee ths
static void eeprom24c0x_write(int scl, int sda)
176 130751ee ths
{
177 130751ee ths
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
178 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
179 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
180 130751ee ths
        if (!sda) {
181 130751ee ths
            eeprom.tick = 1;
182 130751ee ths
            eeprom.command = 0;
183 130751ee ths
        }
184 130751ee ths
    } else if (eeprom.tick == 0 && !eeprom.ack) {
185 130751ee ths
        /* Waiting for start. */
186 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
187 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
188 130751ee ths
    } else if (!eeprom.scl && scl) {
189 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
190 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
191 130751ee ths
        if (eeprom.ack) {
192 130751ee ths
            logout("\ti2c ack bit = 0\n");
193 130751ee ths
            sda = 0;
194 130751ee ths
            eeprom.ack = 0;
195 130751ee ths
        } else if (eeprom.sda == sda) {
196 130751ee ths
            uint8_t bit = (sda != 0);
197 130751ee ths
            logout("\ti2c bit = %d\n", bit);
198 130751ee ths
            if (eeprom.tick < 9) {
199 130751ee ths
                eeprom.command <<= 1;
200 130751ee ths
                eeprom.command += bit;
201 130751ee ths
                eeprom.tick++;
202 130751ee ths
                if (eeprom.tick == 9) {
203 130751ee ths
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
204 130751ee ths
                    eeprom.ack = 1;
205 130751ee ths
                }
206 130751ee ths
            } else if (eeprom.tick < 17) {
207 130751ee ths
                if (eeprom.command & 1) {
208 130751ee ths
                    sda = ((eeprom.data & 0x80) != 0);
209 130751ee ths
                }
210 130751ee ths
                eeprom.address <<= 1;
211 130751ee ths
                eeprom.address += bit;
212 130751ee ths
                eeprom.tick++;
213 130751ee ths
                eeprom.data <<= 1;
214 130751ee ths
                if (eeprom.tick == 17) {
215 130751ee ths
                    eeprom.data = eeprom.contents[eeprom.address];
216 130751ee ths
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
217 130751ee ths
                    eeprom.ack = 1;
218 130751ee ths
                    eeprom.tick = 0;
219 130751ee ths
                }
220 130751ee ths
            } else if (eeprom.tick >= 17) {
221 130751ee ths
                sda = 0;
222 130751ee ths
            }
223 130751ee ths
        } else {
224 130751ee ths
            logout("\tsda changed with raising scl\n");
225 130751ee ths
        }
226 130751ee ths
    } else {
227 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
228 130751ee ths
    }
229 130751ee ths
    eeprom.scl = scl;
230 130751ee ths
    eeprom.sda = sda;
231 130751ee ths
}
232 130751ee ths
233 a8170e5e Avi Kivity
static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
234 ea85df72 Avi Kivity
                                unsigned size)
235 5856de80 ths
{
236 5856de80 ths
    MaltaFPGAState *s = opaque;
237 5856de80 ths
    uint32_t val = 0;
238 5856de80 ths
    uint32_t saddr;
239 5856de80 ths
240 5856de80 ths
    saddr = (addr & 0xfffff);
241 5856de80 ths
242 5856de80 ths
    switch (saddr) {
243 5856de80 ths
244 5856de80 ths
    /* SWITCH Register */
245 5856de80 ths
    case 0x00200:
246 5856de80 ths
        val = 0x00000000;                /* All switches closed */
247 593c0d10 Aurelien Jarno
        break;
248 5856de80 ths
249 5856de80 ths
    /* STATUS Register */
250 5856de80 ths
    case 0x00208:
251 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
252 5856de80 ths
        val = 0x00000012;
253 5856de80 ths
#else
254 5856de80 ths
        val = 0x00000010;
255 5856de80 ths
#endif
256 5856de80 ths
        break;
257 5856de80 ths
258 5856de80 ths
    /* JMPRS Register */
259 5856de80 ths
    case 0x00210:
260 5856de80 ths
        val = 0x00;
261 5856de80 ths
        break;
262 5856de80 ths
263 5856de80 ths
    /* LEDBAR Register */
264 5856de80 ths
    case 0x00408:
265 5856de80 ths
        val = s->leds;
266 5856de80 ths
        break;
267 5856de80 ths
268 5856de80 ths
    /* BRKRES Register */
269 5856de80 ths
    case 0x00508:
270 5856de80 ths
        val = s->brk;
271 5856de80 ths
        break;
272 5856de80 ths
273 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
274 a4bc3afc ths
275 5856de80 ths
    /* GPOUT Register */
276 5856de80 ths
    case 0x00a00:
277 5856de80 ths
        val = s->gpout;
278 5856de80 ths
        break;
279 5856de80 ths
280 5856de80 ths
    /* XXX: implement a real I2C controller */
281 5856de80 ths
282 5856de80 ths
    /* GPINP Register */
283 5856de80 ths
    case 0x00a08:
284 5856de80 ths
        /* IN = OUT until a real I2C control is implemented */
285 5856de80 ths
        if (s->i2csel)
286 5856de80 ths
            val = s->i2cout;
287 5856de80 ths
        else
288 5856de80 ths
            val = 0x00;
289 5856de80 ths
        break;
290 5856de80 ths
291 5856de80 ths
    /* I2CINP Register */
292 5856de80 ths
    case 0x00b00:
293 130751ee ths
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
294 5856de80 ths
        break;
295 5856de80 ths
296 5856de80 ths
    /* I2COE Register */
297 5856de80 ths
    case 0x00b08:
298 5856de80 ths
        val = s->i2coe;
299 5856de80 ths
        break;
300 5856de80 ths
301 5856de80 ths
    /* I2COUT Register */
302 5856de80 ths
    case 0x00b10:
303 5856de80 ths
        val = s->i2cout;
304 5856de80 ths
        break;
305 5856de80 ths
306 5856de80 ths
    /* I2CSEL Register */
307 5856de80 ths
    case 0x00b18:
308 130751ee ths
        val = s->i2csel;
309 5856de80 ths
        break;
310 5856de80 ths
311 5856de80 ths
    default:
312 5856de80 ths
#if 0
313 3594c774 ths
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
314 593c0d10 Aurelien Jarno
                addr);
315 5856de80 ths
#endif
316 5856de80 ths
        break;
317 5856de80 ths
    }
318 5856de80 ths
    return val;
319 5856de80 ths
}
320 5856de80 ths
321 a8170e5e Avi Kivity
static void malta_fpga_write(void *opaque, hwaddr addr,
322 ea85df72 Avi Kivity
                             uint64_t val, unsigned size)
323 5856de80 ths
{
324 5856de80 ths
    MaltaFPGAState *s = opaque;
325 5856de80 ths
    uint32_t saddr;
326 5856de80 ths
327 5856de80 ths
    saddr = (addr & 0xfffff);
328 5856de80 ths
329 5856de80 ths
    switch (saddr) {
330 5856de80 ths
331 5856de80 ths
    /* SWITCH Register */
332 5856de80 ths
    case 0x00200:
333 5856de80 ths
        break;
334 5856de80 ths
335 5856de80 ths
    /* JMPRS Register */
336 5856de80 ths
    case 0x00210:
337 5856de80 ths
        break;
338 5856de80 ths
339 5856de80 ths
    /* LEDBAR Register */
340 5856de80 ths
    case 0x00408:
341 5856de80 ths
        s->leds = val & 0xff;
342 1d7a1197 Stefan Weil
        malta_fpga_update_display(s);
343 5856de80 ths
        break;
344 5856de80 ths
345 5856de80 ths
    /* ASCIIWORD Register */
346 5856de80 ths
    case 0x00410:
347 ea85df72 Avi Kivity
        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
348 5856de80 ths
        malta_fpga_update_display(s);
349 5856de80 ths
        break;
350 5856de80 ths
351 5856de80 ths
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
352 5856de80 ths
    case 0x00418:
353 5856de80 ths
    case 0x00420:
354 5856de80 ths
    case 0x00428:
355 5856de80 ths
    case 0x00430:
356 5856de80 ths
    case 0x00438:
357 5856de80 ths
    case 0x00440:
358 5856de80 ths
    case 0x00448:
359 5856de80 ths
    case 0x00450:
360 5856de80 ths
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
361 5856de80 ths
        malta_fpga_update_display(s);
362 5856de80 ths
        break;
363 5856de80 ths
364 5856de80 ths
    /* SOFTRES Register */
365 5856de80 ths
    case 0x00500:
366 5856de80 ths
        if (val == 0x42)
367 5856de80 ths
            qemu_system_reset_request ();
368 5856de80 ths
        break;
369 5856de80 ths
370 5856de80 ths
    /* BRKRES Register */
371 5856de80 ths
    case 0x00508:
372 5856de80 ths
        s->brk = val & 0xff;
373 5856de80 ths
        break;
374 5856de80 ths
375 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
376 a4bc3afc ths
377 5856de80 ths
    /* GPOUT Register */
378 5856de80 ths
    case 0x00a00:
379 5856de80 ths
        s->gpout = val & 0xff;
380 5856de80 ths
        break;
381 5856de80 ths
382 5856de80 ths
    /* I2COE Register */
383 5856de80 ths
    case 0x00b08:
384 5856de80 ths
        s->i2coe = val & 0x03;
385 5856de80 ths
        break;
386 5856de80 ths
387 5856de80 ths
    /* I2COUT Register */
388 5856de80 ths
    case 0x00b10:
389 130751ee ths
        eeprom24c0x_write(val & 0x02, val & 0x01);
390 130751ee ths
        s->i2cout = val;
391 5856de80 ths
        break;
392 5856de80 ths
393 5856de80 ths
    /* I2CSEL Register */
394 5856de80 ths
    case 0x00b18:
395 130751ee ths
        s->i2csel = val & 0x01;
396 5856de80 ths
        break;
397 5856de80 ths
398 5856de80 ths
    default:
399 5856de80 ths
#if 0
400 3594c774 ths
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
401 593c0d10 Aurelien Jarno
                addr);
402 5856de80 ths
#endif
403 5856de80 ths
        break;
404 5856de80 ths
    }
405 5856de80 ths
}
406 5856de80 ths
407 ea85df72 Avi Kivity
static const MemoryRegionOps malta_fpga_ops = {
408 ea85df72 Avi Kivity
    .read = malta_fpga_read,
409 ea85df72 Avi Kivity
    .write = malta_fpga_write,
410 ea85df72 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
411 5856de80 ths
};
412 5856de80 ths
413 9596ebb7 pbrook
static void malta_fpga_reset(void *opaque)
414 5856de80 ths
{
415 5856de80 ths
    MaltaFPGAState *s = opaque;
416 5856de80 ths
417 5856de80 ths
    s->leds   = 0x00;
418 5856de80 ths
    s->brk    = 0x0a;
419 5856de80 ths
    s->gpout  = 0x00;
420 130751ee ths
    s->i2cin  = 0x3;
421 5856de80 ths
    s->i2coe  = 0x0;
422 5856de80 ths
    s->i2cout = 0x3;
423 5856de80 ths
    s->i2csel = 0x1;
424 5856de80 ths
425 5856de80 ths
    s->display_text[8] = '\0';
426 5856de80 ths
    snprintf(s->display_text, 9, "        ");
427 ceecf1d1 aurel32
}
428 ceecf1d1 aurel32
429 ceecf1d1 aurel32
static void malta_fpga_led_init(CharDriverState *chr)
430 ceecf1d1 aurel32
{
431 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
432 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
433 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+        +\r\n");
434 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
435 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "\n");
436 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
437 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
438 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+        +\r\n");
439 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
440 5856de80 ths
}
441 5856de80 ths
442 ea85df72 Avi Kivity
static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
443 a8170e5e Avi Kivity
         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
444 5856de80 ths
{
445 5856de80 ths
    MaltaFPGAState *s;
446 5856de80 ths
447 7267c094 Anthony Liguori
    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
448 5856de80 ths
449 ea85df72 Avi Kivity
    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
450 ea85df72 Avi Kivity
                          "malta-fpga", 0x100000);
451 ea85df72 Avi Kivity
    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
452 ea85df72 Avi Kivity
                             &s->iomem, 0, 0x900);
453 ea85df72 Avi Kivity
    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
454 ea85df72 Avi Kivity
                             &s->iomem, 0xa00, 0x10000-0xa00);
455 a4bc3afc ths
456 ea85df72 Avi Kivity
    memory_region_add_subregion(address_space, base, &s->iomem_lo);
457 ea85df72 Avi Kivity
    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
458 5856de80 ths
459 27143a44 Anthony Liguori
    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
460 ceecf1d1 aurel32
461 39186d8a Richard Henderson
    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
462 39186d8a Richard Henderson
                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
463 a4bc3afc ths
464 5856de80 ths
    malta_fpga_reset(s);
465 a08d4367 Jan Kiszka
    qemu_register_reset(malta_fpga_reset, s);
466 5856de80 ths
467 5856de80 ths
    return s;
468 5856de80 ths
}
469 5856de80 ths
470 5856de80 ths
/* Network support */
471 5607c388 Markus Armbruster
static void network_init(void)
472 5856de80 ths
{
473 5856de80 ths
    int i;
474 5856de80 ths
475 5856de80 ths
    for(i = 0; i < nb_nics; i++) {
476 cb457d76 aliguori
        NICInfo *nd = &nd_table[i];
477 5607c388 Markus Armbruster
        const char *default_devaddr = NULL;
478 cb457d76 aliguori
479 cb457d76 aliguori
        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
480 5856de80 ths
            /* The malta board has a PCNet card using PCI SLOT 11 */
481 5607c388 Markus Armbruster
            default_devaddr = "0b";
482 cb457d76 aliguori
483 07caea31 Markus Armbruster
        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
484 5856de80 ths
    }
485 5856de80 ths
}
486 5856de80 ths
487 5856de80 ths
/* ROM and pseudo bootloader
488 5856de80 ths

489 5856de80 ths
   The following code implements a very very simple bootloader. It first
490 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
491 5856de80 ths
   then jump at the kernel address.
492 5856de80 ths

493 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
494 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
495 5856de80 ths
   of NULL terminated strings. The environment variables table should be
496 5856de80 ths
   terminated by a NULL address.
497 5856de80 ths

498 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
499 5856de80 ths
   to two (the name of the kernel and the command line), and the two
500 5856de80 ths
   tables are actually the same one.
501 5856de80 ths

502 5856de80 ths
   The registers a0 to a3 should contain the following values:
503 5856de80 ths
     a0 - number of kernel arguments
504 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
505 5856de80 ths
     a2 - 32-bit address of the environment variables table
506 5856de80 ths
     a3 - RAM size in bytes
507 5856de80 ths
*/
508 5856de80 ths
509 61c56c8c Andreas Färber
static void write_bootloader (CPUMIPSState *env, uint8_t *base,
510 d7585251 pbrook
                              int64_t kernel_entry)
511 5856de80 ths
{
512 5856de80 ths
    uint32_t *p;
513 5856de80 ths
514 5856de80 ths
    /* Small bootloader */
515 d7585251 pbrook
    p = (uint32_t *)base;
516 26ea0918 ths
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
517 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
518 5856de80 ths
519 26ea0918 ths
    /* YAMON service vector */
520 d7585251 pbrook
    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
521 d7585251 pbrook
    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
522 d7585251 pbrook
    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
523 d7585251 pbrook
    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
524 d7585251 pbrook
    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
525 d7585251 pbrook
    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
526 d7585251 pbrook
    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
527 d7585251 pbrook
    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
528 d7585251 pbrook
    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
529 d7585251 pbrook
    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
530 d7585251 pbrook
    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
531 d7585251 pbrook
    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
532 d7585251 pbrook
    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
533 26ea0918 ths
534 26ea0918 ths
535 5856de80 ths
    /* Second part of the bootloader */
536 d7585251 pbrook
    p = (uint32_t *) (base + 0x580);
537 d52fff71 ths
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
538 d52fff71 ths
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
539 471ea271 ths
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
540 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
541 471ea271 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
542 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
543 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
544 7df526e3 ths
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
545 7df526e3 ths
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
546 2802bfe3 ths
547 2802bfe3 ths
    /* Load BAR registers as done by YAMON */
548 a0a8793e ths
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
549 a0a8793e ths
550 a0a8793e ths
#ifdef TARGET_WORDS_BIGENDIAN
551 a0a8793e ths
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
552 a0a8793e ths
#else
553 a0a8793e ths
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
554 a0a8793e ths
#endif
555 a0a8793e ths
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
556 a0a8793e ths
557 2802bfe3 ths
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
558 2802bfe3 ths
559 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
560 2802bfe3 ths
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
561 2802bfe3 ths
#else
562 2802bfe3 ths
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
563 2802bfe3 ths
#endif
564 2802bfe3 ths
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
565 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
566 2802bfe3 ths
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
567 2802bfe3 ths
#else
568 2802bfe3 ths
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
569 2802bfe3 ths
#endif
570 2802bfe3 ths
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
571 2802bfe3 ths
572 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
573 2802bfe3 ths
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
574 2802bfe3 ths
#else
575 2802bfe3 ths
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
576 2802bfe3 ths
#endif
577 2802bfe3 ths
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
578 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
579 2802bfe3 ths
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
580 2802bfe3 ths
#else
581 2802bfe3 ths
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
582 2802bfe3 ths
#endif
583 2802bfe3 ths
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
584 2802bfe3 ths
585 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
586 2802bfe3 ths
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
587 2802bfe3 ths
#else
588 2802bfe3 ths
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
589 2802bfe3 ths
#endif
590 2802bfe3 ths
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
591 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
592 2802bfe3 ths
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
593 2802bfe3 ths
#else
594 2802bfe3 ths
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
595 2802bfe3 ths
#endif
596 2802bfe3 ths
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
597 2802bfe3 ths
598 2802bfe3 ths
    /* Jump to kernel code */
599 74287114 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
600 74287114 ths
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
601 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
602 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
603 26ea0918 ths
604 26ea0918 ths
    /* YAMON subroutines */
605 d7585251 pbrook
    p = (uint32_t *) (base + 0x800);
606 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
607 26ea0918 ths
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
608 26ea0918 ths
   /* 808 YAMON print */
609 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
610 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
611 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
612 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
613 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
614 26ea0918 ths
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
615 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
616 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
617 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
618 26ea0918 ths
    stl_raw(p++, 0x08000205);                                     /* j 814 */
619 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
620 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
621 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
622 26ea0918 ths
    /* 0x83c YAMON print_count */
623 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
624 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
625 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
626 26ea0918 ths
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
627 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
628 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
629 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
630 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
631 26ea0918 ths
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
632 26ea0918 ths
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
633 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
634 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
635 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
636 26ea0918 ths
    /* 0x870 */
637 26ea0918 ths
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
638 26ea0918 ths
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
639 26ea0918 ths
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
640 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
641 26ea0918 ths
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
642 26ea0918 ths
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
643 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
644 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
645 26ea0918 ths
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
646 26ea0918 ths
647 5856de80 ths
}
648 5856de80 ths
649 8b7968f7 Stefan Weil
static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
650 8b7968f7 Stefan Weil
                                        const char *string, ...)
651 5856de80 ths
{
652 5856de80 ths
    va_list ap;
653 3ddd0065 ths
    int32_t table_addr;
654 5856de80 ths
655 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
656 5856de80 ths
        return;
657 5856de80 ths
658 5856de80 ths
    if (string == NULL) {
659 c938ada2 Aurelien Jarno
        prom_buf[index] = 0;
660 5856de80 ths
        return;
661 5856de80 ths
    }
662 5856de80 ths
663 c938ada2 Aurelien Jarno
    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
664 c938ada2 Aurelien Jarno
    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
665 5856de80 ths
666 5856de80 ths
    va_start(ap, string);
667 c938ada2 Aurelien Jarno
    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
668 5856de80 ths
    va_end(ap);
669 5856de80 ths
}
670 5856de80 ths
671 5856de80 ths
/* Kernel */
672 e16ad5b0 Aurelien Jarno
static int64_t load_kernel (void)
673 5856de80 ths
{
674 409dbce5 Aurelien Jarno
    int64_t kernel_entry, kernel_high;
675 5856de80 ths
    long initrd_size;
676 c227f099 Anthony Liguori
    ram_addr_t initrd_offset;
677 ca20cf32 Blue Swirl
    int big_endian;
678 c938ada2 Aurelien Jarno
    uint32_t *prom_buf;
679 c938ada2 Aurelien Jarno
    long prom_size;
680 c938ada2 Aurelien Jarno
    int prom_index = 0;
681 ca20cf32 Blue Swirl
682 ca20cf32 Blue Swirl
#ifdef TARGET_WORDS_BIGENDIAN
683 ca20cf32 Blue Swirl
    big_endian = 1;
684 ca20cf32 Blue Swirl
#else
685 ca20cf32 Blue Swirl
    big_endian = 0;
686 ca20cf32 Blue Swirl
#endif
687 5856de80 ths
688 409dbce5 Aurelien Jarno
    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
689 409dbce5 Aurelien Jarno
                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
690 409dbce5 Aurelien Jarno
                 big_endian, ELF_MACHINE, 1) < 0) {
691 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
692 7df526e3 ths
                loaderparams.kernel_filename);
693 acdf72bb ths
        exit(1);
694 5856de80 ths
    }
695 5856de80 ths
696 5856de80 ths
    /* load initrd */
697 5856de80 ths
    initrd_size = 0;
698 74287114 ths
    initrd_offset = 0;
699 7df526e3 ths
    if (loaderparams.initrd_filename) {
700 7df526e3 ths
        initrd_size = get_image_size (loaderparams.initrd_filename);
701 74287114 ths
        if (initrd_size > 0) {
702 74287114 ths
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
703 7df526e3 ths
            if (initrd_offset + initrd_size > ram_size) {
704 74287114 ths
                fprintf(stderr,
705 74287114 ths
                        "qemu: memory too small for initial ram disk '%s'\n",
706 7df526e3 ths
                        loaderparams.initrd_filename);
707 74287114 ths
                exit(1);
708 74287114 ths
            }
709 dcac9679 pbrook
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
710 dcac9679 pbrook
                                              initrd_offset,
711 dcac9679 pbrook
                                              ram_size - initrd_offset);
712 74287114 ths
        }
713 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
714 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
715 7df526e3 ths
                    loaderparams.initrd_filename);
716 5856de80 ths
            exit(1);
717 5856de80 ths
        }
718 5856de80 ths
    }
719 5856de80 ths
720 c938ada2 Aurelien Jarno
    /* Setup prom parameters. */
721 c938ada2 Aurelien Jarno
    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
722 7267c094 Anthony Liguori
    prom_buf = g_malloc(prom_size);
723 c938ada2 Aurelien Jarno
724 f36d53ef Stefan Weil
    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
725 c938ada2 Aurelien Jarno
    if (initrd_size > 0) {
726 409dbce5 Aurelien Jarno
        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
727 409dbce5 Aurelien Jarno
                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
728 7df526e3 ths
                 loaderparams.kernel_cmdline);
729 c938ada2 Aurelien Jarno
    } else {
730 f36d53ef Stefan Weil
        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
731 c938ada2 Aurelien Jarno
    }
732 c938ada2 Aurelien Jarno
733 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "memsize");
734 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
735 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "modetty0");
736 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "38400n8r");
737 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, NULL);
738 c938ada2 Aurelien Jarno
739 c938ada2 Aurelien Jarno
    rom_add_blob_fixed("prom", prom_buf, prom_size,
740 409dbce5 Aurelien Jarno
                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
741 5856de80 ths
742 74287114 ths
    return kernel_entry;
743 5856de80 ths
}
744 5856de80 ths
745 ce3960eb Andreas Färber
static void malta_mips_config(MIPSCPU *cpu)
746 c4cb2578 Edgar E. Iglesias
{
747 ce3960eb Andreas Färber
    CPUMIPSState *env = &cpu->env;
748 ce3960eb Andreas Färber
    CPUState *cs = CPU(cpu);
749 ce3960eb Andreas Färber
750 c4cb2578 Edgar E. Iglesias
    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
751 ce3960eb Andreas Färber
                         ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
752 c4cb2578 Edgar E. Iglesias
}
753 c4cb2578 Edgar E. Iglesias
754 5856de80 ths
static void main_cpu_reset(void *opaque)
755 5856de80 ths
{
756 1004ee8d Andreas Färber
    MIPSCPU *cpu = opaque;
757 1004ee8d Andreas Färber
    CPUMIPSState *env = &cpu->env;
758 1004ee8d Andreas Färber
759 1004ee8d Andreas Färber
    cpu_reset(CPU(cpu));
760 5856de80 ths
761 5c43485f Aurelien Jarno
    /* The bootloader does not need to be rewritten as it is located in a
762 5856de80 ths
       read only location. The kernel location and the arguments table
763 5856de80 ths
       location does not change. */
764 7df526e3 ths
    if (loaderparams.kernel_filename) {
765 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
766 fb82fea0 ths
    }
767 c4cb2578 Edgar E. Iglesias
768 ce3960eb Andreas Färber
    malta_mips_config(cpu);
769 5856de80 ths
}
770 5856de80 ths
771 4556bd8b Blue Swirl
static void cpu_request_exit(void *opaque, int irq, int level)
772 4556bd8b Blue Swirl
{
773 61c56c8c Andreas Färber
    CPUMIPSState *env = cpu_single_env;
774 4556bd8b Blue Swirl
775 4556bd8b Blue Swirl
    if (env && level) {
776 4556bd8b Blue Swirl
        cpu_exit(env);
777 4556bd8b Blue Swirl
    }
778 4556bd8b Blue Swirl
}
779 4556bd8b Blue Swirl
780 70705261 ths
static
781 5f072e1f Eduardo Habkost
void mips_malta_init(QEMUMachineInitArgs *args)
782 5856de80 ths
{
783 5f072e1f Eduardo Habkost
    ram_addr_t ram_size = args->ram_size;
784 5f072e1f Eduardo Habkost
    const char *cpu_model = args->cpu_model;
785 5f072e1f Eduardo Habkost
    const char *kernel_filename = args->kernel_filename;
786 5f072e1f Eduardo Habkost
    const char *kernel_cmdline = args->kernel_cmdline;
787 5f072e1f Eduardo Habkost
    const char *initrd_filename = args->initrd_filename;
788 5cea8590 Paul Brook
    char *filename;
789 cfe5f011 Avi Kivity
    pflash_t *fl;
790 cfe5f011 Avi Kivity
    MemoryRegion *system_memory = get_system_memory();
791 ea85df72 Avi Kivity
    MemoryRegion *ram = g_new(MemoryRegion, 1);
792 cfe5f011 Avi Kivity
    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
793 03a1a8e1 Stefan Weil
    target_long bios_size = FLASH_SIZE;
794 74287114 ths
    int64_t kernel_entry;
795 5856de80 ths
    PCIBus *pci_bus;
796 48a18b3c Hervé Poussineau
    ISABus *isa_bus;
797 7688b134 Andreas Färber
    MIPSCPU *cpu;
798 61c56c8c Andreas Färber
    CPUMIPSState *env;
799 e9b40fd3 Stefan Weil
    qemu_irq *isa_irq;
800 4556bd8b Blue Swirl
    qemu_irq *cpu_exit_irq;
801 7b717336 ths
    int piix4_devfn;
802 7b717336 ths
    i2c_bus *smbus;
803 7b717336 ths
    int i;
804 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
805 f455e98c Gerd Hoffmann
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
806 fd8014e1 Gerd Hoffmann
    DriveInfo *fd[MAX_FD];
807 c8b153d7 ths
    int fl_idx = 0;
808 bb4b3358 Stefan Weil
    int fl_sectors = bios_size >> 16;
809 01e0451a Anthony Liguori
    int be;
810 5856de80 ths
811 e9b40fd3 Stefan Weil
    DeviceState *dev = qdev_create(NULL, "mips-malta");
812 e9b40fd3 Stefan Weil
    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
813 e9b40fd3 Stefan Weil
814 e9b40fd3 Stefan Weil
    qdev_init_nofail(dev);
815 e9b40fd3 Stefan Weil
816 ffabf037 Aurelien Jarno
    /* Make sure the first 3 serial ports are associated with a device. */
817 ffabf037 Aurelien Jarno
    for(i = 0; i < 3; i++) {
818 ffabf037 Aurelien Jarno
        if (!serial_hds[i]) {
819 ffabf037 Aurelien Jarno
            char label[32];
820 ffabf037 Aurelien Jarno
            snprintf(label, sizeof(label), "serial%d", i);
821 27143a44 Anthony Liguori
            serial_hds[i] = qemu_chr_new(label, "null", NULL);
822 ffabf037 Aurelien Jarno
        }
823 ffabf037 Aurelien Jarno
    }
824 ffabf037 Aurelien Jarno
825 33d68b5f ths
    /* init CPUs */
826 33d68b5f ths
    if (cpu_model == NULL) {
827 60aa19ab ths
#ifdef TARGET_MIPS64
828 c9c1a064 ths
        cpu_model = "20Kc";
829 33d68b5f ths
#else
830 1c32f43e ths
        cpu_model = "24Kf";
831 33d68b5f ths
#endif
832 33d68b5f ths
    }
833 c4cb2578 Edgar E. Iglesias
834 c4cb2578 Edgar E. Iglesias
    for (i = 0; i < smp_cpus; i++) {
835 7688b134 Andreas Färber
        cpu = cpu_mips_init(cpu_model);
836 7688b134 Andreas Färber
        if (cpu == NULL) {
837 c4cb2578 Edgar E. Iglesias
            fprintf(stderr, "Unable to find CPU definition\n");
838 c4cb2578 Edgar E. Iglesias
            exit(1);
839 c4cb2578 Edgar E. Iglesias
        }
840 7688b134 Andreas Färber
        env = &cpu->env;
841 7688b134 Andreas Färber
842 c4cb2578 Edgar E. Iglesias
        /* Init internal devices */
843 c4cb2578 Edgar E. Iglesias
        cpu_mips_irq_init_cpu(env);
844 c4cb2578 Edgar E. Iglesias
        cpu_mips_clock_init(env);
845 1004ee8d Andreas Färber
        qemu_register_reset(main_cpu_reset, cpu);
846 aaed909a bellard
    }
847 c4cb2578 Edgar E. Iglesias
    env = first_cpu;
848 5856de80 ths
849 5856de80 ths
    /* allocate RAM */
850 0ccff151 aurel32
    if (ram_size > (256 << 20)) {
851 0ccff151 aurel32
        fprintf(stderr,
852 0ccff151 aurel32
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
853 0ccff151 aurel32
                ((unsigned int)ram_size / (1 << 20)));
854 0ccff151 aurel32
        exit(1);
855 0ccff151 aurel32
    }
856 c5705a77 Avi Kivity
    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
857 c5705a77 Avi Kivity
    vmstate_register_ram_global(ram);
858 ea85df72 Avi Kivity
    memory_region_add_subregion(system_memory, 0, ram);
859 5856de80 ths
860 01e0451a Anthony Liguori
#ifdef TARGET_WORDS_BIGENDIAN
861 01e0451a Anthony Liguori
    be = 1;
862 01e0451a Anthony Liguori
#else
863 01e0451a Anthony Liguori
    be = 0;
864 01e0451a Anthony Liguori
#endif
865 070ce5ed ths
    /* FPGA */
866 68d00192 Aurelien Jarno
    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
867 68d00192 Aurelien Jarno
    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
868 070ce5ed ths
869 bb4b3358 Stefan Weil
    /* Load firmware in flash / BIOS. */
870 bb4b3358 Stefan Weil
    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
871 bb4b3358 Stefan Weil
#ifdef DEBUG_BOARD_INIT
872 bb4b3358 Stefan Weil
    if (dinfo) {
873 bb4b3358 Stefan Weil
        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
874 bb4b3358 Stefan Weil
               "addr %08llx '%s' %x\n",
875 03a1a8e1 Stefan Weil
               fl_idx, bios_size, FLASH_ADDRESS,
876 bb4b3358 Stefan Weil
               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
877 bb4b3358 Stefan Weil
    }
878 bb4b3358 Stefan Weil
#endif
879 03a1a8e1 Stefan Weil
    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
880 bb4b3358 Stefan Weil
                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
881 bb4b3358 Stefan Weil
                               65536, fl_sectors,
882 bb4b3358 Stefan Weil
                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
883 bb4b3358 Stefan Weil
    bios = pflash_cfi01_get_memory(fl);
884 bb4b3358 Stefan Weil
    fl_idx++;
885 c8b153d7 ths
    if (kernel_filename) {
886 c8b153d7 ths
        /* Write a small bootloader to the flash location. */
887 c8b153d7 ths
        loaderparams.ram_size = ram_size;
888 c8b153d7 ths
        loaderparams.kernel_filename = kernel_filename;
889 c8b153d7 ths
        loaderparams.kernel_cmdline = kernel_cmdline;
890 c8b153d7 ths
        loaderparams.initrd_filename = initrd_filename;
891 e16ad5b0 Aurelien Jarno
        kernel_entry = load_kernel();
892 cfe5f011 Avi Kivity
        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
893 c8b153d7 ths
    } else {
894 bb4b3358 Stefan Weil
        /* Load firmware from flash. */
895 bb4b3358 Stefan Weil
        if (!dinfo) {
896 c8b153d7 ths
            /* Load a BIOS image. */
897 bb4b3358 Stefan Weil
            if (bios_name == NULL) {
898 c8b153d7 ths
                bios_name = BIOS_FILENAME;
899 bb4b3358 Stefan Weil
            }
900 5cea8590 Paul Brook
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
901 5cea8590 Paul Brook
            if (filename) {
902 03a1a8e1 Stefan Weil
                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
903 5cea8590 Paul Brook
                                                BIOS_SIZE);
904 7267c094 Anthony Liguori
                g_free(filename);
905 5cea8590 Paul Brook
            } else {
906 5cea8590 Paul Brook
                bios_size = -1;
907 5cea8590 Paul Brook
            }
908 c8b153d7 ths
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
909 c8b153d7 ths
                fprintf(stderr,
910 c8b153d7 ths
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
911 5cea8590 Paul Brook
                        bios_name);
912 c8b153d7 ths
                exit(1);
913 c8b153d7 ths
            }
914 070ce5ed ths
        }
915 3187ef03 ths
        /* In little endian mode the 32bit words in the bios are swapped,
916 3187ef03 ths
           a neat trick which allows bi-endian firmware. */
917 3187ef03 ths
#ifndef TARGET_WORDS_BIGENDIAN
918 3187ef03 ths
        {
919 cfe5f011 Avi Kivity
            uint32_t *addr = memory_region_get_ram_ptr(bios);
920 d7585251 pbrook
            uint32_t *end = addr + bios_size;
921 d7585251 pbrook
            while (addr < end) {
922 d7585251 pbrook
                bswap32s(addr);
923 a30cfee5 Chen Rui
                addr++;
924 3187ef03 ths
            }
925 3187ef03 ths
        }
926 3187ef03 ths
#endif
927 070ce5ed ths
    }
928 070ce5ed ths
929 82a9807b Stefan Weil
    /* Map the BIOS at a 2nd physical location, as on the real board. */
930 82a9807b Stefan Weil
    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
931 03a1a8e1 Stefan Weil
    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
932 82a9807b Stefan Weil
933 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
934 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
935 5856de80 ths
       map to the board ID. */
936 cfe5f011 Avi Kivity
    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
937 5856de80 ths
938 5856de80 ths
    /* Init internal devices */
939 d537cf6c pbrook
    cpu_mips_irq_init_cpu(env);
940 5856de80 ths
    cpu_mips_clock_init(env);
941 5856de80 ths
942 5632ae46 Avi Kivity
    /*
943 5632ae46 Avi Kivity
     * We have a circular dependency problem: pci_bus depends on isa_irq,
944 5632ae46 Avi Kivity
     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
945 5632ae46 Avi Kivity
     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
946 5632ae46 Avi Kivity
     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
947 5632ae46 Avi Kivity
     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
948 5632ae46 Avi Kivity
     */
949 e9b40fd3 Stefan Weil
    isa_irq = qemu_irq_proxy(&s->i8259, 16);
950 5856de80 ths
951 5856de80 ths
    /* Northbridge */
952 5632ae46 Avi Kivity
    pci_bus = gt64120_register(isa_irq);
953 5856de80 ths
954 5856de80 ths
    /* Southbridge */
955 75717903 Isaku Yamahata
    ide_drive_get(hd, MAX_IDE_BUS);
956 e4bcb14c ths
957 142e9787 Hervé Poussineau
    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
958 5632ae46 Avi Kivity
959 5632ae46 Avi Kivity
    /* Interrupt controller */
960 5632ae46 Avi Kivity
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
961 e9b40fd3 Stefan Weil
    s->i8259 = i8259_init(isa_bus, env->irq[2]);
962 5632ae46 Avi Kivity
963 e9b40fd3 Stefan Weil
    isa_bus_irqs(isa_bus, s->i8259);
964 ae027ad3 Stefan Weil
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
965 afb9a60e Gerd Hoffmann
    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
966 48a18b3c Hervé Poussineau
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
967 459ae5ea Gleb Natapov
                          isa_get_irq(NULL, 9), NULL, 0, NULL);
968 a88df0b9 Isaku Yamahata
    /* TODO: Populate SPD eeprom data.  */
969 a88df0b9 Isaku Yamahata
    smbus_eeprom_init(smbus, 8, NULL, 0);
970 319ba9f5 Jan Kiszka
    pit = pit_init(isa_bus, 0x40, 0, NULL);
971 4556bd8b Blue Swirl
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
972 4556bd8b Blue Swirl
    DMA_init(0, cpu_exit_irq);
973 5856de80 ths
974 5856de80 ths
    /* Super I/O */
975 48a18b3c Hervé Poussineau
    isa_create_simple(isa_bus, "i8042");
976 49a2942d Blue Swirl
977 48a18b3c Hervé Poussineau
    rtc_init(isa_bus, 2000, NULL);
978 48a18b3c Hervé Poussineau
    serial_isa_init(isa_bus, 0, serial_hds[0]);
979 48a18b3c Hervé Poussineau
    serial_isa_init(isa_bus, 1, serial_hds[1]);
980 7bcc17dc ths
    if (parallel_hds[0])
981 48a18b3c Hervé Poussineau
        parallel_init(isa_bus, 0, parallel_hds[0]);
982 e4bcb14c ths
    for(i = 0; i < MAX_FD; i++) {
983 fd8014e1 Gerd Hoffmann
        fd[i] = drive_get(IF_FLOPPY, 0, i);
984 e4bcb14c ths
    }
985 48a18b3c Hervé Poussineau
    fdctrl_init_isa(isa_bus, fd);
986 5856de80 ths
987 5856de80 ths
    /* Network card */
988 5607c388 Markus Armbruster
    network_init();
989 11f29511 ths
990 11f29511 ths
    /* Optional PCI video card */
991 9c59864d Aurelien Jarno
    pci_vga_init(pci_bus);
992 5856de80 ths
}
993 5856de80 ths
994 e9b40fd3 Stefan Weil
static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
995 e9b40fd3 Stefan Weil
{
996 e9b40fd3 Stefan Weil
    return 0;
997 e9b40fd3 Stefan Weil
}
998 e9b40fd3 Stefan Weil
999 999e12bb Anthony Liguori
static void mips_malta_class_init(ObjectClass *klass, void *data)
1000 999e12bb Anthony Liguori
{
1001 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1002 999e12bb Anthony Liguori
1003 999e12bb Anthony Liguori
    k->init = mips_malta_sysbus_device_init;
1004 999e12bb Anthony Liguori
}
1005 999e12bb Anthony Liguori
1006 8c43a6f0 Andreas Färber
static const TypeInfo mips_malta_device = {
1007 39bffca2 Anthony Liguori
    .name          = "mips-malta",
1008 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
1009 39bffca2 Anthony Liguori
    .instance_size = sizeof(MaltaState),
1010 39bffca2 Anthony Liguori
    .class_init    = mips_malta_class_init,
1011 e9b40fd3 Stefan Weil
};
1012 e9b40fd3 Stefan Weil
1013 f80f9ec9 Anthony Liguori
static QEMUMachine mips_malta_machine = {
1014 eec2743e ths
    .name = "malta",
1015 eec2743e ths
    .desc = "MIPS Malta Core LV",
1016 eec2743e ths
    .init = mips_malta_init,
1017 c4cb2578 Edgar E. Iglesias
    .max_cpus = 16,
1018 0c257437 Anthony Liguori
    .is_default = 1,
1019 e4ada29e Avik Sil
    DEFAULT_MACHINE_OPTIONS,
1020 5856de80 ths
};
1021 f80f9ec9 Anthony Liguori
1022 83f7d43a Andreas Färber
static void mips_malta_register_types(void)
1023 e9b40fd3 Stefan Weil
{
1024 39bffca2 Anthony Liguori
    type_register_static(&mips_malta_device);
1025 e9b40fd3 Stefan Weil
}
1026 e9b40fd3 Stefan Weil
1027 f80f9ec9 Anthony Liguori
static void mips_malta_machine_init(void)
1028 f80f9ec9 Anthony Liguori
{
1029 f80f9ec9 Anthony Liguori
    qemu_register_machine(&mips_malta_machine);
1030 f80f9ec9 Anthony Liguori
}
1031 f80f9ec9 Anthony Liguori
1032 83f7d43a Andreas Färber
type_init(mips_malta_register_types)
1033 f80f9ec9 Anthony Liguori
machine_init(mips_malta_machine_init);