Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ a4d5f62c

History | View | Annotate | Download (31.8 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 87ecb68b pbrook
#include "hw.h"
26 87ecb68b pbrook
#include "pc.h"
27 ded7ba9c ths
#include "fdc.h"
28 87ecb68b pbrook
#include "net.h"
29 87ecb68b pbrook
#include "boards.h"
30 87ecb68b pbrook
#include "smbus.h"
31 c8b153d7 ths
#include "block.h"
32 c8b153d7 ths
#include "flash.h"
33 87ecb68b pbrook
#include "mips.h"
34 87ecb68b pbrook
#include "pci.h"
35 18e08a55 Michael S. Tsirkin
#include "usb-uhci.h"
36 18e08a55 Michael S. Tsirkin
#include "vmware_vga.h"
37 87ecb68b pbrook
#include "qemu-char.h"
38 87ecb68b pbrook
#include "sysemu.h"
39 87ecb68b pbrook
#include "audio/audio.h"
40 87ecb68b pbrook
#include "boards.h"
41 3b3fb322 blueswir1
#include "qemu-log.h"
42 bba831e8 Paul Brook
#include "mips-bios.h"
43 977e1244 Gerd Hoffmann
#include "ide.h"
44 ca20cf32 Blue Swirl
#include "loader.h"
45 ca20cf32 Blue Swirl
#include "elf.h"
46 5856de80 ths
47 c8b153d7 ths
//#define DEBUG_BOARD_INIT
48 c8b153d7 ths
49 60aa19ab ths
#ifdef TARGET_MIPS64
50 74287114 ths
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
51 5856de80 ths
#else
52 74287114 ths
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
53 5856de80 ths
#endif
54 5856de80 ths
55 74287114 ths
#define ENVP_ADDR (int32_t)0x80002000
56 74287114 ths
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
57 5856de80 ths
58 5856de80 ths
#define ENVP_NB_ENTRIES                 16
59 5856de80 ths
#define ENVP_ENTRY_SIZE                 256
60 5856de80 ths
61 e4bcb14c ths
#define MAX_IDE_BUS 2
62 e4bcb14c ths
63 5856de80 ths
typedef struct {
64 5856de80 ths
    uint32_t leds;
65 5856de80 ths
    uint32_t brk;
66 5856de80 ths
    uint32_t gpout;
67 130751ee ths
    uint32_t i2cin;
68 5856de80 ths
    uint32_t i2coe;
69 5856de80 ths
    uint32_t i2cout;
70 5856de80 ths
    uint32_t i2csel;
71 5856de80 ths
    CharDriverState *display;
72 5856de80 ths
    char display_text[9];
73 a4bc3afc ths
    SerialState *uart;
74 5856de80 ths
} MaltaFPGAState;
75 5856de80 ths
76 5856de80 ths
static PITState *pit;
77 5856de80 ths
78 7df526e3 ths
static struct _loaderparams {
79 7df526e3 ths
    int ram_size;
80 7df526e3 ths
    const char *kernel_filename;
81 7df526e3 ths
    const char *kernel_cmdline;
82 7df526e3 ths
    const char *initrd_filename;
83 7df526e3 ths
} loaderparams;
84 7df526e3 ths
85 5856de80 ths
/* Malta FPGA */
86 5856de80 ths
static void malta_fpga_update_display(void *opaque)
87 5856de80 ths
{
88 5856de80 ths
    char leds_text[9];
89 5856de80 ths
    int i;
90 5856de80 ths
    MaltaFPGAState *s = opaque;
91 5856de80 ths
92 07cf0ba0 ths
    for (i = 7 ; i >= 0 ; i--) {
93 07cf0ba0 ths
        if (s->leds & (1 << i))
94 07cf0ba0 ths
            leds_text[i] = '#';
95 07cf0ba0 ths
        else
96 07cf0ba0 ths
            leds_text[i] = ' ';
97 87ee1669 ths
    }
98 07cf0ba0 ths
    leds_text[8] = '\0';
99 07cf0ba0 ths
100 07cf0ba0 ths
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
101 07cf0ba0 ths
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
102 5856de80 ths
}
103 5856de80 ths
104 130751ee ths
/*
105 130751ee ths
 * EEPROM 24C01 / 24C02 emulation.
106 130751ee ths
 *
107 130751ee ths
 * Emulation for serial EEPROMs:
108 130751ee ths
 * 24C01 - 1024 bit (128 x 8)
109 130751ee ths
 * 24C02 - 2048 bit (256 x 8)
110 130751ee ths
 *
111 130751ee ths
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
112 130751ee ths
 */
113 130751ee ths
114 130751ee ths
//~ #define DEBUG
115 130751ee ths
116 130751ee ths
#if defined(DEBUG)
117 001faf32 Blue Swirl
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
118 130751ee ths
#else
119 001faf32 Blue Swirl
#  define logout(fmt, ...) ((void)0)
120 130751ee ths
#endif
121 130751ee ths
122 c227f099 Anthony Liguori
struct _eeprom24c0x_t {
123 130751ee ths
  uint8_t tick;
124 130751ee ths
  uint8_t address;
125 130751ee ths
  uint8_t command;
126 130751ee ths
  uint8_t ack;
127 130751ee ths
  uint8_t scl;
128 130751ee ths
  uint8_t sda;
129 130751ee ths
  uint8_t data;
130 130751ee ths
  //~ uint16_t size;
131 130751ee ths
  uint8_t contents[256];
132 130751ee ths
};
133 130751ee ths
134 c227f099 Anthony Liguori
typedef struct _eeprom24c0x_t eeprom24c0x_t;
135 130751ee ths
136 c227f099 Anthony Liguori
static eeprom24c0x_t eeprom = {
137 284b08f1 Blue Swirl
    .contents = {
138 130751ee ths
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
139 130751ee ths
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
140 130751ee ths
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
141 130751ee ths
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
142 130751ee ths
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
143 130751ee ths
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 130751ee ths
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145 130751ee ths
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
146 130751ee ths
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 130751ee ths
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148 130751ee ths
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149 130751ee ths
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150 130751ee ths
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151 130751ee ths
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
152 130751ee ths
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
153 130751ee ths
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
154 130751ee ths
    },
155 130751ee ths
};
156 130751ee ths
157 a5f1b965 blueswir1
static uint8_t eeprom24c0x_read(void)
158 130751ee ths
{
159 130751ee ths
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
160 130751ee ths
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
161 130751ee ths
    return eeprom.sda;
162 130751ee ths
}
163 130751ee ths
164 130751ee ths
static void eeprom24c0x_write(int scl, int sda)
165 130751ee ths
{
166 130751ee ths
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
167 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
168 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
169 130751ee ths
        if (!sda) {
170 130751ee ths
            eeprom.tick = 1;
171 130751ee ths
            eeprom.command = 0;
172 130751ee ths
        }
173 130751ee ths
    } else if (eeprom.tick == 0 && !eeprom.ack) {
174 130751ee ths
        /* Waiting for start. */
175 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
176 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
177 130751ee ths
    } else if (!eeprom.scl && scl) {
178 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
179 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
180 130751ee ths
        if (eeprom.ack) {
181 130751ee ths
            logout("\ti2c ack bit = 0\n");
182 130751ee ths
            sda = 0;
183 130751ee ths
            eeprom.ack = 0;
184 130751ee ths
        } else if (eeprom.sda == sda) {
185 130751ee ths
            uint8_t bit = (sda != 0);
186 130751ee ths
            logout("\ti2c bit = %d\n", bit);
187 130751ee ths
            if (eeprom.tick < 9) {
188 130751ee ths
                eeprom.command <<= 1;
189 130751ee ths
                eeprom.command += bit;
190 130751ee ths
                eeprom.tick++;
191 130751ee ths
                if (eeprom.tick == 9) {
192 130751ee ths
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
193 130751ee ths
                    eeprom.ack = 1;
194 130751ee ths
                }
195 130751ee ths
            } else if (eeprom.tick < 17) {
196 130751ee ths
                if (eeprom.command & 1) {
197 130751ee ths
                    sda = ((eeprom.data & 0x80) != 0);
198 130751ee ths
                }
199 130751ee ths
                eeprom.address <<= 1;
200 130751ee ths
                eeprom.address += bit;
201 130751ee ths
                eeprom.tick++;
202 130751ee ths
                eeprom.data <<= 1;
203 130751ee ths
                if (eeprom.tick == 17) {
204 130751ee ths
                    eeprom.data = eeprom.contents[eeprom.address];
205 130751ee ths
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
206 130751ee ths
                    eeprom.ack = 1;
207 130751ee ths
                    eeprom.tick = 0;
208 130751ee ths
                }
209 130751ee ths
            } else if (eeprom.tick >= 17) {
210 130751ee ths
                sda = 0;
211 130751ee ths
            }
212 130751ee ths
        } else {
213 130751ee ths
            logout("\tsda changed with raising scl\n");
214 130751ee ths
        }
215 130751ee ths
    } else {
216 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
217 130751ee ths
    }
218 130751ee ths
    eeprom.scl = scl;
219 130751ee ths
    eeprom.sda = sda;
220 130751ee ths
}
221 130751ee ths
222 c227f099 Anthony Liguori
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
223 5856de80 ths
{
224 5856de80 ths
    MaltaFPGAState *s = opaque;
225 5856de80 ths
    uint32_t val = 0;
226 5856de80 ths
    uint32_t saddr;
227 5856de80 ths
228 5856de80 ths
    saddr = (addr & 0xfffff);
229 5856de80 ths
230 5856de80 ths
    switch (saddr) {
231 5856de80 ths
232 5856de80 ths
    /* SWITCH Register */
233 5856de80 ths
    case 0x00200:
234 5856de80 ths
        val = 0x00000000;                /* All switches closed */
235 593c0d10 Aurelien Jarno
        break;
236 5856de80 ths
237 5856de80 ths
    /* STATUS Register */
238 5856de80 ths
    case 0x00208:
239 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
240 5856de80 ths
        val = 0x00000012;
241 5856de80 ths
#else
242 5856de80 ths
        val = 0x00000010;
243 5856de80 ths
#endif
244 5856de80 ths
        break;
245 5856de80 ths
246 5856de80 ths
    /* JMPRS Register */
247 5856de80 ths
    case 0x00210:
248 5856de80 ths
        val = 0x00;
249 5856de80 ths
        break;
250 5856de80 ths
251 5856de80 ths
    /* LEDBAR Register */
252 5856de80 ths
    case 0x00408:
253 5856de80 ths
        val = s->leds;
254 5856de80 ths
        break;
255 5856de80 ths
256 5856de80 ths
    /* BRKRES Register */
257 5856de80 ths
    case 0x00508:
258 5856de80 ths
        val = s->brk;
259 5856de80 ths
        break;
260 5856de80 ths
261 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
262 a4bc3afc ths
263 5856de80 ths
    /* GPOUT Register */
264 5856de80 ths
    case 0x00a00:
265 5856de80 ths
        val = s->gpout;
266 5856de80 ths
        break;
267 5856de80 ths
268 5856de80 ths
    /* XXX: implement a real I2C controller */
269 5856de80 ths
270 5856de80 ths
    /* GPINP Register */
271 5856de80 ths
    case 0x00a08:
272 5856de80 ths
        /* IN = OUT until a real I2C control is implemented */
273 5856de80 ths
        if (s->i2csel)
274 5856de80 ths
            val = s->i2cout;
275 5856de80 ths
        else
276 5856de80 ths
            val = 0x00;
277 5856de80 ths
        break;
278 5856de80 ths
279 5856de80 ths
    /* I2CINP Register */
280 5856de80 ths
    case 0x00b00:
281 130751ee ths
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
282 5856de80 ths
        break;
283 5856de80 ths
284 5856de80 ths
    /* I2COE Register */
285 5856de80 ths
    case 0x00b08:
286 5856de80 ths
        val = s->i2coe;
287 5856de80 ths
        break;
288 5856de80 ths
289 5856de80 ths
    /* I2COUT Register */
290 5856de80 ths
    case 0x00b10:
291 5856de80 ths
        val = s->i2cout;
292 5856de80 ths
        break;
293 5856de80 ths
294 5856de80 ths
    /* I2CSEL Register */
295 5856de80 ths
    case 0x00b18:
296 130751ee ths
        val = s->i2csel;
297 5856de80 ths
        break;
298 5856de80 ths
299 5856de80 ths
    default:
300 5856de80 ths
#if 0
301 3594c774 ths
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
302 593c0d10 Aurelien Jarno
                addr);
303 5856de80 ths
#endif
304 5856de80 ths
        break;
305 5856de80 ths
    }
