Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 2802bfe3

History | View | Annotate | Download (24 kB)

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

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

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

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

525 5856de80 ths
   The registers a0 to a3 should contain the following values:
526 5856de80 ths
     a0 - number of kernel arguments
527 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
528 5856de80 ths
     a2 - 32-bit address of the environment variables table
529 5856de80 ths
     a3 - RAM size in bytes
530 5856de80 ths
*/
531 5856de80 ths
532 74287114 ths
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
533 5856de80 ths
{
534 5856de80 ths
    uint32_t *p;
535 5856de80 ths
536 5856de80 ths
    /* Small bootloader */
537 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset);
538 3ddd0065 ths
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
539 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
540 5856de80 ths
541 5856de80 ths
    /* Second part of the bootloader */
542 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
543 3ddd0065 ths
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
544 3ddd0065 ths
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
545 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
546 3ddd0065 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
547 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
548 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
549 3ddd0065 ths
    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
550 3ddd0065 ths
    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
551 2802bfe3 ths
552 2802bfe3 ths
    /* Load BAR registers as done by YAMON */
553 2802bfe3 ths
    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
554 2802bfe3 ths
555 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
556 2802bfe3 ths
    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
557 2802bfe3 ths
#else
558 2802bfe3 ths
    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
559 2802bfe3 ths
#endif
560 2802bfe3 ths
    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
561 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
562 2802bfe3 ths
    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
563 2802bfe3 ths
#else
564 2802bfe3 ths
    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
565 2802bfe3 ths
#endif
566 2802bfe3 ths
    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
567 2802bfe3 ths
568 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
569 2802bfe3 ths
    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
570 2802bfe3 ths
#else
571 2802bfe3 ths
    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
572 2802bfe3 ths
#endif
573 2802bfe3 ths
    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
574 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
575 2802bfe3 ths
    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
576 2802bfe3 ths
#else
577 2802bfe3 ths
    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
578 2802bfe3 ths
#endif
579 2802bfe3 ths
    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
580 2802bfe3 ths
581 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
582 2802bfe3 ths
    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
583 2802bfe3 ths
#else
584 2802bfe3 ths
    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
585 2802bfe3 ths
#endif
586 2802bfe3 ths
    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
587 2802bfe3 ths
#ifdef TARGET_WORDS_BIGENDIAN
588 2802bfe3 ths
    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
589 2802bfe3 ths
#else
590 2802bfe3 ths
    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
591 2802bfe3 ths
#endif
592 2802bfe3 ths
    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
593 2802bfe3 ths
594 2802bfe3 ths
    /* Jump to kernel code */
595 74287114 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
596 74287114 ths
    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
597 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
598 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
599 5856de80 ths
}
600 5856de80 ths
601 5856de80 ths
static void prom_set(int index, const char *string, ...)
602 5856de80 ths
{
603 5856de80 ths
    va_list ap;
604 3ddd0065 ths
    int32_t *p;
605 3ddd0065 ths
    int32_t table_addr;
606 5856de80 ths
    char *s;
607 5856de80 ths
608 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
609 5856de80 ths
        return;
610 5856de80 ths
611 3ddd0065 ths
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
612 5856de80 ths
    p += index;
613 5856de80 ths
614 5856de80 ths
    if (string == NULL) {
615 5856de80 ths
        stl_raw(p, 0);
616 5856de80 ths
        return;
617 5856de80 ths
    }
618 5856de80 ths
619 3ddd0065 ths
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
620 5856de80 ths
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
621 5856de80 ths
622 5856de80 ths
    stl_raw(p, table_addr);
623 5856de80 ths
624 5856de80 ths
    va_start(ap, string);
625 5856de80 ths
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
626 5856de80 ths
    va_end(ap);
627 5856de80 ths
}
628 5856de80 ths
629 5856de80 ths
/* Kernel */
630 5856de80 ths
static int64_t load_kernel (CPUState *env)
631 5856de80 ths
{
632 74287114 ths
    int64_t kernel_entry, kernel_low, kernel_high;
633 5856de80 ths
    int index = 0;
634 5856de80 ths
    long initrd_size;
635 74287114 ths
    ram_addr_t initrd_offset;
636 5856de80 ths
637 74287114 ths
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
638 74287114 ths
                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
639 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
640 5856de80 ths
                env->kernel_filename);
641 5856de80 ths
      exit(1);
642 5856de80 ths
    }
643 5856de80 ths
644 5856de80 ths
    /* load initrd */
645 5856de80 ths
    initrd_size = 0;
646 74287114 ths
    initrd_offset = 0;
