Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 183aa454

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

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

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

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

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