Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 2e15e23b

History | View | Annotate | Download (31.3 kB)

1 5856de80 ths
/*
2 5856de80 ths
 * QEMU Malta board support
3 5856de80 ths
 *
4 5856de80 ths
 * Copyright (c) 2006 Aurelien Jarno
5 5856de80 ths
 *
6 5856de80 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 5856de80 ths
 * of this software and associated documentation files (the "Software"), to deal
8 5856de80 ths
 * in the Software without restriction, including without limitation the rights
9 5856de80 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 5856de80 ths
 * copies of the Software, and to permit persons to whom the Software is
11 5856de80 ths
 * furnished to do so, subject to the following conditions:
12 5856de80 ths
 *
13 5856de80 ths
 * The above copyright notice and this permission notice shall be included in
14 5856de80 ths
 * all copies or substantial portions of the Software.
15 5856de80 ths
 *
16 5856de80 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 5856de80 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 5856de80 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 5856de80 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 5856de80 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 5856de80 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 5856de80 ths
 * THE SOFTWARE.
23 5856de80 ths
 */
24 5856de80 ths
25 87ecb68b pbrook
#include "hw.h"
26 87ecb68b pbrook
#include "pc.h"
27 ded7ba9c ths
#include "fdc.h"
28 87ecb68b pbrook
#include "net.h"
29 87ecb68b pbrook
#include "boards.h"
30 87ecb68b pbrook
#include "smbus.h"
31 c8b153d7 ths
#include "block.h"
32 c8b153d7 ths
#include "flash.h"
33 87ecb68b pbrook
#include "mips.h"
34 87ecb68b pbrook
#include "pci.h"
35 87ecb68b pbrook
#include "qemu-char.h"
36 87ecb68b pbrook
#include "sysemu.h"
37 87ecb68b pbrook
#include "audio/audio.h"
38 87ecb68b pbrook
#include "boards.h"
39 3b3fb322 blueswir1
#include "qemu-log.h"
40 bba831e8 Paul Brook
#include "mips-bios.h"
41 977e1244 Gerd Hoffmann
#include "ide.h"
42 5856de80 ths
43 c8b153d7 ths
//#define DEBUG_BOARD_INIT
44 c8b153d7 ths
45 60aa19ab ths
#ifdef TARGET_MIPS64
46 74287114 ths
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
47 5856de80 ths
#else
48 74287114 ths
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
49 5856de80 ths
#endif
50 5856de80 ths
51 74287114 ths
#define ENVP_ADDR (int32_t)0x80002000
52 74287114 ths
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
53 5856de80 ths
54 5856de80 ths
#define ENVP_NB_ENTRIES                 16
55 5856de80 ths
#define ENVP_ENTRY_SIZE                 256
56 5856de80 ths
57 e4bcb14c ths
#define MAX_IDE_BUS 2
58 e4bcb14c ths
59 5856de80 ths
typedef struct {
60 5856de80 ths
    uint32_t leds;
61 5856de80 ths
    uint32_t brk;
62 5856de80 ths
    uint32_t gpout;
63 130751ee ths
    uint32_t i2cin;
64 5856de80 ths
    uint32_t i2coe;
65 5856de80 ths
    uint32_t i2cout;
66 5856de80 ths
    uint32_t i2csel;
67 5856de80 ths
    CharDriverState *display;
68 5856de80 ths
    char display_text[9];
69 a4bc3afc ths
    SerialState *uart;
70 5856de80 ths
} MaltaFPGAState;
71 5856de80 ths
72 5856de80 ths
static PITState *pit;
73 5856de80 ths
74 7df526e3 ths
static struct _loaderparams {
75 7df526e3 ths
    int ram_size;
76 7df526e3 ths
    const char *kernel_filename;
77 7df526e3 ths
    const char *kernel_cmdline;
78 7df526e3 ths
    const char *initrd_filename;
79 7df526e3 ths
} loaderparams;
80 7df526e3 ths
81 5856de80 ths
/* Malta FPGA */
82 5856de80 ths
static void malta_fpga_update_display(void *opaque)
83 5856de80 ths
{
84 5856de80 ths
    char leds_text[9];
85 5856de80 ths
    int i;
86 5856de80 ths
    MaltaFPGAState *s = opaque;
87 5856de80 ths
88 07cf0ba0 ths
    for (i = 7 ; i >= 0 ; i--) {
89 07cf0ba0 ths
        if (s->leds & (1 << i))
90 07cf0ba0 ths
            leds_text[i] = '#';
91 07cf0ba0 ths
        else
92 07cf0ba0 ths
            leds_text[i] = ' ';
93 87ee1669 ths
    }
94 07cf0ba0 ths
    leds_text[8] = '\0';
95 07cf0ba0 ths
96 07cf0ba0 ths
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
97 07cf0ba0 ths
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
98 5856de80 ths
}
99 5856de80 ths
100 130751ee ths
/*
101 130751ee ths
 * EEPROM 24C01 / 24C02 emulation.
102 130751ee ths
 *
103 130751ee ths
 * Emulation for serial EEPROMs:
104 130751ee ths
 * 24C01 - 1024 bit (128 x 8)
105 130751ee ths
 * 24C02 - 2048 bit (256 x 8)
106 130751ee ths
 *
107 130751ee ths
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
108 130751ee ths
 */
