Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 3204db98

History | View | Annotate | Download (33.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 ded7ba9c ths
#include "fdc.h"
28 87ecb68b pbrook
#include "net.h"
29 87ecb68b pbrook
#include "boards.h"
30 87ecb68b pbrook
#include "smbus.h"
31 c8b153d7 ths
#include "block.h"
32 c8b153d7 ths
#include "flash.h"
33 87ecb68b pbrook
#include "mips.h"
34 b970ea8f Blue Swirl
#include "mips_cpudevs.h"
35 87ecb68b pbrook
#include "pci.h"
36 18e08a55 Michael S. Tsirkin
#include "usb-uhci.h"
37 18e08a55 Michael S. Tsirkin
#include "vmware_vga.h"
38 87ecb68b pbrook
#include "qemu-char.h"
39 87ecb68b pbrook
#include "sysemu.h"
40 0dfa5ef9 Isaku Yamahata
#include "arch_init.h"
41 87ecb68b pbrook
#include "boards.h"
42 3b3fb322 blueswir1
#include "qemu-log.h"
43 bba831e8 Paul Brook
#include "mips-bios.h"
44 977e1244 Gerd Hoffmann
#include "ide.h"
45 ca20cf32 Blue Swirl
#include "loader.h"
46 ca20cf32 Blue Swirl
#include "elf.h"
47 1d914fa0 Isaku Yamahata
#include "mc146818rtc.h"
48 2446333c Blue Swirl
#include "blockdev.h"
49 cfe5f011 Avi Kivity
#include "exec-memory.h"
50 5856de80 ths
51 c8b153d7 ths
//#define DEBUG_BOARD_INIT
52 c8b153d7 ths
53 409dbce5 Aurelien Jarno
#define ENVP_ADDR                0x80002000l
54 5856de80 ths
#define ENVP_NB_ENTRIES                 16
55 5856de80 ths
#define ENVP_ENTRY_SIZE                 256
56 5856de80 ths
57 e4bcb14c ths
#define MAX_IDE_BUS 2
58 e4bcb14c ths
59 5856de80 ths
typedef struct {
60 ea85df72 Avi Kivity
    MemoryRegion iomem;
61 ea85df72 Avi Kivity
    MemoryRegion iomem_lo; /* 0 - 0x900 */
62 ea85df72 Avi Kivity
    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
63 5856de80 ths
    uint32_t leds;
64 5856de80 ths
    uint32_t brk;
65 5856de80 ths
    uint32_t gpout;
66 130751ee ths
    uint32_t i2cin;
67 5856de80 ths
    uint32_t i2coe;
68 5856de80 ths
    uint32_t i2cout;
69 5856de80 ths
    uint32_t i2csel;
70 5856de80 ths
    CharDriverState *display;
71 5856de80 ths
    char display_text[9];
72 a4bc3afc ths
    SerialState *uart;
73 5856de80 ths
} MaltaFPGAState;
74 5856de80 ths
75 64d7e9a4 Blue Swirl
static ISADevice *pit;
76 5856de80 ths
77 7df526e3 ths
static struct _loaderparams {
78 7df526e3 ths
    int ram_size;
79 7df526e3 ths
    const char *kernel_filename;
80 7df526e3 ths
    const char *kernel_cmdline;
81 7df526e3 ths
    const char *initrd_filename;
82 7df526e3 ths
} loaderparams;
83 7df526e3 ths
84 5856de80 ths
/* Malta FPGA */
85 5856de80 ths
static void malta_fpga_update_display(void *opaque)
86 5856de80 ths
{
87 5856de80 ths
    char leds_text[9];
88 5856de80 ths
    int i;
89 5856de80 ths
    MaltaFPGAState *s = opaque;
90 5856de80 ths
91 07cf0ba0 ths
    for (i = 7 ; i >= 0 ; i--) {
92 07cf0ba0 ths
        if (s->leds & (1 << i))
93 07cf0ba0 ths
            leds_text[i] = '#';
94 07cf0ba0 ths
        else
95 07cf0ba0 ths
            leds_text[i] = ' ';
96 87ee1669 ths
    }
97 07cf0ba0 ths
    leds_text[8] = '\0';
98 07cf0ba0 ths
99 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
100 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
101 5856de80 ths
}
102 5856de80 ths
103 130751ee ths
/*
104 130751ee ths
 * EEPROM 24C01 / 24C02 emulation.
105 130751ee ths
 *
106 130751ee ths
 * Emulation for serial EEPROMs:
107 130751ee ths
 * 24C01 - 1024 bit (128 x 8)
108 130751ee ths
 * 24C02 - 2048 bit (256 x 8)
109 130751ee ths
 *
110 130751ee ths
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
111 130751ee ths
 */
112 130751ee ths
113 130751ee ths
//~ #define DEBUG
114 130751ee ths
115 130751ee ths
#if defined(DEBUG)
116 001faf32 Blue Swirl
#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
117 130751ee ths
#else
118 001faf32 Blue Swirl
#  define logout(fmt, ...) ((void)0)
119 130751ee ths
#endif
120 130751ee ths
121 c227f099 Anthony Liguori
struct _eeprom24c0x_t {
122 130751ee ths
  uint8_t tick;
123 130751ee ths
  uint8_t address;
124 130751ee ths
  uint8_t command;
125 130751ee ths
  uint8_t ack;
126 130751ee ths
  uint8_t scl;
127 130751ee ths
  uint8_t sda;
128 130751ee ths
  uint8_t data;
129 130751ee ths
  //~ uint16_t size;
130 130751ee ths
  uint8_t contents[256];
131 130751ee ths
};
132 130751ee ths
133 c227f099 Anthony Liguori
typedef struct _eeprom24c0x_t eeprom24c0x_t;
134 130751ee ths
135 c227f099 Anthony Liguori
static eeprom24c0x_t eeprom = {
136 284b08f1 Blue Swirl
    .contents = {
137 130751ee ths
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
138 130751ee ths
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
139 130751ee ths
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
140 130751ee ths
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
141 130751ee ths
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
142 130751ee ths
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 130751ee ths
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 130751ee ths
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
145 130751ee ths
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 130751ee ths
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 130751ee ths
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148 130751ee ths
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149 130751ee ths
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150 130751ee ths
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151 130751ee ths
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
152 130751ee ths
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
153 130751ee ths
    },
154 130751ee ths
};
155 130751ee ths
156 a5f1b965 blueswir1
static uint8_t eeprom24c0x_read(void)
157 130751ee ths
{
158 130751ee ths
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
159 130751ee ths
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
160 130751ee ths
    return eeprom.sda;
161 130751ee ths
}
162 130751ee ths
163 130751ee ths
static void eeprom24c0x_write(int scl, int sda)
164 130751ee ths
{
165 130751ee ths
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
166 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
167 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
168 130751ee ths
        if (!sda) {
169 130751ee ths
            eeprom.tick = 1;
170 130751ee ths
            eeprom.command = 0;
171 130751ee ths
        }
172 130751ee ths
    } else if (eeprom.tick == 0 && !eeprom.ack) {
173 130751ee ths
        /* Waiting for start. */
174 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
175 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
176 130751ee ths
    } else if (!eeprom.scl && scl) {
177 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
178 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
179 130751ee ths
        if (eeprom.ack) {
180 130751ee ths
            logout("\ti2c ack bit = 0\n");
181 130751ee ths
            sda = 0;
182 130751ee ths
            eeprom.ack = 0;
183 130751ee ths
        } else if (eeprom.sda == sda) {
184 130751ee ths
            uint8_t bit = (sda != 0);
185 130751ee ths
            logout("\ti2c bit = %d\n", bit);
186 130751ee ths
            if (eeprom.tick < 9) {
187 130751ee ths
                eeprom.command <<= 1;
188 130751ee ths
                eeprom.command += bit;
189 130751ee ths
                eeprom.tick++;
190 130751ee ths
                if (eeprom.tick == 9) {
191 130751ee ths
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
192 130751ee ths
                    eeprom.ack = 1;
193 130751ee ths
                }
194 130751ee ths
            } else if (eeprom.tick < 17) {
195 130751ee ths
                if (eeprom.command & 1) {
196 130751ee ths
                    sda = ((eeprom.data & 0x80) != 0);
197 130751ee ths
                }
198 130751ee ths
                eeprom.address <<= 1;
199 130751ee ths
                eeprom.address += bit;
200 130751ee ths
                eeprom.tick++;
201 130751ee ths
                eeprom.data <<= 1;
202 130751ee ths
                if (eeprom.tick == 17) {
203 130751ee ths
                    eeprom.data = eeprom.contents[eeprom.address];
204 130751ee ths
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
205 130751ee ths
                    eeprom.ack = 1;
206 130751ee ths
                    eeprom.tick = 0;
207 130751ee ths
                }
208 130751ee ths
            } else if (eeprom.tick >= 17) {
209 130751ee ths
                sda = 0;
210 130751ee ths
            }
211 130751ee ths
        } else {
212 130751ee ths
            logout("\tsda changed with raising scl\n");
213 130751ee ths
        }
214 130751ee ths
    } else {
215 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
216 130751ee ths
    }
217 130751ee ths
    eeprom.scl = scl;
218 130751ee ths
    eeprom.sda = sda;
219 130751ee ths
}
220 130751ee ths
221 ea85df72 Avi Kivity
static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr,
222 ea85df72 Avi Kivity
                                unsigned size)