306 5856de80 ths
    return val;
307 5856de80 ths
}
308 5856de80 ths
309 c227f099 Anthony Liguori
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
310 5856de80 ths
                              uint32_t val)
311 5856de80 ths
{
312 5856de80 ths
    MaltaFPGAState *s = opaque;
313 5856de80 ths
    uint32_t saddr;
314 5856de80 ths
315 5856de80 ths
    saddr = (addr & 0xfffff);
316 5856de80 ths
317 5856de80 ths
    switch (saddr) {
318 5856de80 ths
319 5856de80 ths
    /* SWITCH Register */
320 5856de80 ths
    case 0x00200:
321 5856de80 ths
        break;
322 5856de80 ths
323 5856de80 ths
    /* JMPRS Register */
324 5856de80 ths
    case 0x00210:
325 5856de80 ths
        break;
326 5856de80 ths
327 5856de80 ths
    /* LEDBAR Register */
328 5856de80 ths
    /* XXX: implement a 8-LED array */
329 5856de80 ths
    case 0x00408:
330 5856de80 ths
        s->leds = val & 0xff;
331 5856de80 ths
        break;
332 5856de80 ths
333 5856de80 ths
    /* ASCIIWORD Register */
334 5856de80 ths
    case 0x00410:
335 5856de80 ths
        snprintf(s->display_text, 9, "%08X", val);
336 5856de80 ths
        malta_fpga_update_display(s);
337 5856de80 ths
        break;
338 5856de80 ths
339 5856de80 ths
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
340 5856de80 ths
    case 0x00418:
341 5856de80 ths
    case 0x00420:
342 5856de80 ths
    case 0x00428:
343 5856de80 ths
    case 0x00430:
344 5856de80 ths
    case 0x00438:
345 5856de80 ths
    case 0x00440:
346 5856de80 ths
    case 0x00448:
347 5856de80 ths
    case 0x00450:
348 5856de80 ths
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
349 5856de80 ths
        malta_fpga_update_display(s);
350 5856de80 ths
        break;
351 5856de80 ths
352 5856de80 ths
    /* SOFTRES Register */
353 5856de80 ths
    case 0x00500:
354 5856de80 ths
        if (val == 0x42)
355 5856de80 ths
            qemu_system_reset_request ();
356 5856de80 ths
        break;
357 5856de80 ths
358 5856de80 ths
    /* BRKRES Register */
359 5856de80 ths
    case 0x00508:
360 5856de80 ths
        s->brk = val & 0xff;
361 5856de80 ths
        break;
362 5856de80 ths
363 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
364 a4bc3afc ths
365 5856de80 ths
    /* GPOUT Register */
366 5856de80 ths
    case 0x00a00:
367 5856de80 ths
        s->gpout = val & 0xff;
368 5856de80 ths
        break;
369 5856de80 ths
370 5856de80 ths
    /* I2COE Register */
371 5856de80 ths
    case 0x00b08:
372 5856de80 ths
        s->i2coe = val & 0x03;
373 5856de80 ths
        break;
374 5856de80 ths
375 5856de80 ths
    /* I2COUT Register */
376 5856de80 ths
    case 0x00b10:
377 130751ee ths
        eeprom24c0x_write(val & 0x02, val & 0x01);
378 130751ee ths
        s->i2cout = val;
379 5856de80 ths
        break;
380 5856de80 ths
381 5856de80 ths
    /* I2CSEL Register */
382 5856de80 ths
    case 0x00b18:
383 130751ee ths
        s->i2csel = val & 0x01;
384 5856de80 ths
        break;
385 5856de80 ths
386 5856de80 ths
    default:
387 5856de80 ths
#if 0
388 3594c774 ths
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
389 593c0d10 Aurelien Jarno
                addr);
390 5856de80 ths
#endif
391 5856de80 ths
        break;
392 5856de80 ths
    }