109 130751ee ths
110 130751ee ths
//~ #define DEBUG
111 130751ee ths
112 130751ee ths
#if defined(DEBUG)
113 001faf32 Blue Swirl
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
114 130751ee ths
#else
115 001faf32 Blue Swirl
#  define logout(fmt, ...) ((void)0)
116 130751ee ths
#endif
117 130751ee ths
118 130751ee ths
struct _eeprom24c0x_t {
119 130751ee ths
  uint8_t tick;
120 130751ee ths
  uint8_t address;
121 130751ee ths
  uint8_t command;
122 130751ee ths
  uint8_t ack;
123 130751ee ths
  uint8_t scl;
124 130751ee ths
  uint8_t sda;
125 130751ee ths
  uint8_t data;
126 130751ee ths
  //~ uint16_t size;
127 130751ee ths
  uint8_t contents[256];
128 130751ee ths
};
129 130751ee ths
130 130751ee ths
typedef struct _eeprom24c0x_t eeprom24c0x_t;
131 130751ee ths
132 130751ee ths
static eeprom24c0x_t eeprom = {
133 130751ee ths
    contents: {
134 130751ee ths
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
135 130751ee ths
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
136 130751ee ths
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
137 130751ee ths
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
138 130751ee ths
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
139 130751ee ths
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 130751ee ths
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 130751ee ths
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
142 130751ee ths
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 130751ee ths
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 130751ee ths
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145 130751ee ths
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 130751ee ths
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 130751ee ths
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148 130751ee ths
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149 130751ee ths
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
150 130751ee ths
    },
151 130751ee ths
};
152 130751ee ths
153 a5f1b965 blueswir1
static uint8_t eeprom24c0x_read(void)
154 130751ee ths
{
155 130751ee ths
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
156 130751ee ths
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
157 130751ee ths
    return eeprom.sda;
158 130751ee ths
}
159 130751ee ths
160 130751ee ths
static void eeprom24c0x_write(int scl, int sda)
161 130751ee ths
{
162 130751ee ths
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
163 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
164 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
165 130751ee ths
        if (!sda) {
166 130751ee ths
            eeprom.tick = 1;
167 130751ee ths
            eeprom.command = 0;
168 130751ee ths
        }
169 130751ee ths
    } else if (eeprom.tick == 0 && !eeprom.ack) {
170 130751ee ths
        /* Waiting for start. */
171 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
172 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
173 130751ee ths
    } else if (!eeprom.scl && scl) {
174 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
175 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
176 130751ee ths
        if (eeprom.ack) {
177 130751ee ths
            logout("\ti2c ack bit = 0\n");
178 130751ee ths
            sda = 0;
179 130751ee ths
            eeprom.ack = 0;
180 130751ee ths
        } else if (eeprom.sda == sda) {
181 130751ee ths
            uint8_t bit = (sda != 0);
182 130751ee ths
            logout("\ti2c bit = %d\n", bit);
183 130751ee ths
            if (eeprom.tick < 9) {
184 130751ee ths
                eeprom.command <<= 1;
185 130751ee ths
                eeprom.command += bit;
186 130751ee ths
                eeprom.tick++;
187 130751ee ths
                if (eeprom.tick == 9) {
188 130751ee ths
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
189 130751ee ths
                    eeprom.ack = 1;
190 130751ee ths
                }
191 130751ee ths
            } else if (eeprom.tick < 17) {
192 130751ee ths
                if (eeprom.command & 1) {
193 130751ee ths
                    sda = ((eeprom.data & 0x80) != 0);
194 130751ee ths
                }
195 130751ee ths
                eeprom.address <<= 1;
196 130751ee ths
                eeprom.address += bit;
197 130751ee ths
                eeprom.tick++;
198 130751ee ths
                eeprom.data <<= 1;
199 130751ee ths
                if (eeprom.tick == 17) {
200 130751ee ths
                    eeprom.data = eeprom.contents[eeprom.address];
201 130751ee ths
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
202 130751ee ths
                    eeprom.ack = 1;
203 130751ee ths
                    eeprom.tick = 0;
204 130751ee ths
                }
205 130751ee ths
            } else if (eeprom.tick >= 17) {
206 130751ee ths
                sda = 0;
207 130751ee ths
            }
208 130751ee ths
        } else {
209 130751ee ths
            logout("\tsda changed with raising scl\n");
210 130751ee ths
        }
211 130751ee ths
    } else {
212 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
213 130751ee ths
    }
