Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ a4bc3afc

History | View | Annotate | Download (21.4 kB)

1 5856de80 ths
/*
2 5856de80 ths
 * QEMU Malta board support
3 5856de80 ths
 *
4 5856de80 ths
 * Copyright (c) 2006 Aurelien Jarno
5 5856de80 ths
 *
6 5856de80 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 5856de80 ths
 * of this software and associated documentation files (the "Software"), to deal
8 5856de80 ths
 * in the Software without restriction, including without limitation the rights
9 5856de80 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 5856de80 ths
 * copies of the Software, and to permit persons to whom the Software is
11 5856de80 ths
 * furnished to do so, subject to the following conditions:
12 5856de80 ths
 *
13 5856de80 ths
 * The above copyright notice and this permission notice shall be included in
14 5856de80 ths
 * all copies or substantial portions of the Software.
15 5856de80 ths
 *
16 5856de80 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 5856de80 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 5856de80 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 5856de80 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 5856de80 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 5856de80 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 5856de80 ths
 * THE SOFTWARE.
23 5856de80 ths
 */
24 5856de80 ths
25 5856de80 ths
#include "vl.h"
26 5856de80 ths
27 44cbbf18 ths
#ifdef TARGET_WORDS_BIGENDIAN
28 44cbbf18 ths
#define BIOS_FILENAME "mips_bios.bin"
29 44cbbf18 ths
#else
30 44cbbf18 ths
#define BIOS_FILENAME "mipsel_bios.bin"
31 44cbbf18 ths
#endif
32 44cbbf18 ths
33 5856de80 ths
#ifdef MIPS_HAS_MIPS64
34 44cbbf18 ths
#define INITRD_LOAD_ADDR         (int64_t)0x80800000
35 5856de80 ths
#else
36 44cbbf18 ths
#define INITRD_LOAD_ADDR         (int32_t)0x80800000
37 5856de80 ths
#endif
38 5856de80 ths
39 3ddd0065 ths
#define ENVP_ADDR                (int32_t)0x80002000
40 44cbbf18 ths
#define VIRT_TO_PHYS_ADDEND         (-((int64_t)(int32_t)0x80000000))
41 5856de80 ths
42 5856de80 ths
#define ENVP_NB_ENTRIES                 16
43 5856de80 ths
#define ENVP_ENTRY_SIZE                 256
44 5856de80 ths
45 5856de80 ths
46 5856de80 ths
extern FILE *logfile;
47 5856de80 ths
48 5856de80 ths
typedef struct {
49 5856de80 ths
    uint32_t leds;
50 5856de80 ths
    uint32_t brk;
51 5856de80 ths
    uint32_t gpout;
52 130751ee ths
    uint32_t i2cin;
53 5856de80 ths
    uint32_t i2coe;
54 5856de80 ths
    uint32_t i2cout;
55 5856de80 ths
    uint32_t i2csel;
56 5856de80 ths
    CharDriverState *display;
57 5856de80 ths
    char display_text[9];
58 a4bc3afc ths
    SerialState *uart;
59 5856de80 ths
} MaltaFPGAState;
60 5856de80 ths
61 5856de80 ths
static PITState *pit;
62 5856de80 ths
63 4de9b249 ths
/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
64 5856de80 ths
static void pic_irq_request(void *opaque, int level)
65 5856de80 ths
{
66 4de9b249 ths
    cpu_mips_irq_request(opaque, 2, level);
67 5856de80 ths
}
68 5856de80 ths
69 5856de80 ths
/* Malta FPGA */
70 5856de80 ths
static void malta_fpga_update_display(void *opaque)
71 5856de80 ths
{
72 5856de80 ths
    char leds_text[9];
73 5856de80 ths
    int i;
74 5856de80 ths
    MaltaFPGAState *s = opaque;
75 5856de80 ths
76 5856de80 ths
    for (i = 7 ; i >= 0 ; i--) {
77 5856de80 ths
        if (s->leds & (1 << i))
78 5856de80 ths
            leds_text[i] = '#';
79 5856de80 ths
        else
80 5856de80 ths
            leds_text[i] = ' ';
81 5856de80 ths
    }
82 5856de80 ths
    leds_text[8] = '\0';
83 5856de80 ths
84 472c5273 ths
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
85 472c5273 ths
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
86 5856de80 ths
}
87 5856de80 ths
88 130751ee ths
/*
89 130751ee ths
 * EEPROM 24C01 / 24C02 emulation.
90 130751ee ths
 *
91 130751ee ths
 * Emulation for serial EEPROMs:
92 130751ee ths
 * 24C01 - 1024 bit (128 x 8)
93 130751ee ths
 * 24C02 - 2048 bit (256 x 8)
94 130751ee ths
 *
95 130751ee ths
 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
96 130751ee ths
 */