393 5856de80 ths
}
394 5856de80 ths
395 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const malta_fpga_read[] = {
396 5856de80 ths
   malta_fpga_readl,
397 5856de80 ths
   malta_fpga_readl,
398 5856de80 ths
   malta_fpga_readl
399 5856de80 ths
};
400 5856de80 ths
401 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const malta_fpga_write[] = {
402 5856de80 ths
   malta_fpga_writel,
403 5856de80 ths
   malta_fpga_writel,
404 5856de80 ths
   malta_fpga_writel
405 5856de80 ths
};
406 5856de80 ths
407 9596ebb7 pbrook
static void malta_fpga_reset(void *opaque)
408 5856de80 ths
{
409 5856de80 ths
    MaltaFPGAState *s = opaque;
410 5856de80 ths
411 5856de80 ths
    s->leds   = 0x00;
412 5856de80 ths
    s->brk    = 0x0a;
413 5856de80 ths
    s->gpout  = 0x00;
414 130751ee ths
    s->i2cin  = 0x3;
415 5856de80 ths
    s->i2coe  = 0x0;
416 5856de80 ths
    s->i2cout = 0x3;
417 5856de80 ths
    s->i2csel = 0x1;
418 5856de80 ths
419 5856de80 ths
    s->display_text[8] = '\0';
420 5856de80 ths
    snprintf(s->display_text, 9, "        ");
421 ceecf1d1 aurel32
}
422 ceecf1d1 aurel32
423 ceecf1d1 aurel32
static void malta_fpga_led_init(CharDriverState *chr)
424 ceecf1d1 aurel32
{
425 ceecf1d1 aurel32
    qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
426 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
427 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+        +\r\n");
428 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
429 ceecf1d1 aurel32
    qemu_chr_printf(chr, "\n");
430 ceecf1d1 aurel32
    qemu_chr_printf(chr, "Malta ASCII\r\n");
431 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
432 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+        +\r\n");
433 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
434 5856de80 ths
}
435 5856de80 ths
436 c227f099 Anthony Liguori
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
437 5856de80 ths
{
438 5856de80 ths
    MaltaFPGAState *s;
439 5856de80 ths
    int malta;
440 5856de80 ths
441 5856de80 ths
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
442 5856de80 ths
443 1eed09cb Avi Kivity
    malta = cpu_register_io_memory(malta_fpga_read,
444 5856de80 ths
                                   malta_fpga_write, s);
445 a4bc3afc ths
446 b6dc7ebb ths
    cpu_register_physical_memory(base, 0x900, malta);
447 8da3ff18 pbrook
    /* 0xa00 is less than a page, so will still get the right offsets.  */
448 b6dc7ebb ths
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
449 5856de80 ths
450 ceecf1d1 aurel32
    s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
451 ceecf1d1 aurel32
452 470d86b7 aurel32
    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1);