214 130751ee ths
    eeprom.scl = scl;
215 130751ee ths
    eeprom.sda = sda;
216 130751ee ths
}
217 130751ee ths
218 5856de80 ths
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
219 5856de80 ths
{
220 5856de80 ths
    MaltaFPGAState *s = opaque;
221 5856de80 ths
    uint32_t val = 0;
222 5856de80 ths
    uint32_t saddr;
223 5856de80 ths
224 5856de80 ths
    saddr = (addr & 0xfffff);
225 5856de80 ths
226 5856de80 ths
    switch (saddr) {
227 5856de80 ths
228 5856de80 ths
    /* SWITCH Register */
229 5856de80 ths
    case 0x00200:
230 5856de80 ths
        val = 0x00000000;                /* All switches closed */
231 5856de80 ths
        break;
232 5856de80 ths
233 5856de80 ths
    /* STATUS Register */
234 5856de80 ths
    case 0x00208:
235 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
236 5856de80 ths
        val = 0x00000012;
237 5856de80 ths
#else
238 5856de80 ths
        val = 0x00000010;
239 5856de80 ths
#endif
240 5856de80 ths
        break;
241 5856de80 ths
242 5856de80 ths
    /* JMPRS Register */
243 5856de80 ths
    case 0x00210:
244 5856de80 ths
        val = 0x00;
245 5856de80 ths
        break;
246 5856de80 ths
247 5856de80 ths
    /* LEDBAR Register */
248 5856de80 ths
    case 0x00408:
249 5856de80 ths
        val = s->leds;
250 5856de80 ths
        break;
251 5856de80 ths
252 5856de80 ths
    /* BRKRES Register */
253 5856de80 ths
    case 0x00508:
254 5856de80 ths
        val = s->brk;
255 5856de80 ths
        break;
256 5856de80 ths
257 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
258 a4bc3afc ths
259 5856de80 ths
    /* GPOUT Register */
260 5856de80 ths
    case 0x00a00:
261 5856de80 ths
        val = s->gpout;
262 5856de80 ths
        break;
263 5856de80 ths
264 5856de80 ths
    /* XXX: implement a real I2C controller */
265 5856de80 ths
266 5856de80 ths
    /* GPINP Register */
267 5856de80 ths
    case 0x00a08:
268 5856de80 ths
        /* IN = OUT until a real I2C control is implemented */
269 5856de80 ths
        if (s->i2csel)
270 5856de80 ths
            val = s->i2cout;
271 5856de80 ths
        else
272 5856de80 ths
            val = 0x00;
273 5856de80 ths
        break;
274 5856de80 ths
275 5856de80 ths
    /* I2CINP Register */
276 5856de80 ths
    case 0x00b00:
277 130751ee ths
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
278 5856de80 ths
        break;
279 5856de80 ths
280 5856de80 ths
    /* I2COE Register */
281 5856de80 ths
    case 0x00b08:
282 5856de80 ths
        val = s->i2coe;
283 5856de80 ths
        break;
284 5856de80 ths
285 5856de80 ths
    /* I2COUT Register */
286 5856de80 ths
    case 0x00b10:
287 5856de80 ths
        val = s->i2cout;
288 5856de80 ths
        break;
289 5856de80 ths
290 5856de80 ths
    /* I2CSEL Register */
291 5856de80 ths
    case 0x00b18:
292 130751ee ths
        val = s->i2csel;
293 5856de80 ths
        break;
294 5856de80 ths
295 5856de80 ths
    default:
296 5856de80 ths
#if 0
297 3594c774 ths
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
298 44cbbf18 ths
                addr);
299 5856de80 ths
#endif
300 5856de80 ths
        break;
301 5856de80 ths
    }
302 5856de80 ths
    return val;
303 5856de80 ths
}
304 5856de80 ths
305 5856de80 ths
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
306 5856de80 ths
                              uint32_t val)