97 130751ee ths
98 130751ee ths
//~ #define DEBUG
99 130751ee ths
100 130751ee ths
#if defined(DEBUG)
101 130751ee ths
#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
102 130751ee ths
#else
103 130751ee ths
#  define logout(fmt, args...) ((void)0)
104 130751ee ths
#endif
105 130751ee ths
106 130751ee ths
struct _eeprom24c0x_t {
107 130751ee ths
  uint8_t tick;
108 130751ee ths
  uint8_t address;
109 130751ee ths
  uint8_t command;
110 130751ee ths
  uint8_t ack;
111 130751ee ths
  uint8_t scl;
112 130751ee ths
  uint8_t sda;
113 130751ee ths
  uint8_t data;
114 130751ee ths
  //~ uint16_t size;
115 130751ee ths
  uint8_t contents[256];
116 130751ee ths
};
117 130751ee ths
118 130751ee ths
typedef struct _eeprom24c0x_t eeprom24c0x_t;
119 130751ee ths
120 130751ee ths
static eeprom24c0x_t eeprom = {
121 130751ee ths
    contents: {
122 130751ee ths
        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
123 130751ee ths
        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
124 130751ee ths
        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
125 130751ee ths
        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
126 130751ee ths
        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
127 130751ee ths
        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 130751ee ths
        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129 130751ee ths
        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
130 130751ee ths
        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 130751ee ths
        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132 130751ee ths
        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133 130751ee ths
        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134 130751ee ths
        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135 130751ee ths
        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
136 130751ee ths
        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
137 130751ee ths
        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
138 130751ee ths
    },
139 130751ee ths
};
140 130751ee ths
141 130751ee ths
static uint8_t eeprom24c0x_read()
142 130751ee ths
{
143 130751ee ths
    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
144 130751ee ths
        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
145 130751ee ths
    return eeprom.sda;
146 130751ee ths
}
147 130751ee ths
148 130751ee ths
static void eeprom24c0x_write(int scl, int sda)
149 130751ee ths
{
150 130751ee ths
    if (eeprom.scl && scl && (eeprom.sda != sda)) {
151 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
152 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
153 130751ee ths
        if (!sda) {
154 130751ee ths
            eeprom.tick = 1;
155 130751ee ths
            eeprom.command = 0;
156 130751ee ths
        }
157 130751ee ths
    } else if (eeprom.tick == 0 && !eeprom.ack) {
158 130751ee ths
        /* Waiting for start. */
159 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
160 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
161 130751ee ths
    } else if (!eeprom.scl && scl) {
162 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
163 130751ee ths
                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
164 130751ee ths
        if (eeprom.ack) {
165 130751ee ths
            logout("\ti2c ack bit = 0\n");
166 130751ee ths
            sda = 0;
167 130751ee ths
            eeprom.ack = 0;
168 130751ee ths
        } else if (eeprom.sda == sda) {
169 130751ee ths
            uint8_t bit = (sda != 0);
170 130751ee ths
            logout("\ti2c bit = %d\n", bit);
171 130751ee ths
            if (eeprom.tick < 9) {
172 130751ee ths
                eeprom.command <<= 1;
173 130751ee ths
                eeprom.command += bit;
174 130751ee ths
                eeprom.tick++;
175 130751ee ths
                if (eeprom.tick == 9) {
176 130751ee ths
                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
177 130751ee ths
                    eeprom.ack = 1;
178 130751ee ths
                }
179 130751ee ths
            } else if (eeprom.tick < 17) {
180 130751ee ths
                if (eeprom.command & 1) {
181 130751ee ths
                    sda = ((eeprom.data & 0x80) != 0);
182 130751ee ths
                }
183 130751ee ths
                eeprom.address <<= 1;
184 130751ee ths
                eeprom.address += bit;
185 130751ee ths
                eeprom.tick++;
186 130751ee ths
                eeprom.data <<= 1;
187 130751ee ths
                if (eeprom.tick == 17) {
188 130751ee ths
                    eeprom.data = eeprom.contents[eeprom.address];
189 130751ee ths
                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
190 130751ee ths
                    eeprom.ack = 1;
191 130751ee ths
                    eeprom.tick = 0;
192 130751ee ths
                }
193 130751ee ths
            } else if (eeprom.tick >= 17) {
194 130751ee ths
                sda = 0;
195 130751ee ths
            }
196 130751ee ths
        } else {
197 130751ee ths
            logout("\tsda changed with raising scl\n");
198 130751ee ths
        }
199 130751ee ths
    } else {
200 130751ee ths
        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
201 130751ee ths
    }
202 130751ee ths
    eeprom.scl = scl;
203 130751ee ths
    eeprom.sda = sda;
204 130751ee ths
}
205 130751ee ths
206 5856de80 ths
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
207 5856de80 ths
{
208 5856de80 ths
    MaltaFPGAState *s = opaque;
209 5856de80 ths
    uint32_t val = 0;
210 5856de80 ths
    uint32_t saddr;
211 5856de80 ths
212 5856de80 ths
    saddr = (addr & 0xfffff);
213 5856de80 ths
214 5856de80 ths
    switch (saddr) {
215 5856de80 ths
216 5856de80 ths
    /* SWITCH Register */
217 5856de80 ths
    case 0x00200:
218 5856de80 ths
        val = 0x00000000;                /* All switches closed */
219 5856de80 ths
        break;
220 5856de80 ths
221 5856de80 ths
    /* STATUS Register */
222 5856de80 ths
    case 0x00208:
223 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
224 5856de80 ths
        val = 0x00000012;
225 5856de80 ths
#else
226 5856de80 ths
        val = 0x00000010;
227 5856de80 ths
#endif
228 5856de80 ths
        break;
229 5856de80 ths
230 5856de80 ths
    /* JMPRS Register */
231 5856de80 ths
    case 0x00210:
232 5856de80 ths
        val = 0x00;
233 5856de80 ths
        break;
234 5856de80 ths
235 5856de80 ths
    /* LEDBAR Register */
236 5856de80 ths
    case 0x00408:
237 5856de80 ths
        val = s->leds;
238 5856de80 ths
        break;
239 5856de80 ths
240 5856de80 ths
    /* BRKRES Register */
241 5856de80 ths
    case 0x00508:
242 5856de80 ths
        val = s->brk;
243 5856de80 ths
        break;
244 5856de80 ths
245 a4bc3afc ths
    /* UART Registers */
246 a4bc3afc ths
    case 0x00900:
247 a4bc3afc ths
    case 0x00904:
248 a4bc3afc ths
    case 0x00908:
249 a4bc3afc ths
    case 0x0090c:
250 a4bc3afc ths
    case 0x00910:
251 a4bc3afc ths
    case 0x00914:
252 a4bc3afc ths
    case 0x00918:
253 a4bc3afc ths
    case 0x0091c:
254 a4bc3afc ths
        val = serial_mm_readl(s->uart, addr);
255 a4bc3afc ths
        break;
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 a4bc3afc ths
    /* UART Registers */
358 a4bc3afc ths
    case 0x00900:
359 a4bc3afc ths
    case 0x00904:
360 a4bc3afc ths
    case 0x00908:
361 a4bc3afc ths
    case 0x0090c:
362 a4bc3afc ths
    case 0x00910:
363 a4bc3afc ths
    case 0x00914:
364 a4bc3afc ths
    case 0x00918:
365 a4bc3afc ths
    case 0x0091c:
366 a4bc3afc ths
        serial_mm_writel(s->uart, addr, val);
367 a4bc3afc ths
        break;
368 a4bc3afc ths
369 5856de80 ths
    /* GPOUT Register */
370 5856de80 ths
    case 0x00a00:
371 5856de80 ths
        s->gpout = val & 0xff;
372 5856de80 ths
        break;
373 5856de80 ths
374 5856de80 ths
    /* I2COE Register */
375 5856de80 ths
    case 0x00b08:
376 5856de80 ths
        s->i2coe = val & 0x03;
377 5856de80 ths
        break;
378 5856de80 ths
379 5856de80 ths
    /* I2COUT Register */
380 5856de80 ths
    case 0x00b10:
381 130751ee ths
        eeprom24c0x_write(val & 0x02, val & 0x01);
382 130751ee ths
        s->i2cout = val;
383 5856de80 ths
        break;
384 5856de80 ths
385 5856de80 ths
    /* I2CSEL Register */
386 5856de80 ths
    case 0x00b18:
387 130751ee ths
        s->i2csel = val & 0x01;
388 5856de80 ths
        break;
389 5856de80 ths
390 5856de80 ths
    default:
391 5856de80 ths
#if 0
392 3594c774 ths
        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
393 44cbbf18 ths
                addr);
394 5856de80 ths
#endif
395 5856de80 ths
        break;
396 5856de80 ths
    }