453 a4bc3afc ths
454 5856de80 ths
    malta_fpga_reset(s);
455 a08d4367 Jan Kiszka
    qemu_register_reset(malta_fpga_reset, s);
456 5856de80 ths
457 5856de80 ths
    return s;
458 5856de80 ths
}
459 5856de80 ths
460 5856de80 ths
/* Audio support */
461 5856de80 ths
#ifdef HAS_AUDIO
462 5856de80 ths
static void audio_init (PCIBus *pci_bus)
463 5856de80 ths
{
464 5856de80 ths
    struct soundhw *c;
465 5856de80 ths
    int audio_enabled = 0;
466 5856de80 ths
467 5856de80 ths
    for (c = soundhw; !audio_enabled && c->name; ++c) {
468 5856de80 ths
        audio_enabled = c->enabled;
469 5856de80 ths
    }
470 5856de80 ths
471 5856de80 ths
    if (audio_enabled) {
472 0d9acba8 Paul Brook
        for (c = soundhw; c->name; ++c) {
473 0d9acba8 Paul Brook
            if (c->enabled) {
474 22d83b14 Paul Brook
                c->init.init_pci(pci_bus);
475 5856de80 ths
            }
476 5856de80 ths
        }
477 5856de80 ths
    }
478 5856de80 ths
}
479 5856de80 ths
#endif
480 5856de80 ths
481 5856de80 ths
/* Network support */
482 5607c388 Markus Armbruster
static void network_init(void)
483 5856de80 ths
{
484 5856de80 ths
    int i;
485 5856de80 ths
486 5856de80 ths
    for(i = 0; i < nb_nics; i++) {
487 cb457d76 aliguori
        NICInfo *nd = &nd_table[i];
488 5607c388 Markus Armbruster
        const char *default_devaddr = NULL;
489 cb457d76 aliguori
490 cb457d76 aliguori
        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
491 5856de80 ths
            /* The malta board has a PCNet card using PCI SLOT 11 */
492 5607c388 Markus Armbruster
            default_devaddr = "0b";
493 cb457d76 aliguori
494 07caea31 Markus Armbruster
        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
495 5856de80 ths
    }
496 5856de80 ths
}
497 5856de80 ths
498 5856de80 ths
/* ROM and pseudo bootloader
499 5856de80 ths

500 5856de80 ths
   The following code implements a very very simple bootloader. It first
501 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
502 5856de80 ths
   then jump at the kernel address.
503 5856de80 ths

504 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
505 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
506 5856de80 ths
   of NULL terminated strings. The environment variables table should be
507 5856de80 ths
   terminated by a NULL address.
508 5856de80 ths

509 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
510 5856de80 ths
   to two (the name of the kernel and the command line), and the two
511 5856de80 ths
   tables are actually the same one.
512 5856de80 ths

513 5856de80 ths
   The registers a0 to a3 should contain the following values:
514 5856de80 ths
     a0 - number of kernel arguments
515 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
516 5856de80 ths
     a2 - 32-bit address of the environment variables table
517 5856de80 ths
     a3 - RAM size in bytes
518 5856de80 ths
*/
519 5856de80 ths
520 d7585251 pbrook
static void write_bootloader (CPUState *env, uint8_t *base,
521 d7585251 pbrook
                              int64_t kernel_entry)