307 5856de80 ths
{
308 5856de80 ths
    MaltaFPGAState *s = opaque;
309 5856de80 ths
    uint32_t saddr;
310 5856de80 ths
311 5856de80 ths
    saddr = (addr & 0xfffff);
312 5856de80 ths
313 5856de80 ths
    switch (saddr) {
314 5856de80 ths
315 5856de80 ths
    /* SWITCH Register */
316 5856de80 ths
    case 0x00200:
317 5856de80 ths
        break;
318 5856de80 ths
319 5856de80 ths
    /* JMPRS Register */
320 5856de80 ths
    case 0x00210:
321 5856de80 ths
        break;
322 5856de80 ths
323 5856de80 ths
    /* LEDBAR Register */
324 5856de80 ths
    /* XXX: implement a 8-LED array */
325 5856de80 ths
    case 0x00408:
326 5856de80 ths
        s->leds = val & 0xff;
327 5856de80 ths
        break;
328 5856de80 ths
329 5856de80 ths
    /* ASCIIWORD Register */
330 5856de80 ths
    case 0x00410:
331 5856de80 ths
        snprintf(s->display_text, 9, "%08X", val);
332 5856de80 ths
        malta_fpga_update_display(s);
333 5856de80 ths
        break;
334 5856de80 ths
335 5856de80 ths
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
336 5856de80 ths
    case 0x00418:
337 5856de80 ths
    case 0x00420:
338 5856de80 ths
    case 0x00428:
339 5856de80 ths
    case 0x00430:
340 5856de80 ths
    case 0x00438:
341 5856de80 ths
    case 0x00440:
342 5856de80 ths
    case 0x00448:
343 5856de80 ths
    case 0x00450:
344 5856de80 ths
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
345 5856de80 ths
        malta_fpga_update_display(s);
346 5856de80 ths
        break;
347 5856de80 ths
348 5856de80 ths
    /* SOFTRES Register */
349 5856de80 ths
    case 0x00500:
350 5856de80 ths
        if (val == 0x42)
351 5856de80 ths
            qemu_system_reset_request ();
352 5856de80 ths
        break;
353 5856de80 ths
354 5856de80 ths
    /* BRKRES Register */
355 5856de80 ths
    case 0x00508:
356 5856de80 ths
        s->brk = val & 0xff;
357 5856de80 ths
        break;
358 5856de80 ths
359 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
360 a4bc3afc ths
361 5856de80 ths
    /* GPOUT Register */
362 5856de80 ths
    case 0x00a00:
363 5856de80 ths
        s->gpout = val & 0xff;
364 5856de80 ths
        break;
365 5856de80 ths
366 5856de80 ths
    /* I2COE Register */
367 5856de80 ths
    case 0x00b08:
368 5856de80 ths
        s->i2coe = val & 0x03;
369 5856de80 ths
        break;
370 5856de80 ths
371 5856de80 ths
    /* I2COUT Register */
372 5856de80 ths
    case 0x00b10:
373 130751ee ths
        eeprom24c0x_write(val & 0x02, val & 0x01);
374 130751ee ths
        s->i2cout = val;
375 5856de80 ths
        break;
376 5856de80 ths
377 5856de80 ths
    /* I2CSEL Register */
378 5856de80 ths
    case 0x00b18:
379 130751ee ths
        s->i2csel = val & 0x01;
380 5856de80 ths
        break;
381 5856de80 ths
382 5856de80 ths
    default:
383 5856de80 ths
#if 0
384 3594c774 ths
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
385 44cbbf18 ths
                addr);
386 5856de80 ths
#endif
387 5856de80 ths
        break;
388 5856de80 ths
    }
389 5856de80 ths
}
390 5856de80 ths
391 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const malta_fpga_read[] = {
392 5856de80 ths
   malta_fpga_readl,
393 5856de80 ths
   malta_fpga_readl,
394 5856de80 ths
   malta_fpga_readl
395 5856de80 ths
};
396 5856de80 ths
397 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const malta_fpga_write[] = {
398 5856de80 ths
   malta_fpga_writel,
399 5856de80 ths
   malta_fpga_writel,
400 5856de80 ths
   malta_fpga_writel
401 5856de80 ths
};
402 5856de80 ths
403 9596ebb7 pbrook
static void malta_fpga_reset(void *opaque)
404 5856de80 ths
{
405 5856de80 ths
    MaltaFPGAState *s = opaque;
406 5856de80 ths
407 5856de80 ths
    s->leds   = 0x00;
408 5856de80 ths
    s->brk    = 0x0a;
409 5856de80 ths
    s->gpout  = 0x00;
410 130751ee ths
    s->i2cin  = 0x3;
411 5856de80 ths
    s->i2coe  = 0x0;
412 5856de80 ths
    s->i2cout = 0x3;
413 5856de80 ths
    s->i2csel = 0x1;
414 5856de80 ths
415 5856de80 ths
    s->display_text[8] = '\0';
416 5856de80 ths
    snprintf(s->display_text, 9, "        ");
417 ceecf1d1 aurel32
}
418 ceecf1d1 aurel32
419 ceecf1d1 aurel32
static void malta_fpga_led_init(CharDriverState *chr)
420 ceecf1d1 aurel32
{
421 ceecf1d1 aurel32
    qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
422 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
423 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+        +\r\n");
424 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
425 ceecf1d1 aurel32
    qemu_chr_printf(chr, "\n");
426 ceecf1d1 aurel32
    qemu_chr_printf(chr, "Malta ASCII\r\n");
427 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
428 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+        +\r\n");
429 ceecf1d1 aurel32
    qemu_chr_printf(chr, "+--------+\r\n");
430 5856de80 ths
}
431 5856de80 ths
432 470d86b7 aurel32
static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
433 5856de80 ths
{
434 5856de80 ths
    MaltaFPGAState *s;
435 5856de80 ths
    int malta;
436 5856de80 ths
437 5856de80 ths
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
438 5856de80 ths
439 1eed09cb Avi Kivity
    malta = cpu_register_io_memory(malta_fpga_read,
440 5856de80 ths
                                   malta_fpga_write, s);
441 a4bc3afc ths
442 b6dc7ebb ths
    cpu_register_physical_memory(base, 0x900, malta);
443 8da3ff18 pbrook
    /* 0xa00 is less than a page, so will still get the right offsets.  */
444 b6dc7ebb ths
    cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
445 5856de80 ths
446 ceecf1d1 aurel32
    s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
447 ceecf1d1 aurel32
448 470d86b7 aurel32
    s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1);