397 5856de80 ths
}
398 5856de80 ths
399 5856de80 ths
static CPUReadMemoryFunc *malta_fpga_read[] = {
400 5856de80 ths
   malta_fpga_readl,
401 5856de80 ths
   malta_fpga_readl,
402 5856de80 ths
   malta_fpga_readl
403 5856de80 ths
};
404 5856de80 ths
405 5856de80 ths
static CPUWriteMemoryFunc *malta_fpga_write[] = {
406 5856de80 ths
   malta_fpga_writel,
407 5856de80 ths
   malta_fpga_writel,
408 5856de80 ths
   malta_fpga_writel
409 5856de80 ths
};
410 5856de80 ths
411 5856de80 ths
void malta_fpga_reset(void *opaque)
412 5856de80 ths
{
413 5856de80 ths
    MaltaFPGAState *s = opaque;
414 5856de80 ths
415 5856de80 ths
    s->leds   = 0x00;
416 5856de80 ths
    s->brk    = 0x0a;
417 5856de80 ths
    s->gpout  = 0x00;
418 130751ee ths
    s->i2cin  = 0x3;
419 5856de80 ths
    s->i2coe  = 0x0;
420 5856de80 ths
    s->i2cout = 0x3;
421 5856de80 ths
    s->i2csel = 0x1;
422 5856de80 ths
423 5856de80 ths
    s->display_text[8] = '\0';
424 5856de80 ths
    snprintf(s->display_text, 9, "        ");
425 5856de80 ths
    malta_fpga_update_display(s);
426 5856de80 ths
}
427 5856de80 ths
428 a4bc3afc ths
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
429 5856de80 ths
{
430 5856de80 ths
    MaltaFPGAState *s;
431 a4bc3afc ths
    CharDriverState *uart_chr;
432 5856de80 ths
    int malta;
433 5856de80 ths
434 5856de80 ths
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
435 5856de80 ths
436 5856de80 ths
    malta = cpu_register_io_memory(0, malta_fpga_read,
437 5856de80 ths
                                   malta_fpga_write, s);
438 a4bc3afc ths
439 5856de80 ths
    cpu_register_physical_memory(base, 0x100000, malta);
440 5856de80 ths
441 5856de80 ths
    s->display = qemu_chr_open("vc");
442 af23902b ths
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
443 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
444 5856de80 ths
    qemu_chr_printf(s->display, "+        +\r\n");
445 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
446 5856de80 ths
    qemu_chr_printf(s->display, "\n");
447 5856de80 ths
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
448 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
449 5856de80 ths
    qemu_chr_printf(s->display, "+        +\r\n");
450 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
451 5856de80 ths
452 a4bc3afc ths
    uart_chr = qemu_chr_open("vc");
453 a4bc3afc ths
    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
454 a4bc3afc ths
    s->uart = serial_mm_init(&cpu_mips_irq_request, env, base, 3, 2,
455 a4bc3afc ths
                             uart_chr, 0);
456 a4bc3afc ths
457 5856de80 ths
    malta_fpga_reset(s);
458 5856de80 ths
    qemu_register_reset(malta_fpga_reset, s);
459 5856de80 ths
460 5856de80 ths
    return s;
461 5856de80 ths
}
462 5856de80 ths
463 5856de80 ths
/* Audio support */
464 5856de80 ths
#ifdef HAS_AUDIO
465 5856de80 ths
static void audio_init (PCIBus *pci_bus)
466 5856de80 ths
{
467 5856de80 ths
    struct soundhw *c;
468 5856de80 ths
    int audio_enabled = 0;
469 5856de80 ths
470 5856de80 ths
    for (c = soundhw; !audio_enabled && c->name; ++c) {
471 5856de80 ths
        audio_enabled = c->enabled;
472 5856de80 ths
    }
473 5856de80 ths
474 5856de80 ths
    if (audio_enabled) {
475 5856de80 ths
        AudioState *s;
476 5856de80 ths
477 5856de80 ths
        s = AUD_init ();
478 5856de80 ths
        if (s) {
479 5856de80 ths
            for (c = soundhw; c->name; ++c) {
480 5856de80 ths
                if (c->enabled) {
481 5856de80 ths
                    if (c->isa) {
482 5856de80 ths
                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
483 5856de80 ths
                        exit(1);
484 5856de80 ths
                    }
485 5856de80 ths
                    else {
486 5856de80 ths
                        if (pci_bus) {
487 5856de80 ths
                            c->init.init_pci (pci_bus, s);
488 5856de80 ths
                        }
489 5856de80 ths
                    }
490 5856de80 ths
                }
491 5856de80 ths
            }
492 5856de80 ths
        }
493 5856de80 ths
    }
494 5856de80 ths
}
495 5856de80 ths
#endif
496 5856de80 ths
497 5856de80 ths
/* Network support */
498 5856de80 ths
static void network_init (PCIBus *pci_bus)
499 5856de80 ths
{
500 5856de80 ths
    int i;
501 5856de80 ths
    NICInfo *nd;
502 5856de80 ths
503 5856de80 ths
    for(i = 0; i < nb_nics; i++) {
504 5856de80 ths
        nd = &nd_table[i];
505 5856de80 ths
        if (!nd->model) {
506 5856de80 ths
            nd->model = "pcnet";
507 5856de80 ths
        }
508 5856de80 ths
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
509 5856de80 ths
            /* The malta board has a PCNet card using PCI SLOT 11 */
510 5856de80 ths
            pci_nic_init(pci_bus, nd, 88);
511 5856de80 ths
        } else {
512 5856de80 ths
            pci_nic_init(pci_bus, nd, -1);
513 5856de80 ths
        }
514 5856de80 ths
    }