522 5856de80 ths
{
523 5856de80 ths
    uint32_t *p;
524 5856de80 ths
525 5856de80 ths
    /* Small bootloader */
526 d7585251 pbrook
    p = (uint32_t *)base;
527 26ea0918 ths
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
528 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
529 5856de80 ths
530 26ea0918 ths
    /* YAMON service vector */
531 d7585251 pbrook
    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
532 d7585251 pbrook
    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
533 d7585251 pbrook
    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
534 d7585251 pbrook
    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
535 d7585251 pbrook
    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
536 d7585251 pbrook
    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
537 d7585251 pbrook
    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
538 d7585251 pbrook
    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
539 d7585251 pbrook
    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
540 d7585251 pbrook
    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
541 d7585251 pbrook
    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
542 d7585251 pbrook
    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
543 d7585251 pbrook
    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
544 26ea0918 ths
545 26ea0918 ths
546 5856de80 ths
    /* Second part of the bootloader */
547 d7585251 pbrook
    p = (uint32_t *) (base + 0x580);
548 d52fff71 ths
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
549 d52fff71 ths
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
550 471ea271 ths
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
551 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
552 471ea271 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
553 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
554 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
555 7df526e3 ths
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
556 7df526e3 ths
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
557 2802bfe3 ths
558 2802bfe3 ths
    /* Load BAR registers as done by YAMON */
559 a0a8793e ths
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
560 a0a8793e ths
561 a0a8793e ths
#ifdef TARGET_WORDS_BIGENDIAN
562 a0a8793e ths
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
563 a0a8793e ths
#else
564 a0a8793e ths
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
565 a0a8793e ths
#endif
566 a0a8793e ths
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
567 a0a8793e ths
568 2802bfe3 ths
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
569 2802bfe3 ths
570 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
571 2802bfe3 ths
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
572 2802bfe3 ths
#else
573 2802bfe3 ths
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
574 2802bfe3 ths
#endif
575 2802bfe3 ths
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
576 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
577 2802bfe3 ths
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
578 2802bfe3 ths
#else
579 2802bfe3 ths
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
580 2802bfe3 ths
#endif
581 2802bfe3 ths
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
582 2802bfe3 ths
583 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
584 2802bfe3 ths
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
585 2802bfe3 ths
#else
586 2802bfe3 ths
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
587 2802bfe3 ths
#endif
588 2802bfe3 ths
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
589 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
590 2802bfe3 ths
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
591 2802bfe3 ths
#else
592 2802bfe3 ths
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
593 2802bfe3 ths
#endif
594 2802bfe3 ths
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
595 2802bfe3 ths
596 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
597 2802bfe3 ths
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
598 2802bfe3 ths
#else
599 2802bfe3 ths
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
600 2802bfe3 ths
#endif
601 2802bfe3 ths
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
602 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
603 2802bfe3 ths
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
604 2802bfe3 ths
#else
605 2802bfe3 ths
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
606 2802bfe3 ths
#endif
607 2802bfe3 ths
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
608 2802bfe3 ths
609 2802bfe3 ths
    /* Jump to kernel code */
610 74287114 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
611 74287114 ths
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
612 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
613 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
614 26ea0918 ths
615 26ea0918 ths
    /* YAMON subroutines */
616 d7585251 pbrook
    p = (uint32_t *) (base + 0x800);
617 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
618 26ea0918 ths
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
619 26ea0918 ths
   /* 808 YAMON print */
620 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
621 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
622 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
623 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
624 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
625 26ea0918 ths
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
626 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
627 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
628 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
629 26ea0918 ths
    stl_raw(p++, 0x08000205);                                     /* j 814 */
630 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
631 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
632 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
633 26ea0918 ths
    /* 0x83c YAMON print_count */
634 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
635 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
636 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
637 26ea0918 ths
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
638 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
639 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
640 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
641 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
642 26ea0918 ths
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
643 26ea0918 ths
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
644 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
645 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
646 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
647 26ea0918 ths
    /* 0x870 */
648 26ea0918 ths
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
649 26ea0918 ths
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
650 26ea0918 ths
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
651 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
652 26ea0918 ths
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
653 26ea0918 ths
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
654 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
655 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
656 26ea0918 ths
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
657 26ea0918 ths
658 5856de80 ths
}
659 5856de80 ths
660 c938ada2 Aurelien Jarno
static void prom_set(uint32_t* prom_buf, int index, const char *string, ...)
661 5856de80 ths
{
662 5856de80 ths
    va_list ap;
663 3ddd0065 ths
    int32_t table_addr;
664 5856de80 ths
665 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
666 5856de80 ths
        return;
667 5856de80 ths
668 5856de80 ths
    if (string == NULL) {
669 c938ada2 Aurelien Jarno
        prom_buf[index] = 0;
670 5856de80 ths
        return;
671 5856de80 ths
    }
672 5856de80 ths
673 c938ada2 Aurelien Jarno
    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
674 c938ada2 Aurelien Jarno
    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
675 5856de80 ths
676 5856de80 ths
    va_start(ap, string);
677 c938ada2 Aurelien Jarno
    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
678 5856de80 ths
    va_end(ap);
679 5856de80 ths
}
680 5856de80 ths
681 5856de80 ths
/* Kernel */
682 e16ad5b0 Aurelien Jarno
static int64_t load_kernel (void)
683 5856de80 ths
{
684 74287114 ths
    int64_t kernel_entry, kernel_low, kernel_high;
685 5856de80 ths
    long initrd_size;
686 c227f099 Anthony Liguori
    ram_addr_t initrd_offset;
687 ca20cf32 Blue Swirl
    int big_endian;
688 c938ada2 Aurelien Jarno
    uint32_t *prom_buf;
689 c938ada2 Aurelien Jarno
    long prom_size;
690 c938ada2 Aurelien Jarno
    int prom_index = 0;
691 ca20cf32 Blue Swirl
692 ca20cf32 Blue Swirl
#ifdef TARGET_WORDS_BIGENDIAN
693 ca20cf32 Blue Swirl
    big_endian = 1;
694 ca20cf32 Blue Swirl
#else
695 ca20cf32 Blue Swirl
    big_endian = 0;
696 ca20cf32 Blue Swirl
#endif
697 5856de80 ths
698 7df526e3 ths
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
699 b55266b5 blueswir1
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
700 ca20cf32 Blue Swirl
                 (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
701 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
702 7df526e3 ths
                loaderparams.kernel_filename);
703 acdf72bb ths
        exit(1);
704 5856de80 ths
    }