449 a4bc3afc ths
450 5856de80 ths
    malta_fpga_reset(s);
451 a08d4367 Jan Kiszka
    qemu_register_reset(malta_fpga_reset, s);
452 5856de80 ths
453 5856de80 ths
    return s;
454 5856de80 ths
}
455 5856de80 ths
456 5856de80 ths
/* Audio support */
457 5856de80 ths
#ifdef HAS_AUDIO
458 5856de80 ths
static void audio_init (PCIBus *pci_bus)
459 5856de80 ths
{
460 5856de80 ths
    struct soundhw *c;
461 5856de80 ths
    int audio_enabled = 0;
462 5856de80 ths
463 5856de80 ths
    for (c = soundhw; !audio_enabled && c->name; ++c) {
464 5856de80 ths
        audio_enabled = c->enabled;
465 5856de80 ths
    }
466 5856de80 ths
467 5856de80 ths
    if (audio_enabled) {
468 0d9acba8 Paul Brook
        for (c = soundhw; c->name; ++c) {
469 0d9acba8 Paul Brook
            if (c->enabled) {
470 22d83b14 Paul Brook
                c->init.init_pci(pci_bus);
471 5856de80 ths
            }
472 5856de80 ths
        }
473 5856de80 ths
    }
474 5856de80 ths
}
475 5856de80 ths
#endif
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 5607c388 Markus Armbruster
        pci_nic_init(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 5856de80 ths
static void prom_set(int index, const char *string, ...)
657 5856de80 ths
{
658 d7585251 pbrook
    char buf[ENVP_ENTRY_SIZE];
659 d7585251 pbrook
    target_phys_addr_t p;
660 5856de80 ths
    va_list ap;
661 3ddd0065 ths
    int32_t table_addr;
662 5856de80 ths
663 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
664 5856de80 ths
        return;
665 5856de80 ths
666 d7585251 pbrook
    p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
667 5856de80 ths
668 5856de80 ths
    if (string == NULL) {
669 d7585251 pbrook
        stl_phys(p, 0);
670 5856de80 ths
        return;
671 5856de80 ths
    }
672 5856de80 ths
673 d7585251 pbrook
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES
674 39303672 aurel32
                 + index * ENVP_ENTRY_SIZE;
675 39303672 aurel32
    stl_phys(p, table_addr);
676 5856de80 ths
677 5856de80 ths
    va_start(ap, string);
678 d7585251 pbrook
    vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap);
679 5856de80 ths
    va_end(ap);
680 39303672 aurel32
    pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf);
681 5856de80 ths
}
682 5856de80 ths
683 5856de80 ths
/* Kernel */
684 5856de80 ths
static int64_t load_kernel (CPUState *env)
685 5856de80 ths
{
686 74287114 ths
    int64_t kernel_entry, kernel_low, kernel_high;
687 5856de80 ths
    int index = 0;
688 5856de80 ths
    long initrd_size;
689 74287114 ths
    ram_addr_t initrd_offset;
690 5856de80 ths
691 7df526e3 ths
    if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
692 b55266b5 blueswir1
                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
693 b55266b5 blueswir1
                 (uint64_t *)&kernel_high) < 0) {
694 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
695 7df526e3 ths
                loaderparams.kernel_filename);
696 acdf72bb ths
        exit(1);
697 5856de80 ths
    }
698 5856de80 ths
699 5856de80 ths
    /* load initrd */
700 5856de80 ths
    initrd_size = 0;
701 74287114 ths
    initrd_offset = 0;
702 7df526e3 ths
    if (loaderparams.initrd_filename) {
703 7df526e3 ths
        initrd_size = get_image_size (loaderparams.initrd_filename);
704 74287114 ths
        if (initrd_size > 0) {
705 74287114 ths
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
706 7df526e3 ths
            if (initrd_offset + initrd_size > ram_size) {
707 74287114 ths
                fprintf(stderr,
708 74287114 ths
                        "qemu: memory too small for initial ram disk '%s'\n",
709 7df526e3 ths
                        loaderparams.initrd_filename);
710 74287114 ths
                exit(1);
711 74287114 ths
            }
712 dcac9679 pbrook
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
713 dcac9679 pbrook
                                              initrd_offset,
714 dcac9679 pbrook
                                              ram_size - initrd_offset);
715 74287114 ths
        }