647 5856de80 ths
    if (env->initrd_filename) {
648 74287114 ths
        initrd_size = get_image_size (env->initrd_filename);
649 74287114 ths
        if (initrd_size > 0) {
650 74287114 ths
            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
651 74287114 ths
            if (initrd_offset + initrd_size > env->ram_size) {
652 74287114 ths
                fprintf(stderr,
653 74287114 ths
                        "qemu: memory too small for initial ram disk '%s'\n",
654 74287114 ths
                        env->initrd_filename);
655 74287114 ths
                exit(1);
656 74287114 ths
            }
657 74287114 ths
            initrd_size = load_image(env->initrd_filename,
658 74287114 ths
                                     phys_ram_base + initrd_offset);
659 74287114 ths
        }
660 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
661 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
662 5856de80 ths
                    env->initrd_filename);
663 5856de80 ths
            exit(1);
664 5856de80 ths
        }
665 5856de80 ths
    }
666 5856de80 ths
667 5856de80 ths
    /* Store command line.  */
668 5856de80 ths
    prom_set(index++, env->kernel_filename);
669 5856de80 ths
    if (initrd_size > 0)
670 74287114 ths
        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
671 74287114 ths
                 PHYS_TO_VIRT(initrd_offset), initrd_size,
672 74287114 ths
                 env->kernel_cmdline);
673 5856de80 ths
    else
674 5856de80 ths
        prom_set(index++, env->kernel_cmdline);
675 5856de80 ths
676 5856de80 ths
    /* Setup minimum environment variables */
677 5856de80 ths
    prom_set(index++, "memsize");
678 5856de80 ths
    prom_set(index++, "%i", env->ram_size);
679 5856de80 ths
    prom_set(index++, "modetty0");
680 5856de80 ths
    prom_set(index++, "38400n8r");
681 5856de80 ths
    prom_set(index++, NULL);
682 5856de80 ths
683 74287114 ths
    return kernel_entry;
684 5856de80 ths
}
685 5856de80 ths
686 5856de80 ths
static void main_cpu_reset(void *opaque)
687 5856de80 ths
{
688 5856de80 ths
    CPUState *env = opaque;
689 5856de80 ths
    cpu_reset(env);
690 5856de80 ths
691 5856de80 ths
    /* The bootload does not need to be rewritten as it is located in a
692 5856de80 ths
       read only location. The kernel location and the arguments table
693 5856de80 ths
       location does not change. */
694 fb82fea0 ths
    if (env->kernel_filename) {
695 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
696 5856de80 ths
        load_kernel (env);
697 fb82fea0 ths
    }
698 5856de80 ths
}
699 5856de80 ths
700 70705261 ths
static
701 5856de80 ths
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
702 5856de80 ths
                      DisplayState *ds, const char **fd_filename, int snapshot,
703 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
704 94fc95cd j_mayer
                      const char *initrd_filename, const char *cpu_model)
