Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 8e00128d

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

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

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

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

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