223 5856de80 ths
{
224 5856de80 ths
    MaltaFPGAState *s = opaque;
225 5856de80 ths
    uint32_t val = 0;
226 5856de80 ths
    uint32_t saddr;
227 5856de80 ths
228 5856de80 ths
    saddr = (addr & 0xfffff);
229 5856de80 ths
230 5856de80 ths
    switch (saddr) {
231 5856de80 ths
232 5856de80 ths
    /* SWITCH Register */
233 5856de80 ths
    case 0x00200:
234 5856de80 ths
        val = 0x00000000;                /* All switches closed */
235 593c0d10 Aurelien Jarno
        break;
236 5856de80 ths
237 5856de80 ths
    /* STATUS Register */
238 5856de80 ths
    case 0x00208:
239 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
240 5856de80 ths
        val = 0x00000012;
241 5856de80 ths
#else
242 5856de80 ths
        val = 0x00000010;
243 5856de80 ths
#endif
244 5856de80 ths
        break;
245 5856de80 ths
246 5856de80 ths
    /* JMPRS Register */
247 5856de80 ths
    case 0x00210:
248 5856de80 ths
        val = 0x00;
249 5856de80 ths
        break;
250 5856de80 ths
251 5856de80 ths
    /* LEDBAR Register */
252 5856de80 ths
    case 0x00408:
253 5856de80 ths
        val = s->leds;
254 5856de80 ths
        break;
255 5856de80 ths
256 5856de80 ths
    /* BRKRES Register */
257 5856de80 ths
    case 0x00508:
258 5856de80 ths
        val = s->brk;
259 5856de80 ths
        break;
260 5856de80 ths
261 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
262 a4bc3afc ths
263 5856de80 ths
    /* GPOUT Register */
264 5856de80 ths
    case 0x00a00:
265 5856de80 ths
        val = s->gpout;
266 5856de80 ths
        break;
267 5856de80 ths
268 5856de80 ths
    /* XXX: implement a real I2C controller */
269 5856de80 ths
270 5856de80 ths
    /* GPINP Register */
271 5856de80 ths
    case 0x00a08:
272 5856de80 ths
        /* IN = OUT until a real I2C control is implemented */
273 5856de80 ths
        if (s->i2csel)
274 5856de80 ths
            val = s->i2cout;
275 5856de80 ths
        else
276 5856de80 ths
            val = 0x00;
277 5856de80 ths
        break;
278 5856de80 ths
279 5856de80 ths
    /* I2CINP Register */
280 5856de80 ths
    case 0x00b00:
281 130751ee ths
        val = ((s->i2cin & ~1) | eeprom24c0x_read());
282 5856de80 ths
        break;
283 5856de80 ths
284 5856de80 ths
    /* I2COE Register */
285 5856de80 ths
    case 0x00b08:
286 5856de80 ths
        val = s->i2coe;
287 5856de80 ths
        break;
288 5856de80 ths
289 5856de80 ths
    /* I2COUT Register */
290 5856de80 ths
    case 0x00b10:
291 5856de80 ths
        val = s->i2cout;
292 5856de80 ths
        break;
293 5856de80 ths
294 5856de80 ths
    /* I2CSEL Register */
295 5856de80 ths
    case 0x00b18:
296 130751ee ths
        val = s->i2csel;
297 5856de80 ths
        break;
298 5856de80 ths
299 5856de80 ths
    default:
300 5856de80 ths
#if 0
301 3594c774 ths
        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
302 593c0d10 Aurelien Jarno
                addr);
303 5856de80 ths
#endif
304 5856de80 ths
        break;
305 5856de80 ths
    }