515 5856de80 ths
}
516 5856de80 ths
517 5856de80 ths
/* ROM and pseudo bootloader
518 5856de80 ths

519 5856de80 ths
   The following code implements a very very simple bootloader. It first
520 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
521 5856de80 ths
   then jump at the kernel address.
522 5856de80 ths

523 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
524 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
525 5856de80 ths
   of NULL terminated strings. The environment variables table should be
526 5856de80 ths
   terminated by a NULL address.
527 5856de80 ths

528 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
529 5856de80 ths
   to two (the name of the kernel and the command line), and the two
530 5856de80 ths
   tables are actually the same one.
531 5856de80 ths

532 5856de80 ths
   The registers a0 to a3 should contain the following values:
533 5856de80 ths
     a0 - number of kernel arguments
534 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
535 5856de80 ths
     a2 - 32-bit address of the environment variables table
536 5856de80 ths
     a3 - RAM size in bytes
537 5856de80 ths
*/
538 5856de80 ths
539 5856de80 ths
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
540 5856de80 ths
{
541 5856de80 ths
    uint32_t *p;
542 5856de80 ths
543 5856de80 ths
    /* Small bootloader */
544 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset);
545 3ddd0065 ths
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
546 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
547 5856de80 ths
548 5856de80 ths
    /* Second part of the bootloader */