705 5856de80 ths
706 5856de80 ths
    /* load initrd */
707 5856de80 ths
    initrd_size = 0;
708 74287114 ths
    initrd_offset = 0;
709 7df526e3 ths
    if (loaderparams.initrd_filename) {
710 7df526e3 ths
        initrd_size = get_image_size (loaderparams.initrd_filename);
711 74287114 ths
        if (initrd_size > 0) {
712 74287114 ths
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
713 7df526e3 ths
            if (initrd_offset + initrd_size > ram_size) {
714 74287114 ths
                fprintf(stderr,
715 74287114 ths
                        "qemu: memory too small for initial ram disk '%s'\n",
716 7df526e3 ths
                        loaderparams.initrd_filename);
717 74287114 ths
                exit(1);
718 74287114 ths
            }
719 dcac9679 pbrook
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
720 dcac9679 pbrook
                                              initrd_offset,
721 dcac9679 pbrook
                                              ram_size - initrd_offset);
722 74287114 ths
        }
723 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
724 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
725 7df526e3 ths
                    loaderparams.initrd_filename);
726 5856de80 ths
            exit(1);
727 5856de80 ths
        }
728 5856de80 ths
    }
729 5856de80 ths
730 c938ada2 Aurelien Jarno
    /* Setup prom parameters. */
731 c938ada2 Aurelien Jarno
    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
732 c938ada2 Aurelien Jarno
    prom_buf = qemu_malloc(prom_size);
733 c938ada2 Aurelien Jarno
734 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
735 c938ada2 Aurelien Jarno
    if (initrd_size > 0) {
736 c938ada2 Aurelien Jarno
        prom_set(prom_buf, prom_index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
737 74287114 ths
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
738 7df526e3 ths
                 loaderparams.kernel_cmdline);
739 c938ada2 Aurelien Jarno
    } else {
740 c938ada2 Aurelien Jarno
        prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
741 c938ada2 Aurelien Jarno
    }
742 c938ada2 Aurelien Jarno
743 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "memsize");
744 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
745 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "modetty0");
746 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "38400n8r");
747 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, NULL);
748 c938ada2 Aurelien Jarno
749 c938ada2 Aurelien Jarno
    rom_add_blob_fixed("prom", prom_buf, prom_size,
750 c938ada2 Aurelien Jarno
                       ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
751 5856de80 ths
752 74287114 ths
    return kernel_entry;
753 5856de80 ths
}
754 5856de80 ths
755 5856de80 ths
static void main_cpu_reset(void *opaque)
756 5856de80 ths
{
757 5856de80 ths
    CPUState *env = opaque;
758 5856de80 ths
    cpu_reset(env);
759 5856de80 ths
760 5856de80 ths
    /* The bootload does not need to be rewritten as it is located in a
761 5856de80 ths
       read only location. The kernel location and the arguments table
762 5856de80 ths
       location does not change. */
763 7df526e3 ths
    if (loaderparams.kernel_filename) {
764 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
765 fb82fea0 ths
    }
766 5856de80 ths
}
767 5856de80 ths
768 70705261 ths
static
769 c227f099 Anthony Liguori
void mips_malta_init (ram_addr_t ram_size,
770 3023f332 aliguori
                      const char *boot_device,
771 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
772 94fc95cd j_mayer
                      const char *initrd_filename, const char *cpu_model)