716 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
717 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
718 7df526e3 ths
                    loaderparams.initrd_filename);
719 5856de80 ths
            exit(1);
720 5856de80 ths
        }
721 5856de80 ths
    }
722 5856de80 ths
723 5856de80 ths
    /* Store command line.  */
724 7df526e3 ths
    prom_set(index++, loaderparams.kernel_filename);
725 5856de80 ths
    if (initrd_size > 0)
726 74287114 ths
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
727 74287114 ths
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
728 7df526e3 ths
                 loaderparams.kernel_cmdline);
729 5856de80 ths
    else
730 7df526e3 ths
        prom_set(index++, loaderparams.kernel_cmdline);
731 5856de80 ths
732 5856de80 ths
    /* Setup minimum environment variables */
733 5856de80 ths
    prom_set(index++, "memsize");
734 7df526e3 ths
    prom_set(index++, "%i", loaderparams.ram_size);
735 5856de80 ths
    prom_set(index++, "modetty0");
736 5856de80 ths
    prom_set(index++, "38400n8r");
737 5856de80 ths
    prom_set(index++, NULL);
738 5856de80 ths
739 74287114 ths
    return kernel_entry;
740 5856de80 ths
}
741 5856de80 ths
742 5856de80 ths
static void main_cpu_reset(void *opaque)
743 5856de80 ths
{
744 5856de80 ths
    CPUState *env = opaque;
745 5856de80 ths
    cpu_reset(env);
746 5856de80 ths
747 5856de80 ths
    /* The bootload does not need to be rewritten as it is located in a
748 5856de80 ths
       read only location. The kernel location and the arguments table
749 5856de80 ths
       location does not change. */
750 7df526e3 ths
    if (loaderparams.kernel_filename) {
751 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
752 5856de80 ths
        load_kernel (env);
753 fb82fea0 ths
    }
754 5856de80 ths
}
755 5856de80 ths
756 70705261 ths
static
757 fbe1b595 Paul Brook
void mips_malta_init (ram_addr_t ram_size,
758 3023f332 aliguori
                      const char *boot_device,
759 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
760 94fc95cd j_mayer
                      const char *initrd_filename, const char *cpu_model)