306 5856de80 ths
    return val;
307 5856de80 ths
}
308 5856de80 ths
309 ea85df72 Avi Kivity
static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
310 ea85df72 Avi Kivity
                             uint64_t val, unsigned size)
311 5856de80 ths
{
312 5856de80 ths
    MaltaFPGAState *s = opaque;
313 5856de80 ths
    uint32_t saddr;
314 5856de80 ths
315 5856de80 ths
    saddr = (addr & 0xfffff);
316 5856de80 ths
317 5856de80 ths
    switch (saddr) {
318 5856de80 ths
319 5856de80 ths
    /* SWITCH Register */
320 5856de80 ths
    case 0x00200:
321 5856de80 ths
        break;
322 5856de80 ths
323 5856de80 ths
    /* JMPRS Register */
324 5856de80 ths
    case 0x00210:
325 5856de80 ths
        break;
326 5856de80 ths
327 5856de80 ths
    /* LEDBAR Register */
328 5856de80 ths
    /* XXX: implement a 8-LED array */
329 5856de80 ths
    case 0x00408:
330 5856de80 ths
        s->leds = val & 0xff;
331 5856de80 ths
        break;
332 5856de80 ths
333 5856de80 ths
    /* ASCIIWORD Register */
334 5856de80 ths
    case 0x00410:
335 ea85df72 Avi Kivity
        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
336 5856de80 ths
        malta_fpga_update_display(s);
337 5856de80 ths
        break;
338 5856de80 ths
339 5856de80 ths
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
340 5856de80 ths
    case 0x00418:
341 5856de80 ths
    case 0x00420:
342 5856de80 ths
    case 0x00428:
343 5856de80 ths
    case 0x00430:
344 5856de80 ths
    case 0x00438:
345 5856de80 ths
    case 0x00440:
346 5856de80 ths
    case 0x00448:
347 5856de80 ths
    case 0x00450:
348 5856de80 ths
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
349 5856de80 ths
        malta_fpga_update_display(s);
350 5856de80 ths
        break;
351 5856de80 ths
352 5856de80 ths
    /* SOFTRES Register */
353 5856de80 ths
    case 0x00500:
354 5856de80 ths
        if (val == 0x42)
355 5856de80 ths
            qemu_system_reset_request ();
356 5856de80 ths
        break;
357 5856de80 ths
358 5856de80 ths
    /* BRKRES Register */
359 5856de80 ths
    case 0x00508:
360 5856de80 ths
        s->brk = val & 0xff;
361 5856de80 ths
        break;
362 5856de80 ths
363 b6dc7ebb ths
    /* UART Registers are handled directly by the serial device */
364 a4bc3afc ths
365 5856de80 ths
    /* GPOUT Register */
366 5856de80 ths
    case 0x00a00:
367 5856de80 ths
        s->gpout = val & 0xff;
368 5856de80 ths
        break;
369 5856de80 ths
370 5856de80 ths
    /* I2COE Register */
371 5856de80 ths
    case 0x00b08:
372 5856de80 ths
        s->i2coe = val & 0x03;
373 5856de80 ths
        break;
374 5856de80 ths
375 5856de80 ths
    /* I2COUT Register */
376 5856de80 ths
    case 0x00b10:
377 130751ee ths
        eeprom24c0x_write(val & 0x02, val & 0x01);
378 130751ee ths
        s->i2cout = val;
379 5856de80 ths
        break;
380 5856de80 ths
381 5856de80 ths
    /* I2CSEL Register */
382 5856de80 ths
    case 0x00b18:
383 130751ee ths
        s->i2csel = val & 0x01;
384 5856de80 ths
        break;
385 5856de80 ths
386 5856de80 ths
    default:
387 5856de80 ths
#if 0
388 3594c774 ths
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
389 593c0d10 Aurelien Jarno
                addr);
390 5856de80 ths
#endif
391 5856de80 ths
        break;
392 5856de80 ths
    }
393 5856de80 ths
}
394 5856de80 ths
395 ea85df72 Avi Kivity
static const MemoryRegionOps malta_fpga_ops = {
396 ea85df72 Avi Kivity
    .read = malta_fpga_read,
397 ea85df72 Avi Kivity
    .write = malta_fpga_write,
398 ea85df72 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
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 ceecf1d1 aurel32
}
416 ceecf1d1 aurel32
417 ceecf1d1 aurel32
static void malta_fpga_led_init(CharDriverState *chr)
418 ceecf1d1 aurel32
{
419 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
420 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
421 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+        +\r\n");
422 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
423 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "\n");
424 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
425 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
426 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+        +\r\n");
427 e7e71b0e Anthony Liguori
    qemu_chr_fe_printf(chr, "+--------+\r\n");
428 5856de80 ths
}
429 5856de80 ths
430 ea85df72 Avi Kivity
static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
431 ea85df72 Avi Kivity
         target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
432 5856de80 ths
{
433 5856de80 ths
    MaltaFPGAState *s;
434 5856de80 ths
435 7267c094 Anthony Liguori
    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
436 5856de80 ths
437 ea85df72 Avi Kivity
    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
438 ea85df72 Avi Kivity
                          "malta-fpga", 0x100000);