773 5856de80 ths
{
774 5cea8590 Paul Brook
    char *filename;
775 c227f099 Anthony Liguori
    ram_addr_t ram_offset;
776 c227f099 Anthony Liguori
    ram_addr_t bios_offset;
777 c8b153d7 ths
    target_long bios_size;
778 74287114 ths
    int64_t kernel_entry;
779 5856de80 ths
    PCIBus *pci_bus;
780 ae027ad3 Stefan Weil
    ISADevice *isa_dev;
781 5856de80 ths
    CPUState *env;
782 5856de80 ths
    RTCState *rtc_state;
783 c227f099 Anthony Liguori
    fdctrl_t *floppy_controller;
784 5856de80 ths
    MaltaFPGAState *malta_fpga;
785 d537cf6c pbrook
    qemu_irq *i8259;
786 7b717336 ths
    int piix4_devfn;
787 7b717336 ths
    uint8_t *eeprom_buf;
788 7b717336 ths
    i2c_bus *smbus;
789 7b717336 ths
    int i;
790 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
791 f455e98c Gerd Hoffmann
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
792 fd8014e1 Gerd Hoffmann
    DriveInfo *fd[MAX_FD];
793 c8b153d7 ths
    int fl_idx = 0;
794 c8b153d7 ths
    int fl_sectors = 0;
795 5856de80 ths
796 ffabf037 Aurelien Jarno
    /* Make sure the first 3 serial ports are associated with a device. */
797 ffabf037 Aurelien Jarno
    for(i = 0; i < 3; i++) {
798 ffabf037 Aurelien Jarno
        if (!serial_hds[i]) {
799 ffabf037 Aurelien Jarno
            char label[32];
800 ffabf037 Aurelien Jarno
            snprintf(label, sizeof(label), "serial%d", i);
801 ffabf037 Aurelien Jarno
            serial_hds[i] = qemu_chr_open(label, "null", NULL);
802 ffabf037 Aurelien Jarno
        }
803 ffabf037 Aurelien Jarno
    }
804 ffabf037 Aurelien Jarno
805 33d68b5f ths
    /* init CPUs */
806 33d68b5f ths
    if (cpu_model == NULL) {
807 60aa19ab ths
#ifdef TARGET_MIPS64
808 c9c1a064 ths
        cpu_model = "20Kc";
809 33d68b5f ths
#else
810 1c32f43e ths
        cpu_model = "24Kf";
811 33d68b5f ths
#endif
812 33d68b5f ths
    }
813 aaed909a bellard
    env = cpu_init(cpu_model);
814 aaed909a bellard
    if (!env) {
815 aaed909a bellard
        fprintf(stderr, "Unable to find CPU definition\n");
816 aaed909a bellard
        exit(1);
817 aaed909a bellard
    }
818 a08d4367 Jan Kiszka
    qemu_register_reset(main_cpu_reset, env);
819 5856de80 ths
820 5856de80 ths
    /* allocate RAM */
821 0ccff151 aurel32
    if (ram_size > (256 << 20)) {
822 0ccff151 aurel32
        fprintf(stderr,
823 0ccff151 aurel32
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
824 0ccff151 aurel32
                ((unsigned int)ram_size / (1 << 20)));
825 0ccff151 aurel32
        exit(1);
826 0ccff151 aurel32
    }
827 dcac9679 pbrook
    ram_offset = qemu_ram_alloc(ram_size);
828 dcac9679 pbrook
    bios_offset = qemu_ram_alloc(BIOS_SIZE);
829 dcac9679 pbrook
830 dcac9679 pbrook
831 dcac9679 pbrook
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
832 5856de80 ths
833 c8b153d7 ths
    /* Map the bios at two physical locations, as on the real board. */
834 5856de80 ths
    cpu_register_physical_memory(0x1e000000LL,
835 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
836 5856de80 ths
    cpu_register_physical_memory(0x1fc00000LL,
837 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
838 5856de80 ths
839 070ce5ed ths
    /* FPGA */
840 470d86b7 aurel32
    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
841 070ce5ed ths
842 c8b153d7 ths
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
843 c8b153d7 ths
    if (kernel_filename) {
844 c8b153d7 ths
        /* Write a small bootloader to the flash location. */
845 c8b153d7 ths
        loaderparams.ram_size = ram_size;
846 c8b153d7 ths
        loaderparams.kernel_filename = kernel_filename;
847 c8b153d7 ths
        loaderparams.kernel_cmdline = kernel_cmdline;
848 c8b153d7 ths
        loaderparams.initrd_filename = initrd_filename;
849 e16ad5b0 Aurelien Jarno
        kernel_entry = load_kernel();
850 d7585251 pbrook
        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
851 c8b153d7 ths
    } else {
852 751c6a17 Gerd Hoffmann
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
853 751c6a17 Gerd Hoffmann
        if (dinfo) {
854 c8b153d7 ths
            /* Load firmware from flash. */
855 c8b153d7 ths
            bios_size = 0x400000;
856 c8b153d7 ths
            fl_sectors = bios_size >> 16;
857 c8b153d7 ths
#ifdef DEBUG_BOARD_INIT
858 c8b153d7 ths
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
859 c8b153d7 ths
                   "offset %08lx addr %08llx '%s' %x\n",
860 c8b153d7 ths
                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
861 751c6a17 Gerd Hoffmann
                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
862 c8b153d7 ths
#endif
863 c8b153d7 ths
            pflash_cfi01_register(0x1e000000LL, bios_offset,
864 751c6a17 Gerd Hoffmann
                                  dinfo->bdrv, 65536, fl_sectors,
865 c8b153d7 ths
                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
866 c8b153d7 ths
            fl_idx++;
867 c8b153d7 ths
        } else {
868 c8b153d7 ths
            /* Load a BIOS image. */
869 c8b153d7 ths
            if (bios_name == NULL)
870 c8b153d7 ths
                bios_name = BIOS_FILENAME;
871 5cea8590 Paul Brook
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
872 5cea8590 Paul Brook
            if (filename) {
873 5cea8590 Paul Brook
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
874 5cea8590 Paul Brook
                                                BIOS_SIZE);
875 5cea8590 Paul Brook
                qemu_free(filename);
876 5cea8590 Paul Brook
            } else {
877 5cea8590 Paul Brook
                bios_size = -1;
878 5cea8590 Paul Brook
            }
879 c8b153d7 ths
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
880 c8b153d7 ths
                fprintf(stderr,
881 c8b153d7 ths
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
882 5cea8590 Paul Brook
                        bios_name);
883 c8b153d7 ths
                exit(1);
884 c8b153d7 ths
            }
885 070ce5ed ths
        }
886 3187ef03 ths
        /* In little endian mode the 32bit words in the bios are swapped,
887 3187ef03 ths
           a neat trick which allows bi-endian firmware. */
888 3187ef03 ths
#ifndef TARGET_WORDS_BIGENDIAN
889 3187ef03 ths
        {
890 d7585251 pbrook
            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
891 d7585251 pbrook
            uint32_t *end = addr + bios_size;
892 d7585251 pbrook
            while (addr < end) {
893 d7585251 pbrook
                bswap32s(addr);
894 3187ef03 ths
            }
895 3187ef03 ths
        }
896 3187ef03 ths
#endif
897 070ce5ed ths
    }
898 070ce5ed ths
899 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
900 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
901 5856de80 ths
       map to the board ID. */
902 d7585251 pbrook
    stl_phys(0x1fc00010LL, 0x00000420);
903 5856de80 ths
904 5856de80 ths
    /* Init internal devices */
905 d537cf6c pbrook
    cpu_mips_irq_init_cpu(env);
906 5856de80 ths
    cpu_mips_clock_init(env);
907 5856de80 ths
908 5856de80 ths
    /* Interrupt controller */
909 d537cf6c pbrook
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
910 d537cf6c pbrook
    i8259 = i8259_init(env->irq[2]);
911 5856de80 ths
912 5856de80 ths
    /* Northbridge */
913 d537cf6c pbrook
    pci_bus = pci_gt64120_init(i8259);
914 5856de80 ths
915 5856de80 ths
    /* Southbridge */
916 e4bcb14c ths
917 e4bcb14c ths
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
918 e4bcb14c ths
        fprintf(stderr, "qemu: too many IDE bus\n");
919 e4bcb14c ths
        exit(1);
920 e4bcb14c ths
    }
921 e4bcb14c ths
922 e4bcb14c ths
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
923 f455e98c Gerd Hoffmann
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
924 e4bcb14c ths
    }
