Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 9596ebb7

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

500 5856de80 ths
   The following code implements a very very simple bootloader. It first
501 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
502 5856de80 ths
   then jump at the kernel address.
503 5856de80 ths

504 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
505 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
506 5856de80 ths
   of NULL terminated strings. The environment variables table should be
507 5856de80 ths
   terminated by a NULL address.
508 5856de80 ths

509 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
510 5856de80 ths
   to two (the name of the kernel and the command line), and the two
511 5856de80 ths
   tables are actually the same one.
512 5856de80 ths

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