439 ea85df72 Avi Kivity
    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
440 ea85df72 Avi Kivity
                             &s->iomem, 0, 0x900);
441 ea85df72 Avi Kivity
    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
442 ea85df72 Avi Kivity
                             &s->iomem, 0xa00, 0x10000-0xa00);
443 a4bc3afc ths
444 ea85df72 Avi Kivity
    memory_region_add_subregion(address_space, base, &s->iomem_lo);
445 ea85df72 Avi Kivity
    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
446 5856de80 ths
447 27143a44 Anthony Liguori
    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
448 ceecf1d1 aurel32
449 39186d8a Richard Henderson
    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
450 39186d8a Richard Henderson
                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
451 a4bc3afc ths
452 5856de80 ths
    malta_fpga_reset(s);
453 a08d4367 Jan Kiszka
    qemu_register_reset(malta_fpga_reset, s);
454 5856de80 ths
455 5856de80 ths
    return s;
456 5856de80 ths
}
457 5856de80 ths
458 5856de80 ths
/* Network support */
459 5607c388 Markus Armbruster
static void network_init(void)
460 5856de80 ths
{
461 5856de80 ths
    int i;
462 5856de80 ths
463 5856de80 ths
    for(i = 0; i < nb_nics; i++) {
464 cb457d76 aliguori
        NICInfo *nd = &nd_table[i];
465 5607c388 Markus Armbruster
        const char *default_devaddr = NULL;
466 cb457d76 aliguori
467 cb457d76 aliguori
        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
468 5856de80 ths
            /* The malta board has a PCNet card using PCI SLOT 11 */
469 5607c388 Markus Armbruster
            default_devaddr = "0b";
470 cb457d76 aliguori
471 07caea31 Markus Armbruster
        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
472 5856de80 ths
    }
473 5856de80 ths
}
474 5856de80 ths
475 5856de80 ths
/* ROM and pseudo bootloader
476 5856de80 ths

477 5856de80 ths
   The following code implements a very very simple bootloader. It first
478 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
479 5856de80 ths
   then jump at the kernel address.
480 5856de80 ths

481 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
482 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
483 5856de80 ths
   of NULL terminated strings. The environment variables table should be
484 5856de80 ths
   terminated by a NULL address.
485 5856de80 ths

486 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
487 5856de80 ths
   to two (the name of the kernel and the command line), and the two
488 5856de80 ths
   tables are actually the same one.
489 5856de80 ths

490 5856de80 ths
   The registers a0 to a3 should contain the following values:
491 5856de80 ths
     a0 - number of kernel arguments
492 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
493 5856de80 ths
     a2 - 32-bit address of the environment variables table
494 5856de80 ths
     a3 - RAM size in bytes
495 5856de80 ths
*/
496 5856de80 ths
497 d7585251 pbrook
static void write_bootloader (CPUState *env, uint8_t *base,
498 d7585251 pbrook
                              int64_t kernel_entry)
499 5856de80 ths
{
500 5856de80 ths
    uint32_t *p;
501 5856de80 ths
502 5856de80 ths
    /* Small bootloader */
503 d7585251 pbrook
    p = (uint32_t *)base;
504 26ea0918 ths
    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
505 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
506 5856de80 ths
507 26ea0918 ths
    /* YAMON service vector */
508 d7585251 pbrook
    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
509 d7585251 pbrook
    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
510 d7585251 pbrook
    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
511 d7585251 pbrook
    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
512 d7585251 pbrook
    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
513 d7585251 pbrook
    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
514 d7585251 pbrook
    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
515 d7585251 pbrook
    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
516 d7585251 pbrook
    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
517 d7585251 pbrook
    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
518 d7585251 pbrook
    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
519 d7585251 pbrook
    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
520 d7585251 pbrook
    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
521 26ea0918 ths
522 26ea0918 ths
523 5856de80 ths
    /* Second part of the bootloader */
524 d7585251 pbrook
    p = (uint32_t *) (base + 0x580);
525 d52fff71 ths
    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
526 d52fff71 ths
    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
527 471ea271 ths
    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
528 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
529 471ea271 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
530 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
531 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
532 7df526e3 ths
    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
533 7df526e3 ths
    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
534 2802bfe3 ths
535 2802bfe3 ths
    /* Load BAR registers as done by YAMON */
536 a0a8793e ths
    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
537 a0a8793e ths
538 a0a8793e ths
#ifdef TARGET_WORDS_BIGENDIAN
539 a0a8793e ths
    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
540 a0a8793e ths
#else
541 a0a8793e ths
    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
542 a0a8793e ths
#endif
543 a0a8793e ths
    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
544 a0a8793e ths
545 2802bfe3 ths
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
546 2802bfe3 ths
547 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
548 2802bfe3 ths
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
549 2802bfe3 ths
#else
550 2802bfe3 ths
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
551 2802bfe3 ths
#endif
552 2802bfe3 ths
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
553 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
554 2802bfe3 ths
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
555 2802bfe3 ths
#else
556 2802bfe3 ths
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
557 2802bfe3 ths
#endif
558 2802bfe3 ths
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
559 2802bfe3 ths
560 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
561 2802bfe3 ths
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
562 2802bfe3 ths
#else
563 2802bfe3 ths
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
564 2802bfe3 ths
#endif
565 2802bfe3 ths
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
566 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
567 2802bfe3 ths
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
568 2802bfe3 ths
#else
569 2802bfe3 ths
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
570 2802bfe3 ths
#endif
571 2802bfe3 ths
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
572 2802bfe3 ths
573 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
574 2802bfe3 ths
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
575 2802bfe3 ths
#else
576 2802bfe3 ths
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
577 2802bfe3 ths
#endif
578 2802bfe3 ths
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
579 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
580 2802bfe3 ths
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
581 2802bfe3 ths
#else
582 2802bfe3 ths
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
583 2802bfe3 ths
#endif
584 2802bfe3 ths
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
585 2802bfe3 ths
586 2802bfe3 ths
    /* Jump to kernel code */
587 74287114 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
588 74287114 ths
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
589 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
590 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
591 26ea0918 ths
592 26ea0918 ths
    /* YAMON subroutines */
593 d7585251 pbrook
    p = (uint32_t *) (base + 0x800);
594 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
595 26ea0918 ths
    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
596 26ea0918 ths
   /* 808 YAMON print */
597 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
598 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
599 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
600 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
601 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
602 26ea0918 ths
    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
603 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
604 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
605 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
606 26ea0918 ths
    stl_raw(p++, 0x08000205);                                     /* j 814 */
607 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
608 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
609 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
610 26ea0918 ths
    /* 0x83c YAMON print_count */
611 26ea0918 ths
    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
612 26ea0918 ths
    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
613 26ea0918 ths
    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
614 26ea0918 ths
    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
615 26ea0918 ths
    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
616 26ea0918 ths
    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
617 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
618 26ea0918 ths
    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
619 26ea0918 ths
    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
620 26ea0918 ths
    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
621 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
622 26ea0918 ths
    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
623 26ea0918 ths
    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
624 26ea0918 ths
    /* 0x870 */
625 26ea0918 ths
    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
626 26ea0918 ths
    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
627 26ea0918 ths
    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
628 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
629 26ea0918 ths
    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
630 26ea0918 ths
    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
631 26ea0918 ths
    stl_raw(p++, 0x00000000);                                     /* nop */
632 26ea0918 ths
    stl_raw(p++, 0x03e00008);                                     /* jr ra */
633 26ea0918 ths
    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
634 26ea0918 ths
635 5856de80 ths
}
636 5856de80 ths
637 8b7968f7 Stefan Weil
static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
638 8b7968f7 Stefan Weil
                                        const char *string, ...)
