Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 51b2772f

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

512 5856de80 ths
   The following code implements a very very simple bootloader. It first
513 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
514 5856de80 ths
   then jump at the kernel address.
515 5856de80 ths

516 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
517 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
518 5856de80 ths
   of NULL terminated strings. The environment variables table should be
519 5856de80 ths
   terminated by a NULL address.
520 5856de80 ths

521 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
522 5856de80 ths
   to two (the name of the kernel and the command line), and the two
523 5856de80 ths
   tables are actually the same one.
524 5856de80 ths

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