Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 5fafdf24

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

483 5856de80 ths
   The following code implements a very very simple bootloader. It first
484 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
485 5856de80 ths
   then jump at the kernel address.
486 5856de80 ths

487 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
488 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
489 5856de80 ths
   of NULL terminated strings. The environment variables table should be
490 5856de80 ths
   terminated by a NULL address.
491 5856de80 ths

492 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
493 5856de80 ths
   to two (the name of the kernel and the command line), and the two
494 5856de80 ths
   tables are actually the same one.
495 5856de80 ths

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