639 5856de80 ths
{
640 5856de80 ths
    va_list ap;
641 3ddd0065 ths
    int32_t table_addr;
642 5856de80 ths
643 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
644 5856de80 ths
        return;
645 5856de80 ths
646 5856de80 ths
    if (string == NULL) {
647 c938ada2 Aurelien Jarno
        prom_buf[index] = 0;
648 5856de80 ths
        return;
649 5856de80 ths
    }
650 5856de80 ths
651 c938ada2 Aurelien Jarno
    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
652 c938ada2 Aurelien Jarno
    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
653 5856de80 ths
654 5856de80 ths
    va_start(ap, string);
655 c938ada2 Aurelien Jarno
    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
656 5856de80 ths
    va_end(ap);
657 5856de80 ths
}
658 5856de80 ths
659 5856de80 ths
/* Kernel */
660 e16ad5b0 Aurelien Jarno
static int64_t load_kernel (void)
661 5856de80 ths
{
662 409dbce5 Aurelien Jarno
    int64_t kernel_entry, kernel_high;
663 5856de80 ths
    long initrd_size;
664 c227f099 Anthony Liguori
    ram_addr_t initrd_offset;
665 ca20cf32 Blue Swirl
    int big_endian;
666 c938ada2 Aurelien Jarno
    uint32_t *prom_buf;
667 c938ada2 Aurelien Jarno
    long prom_size;
668 c938ada2 Aurelien Jarno
    int prom_index = 0;
669 ca20cf32 Blue Swirl
670 ca20cf32 Blue Swirl
#ifdef TARGET_WORDS_BIGENDIAN
671 ca20cf32 Blue Swirl
    big_endian = 1;
672 ca20cf32 Blue Swirl
#else
673 ca20cf32 Blue Swirl
    big_endian = 0;
674 ca20cf32 Blue Swirl
#endif
675 5856de80 ths
676 409dbce5 Aurelien Jarno
    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
677 409dbce5 Aurelien Jarno
                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
678 409dbce5 Aurelien Jarno
                 big_endian, ELF_MACHINE, 1) < 0) {
679 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
680 7df526e3 ths
                loaderparams.kernel_filename);
681 acdf72bb ths
        exit(1);
682 5856de80 ths
    }
683 5856de80 ths
684 5856de80 ths
    /* load initrd */
685 5856de80 ths
    initrd_size = 0;
686 74287114 ths
    initrd_offset = 0;
687 7df526e3 ths
    if (loaderparams.initrd_filename) {
688 7df526e3 ths
        initrd_size = get_image_size (loaderparams.initrd_filename);
689 74287114 ths
        if (initrd_size > 0) {
690 74287114 ths
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
691 7df526e3 ths
            if (initrd_offset + initrd_size > ram_size) {
692 74287114 ths
                fprintf(stderr,
693 74287114 ths
                        "qemu: memory too small for initial ram disk '%s'\n",
694 7df526e3 ths
                        loaderparams.initrd_filename);
695 74287114 ths
                exit(1);
696 74287114 ths
            }
697 dcac9679 pbrook
            initrd_size = load_image_targphys(loaderparams.initrd_filename,
698 dcac9679 pbrook
                                              initrd_offset,
699 dcac9679 pbrook
                                              ram_size - 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 7df526e3 ths
                    loaderparams.initrd_filename);
704 5856de80 ths
            exit(1);
705 5856de80 ths
        }
706 5856de80 ths
    }
707 5856de80 ths
708 c938ada2 Aurelien Jarno
    /* Setup prom parameters. */
709 c938ada2 Aurelien Jarno
    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
710 7267c094 Anthony Liguori
    prom_buf = g_malloc(prom_size);
711 c938ada2 Aurelien Jarno
712 f36d53ef Stefan Weil
    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
713 c938ada2 Aurelien Jarno
    if (initrd_size > 0) {
714 409dbce5 Aurelien Jarno
        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
715 409dbce5 Aurelien Jarno
                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
716 7df526e3 ths
                 loaderparams.kernel_cmdline);
717 c938ada2 Aurelien Jarno
    } else {
718 f36d53ef Stefan Weil
        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
719 c938ada2 Aurelien Jarno
    }
720 c938ada2 Aurelien Jarno
721 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "memsize");
722 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
723 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "modetty0");
724 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, "38400n8r");
725 c938ada2 Aurelien Jarno
    prom_set(prom_buf, prom_index++, NULL);