925 e4bcb14c ths
926 7b717336 ths
    piix4_devfn = piix4_init(pci_bus, 80);
927 ae027ad3 Stefan Weil
    isa_bus_irqs(i8259);
928 ae027ad3 Stefan Weil
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
929 afcc3cdf ths
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
930 ae027ad3 Stefan Weil
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9));
931 7b717336 ths
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
932 7b717336 ths
    for (i = 0; i < 8; i++) {
933 7b717336 ths
        /* TODO: Populate SPD eeprom data.  */
934 1ea96673 Paul Brook
        DeviceState *eeprom;
935 02e2da45 Paul Brook
        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
936 5b7f5327 Juan Quintela
        qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
937 ee6847d1 Gerd Hoffmann
        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
938 e23a1b33 Markus Armbruster
        qdev_init_nofail(eeprom);
939 7b717336 ths
    }
940 ae027ad3 Stefan Weil
    pit = pit_init(0x40, isa_reserve_irq(0));
941 5856de80 ths
    DMA_init(0);
942 5856de80 ths
943 5856de80 ths
    /* Super I/O */
944 2e15e23b Gerd Hoffmann
    isa_dev = isa_create_simple("i8042");
945 ae027ad3 Stefan Weil
 
946 32e0c826 Gerd Hoffmann
    rtc_state = rtc_init(2000);
947 ac0be998 Gerd Hoffmann
    serial_isa_init(0, serial_hds[0]);
948 ac0be998 Gerd Hoffmann
    serial_isa_init(1, serial_hds[1]);
949 7bcc17dc ths
    if (parallel_hds[0])
950 021f0674 Gerd Hoffmann
        parallel_init(0, parallel_hds[0]);
951 e4bcb14c ths
    for(i = 0; i < MAX_FD; i++) {
952 fd8014e1 Gerd Hoffmann
        fd[i] = drive_get(IF_FLOPPY, 0, i);
953 e4bcb14c ths
    }
954 86c86157 Gerd Hoffmann
    floppy_controller = fdctrl_init_isa(fd);
955 5856de80 ths
956 5856de80 ths
    /* Sound card */
957 5856de80 ths
#ifdef HAS_AUDIO
958 5856de80 ths
    audio_init(pci_bus);
959 5856de80 ths
#endif
960 5856de80 ths
961 5856de80 ths
    /* Network card */
962 5607c388 Markus Armbruster
    network_init();
963 11f29511 ths
964 11f29511 ths
    /* Optional PCI video card */
965 1f605a76 aurel32
    if (cirrus_vga_enabled) {
966 fbe1b595 Paul Brook
        pci_cirrus_vga_init(pci_bus);
967 1f605a76 aurel32
    } else if (vmsvga_enabled) {
968 fbe1b595 Paul Brook
        pci_vmsvga_init(pci_bus);
969 1f605a76 aurel32
    } else if (std_vga_enabled) {
970 fbe1b595 Paul Brook
        pci_vga_init(pci_bus, 0, 0);
971 1f605a76 aurel32
    }
972 5856de80 ths
}
973 5856de80 ths
974 f80f9ec9 Anthony Liguori
static QEMUMachine mips_malta_machine = {
975 eec2743e ths
    .name = "malta",
976 eec2743e ths
    .desc = "MIPS Malta Core LV",
977 eec2743e ths
    .init = mips_malta_init,
978 0c257437 Anthony Liguori
    .is_default = 1,
979 5856de80 ths
};
980 f80f9ec9 Anthony Liguori
981 f80f9ec9 Anthony Liguori
static void mips_malta_machine_init(void)
982 f80f9ec9 Anthony Liguori
{
983 f80f9ec9 Anthony Liguori
    qemu_register_machine(&mips_malta_machine);
984 f80f9ec9 Anthony Liguori
}
985 f80f9ec9 Anthony Liguori
986 f80f9ec9 Anthony Liguori
machine_init(mips_malta_machine_init);