Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 9277bc72

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

508 5856de80 ths
   The following code implements a very very simple bootloader. It first
509 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
510 5856de80 ths
   then jump at the kernel address.
511 5856de80 ths

512 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
513 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
514 5856de80 ths
   of NULL terminated strings. The environment variables table should be
515 5856de80 ths
   terminated by a NULL address.
516 5856de80 ths

517 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
518 5856de80 ths
   to two (the name of the kernel and the command line), and the two
519 5856de80 ths
   tables are actually the same one.
520 5856de80 ths

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