726 c938ada2 Aurelien Jarno
727 c938ada2 Aurelien Jarno
    rom_add_blob_fixed("prom", prom_buf, prom_size,
728 409dbce5 Aurelien Jarno
                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
729 5856de80 ths
730 74287114 ths
    return kernel_entry;
731 5856de80 ths
}
732 5856de80 ths
733 c4cb2578 Edgar E. Iglesias
static void malta_mips_config(CPUState *env)
734 c4cb2578 Edgar E. Iglesias
{
735 c4cb2578 Edgar E. Iglesias
    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
736 c4cb2578 Edgar E. Iglesias
                         ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC);
737 c4cb2578 Edgar E. Iglesias
}
738 c4cb2578 Edgar E. Iglesias
739 5856de80 ths
static void main_cpu_reset(void *opaque)
740 5856de80 ths
{
741 5856de80 ths
    CPUState *env = opaque;
742 5856de80 ths
    cpu_reset(env);
743 5856de80 ths
744 5c43485f Aurelien Jarno
    /* The bootloader does not need to be rewritten as it is located in a
745 5856de80 ths
       read only location. The kernel location and the arguments table
746 5856de80 ths
       location does not change. */
747 7df526e3 ths
    if (loaderparams.kernel_filename) {
748 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
749 fb82fea0 ths
    }
750 c4cb2578 Edgar E. Iglesias
751 c4cb2578 Edgar E. Iglesias
    malta_mips_config(env);
752 5856de80 ths
}
753 5856de80 ths
754 4556bd8b Blue Swirl
static void cpu_request_exit(void *opaque, int irq, int level)
755 4556bd8b Blue Swirl
{
756 4556bd8b Blue Swirl
    CPUState *env = cpu_single_env;
757 4556bd8b Blue Swirl
758 4556bd8b Blue Swirl
    if (env && level) {
759 4556bd8b Blue Swirl
        cpu_exit(env);
760 4556bd8b Blue Swirl
    }
761 4556bd8b Blue Swirl
}
762 4556bd8b Blue Swirl
763 70705261 ths
static
764 c227f099 Anthony Liguori
void mips_malta_init (ram_addr_t ram_size,
765 3023f332 aliguori
                      const char *boot_device,
766 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
767 94fc95cd j_mayer
                      const char *initrd_filename, const char *cpu_model)