761 5856de80 ths
{
762 5cea8590 Paul Brook
    char *filename;
763 dcac9679 pbrook
    ram_addr_t ram_offset;
764 dcac9679 pbrook
    ram_addr_t bios_offset;
765 c8b153d7 ths
    target_long bios_size;
766 74287114 ths
    int64_t kernel_entry;
767 5856de80 ths
    PCIBus *pci_bus;
768 ae027ad3 Stefan Weil
    ISADevice *isa_dev;
769 5856de80 ths
    CPUState *env;
770 5856de80 ths
    RTCState *rtc_state;
771 ded7ba9c ths
    fdctrl_t *floppy_controller;
772 5856de80 ths
    MaltaFPGAState *malta_fpga;
773 d537cf6c pbrook
    qemu_irq *i8259;
774 7b717336 ths
    int piix4_devfn;
775 7b717336 ths
    uint8_t *eeprom_buf;
776 7b717336 ths
    i2c_bus *smbus;
777 7b717336 ths
    int i;
778 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
779 f455e98c Gerd Hoffmann
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
780 e4bcb14c ths
    BlockDriverState *fd[MAX_FD];
781 c8b153d7 ths
    int fl_idx = 0;
782 c8b153d7 ths
    int fl_sectors = 0;
783 5856de80 ths
784 33d68b5f ths
    /* init CPUs */
785 33d68b5f ths
    if (cpu_model == NULL) {
786 60aa19ab ths
#ifdef TARGET_MIPS64
787 c9c1a064 ths
        cpu_model = "20Kc";
788 33d68b5f ths
#else
789 1c32f43e ths
        cpu_model = "24Kf";
790 33d68b5f ths
#endif
791 33d68b5f ths
    }
792 aaed909a bellard
    env = cpu_init(cpu_model);
793 aaed909a bellard
    if (!env) {
794 aaed909a bellard
        fprintf(stderr, "Unable to find CPU definition\n");
795 aaed909a bellard
        exit(1);
796 aaed909a bellard
    }
797 a08d4367 Jan Kiszka
    qemu_register_reset(main_cpu_reset, env);
798 5856de80 ths
799 5856de80 ths
    /* allocate RAM */
800 0ccff151 aurel32
    if (ram_size > (256 << 20)) {
801 0ccff151 aurel32
        fprintf(stderr,
802 0ccff151 aurel32
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
803 0ccff151 aurel32
                ((unsigned int)ram_size / (1 << 20)));
804 0ccff151 aurel32
        exit(1);
805 0ccff151 aurel32
    }
806 dcac9679 pbrook
    ram_offset = qemu_ram_alloc(ram_size);
807 dcac9679 pbrook
    bios_offset = qemu_ram_alloc(BIOS_SIZE);
808 dcac9679 pbrook
809 dcac9679 pbrook
810 dcac9679 pbrook
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
811 5856de80 ths
812 c8b153d7 ths
    /* Map the bios at two physical locations, as on the real board. */
813 5856de80 ths
    cpu_register_physical_memory(0x1e000000LL,
814 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
815 5856de80 ths
    cpu_register_physical_memory(0x1fc00000LL,
816 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
817 5856de80 ths
818 070ce5ed ths
    /* FPGA */
819 470d86b7 aurel32
    malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
820 070ce5ed ths
821 c8b153d7 ths
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
822 c8b153d7 ths
    if (kernel_filename) {
823 c8b153d7 ths
        /* Write a small bootloader to the flash location. */
824 c8b153d7 ths
        loaderparams.ram_size = ram_size;
825 c8b153d7 ths
        loaderparams.kernel_filename = kernel_filename;
826 c8b153d7 ths
        loaderparams.kernel_cmdline = kernel_cmdline;
827 c8b153d7 ths
        loaderparams.initrd_filename = initrd_filename;
828 c8b153d7 ths
        kernel_entry = load_kernel(env);
829 c8b153d7 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
830 d7585251 pbrook
        write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
831 c8b153d7 ths
    } else {
832 751c6a17 Gerd Hoffmann
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
833 751c6a17 Gerd Hoffmann
        if (dinfo) {
834 c8b153d7 ths
            /* Load firmware from flash. */
835 c8b153d7 ths
            bios_size = 0x400000;
836 c8b153d7 ths
            fl_sectors = bios_size >> 16;
837 c8b153d7 ths
#ifdef DEBUG_BOARD_INIT
838 c8b153d7 ths
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
839 c8b153d7 ths
                   "offset %08lx addr %08llx '%s' %x\n",
840 c8b153d7 ths
                   fl_idx, bios_size, bios_offset, 0x1e000000LL,
841 751c6a17 Gerd Hoffmann
                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
842 c8b153d7 ths
#endif
843 c8b153d7 ths
            pflash_cfi01_register(0x1e000000LL, bios_offset,
844 751c6a17 Gerd Hoffmann
                                  dinfo->bdrv, 65536, fl_sectors,
845 c8b153d7 ths
                                  4, 0x0000, 0x0000, 0x0000, 0x0000);
846 c8b153d7 ths
            fl_idx++;
847 c8b153d7 ths
        } else {
848 c8b153d7 ths
            /* Load a BIOS image. */
849 c8b153d7 ths
            if (bios_name == NULL)
850 c8b153d7 ths
                bios_name = BIOS_FILENAME;
851 5cea8590 Paul Brook
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
852 5cea8590 Paul Brook
            if (filename) {
853 5cea8590 Paul Brook
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
854 5cea8590 Paul Brook
                                                BIOS_SIZE);
855 5cea8590 Paul Brook
                qemu_free(filename);
856 5cea8590 Paul Brook
            } else {
857 5cea8590 Paul Brook
                bios_size = -1;
858 5cea8590 Paul Brook
            }
859 c8b153d7 ths
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
860 c8b153d7 ths
                fprintf(stderr,
861 c8b153d7 ths
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
862 5cea8590 Paul Brook
                        bios_name);
863 c8b153d7 ths
                exit(1);
864 c8b153d7 ths
            }
865 070ce5ed ths
        }
866 3187ef03 ths
        /* In little endian mode the 32bit words in the bios are swapped,
867 3187ef03 ths
           a neat trick which allows bi-endian firmware. */
868 3187ef03 ths
#ifndef TARGET_WORDS_BIGENDIAN
869 3187ef03 ths
        {
870 d7585251 pbrook
            uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
871 d7585251 pbrook
            uint32_t *end = addr + bios_size;
872 d7585251 pbrook
            while (addr < end) {
873 d7585251 pbrook
                bswap32s(addr);
874 3187ef03 ths
            }
875 3187ef03 ths
        }
876 3187ef03 ths
#endif
877 070ce5ed ths
    }
878 070ce5ed ths
879 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
880 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
881 5856de80 ths
       map to the board ID. */
882 d7585251 pbrook
    stl_phys(0x1fc00010LL, 0x00000420);
883 5856de80 ths
884 5856de80 ths
    /* Init internal devices */
885 d537cf6c pbrook
    cpu_mips_irq_init_cpu(env);
886 5856de80 ths
    cpu_mips_clock_init(env);
887 5856de80 ths
888 5856de80 ths
    /* Interrupt controller */
889 d537cf6c pbrook
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
890 d537cf6c pbrook
    i8259 = i8259_init(env->irq[2]);
891 5856de80 ths
892 5856de80 ths
    /* Northbridge */
893 d537cf6c pbrook
    pci_bus = pci_gt64120_init(i8259);
894 5856de80 ths
895 5856de80 ths
    /* Southbridge */
896 e4bcb14c ths
897 e4bcb14c ths
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
898 e4bcb14c ths
        fprintf(stderr, "qemu: too many IDE bus\n");
899 e4bcb14c ths
        exit(1);
900 e4bcb14c ths
    }