549 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
550 3ddd0065 ths
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
551 3ddd0065 ths
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
552 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
553 3ddd0065 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
554 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
555 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
556 3ddd0065 ths
    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
557 3ddd0065 ths
    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
558 3ddd0065 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
559 3ddd0065 ths
    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
560 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
561 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
562 5856de80 ths
}
563 5856de80 ths
564 5856de80 ths
static void prom_set(int index, const char *string, ...)
565 5856de80 ths
{
566 5856de80 ths
    va_list ap;
567 3ddd0065 ths
    int32_t *p;
568 3ddd0065 ths
    int32_t table_addr;
569 5856de80 ths
    char *s;
570 5856de80 ths
571 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
572 5856de80 ths
        return;
573 5856de80 ths
574 3ddd0065 ths
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
575 5856de80 ths
    p += index;
576 5856de80 ths
577 5856de80 ths
    if (string == NULL) {
578 5856de80 ths
        stl_raw(p, 0);
579 5856de80 ths
        return;
580 5856de80 ths
    }
581 5856de80 ths
582 3ddd0065 ths
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
583 5856de80 ths
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
584 5856de80 ths
585 5856de80 ths
    stl_raw(p, table_addr);
586 5856de80 ths
587 5856de80 ths
    va_start(ap, string);
588 5856de80 ths
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
589 5856de80 ths
    va_end(ap);
590 5856de80 ths
}
591 5856de80 ths
592 5856de80 ths
/* Kernel */
593 5856de80 ths
static int64_t load_kernel (CPUState *env)
594 5856de80 ths
{
595 5856de80 ths
    int64_t kernel_addr = 0;
596 5856de80 ths
    int index = 0;
597 5856de80 ths
    long initrd_size;
598 5856de80 ths
599 5856de80 ths
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
600 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
601 5856de80 ths
                env->kernel_filename);