768 5856de80 ths
{
769 5cea8590 Paul Brook
    char *filename;
770 cfe5f011 Avi Kivity
    pflash_t *fl;
771 cfe5f011 Avi Kivity
    MemoryRegion *system_memory = get_system_memory();
772 ea85df72 Avi Kivity
    MemoryRegion *ram = g_new(MemoryRegion, 1);
773 cfe5f011 Avi Kivity
    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
774 c8b153d7 ths
    target_long bios_size;
775 74287114 ths
    int64_t kernel_entry;
776 5856de80 ths
    PCIBus *pci_bus;
777 5856de80 ths
    CPUState *env;
778 5632ae46 Avi Kivity
    qemu_irq *i8259 = NULL, *isa_irq;
779 4556bd8b Blue Swirl
    qemu_irq *cpu_exit_irq;
780 7b717336 ths
    int piix4_devfn;
781 7b717336 ths
    i2c_bus *smbus;
782 7b717336 ths
    int i;
783 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
784 f455e98c Gerd Hoffmann
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
785 fd8014e1 Gerd Hoffmann
    DriveInfo *fd[MAX_FD];
786 c8b153d7 ths
    int fl_idx = 0;
787 c8b153d7 ths
    int fl_sectors = 0;
788 01e0451a Anthony Liguori
    int be;
789 5856de80 ths
790 ffabf037 Aurelien Jarno
    /* Make sure the first 3 serial ports are associated with a device. */
791 ffabf037 Aurelien Jarno
    for(i = 0; i < 3; i++) {
792 ffabf037 Aurelien Jarno
        if (!serial_hds[i]) {
793 ffabf037 Aurelien Jarno
            char label[32];
794 ffabf037 Aurelien Jarno
            snprintf(label, sizeof(label), "serial%d", i);
795 27143a44 Anthony Liguori
            serial_hds[i] = qemu_chr_new(label, "null", NULL);
796 ffabf037 Aurelien Jarno
        }
797 ffabf037 Aurelien Jarno
    }
798 ffabf037 Aurelien Jarno
799 33d68b5f ths
    /* init CPUs */
800 33d68b5f ths
    if (cpu_model == NULL) {
801 60aa19ab ths
#ifdef TARGET_MIPS64
802 c9c1a064 ths
        cpu_model = "20Kc";
803 33d68b5f ths
#else
804 1c32f43e ths
        cpu_model = "24Kf";
805 33d68b5f ths
#endif
806 33d68b5f ths
    }
807 c4cb2578 Edgar E. Iglesias
808 c4cb2578 Edgar E. Iglesias
    for (i = 0; i < smp_cpus; i++) {
809 c4cb2578 Edgar E. Iglesias
        env = cpu_init(cpu_model);
810 c4cb2578 Edgar E. Iglesias
        if (!env) {
811 c4cb2578 Edgar E. Iglesias
            fprintf(stderr, "Unable to find CPU definition\n");
812 c4cb2578 Edgar E. Iglesias
            exit(1);
813 c4cb2578 Edgar E. Iglesias
        }
814 c4cb2578 Edgar E. Iglesias
        /* Init internal devices */
815 c4cb2578 Edgar E. Iglesias
        cpu_mips_irq_init_cpu(env);
816 c4cb2578 Edgar E. Iglesias
        cpu_mips_clock_init(env);
817 c4cb2578 Edgar E. Iglesias
        qemu_register_reset(main_cpu_reset, env);
818 aaed909a bellard
    }
819 c4cb2578 Edgar E. Iglesias
    env = first_cpu;
820 5856de80 ths
821 5856de80 ths
    /* allocate RAM */
822 0ccff151 aurel32
    if (ram_size > (256 << 20)) {
823 0ccff151 aurel32
        fprintf(stderr,
824 0ccff151 aurel32
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
825 0ccff151 aurel32
                ((unsigned int)ram_size / (1 << 20)));
826 0ccff151 aurel32
        exit(1);
827 0ccff151 aurel32
    }
828 ea85df72 Avi Kivity
    memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
829 ea85df72 Avi Kivity
    memory_region_add_subregion(system_memory, 0, ram);
830 5856de80 ths
831 01e0451a Anthony Liguori
#ifdef TARGET_WORDS_BIGENDIAN
832 01e0451a Anthony Liguori
    be = 1;
833 01e0451a Anthony Liguori
#else
834 01e0451a Anthony Liguori
    be = 0;
835 01e0451a Anthony Liguori
#endif
836 070ce5ed ths
    /* FPGA */
837 ea85df72 Avi Kivity
    malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
838 070ce5ed ths
839 c8b153d7 ths
    /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
840 c8b153d7 ths
    if (kernel_filename) {
841 c8b153d7 ths
        /* Write a small bootloader to the flash location. */
842 cfe5f011 Avi Kivity
        bios = g_new(MemoryRegion, 1);
843 cfe5f011 Avi Kivity
        memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
844 cfe5f011 Avi Kivity
        memory_region_set_readonly(bios, true);
845 cfe5f011 Avi Kivity
        memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
846 cfe5f011 Avi Kivity
        /* Map the bios at two physical locations, as on the real board. */
847 cfe5f011 Avi Kivity
        memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
848 cfe5f011 Avi Kivity
        memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
849 c8b153d7 ths
        loaderparams.ram_size = ram_size;
850 c8b153d7 ths
        loaderparams.kernel_filename = kernel_filename;
851 c8b153d7 ths
        loaderparams.kernel_cmdline = kernel_cmdline;
852 c8b153d7 ths
        loaderparams.initrd_filename = initrd_filename;
853 e16ad5b0 Aurelien Jarno
        kernel_entry = load_kernel();
854 cfe5f011 Avi Kivity
        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
855 c8b153d7 ths
    } else {
856 751c6a17 Gerd Hoffmann
        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
857 751c6a17 Gerd Hoffmann
        if (dinfo) {
858 c8b153d7 ths
            /* Load firmware from flash. */
859 c8b153d7 ths
            bios_size = 0x400000;
860 c8b153d7 ths
            fl_sectors = bios_size >> 16;
861 c8b153d7 ths
#ifdef DEBUG_BOARD_INIT
862 c8b153d7 ths
            printf("Register parallel flash %d size " TARGET_FMT_lx " at "
863 cfe5f011 Avi Kivity
                   "addr %08llx '%s' %x\n",
864 cfe5f011 Avi Kivity
                   fl_idx, bios_size, 0x1e000000LL,
865 751c6a17 Gerd Hoffmann
                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
866 c8b153d7 ths
#endif
867 cfe5f011 Avi Kivity
            fl = pflash_cfi01_register(0x1e000000LL,
868 cfe5f011 Avi Kivity
                                       NULL, "mips_malta.bios", BIOS_SIZE,
869 cfe5f011 Avi Kivity
                                       dinfo->bdrv, 65536, fl_sectors,
870 cfe5f011 Avi Kivity
                                       4, 0x0000, 0x0000, 0x0000, 0x0000, be);
871 cfe5f011 Avi Kivity
            bios = pflash_cfi01_get_memory(fl);
872 cfe5f011 Avi Kivity
            /* Map the bios at two physical locations, as on the real board. */
873 cfe5f011 Avi Kivity
            memory_region_init_alias(bios_alias, "bios.1fc",
874 cfe5f011 Avi Kivity
                                     bios, 0, BIOS_SIZE);
875 cfe5f011 Avi Kivity
            memory_region_add_subregion(system_memory, 0x1fc00000LL,
876 cfe5f011 Avi Kivity
                                        bios_alias);
877 cfe5f011 Avi Kivity
           fl_idx++;
878 c8b153d7 ths
        } else {
879 cfe5f011 Avi Kivity
            bios = g_new(MemoryRegion, 1);
880 cfe5f011 Avi Kivity
            memory_region_init_ram(bios, NULL, "mips_malta.bios", BIOS_SIZE);
881 cfe5f011 Avi Kivity
            memory_region_set_readonly(bios, true);
882 cfe5f011 Avi Kivity
            memory_region_init_alias(bios_alias, "bios.1fc",
883 cfe5f011 Avi Kivity
                                     bios, 0, BIOS_SIZE);
884 cfe5f011 Avi Kivity
            /* Map the bios at two physical locations, as on the real board. */
885 cfe5f011 Avi Kivity
            memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
886 cfe5f011 Avi Kivity
            memory_region_add_subregion(system_memory, 0x1fc00000LL,
887 cfe5f011 Avi Kivity
                                        bios_alias);
888 c8b153d7 ths
            /* Load a BIOS image. */
889 c8b153d7 ths
            if (bios_name == NULL)
890 c8b153d7 ths
                bios_name = BIOS_FILENAME;
891 5cea8590 Paul Brook
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
892 5cea8590 Paul Brook
            if (filename) {
893 5cea8590 Paul Brook
                bios_size = load_image_targphys(filename, 0x1fc00000LL,
894 5cea8590 Paul Brook
                                                BIOS_SIZE);
895 7267c094 Anthony Liguori
                g_free(filename);
896 5cea8590 Paul Brook
            } else {
897 5cea8590 Paul Brook
                bios_size = -1;
898 5cea8590 Paul Brook
            }
899 c8b153d7 ths
            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
900 c8b153d7 ths
                fprintf(stderr,
901 c8b153d7 ths
                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
902 5cea8590 Paul Brook
                        bios_name);
903 c8b153d7 ths
                exit(1);
904 c8b153d7 ths
            }
905 070ce5ed ths
        }
906 3187ef03 ths
        /* In little endian mode the 32bit words in the bios are swapped,
907 3187ef03 ths
           a neat trick which allows bi-endian firmware. */
908 3187ef03 ths
#ifndef TARGET_WORDS_BIGENDIAN
909 3187ef03 ths
        {
910 cfe5f011 Avi Kivity
            uint32_t *addr = memory_region_get_ram_ptr(bios);
911 d7585251 pbrook
            uint32_t *end = addr + bios_size;
912 d7585251 pbrook
            while (addr < end) {
913 d7585251 pbrook
                bswap32s(addr);
914 3187ef03 ths
            }
915 3187ef03 ths
        }
916 3187ef03 ths
#endif
917 070ce5ed ths
    }
918 070ce5ed ths
919 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
920 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
921 5856de80 ths
       map to the board ID. */
922 cfe5f011 Avi Kivity
    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
923 5856de80 ths
924 5856de80 ths
    /* Init internal devices */
925 d537cf6c pbrook
    cpu_mips_irq_init_cpu(env);
926 5856de80 ths
    cpu_mips_clock_init(env);
927 5856de80 ths
928 5632ae46 Avi Kivity
    /*
929 5632ae46 Avi Kivity
     * We have a circular dependency problem: pci_bus depends on isa_irq,
930 5632ae46 Avi Kivity
     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
931 5632ae46 Avi Kivity
     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
932 5632ae46 Avi Kivity
     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
933 5632ae46 Avi Kivity
     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
934 5632ae46 Avi Kivity
     */
935 5632ae46 Avi Kivity
    isa_irq = qemu_irq_proxy(&i8259, 16);
936 5856de80 ths
937 5856de80 ths
    /* Northbridge */
938 5632ae46 Avi Kivity
    pci_bus = gt64120_register(isa_irq);
939 5856de80 ths
940 5856de80 ths
    /* Southbridge */
941 75717903 Isaku Yamahata
    ide_drive_get(hd, MAX_IDE_BUS);
942 e4bcb14c ths
943 7b717336 ths
    piix4_devfn = piix4_init(pci_bus, 80);
944 5632ae46 Avi Kivity
945 5632ae46 Avi Kivity
    /* Interrupt controller */
946 5632ae46 Avi Kivity
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
947 5632ae46 Avi Kivity
    i8259 = i8259_init(env->irq[2]);
948 5632ae46 Avi Kivity
949 ae027ad3 Stefan Weil
    isa_bus_irqs(i8259);
950 ae027ad3 Stefan Weil
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
951 afcc3cdf ths
    usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
952 ee951a37 Jan Kiszka
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(9),
953 53b67b30 Blue Swirl
                          NULL, NULL, 0);