901 e4bcb14c ths
902 e4bcb14c ths
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
903 f455e98c Gerd Hoffmann
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
904 e4bcb14c ths
    }
905 e4bcb14c ths
906 7b717336 ths
    piix4_devfn = piix4_init(pci_bus, 80);
907 ae027ad3 Stefan Weil
    isa_bus_irqs(i8259);
908 ae027ad3 Stefan Weil
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
909 afcc3cdf ths
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
910 ae027ad3 Stefan Weil
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9));
911 7b717336 ths
    eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
912 7b717336 ths
    for (i = 0; i < 8; i++) {
913 7b717336 ths
        /* TODO: Populate SPD eeprom data.  */
914 1ea96673 Paul Brook
        DeviceState *eeprom;
915 02e2da45 Paul Brook
        eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
916 ee6847d1 Gerd Hoffmann
        qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
917 ee6847d1 Gerd Hoffmann
        qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
918 1ea96673 Paul Brook
        qdev_init(eeprom);
919 7b717336 ths
    }
920 ae027ad3 Stefan Weil
    pit = pit_init(0x40, isa_reserve_irq(0));
921 5856de80 ths
    DMA_init(0);
922 5856de80 ths
923 5856de80 ths
    /* Super I/O */
924 2e15e23b Gerd Hoffmann
    isa_dev = isa_create_simple("i8042");
925 ae027ad3 Stefan Weil
 
926 ae027ad3 Stefan Weil
    rtc_state = rtc_init(0x70, isa_reserve_irq(8), 2000);
927 ae027ad3 Stefan Weil
    serial_init(0x3f8, isa_reserve_irq(4), 115200, serial_hds[0]);
928 ae027ad3 Stefan Weil
    serial_init(0x2f8, isa_reserve_irq(3), 115200, serial_hds[1]);
929 7bcc17dc ths
    if (parallel_hds[0])
930 ae027ad3 Stefan Weil
        parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]);
931 e4bcb14c ths
    for(i = 0; i < MAX_FD; i++) {
932 751c6a17 Gerd Hoffmann
        dinfo = drive_get(IF_FLOPPY, 0, i);
933 751c6a17 Gerd Hoffmann
        fd[i] = dinfo ? dinfo->bdrv : NULL;
934 e4bcb14c ths
    }
935 86c86157 Gerd Hoffmann
    floppy_controller = fdctrl_init_isa(fd);
936 5856de80 ths
937 5856de80 ths
    /* Sound card */
938 5856de80 ths
#ifdef HAS_AUDIO
939 5856de80 ths
    audio_init(pci_bus);
940 5856de80 ths
#endif
941 5856de80 ths
942 5856de80 ths
    /* Network card */
943 5607c388 Markus Armbruster
    network_init();
944 11f29511 ths
945 11f29511 ths
    /* Optional PCI video card */
946 1f605a76 aurel32
    if (cirrus_vga_enabled) {
947 fbe1b595 Paul Brook
        pci_cirrus_vga_init(pci_bus);
948 1f605a76 aurel32
    } else if (vmsvga_enabled) {
949 fbe1b595 Paul Brook
        pci_vmsvga_init(pci_bus);
950 1f605a76 aurel32
    } else if (std_vga_enabled) {
951 fbe1b595 Paul Brook
        pci_vga_init(pci_bus, 0, 0);
952 1f605a76 aurel32
    }
953 5856de80 ths
}
954 5856de80 ths
955 f80f9ec9 Anthony Liguori
static QEMUMachine mips_malta_machine = {
956 eec2743e ths
    .name = "malta",
957 eec2743e ths
    .desc = "MIPS Malta Core LV",
958 eec2743e ths
    .init = mips_malta_init,
959 0c257437 Anthony Liguori
    .is_default = 1,
960 5856de80 ths
};
961 f80f9ec9 Anthony Liguori
962 f80f9ec9 Anthony Liguori
static void mips_malta_machine_init(void)
963 f80f9ec9 Anthony Liguori
{
964 f80f9ec9 Anthony Liguori
    qemu_register_machine(&mips_malta_machine);
965 f80f9ec9 Anthony Liguori
}
966 f80f9ec9 Anthony Liguori
967 f80f9ec9 Anthony Liguori
machine_init(mips_malta_machine_init);