705 5856de80 ths
{
706 5856de80 ths
    char buf[1024];
707 5856de80 ths
    unsigned long bios_offset;
708 74287114 ths
    int64_t kernel_entry;
709 5856de80 ths
    PCIBus *pci_bus;
710 5856de80 ths
    CPUState *env;
711 5856de80 ths
    RTCState *rtc_state;
712 f1770b3e ths
    /* fdctrl_t *floppy_controller; */
713 5856de80 ths
    MaltaFPGAState *malta_fpga;
714 5856de80 ths
    int ret;
715 33d68b5f ths
    mips_def_t *def;
716 d537cf6c pbrook
    qemu_irq *i8259;
717 5856de80 ths
718 33d68b5f ths
    /* init CPUs */
719 33d68b5f ths
    if (cpu_model == NULL) {
720 60aa19ab ths
#ifdef TARGET_MIPS64
721 33d68b5f ths
        cpu_model = "R4000";
722 33d68b5f ths
#else
723 33d68b5f ths
        cpu_model = "4KEc";
724 33d68b5f ths
#endif
725 33d68b5f ths
    }
726 33d68b5f ths
    if (mips_find_by_name(cpu_model, &def) != 0)
727 33d68b5f ths
        def = NULL;
728 5856de80 ths
    env = cpu_init();
729 33d68b5f ths
    cpu_mips_register(env, def);
730 5856de80 ths
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
731 5856de80 ths
    qemu_register_reset(main_cpu_reset, env);
732 5856de80 ths
733 5856de80 ths
    /* allocate RAM */
734 5856de80 ths
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
735 5856de80 ths
736 5856de80 ths
    /* Map the bios at two physical locations, as on the real board */
737 5856de80 ths
    bios_offset = ram_size + vga_ram_size;
738 5856de80 ths
    cpu_register_physical_memory(0x1e000000LL,
739 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
740 5856de80 ths
    cpu_register_physical_memory(0x1fc00000LL,
741 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
742 5856de80 ths
743 5856de80 ths
    /* Load a BIOS image except if a kernel image has been specified. In
744 5856de80 ths
       the later case, just write a small bootloader to the flash
745 5856de80 ths
       location. */
746 5856de80 ths
    if (kernel_filename) {
747 5856de80 ths
        env->ram_size = ram_size;
748 5856de80 ths
        env->kernel_filename = kernel_filename;
749 5856de80 ths
        env->kernel_cmdline = kernel_cmdline;
750 5856de80 ths
        env->initrd_filename = initrd_filename;
751 74287114 ths
        kernel_entry = load_kernel(env);
752 fb82fea0 ths
        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
753 74287114 ths
        write_bootloader(env, bios_offset, kernel_entry);
754 5856de80 ths
    } else {
755 5856de80 ths
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
756 5856de80 ths
        ret = load_image(buf, phys_ram_base + bios_offset);
757 331ad6f4 ths
        if (ret < 0 || ret > BIOS_SIZE) {
758 5856de80 ths
            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
759 5856de80 ths
                    buf);
760 5856de80 ths
            exit(1);
761 5856de80 ths
        }
762 5856de80 ths
    }
763 5856de80 ths
764 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
765 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
766 5856de80 ths
       map to the board ID. */
767 5856de80 ths
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
768 5856de80 ths
769 5856de80 ths
    /* Init internal devices */
770 d537cf6c pbrook
    cpu_mips_irq_init_cpu(env);
771 5856de80 ths
    cpu_mips_clock_init(env);
772 5856de80 ths
    cpu_mips_irqctrl_init();
773 5856de80 ths
774 5856de80 ths
    /* FPGA */
775 a4bc3afc ths
    malta_fpga = malta_fpga_init(0x1f000000LL, env);
776 5856de80 ths
777 5856de80 ths
    /* Interrupt controller */
778 d537cf6c pbrook
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
779 d537cf6c pbrook
    i8259 = i8259_init(env->irq[2]);
780 5856de80 ths
781 5856de80 ths
    /* Northbridge */
782 d537cf6c pbrook
    pci_bus = pci_gt64120_init(i8259);
783 5856de80 ths
784 5856de80 ths
    /* Southbridge */
785 5856de80 ths
    piix4_init(pci_bus, 80);
786 d537cf6c pbrook
    pci_piix3_ide_init(pci_bus, bs_table, 81, i8259);
787 5856de80 ths
    usb_uhci_init(pci_bus, 82);
788 5856de80 ths
    piix4_pm_init(pci_bus, 83);
789 d537cf6c pbrook
    pit = pit_init(0x40, i8259[0]);
790 5856de80 ths
    DMA_init(0);
791 5856de80 ths
792 5856de80 ths
    /* Super I/O */
793 d537cf6c pbrook
    i8042_init(i8259[1], i8259[12], 0x60);
794 d537cf6c pbrook
    rtc_state = rtc_init(0x70, i8259[8]);
795 7bcc17dc ths
    if (serial_hds[0])
796 d537cf6c pbrook
        serial_init(0x3f8, i8259[4], serial_hds[0]);
797 7bcc17dc ths
    if (serial_hds[1])
798 d537cf6c pbrook
        serial_init(0x2f8, i8259[3], serial_hds[1]);
799 7bcc17dc ths
    if (parallel_hds[0])
800 d537cf6c pbrook
        parallel_init(0x378, i8259[7], parallel_hds[0]);
801 5856de80 ths
    /* XXX: The floppy controller does not work correctly, something is
802 f1770b3e ths
       probably wrong.
803 d537cf6c pbrook
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
804 5856de80 ths
805 5856de80 ths
    /* Sound card */
806 5856de80 ths
#ifdef HAS_AUDIO
807 5856de80 ths
    audio_init(pci_bus);
808 5856de80 ths
#endif
809 5856de80 ths
810 5856de80 ths
    /* Network card */
811 5856de80 ths
    network_init(pci_bus);
812 11f29511 ths
813 11f29511 ths
    /* Optional PCI video card */
814 11f29511 ths
    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
815 11f29511 ths
                        ram_size, vga_ram_size);
816 5856de80 ths
}
817 5856de80 ths
818 5856de80 ths
QEMUMachine mips_malta_machine = {
819 5856de80 ths
    "malta",
820 5856de80 ths
    "MIPS Malta Core LV",
821 5856de80 ths
    mips_malta_init,
822 5856de80 ths
};