954 a88df0b9 Isaku Yamahata
    /* TODO: Populate SPD eeprom data.  */
955 a88df0b9 Isaku Yamahata
    smbus_eeprom_init(smbus, 8, NULL, 0);
956 64d7e9a4 Blue Swirl
    pit = pit_init(0x40, 0);
957 4556bd8b Blue Swirl
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
958 4556bd8b Blue Swirl
    DMA_init(0, cpu_exit_irq);
959 5856de80 ths
960 5856de80 ths
    /* Super I/O */
961 49a2942d Blue Swirl
    isa_create_simple("i8042");
962 49a2942d Blue Swirl
963 49a2942d Blue Swirl
    rtc_init(2000, NULL);
964 ac0be998 Gerd Hoffmann
    serial_isa_init(0, serial_hds[0]);
965 ac0be998 Gerd Hoffmann
    serial_isa_init(1, serial_hds[1]);
966 7bcc17dc ths
    if (parallel_hds[0])
967 021f0674 Gerd Hoffmann
        parallel_init(0, parallel_hds[0]);
968 e4bcb14c ths
    for(i = 0; i < MAX_FD; i++) {
969 fd8014e1 Gerd Hoffmann
        fd[i] = drive_get(IF_FLOPPY, 0, i);
970 e4bcb14c ths
    }
971 49a2942d Blue Swirl
    fdctrl_init_isa(fd);
972 5856de80 ths
973 5856de80 ths
    /* Sound card */
974 0dfa5ef9 Isaku Yamahata
    audio_init(NULL, pci_bus);
975 5856de80 ths
976 5856de80 ths
    /* Network card */
977 5607c388 Markus Armbruster
    network_init();
978 11f29511 ths
979 11f29511 ths
    /* Optional PCI video card */
980 1f605a76 aurel32
    if (cirrus_vga_enabled) {
981 fbe1b595 Paul Brook
        pci_cirrus_vga_init(pci_bus);
982 1f605a76 aurel32
    } else if (vmsvga_enabled) {
983 7ba7e49e Blue Swirl
        if (!pci_vmsvga_init(pci_bus)) {
984 7ba7e49e Blue Swirl
            fprintf(stderr, "Warning: vmware_vga not available,"
985 7ba7e49e Blue Swirl
                    " using standard VGA instead\n");
986 7ba7e49e Blue Swirl
            pci_vga_init(pci_bus);
987 7ba7e49e Blue Swirl
        }
988 1f605a76 aurel32
    } else if (std_vga_enabled) {
989 78895427 Gerd Hoffmann
        pci_vga_init(pci_bus);
990 1f605a76 aurel32
    }
991 5856de80 ths
}
992 5856de80 ths
993 f80f9ec9 Anthony Liguori
static QEMUMachine mips_malta_machine = {
994 eec2743e ths
    .name = "malta",
995 eec2743e ths
    .desc = "MIPS Malta Core LV",
996 eec2743e ths
    .init = mips_malta_init,
997 c4cb2578 Edgar E. Iglesias
    .max_cpus = 16,
998 0c257437 Anthony Liguori
    .is_default = 1,
999 5856de80 ths
};
1000 f80f9ec9 Anthony Liguori
1001 f80f9ec9 Anthony Liguori
static void mips_malta_machine_init(void)
1002 f80f9ec9 Anthony Liguori
{
1003 f80f9ec9 Anthony Liguori
    qemu_register_machine(&mips_malta_machine);
1004 f80f9ec9 Anthony Liguori
}
1005 f80f9ec9 Anthony Liguori
1006 f80f9ec9 Anthony Liguori
machine_init(mips_malta_machine_init);