602 5856de80 ths
      exit(1);
603 5856de80 ths
    }
604 5856de80 ths
605 5856de80 ths
    /* load initrd */
606 5856de80 ths
    initrd_size = 0;
607 5856de80 ths
    if (env->initrd_filename) {
608 5856de80 ths
        initrd_size = load_image(env->initrd_filename,
609 5856de80 ths
                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
610 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
611 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
612 5856de80 ths
                    env->initrd_filename);
613 5856de80 ths
            exit(1);
614 5856de80 ths
        }
615 5856de80 ths
    }
616 5856de80 ths
617 5856de80 ths
    /* Store command line.  */
618 5856de80 ths
    prom_set(index++, env->kernel_filename);
619 5856de80 ths
    if (initrd_size > 0)
620 3594c774 ths
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
621 5856de80 ths
    else
622 5856de80 ths
        prom_set(index++, env->kernel_cmdline);
623 5856de80 ths
624 5856de80 ths
    /* Setup minimum environment variables */
625 5856de80 ths
    prom_set(index++, "memsize");
626 5856de80 ths
    prom_set(index++, "%i", env->ram_size);
627 5856de80 ths
    prom_set(index++, "modetty0");
628 5856de80 ths
    prom_set(index++, "38400n8r");
629 5856de80 ths
    prom_set(index++, NULL);
630 5856de80 ths
631 5856de80 ths
    return kernel_addr;
632 5856de80 ths
}
633 5856de80 ths
634 5856de80 ths
static void main_cpu_reset(void *opaque)
635 5856de80 ths
{
636 5856de80 ths
    CPUState *env = opaque;
637 5856de80 ths
    cpu_reset(env);
638 5856de80 ths
639 5856de80 ths
    /* The bootload does not need to be rewritten as it is located in a
640 5856de80 ths
       read only location. The kernel location and the arguments table
641 5856de80 ths
       location does not change. */
642 5856de80 ths
    if (env->kernel_filename)
643 5856de80 ths
        load_kernel (env);
644 5856de80 ths
}
645 5856de80 ths
646 70705261 ths
static
647 5856de80 ths
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
648 5856de80 ths
                      DisplayState *ds, const char **fd_filename, int snapshot,
649 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
650 94fc95cd j_mayer
                      const char *initrd_filename, const char *cpu_model)
651 5856de80 ths
{
652 5856de80 ths
    char buf[1024];
653 5856de80 ths
    unsigned long bios_offset;
654 5856de80 ths
    int64_t kernel_addr;
655 5856de80 ths
    PCIBus *pci_bus;
656 5856de80 ths
    CPUState *env;
657 5856de80 ths
    RTCState *rtc_state;
658 f1770b3e ths
    /* fdctrl_t *floppy_controller; */
659 5856de80 ths
    MaltaFPGAState *malta_fpga;
660 5856de80 ths
    int ret;
661 33d68b5f ths
    mips_def_t *def;
662 5856de80 ths
663 33d68b5f ths
    /* init CPUs */
664 33d68b5f ths
    if (cpu_model == NULL) {
665 33d68b5f ths
#ifdef MIPS_HAS_MIPS64
666 33d68b5f ths
        cpu_model = "R4000";
667 33d68b5f ths
#else
668 33d68b5f ths
        cpu_model = "4KEc";
669 33d68b5f ths
#endif
670 33d68b5f ths
    }
671 33d68b5f ths
    if (mips_find_by_name(cpu_model, &def) != 0)
672 33d68b5f ths
        def = NULL;
673 5856de80 ths
    env = cpu_init();
674 33d68b5f ths
    cpu_mips_register(env, def);
675 5856de80 ths
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
676 5856de80 ths
    qemu_register_reset(main_cpu_reset, env);
677 5856de80 ths
678 5856de80 ths
    /* allocate RAM */
679 5856de80 ths
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
680 5856de80 ths
681 5856de80 ths
    /* Map the bios at two physical locations, as on the real board */
682 5856de80 ths
    bios_offset = ram_size + vga_ram_size;
683 5856de80 ths
    cpu_register_physical_memory(0x1e000000LL,
684 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
685 5856de80 ths
    cpu_register_physical_memory(0x1fc00000LL,
686 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
687 5856de80 ths
688 5856de80 ths
    /* Load a BIOS image except if a kernel image has been specified. In
689 5856de80 ths
       the later case, just write a small bootloader to the flash
690 5856de80 ths
       location. */
691 5856de80 ths
    if (kernel_filename) {
692 5856de80 ths
        env->ram_size = ram_size;
693 5856de80 ths
        env->kernel_filename = kernel_filename;
694 5856de80 ths
        env->kernel_cmdline = kernel_cmdline;
695 5856de80 ths
        env->initrd_filename = initrd_filename;
696 5856de80 ths
        kernel_addr = load_kernel(env);
697 5856de80 ths
        write_bootloader(env, bios_offset, kernel_addr);
698 5856de80 ths
    } else {
699 5856de80 ths
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
700 5856de80 ths
        ret = load_image(buf, phys_ram_base + bios_offset);
701 331ad6f4 ths
        if (ret < 0 || ret > BIOS_SIZE) {
702 5856de80 ths
            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
703 5856de80 ths
                    buf);
704 5856de80 ths
            exit(1);
705 5856de80 ths
        }
706 5856de80 ths
    }
707 5856de80 ths
708 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
709 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
710 5856de80 ths
       map to the board ID. */
711 5856de80 ths
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
712 5856de80 ths
713 5856de80 ths
    /* Init internal devices */
714 5856de80 ths
    cpu_mips_clock_init(env);
715 5856de80 ths
    cpu_mips_irqctrl_init();
716 5856de80 ths
717 5856de80 ths
    /* FPGA */
718 a4bc3afc ths
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
719 5856de80 ths
720 5856de80 ths
    /* Interrupt controller */
721 5856de80 ths
    isa_pic = pic_init(pic_irq_request, env);
722 5856de80 ths
723 5856de80 ths
    /* Northbridge */
724 5856de80 ths
    pci_bus = pci_gt64120_init(isa_pic);
725 5856de80 ths
726 5856de80 ths
    /* Southbridge */
727 5856de80 ths
    piix4_init(pci_bus, 80);
728 5856de80 ths
    pci_piix3_ide_init(pci_bus, bs_table, 81);
729 5856de80 ths
    usb_uhci_init(pci_bus, 82);
730 5856de80 ths
    piix4_pm_init(pci_bus, 83);
731 5856de80 ths
    pit = pit_init(0x40, 0);
732 5856de80 ths
    DMA_init(0);
733 5856de80 ths
734 5856de80 ths
    /* Super I/O */
735 5856de80 ths
    kbd_init();
736 5856de80 ths
    rtc_state = rtc_init(0x70, 8);
737 7bcc17dc ths
    if (serial_hds[0])
738 7bcc17dc ths
        serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
739 7bcc17dc ths
    if (serial_hds[1])
740 c05ac0cd ths
        serial_init(&pic_set_irq_new, isa_pic, 0x2f8, 3, serial_hds[1]);
741 7bcc17dc ths
    if (parallel_hds[0])
742 7bcc17dc ths
        parallel_init(0x378, 7, parallel_hds[0]);
743 5856de80 ths
    /* XXX: The floppy controller does not work correctly, something is
744 f1770b3e ths
       probably wrong.
745 f1770b3e ths
    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
746 5856de80 ths
747 5856de80 ths
    /* Sound card */
748 5856de80 ths
#ifdef HAS_AUDIO
749 5856de80 ths
    audio_init(pci_bus);
750 5856de80 ths
#endif
751 5856de80 ths
752 5856de80 ths
    /* Network card */
753 5856de80 ths
    network_init(pci_bus);
754 11f29511 ths
755 11f29511 ths
    /* Optional PCI video card */
756 11f29511 ths
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
757 11f29511 ths
                        ram_size, vga_ram_size);
758 5856de80 ths
}
759 5856de80 ths
760 5856de80 ths
QEMUMachine mips_malta_machine = {
761 5856de80 ths
    "malta",
762 5856de80 ths
    "MIPS Malta Core LV",
763 5856de80 ths
    mips_malta_init,
764 5856de80 ths
};