Statistics
| Branch: | Revision:

root / hw / mips_malta.c @ 70705261

History | View | Annotate | Download (15.9 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 5856de80 ths
    uint32_t i2coe;
53 5856de80 ths
    uint32_t i2cout;
54 5856de80 ths
    uint32_t i2csel;
55 5856de80 ths
    CharDriverState *display;
56 5856de80 ths
    char display_text[9];
57 5856de80 ths
} MaltaFPGAState;
58 5856de80 ths
59 5856de80 ths
static PITState *pit;
60 5856de80 ths
61 4de9b249 ths
/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
62 5856de80 ths
static void pic_irq_request(void *opaque, int level)
63 5856de80 ths
{
64 4de9b249 ths
    cpu_mips_irq_request(opaque, 2, level);
65 5856de80 ths
}
66 5856de80 ths
67 5856de80 ths
/* Malta FPGA */
68 5856de80 ths
static void malta_fpga_update_display(void *opaque)
69 5856de80 ths
{
70 5856de80 ths
    char leds_text[9];
71 5856de80 ths
    int i;
72 5856de80 ths
    MaltaFPGAState *s = opaque;
73 5856de80 ths
74 5856de80 ths
    for (i = 7 ; i >= 0 ; i--) {
75 5856de80 ths
        if (s->leds & (1 << i))
76 5856de80 ths
            leds_text[i] = '#';
77 5856de80 ths
        else
78 5856de80 ths
            leds_text[i] = ' ';
79 5856de80 ths
    }
80 5856de80 ths
    leds_text[8] = '\0';
81 5856de80 ths
82 472c5273 ths
    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
83 472c5273 ths
    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
84 5856de80 ths
}
85 5856de80 ths
86 5856de80 ths
static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
87 5856de80 ths
{
88 5856de80 ths
    MaltaFPGAState *s = opaque;
89 5856de80 ths
    uint32_t val = 0;
90 5856de80 ths
    uint32_t saddr;
91 5856de80 ths
92 5856de80 ths
    saddr = (addr & 0xfffff);
93 5856de80 ths
94 5856de80 ths
    switch (saddr) {
95 5856de80 ths
96 5856de80 ths
    /* SWITCH Register */
97 5856de80 ths
    case 0x00200:
98 5856de80 ths
        val = 0x00000000;                /* All switches closed */
99 5856de80 ths
        break;
100 5856de80 ths
101 5856de80 ths
    /* STATUS Register */
102 5856de80 ths
    case 0x00208:
103 5856de80 ths
#ifdef TARGET_WORDS_BIGENDIAN
104 5856de80 ths
        val = 0x00000012;
105 5856de80 ths
#else
106 5856de80 ths
        val = 0x00000010;
107 5856de80 ths
#endif
108 5856de80 ths
        break;
109 5856de80 ths
110 5856de80 ths
    /* JMPRS Register */
111 5856de80 ths
    case 0x00210:
112 5856de80 ths
        val = 0x00;
113 5856de80 ths
        break;
114 5856de80 ths
115 5856de80 ths
    /* LEDBAR Register */
116 5856de80 ths
    case 0x00408:
117 5856de80 ths
        val = s->leds;
118 5856de80 ths
        break;
119 5856de80 ths
120 5856de80 ths
    /* BRKRES Register */
121 5856de80 ths
    case 0x00508:
122 5856de80 ths
        val = s->brk;
123 5856de80 ths
        break;
124 5856de80 ths
125 5856de80 ths
    /* GPOUT Register */
126 5856de80 ths
    case 0x00a00:
127 5856de80 ths
        val = s->gpout;
128 5856de80 ths
        break;
129 5856de80 ths
130 5856de80 ths
    /* XXX: implement a real I2C controller */
131 5856de80 ths
132 5856de80 ths
    /* GPINP Register */
133 5856de80 ths
    case 0x00a08:
134 5856de80 ths
        /* IN = OUT until a real I2C control is implemented */
135 5856de80 ths
        if (s->i2csel)
136 5856de80 ths
            val = s->i2cout;
137 5856de80 ths
        else
138 5856de80 ths
            val = 0x00;
139 5856de80 ths
        break;
140 5856de80 ths
141 5856de80 ths
    /* I2CINP Register */
142 5856de80 ths
    case 0x00b00:
143 5856de80 ths
        val = 0x00000003;
144 5856de80 ths
        break;
145 5856de80 ths
146 5856de80 ths
    /* I2COE Register */
147 5856de80 ths
    case 0x00b08:
148 5856de80 ths
        val = s->i2coe;
149 5856de80 ths
        break;
150 5856de80 ths
151 5856de80 ths
    /* I2COUT Register */
152 5856de80 ths
    case 0x00b10:
153 5856de80 ths
        val = s->i2cout;
154 5856de80 ths
        break;
155 5856de80 ths
156 5856de80 ths
    /* I2CSEL Register */
157 5856de80 ths
    case 0x00b18:
158 5856de80 ths
        val = s->i2cout;
159 5856de80 ths
        break;
160 5856de80 ths
161 5856de80 ths
    default:
162 5856de80 ths
#if 0
163 44cbbf18 ths
        printf ("malta_fpga_read: Bad register offset 0x" TLSZ "\n",
164 44cbbf18 ths
                addr);
165 5856de80 ths
#endif
166 5856de80 ths
        break;
167 5856de80 ths
    }
168 5856de80 ths
    return val;
169 5856de80 ths
}
170 5856de80 ths
171 5856de80 ths
static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
172 5856de80 ths
                              uint32_t val)
173 5856de80 ths
{
174 5856de80 ths
    MaltaFPGAState *s = opaque;
175 5856de80 ths
    uint32_t saddr;
176 5856de80 ths
177 5856de80 ths
    saddr = (addr & 0xfffff);
178 5856de80 ths
179 5856de80 ths
    switch (saddr) {
180 5856de80 ths
181 5856de80 ths
    /* SWITCH Register */
182 5856de80 ths
    case 0x00200:
183 5856de80 ths
        break;
184 5856de80 ths
185 5856de80 ths
    /* JMPRS Register */
186 5856de80 ths
    case 0x00210:
187 5856de80 ths
        break;
188 5856de80 ths
189 5856de80 ths
    /* LEDBAR Register */
190 5856de80 ths
    /* XXX: implement a 8-LED array */
191 5856de80 ths
    case 0x00408:
192 5856de80 ths
        s->leds = val & 0xff;
193 5856de80 ths
        break;
194 5856de80 ths
195 5856de80 ths
    /* ASCIIWORD Register */
196 5856de80 ths
    case 0x00410:
197 5856de80 ths
        snprintf(s->display_text, 9, "%08X", val);
198 5856de80 ths
        malta_fpga_update_display(s);
199 5856de80 ths
        break;
200 5856de80 ths
201 5856de80 ths
    /* ASCIIPOS0 to ASCIIPOS7 Registers */
202 5856de80 ths
    case 0x00418:
203 5856de80 ths
    case 0x00420:
204 5856de80 ths
    case 0x00428:
205 5856de80 ths
    case 0x00430:
206 5856de80 ths
    case 0x00438:
207 5856de80 ths
    case 0x00440:
208 5856de80 ths
    case 0x00448:
209 5856de80 ths
    case 0x00450:
210 5856de80 ths
        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
211 5856de80 ths
        malta_fpga_update_display(s);
212 5856de80 ths
        break;
213 5856de80 ths
214 5856de80 ths
    /* SOFTRES Register */
215 5856de80 ths
    case 0x00500:
216 5856de80 ths
        if (val == 0x42)
217 5856de80 ths
            qemu_system_reset_request ();
218 5856de80 ths
        break;
219 5856de80 ths
220 5856de80 ths
    /* BRKRES Register */
221 5856de80 ths
    case 0x00508:
222 5856de80 ths
        s->brk = val & 0xff;
223 5856de80 ths
        break;
224 5856de80 ths
225 5856de80 ths
    /* GPOUT Register */
226 5856de80 ths
    case 0x00a00:
227 5856de80 ths
        s->gpout = val & 0xff;
228 5856de80 ths
        break;
229 5856de80 ths
230 5856de80 ths
    /* I2COE Register */
231 5856de80 ths
    case 0x00b08:
232 5856de80 ths
        s->i2coe = val & 0x03;
233 5856de80 ths
        break;
234 5856de80 ths
235 5856de80 ths
    /* I2COUT Register */
236 5856de80 ths
    case 0x00b10:
237 5856de80 ths
        s->i2cout = val & 0x03;
238 5856de80 ths
        break;
239 5856de80 ths
240 5856de80 ths
    /* I2CSEL Register */
241 5856de80 ths
    case 0x00b18:
242 5856de80 ths
        s->i2cout = val & 0x01;
243 5856de80 ths
        break;
244 5856de80 ths
245 5856de80 ths
    default:
246 5856de80 ths
#if 0
247 44cbbf18 ths
        printf ("malta_fpga_write: Bad register offset 0x" TLSZ "\n",
248 44cbbf18 ths
                addr);
249 5856de80 ths
#endif
250 5856de80 ths
        break;
251 5856de80 ths
    }
252 5856de80 ths
}
253 5856de80 ths
254 5856de80 ths
static CPUReadMemoryFunc *malta_fpga_read[] = {
255 5856de80 ths
   malta_fpga_readl,
256 5856de80 ths
   malta_fpga_readl,
257 5856de80 ths
   malta_fpga_readl
258 5856de80 ths
};
259 5856de80 ths
260 5856de80 ths
static CPUWriteMemoryFunc *malta_fpga_write[] = {
261 5856de80 ths
   malta_fpga_writel,
262 5856de80 ths
   malta_fpga_writel,
263 5856de80 ths
   malta_fpga_writel
264 5856de80 ths
};
265 5856de80 ths
266 5856de80 ths
void malta_fpga_reset(void *opaque)
267 5856de80 ths
{
268 5856de80 ths
    MaltaFPGAState *s = opaque;
269 5856de80 ths
270 5856de80 ths
    s->leds   = 0x00;
271 5856de80 ths
    s->brk    = 0x0a;
272 5856de80 ths
    s->gpout  = 0x00;
273 5856de80 ths
    s->i2coe  = 0x0;
274 5856de80 ths
    s->i2cout = 0x3;
275 5856de80 ths
    s->i2csel = 0x1;
276 5856de80 ths
277 5856de80 ths
    s->display_text[8] = '\0';
278 5856de80 ths
    snprintf(s->display_text, 9, "        ");
279 5856de80 ths
    malta_fpga_update_display(s);
280 5856de80 ths
}
281 5856de80 ths
282 5856de80 ths
MaltaFPGAState *malta_fpga_init(target_phys_addr_t base)
283 5856de80 ths
{
284 5856de80 ths
    MaltaFPGAState *s;
285 5856de80 ths
    int malta;
286 5856de80 ths
287 5856de80 ths
    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
288 5856de80 ths
289 5856de80 ths
    malta = cpu_register_io_memory(0, malta_fpga_read,
290 5856de80 ths
                                   malta_fpga_write, s);
291 5856de80 ths
    cpu_register_physical_memory(base, 0x100000, malta);
292 5856de80 ths
293 5856de80 ths
    s->display = qemu_chr_open("vc");
294 af23902b ths
    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
295 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
296 5856de80 ths
    qemu_chr_printf(s->display, "+        +\r\n");
297 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
298 5856de80 ths
    qemu_chr_printf(s->display, "\n");
299 5856de80 ths
    qemu_chr_printf(s->display, "Malta ASCII\r\n");
300 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
301 5856de80 ths
    qemu_chr_printf(s->display, "+        +\r\n");
302 5856de80 ths
    qemu_chr_printf(s->display, "+--------+\r\n");
303 5856de80 ths
304 5856de80 ths
    malta_fpga_reset(s);
305 5856de80 ths
    qemu_register_reset(malta_fpga_reset, s);
306 5856de80 ths
307 5856de80 ths
    return s;
308 5856de80 ths
}
309 5856de80 ths
310 5856de80 ths
/* Audio support */
311 5856de80 ths
#ifdef HAS_AUDIO
312 5856de80 ths
static void audio_init (PCIBus *pci_bus)
313 5856de80 ths
{
314 5856de80 ths
    struct soundhw *c;
315 5856de80 ths
    int audio_enabled = 0;
316 5856de80 ths
317 5856de80 ths
    for (c = soundhw; !audio_enabled && c->name; ++c) {
318 5856de80 ths
        audio_enabled = c->enabled;
319 5856de80 ths
    }
320 5856de80 ths
321 5856de80 ths
    if (audio_enabled) {
322 5856de80 ths
        AudioState *s;
323 5856de80 ths
324 5856de80 ths
        s = AUD_init ();
325 5856de80 ths
        if (s) {
326 5856de80 ths
            for (c = soundhw; c->name; ++c) {
327 5856de80 ths
                if (c->enabled) {
328 5856de80 ths
                    if (c->isa) {
329 5856de80 ths
                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
330 5856de80 ths
                        exit(1);
331 5856de80 ths
                    }
332 5856de80 ths
                    else {
333 5856de80 ths
                        if (pci_bus) {
334 5856de80 ths
                            c->init.init_pci (pci_bus, s);
335 5856de80 ths
                        }
336 5856de80 ths
                    }
337 5856de80 ths
                }
338 5856de80 ths
            }
339 5856de80 ths
        }
340 5856de80 ths
    }
341 5856de80 ths
}
342 5856de80 ths
#endif
343 5856de80 ths
344 5856de80 ths
/* Network support */
345 5856de80 ths
static void network_init (PCIBus *pci_bus)
346 5856de80 ths
{
347 5856de80 ths
    int i;
348 5856de80 ths
    NICInfo *nd;
349 5856de80 ths
350 5856de80 ths
    for(i = 0; i < nb_nics; i++) {
351 5856de80 ths
        nd = &nd_table[i];
352 5856de80 ths
        if (!nd->model) {
353 5856de80 ths
            nd->model = "pcnet";
354 5856de80 ths
        }
355 5856de80 ths
        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
356 5856de80 ths
            /* The malta board has a PCNet card using PCI SLOT 11 */
357 5856de80 ths
            pci_nic_init(pci_bus, nd, 88);
358 5856de80 ths
        } else {
359 5856de80 ths
            pci_nic_init(pci_bus, nd, -1);
360 5856de80 ths
        }
361 5856de80 ths
    }
362 5856de80 ths
}
363 5856de80 ths
364 5856de80 ths
/* ROM and pseudo bootloader
365 5856de80 ths

366 5856de80 ths
   The following code implements a very very simple bootloader. It first
367 5856de80 ths
   loads the registers a0 to a3 to the values expected by the OS, and
368 5856de80 ths
   then jump at the kernel address.
369 5856de80 ths

370 5856de80 ths
   The bootloader should pass the locations of the kernel arguments and
371 5856de80 ths
   environment variables tables. Those tables contain the 32-bit address
372 5856de80 ths
   of NULL terminated strings. The environment variables table should be
373 5856de80 ths
   terminated by a NULL address.
374 5856de80 ths

375 5856de80 ths
   For a simpler implementation, the number of kernel arguments is fixed
376 5856de80 ths
   to two (the name of the kernel and the command line), and the two
377 5856de80 ths
   tables are actually the same one.
378 5856de80 ths

379 5856de80 ths
   The registers a0 to a3 should contain the following values:
380 5856de80 ths
     a0 - number of kernel arguments
381 5856de80 ths
     a1 - 32-bit address of the kernel arguments table
382 5856de80 ths
     a2 - 32-bit address of the environment variables table
383 5856de80 ths
     a3 - RAM size in bytes
384 5856de80 ths
*/
385 5856de80 ths
386 5856de80 ths
static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr)
387 5856de80 ths
{
388 5856de80 ths
    uint32_t *p;
389 5856de80 ths
390 5856de80 ths
    /* Small bootloader */
391 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset);
392 3ddd0065 ths
    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
393 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
394 5856de80 ths
395 5856de80 ths
    /* Second part of the bootloader */
396 5856de80 ths
    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);
397 3ddd0065 ths
    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
398 3ddd0065 ths
    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
399 3ddd0065 ths
    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
400 3ddd0065 ths
    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
401 3ddd0065 ths
    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
402 3ddd0065 ths
    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
403 3ddd0065 ths
    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
404 3ddd0065 ths
    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
405 3ddd0065 ths
    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
406 3ddd0065 ths
    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
407 3ddd0065 ths
    stl_raw(p++, 0x03e00008);                                      /* jr ra */
408 3ddd0065 ths
    stl_raw(p++, 0x00000000);                                      /* nop */
409 5856de80 ths
}
410 5856de80 ths
411 5856de80 ths
static void prom_set(int index, const char *string, ...)
412 5856de80 ths
{
413 5856de80 ths
    va_list ap;
414 3ddd0065 ths
    int32_t *p;
415 3ddd0065 ths
    int32_t table_addr;
416 5856de80 ths
    char *s;
417 5856de80 ths
418 5856de80 ths
    if (index >= ENVP_NB_ENTRIES)
419 5856de80 ths
        return;
420 5856de80 ths
421 3ddd0065 ths
    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
422 5856de80 ths
    p += index;
423 5856de80 ths
424 5856de80 ths
    if (string == NULL) {
425 5856de80 ths
        stl_raw(p, 0);
426 5856de80 ths
        return;
427 5856de80 ths
    }
428 5856de80 ths
429 3ddd0065 ths
    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
430 5856de80 ths
    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
431 5856de80 ths
432 5856de80 ths
    stl_raw(p, table_addr);
433 5856de80 ths
434 5856de80 ths
    va_start(ap, string);
435 5856de80 ths
    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
436 5856de80 ths
    va_end(ap);
437 5856de80 ths
}
438 5856de80 ths
439 5856de80 ths
/* Kernel */
440 5856de80 ths
static int64_t load_kernel (CPUState *env)
441 5856de80 ths
{
442 5856de80 ths
    int64_t kernel_addr = 0;
443 5856de80 ths
    int index = 0;
444 5856de80 ths
    long initrd_size;
445 5856de80 ths
446 5856de80 ths
    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {
447 5856de80 ths
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
448 5856de80 ths
                env->kernel_filename);
449 5856de80 ths
      exit(1);
450 5856de80 ths
    }
451 5856de80 ths
452 5856de80 ths
    /* load initrd */
453 5856de80 ths
    initrd_size = 0;
454 5856de80 ths
    if (env->initrd_filename) {
455 5856de80 ths
        initrd_size = load_image(env->initrd_filename,
456 5856de80 ths
                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
457 5856de80 ths
        if (initrd_size == (target_ulong) -1) {
458 5856de80 ths
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
459 5856de80 ths
                    env->initrd_filename);
460 5856de80 ths
            exit(1);
461 5856de80 ths
        }
462 5856de80 ths
    }
463 5856de80 ths
464 5856de80 ths
    /* Store command line.  */
465 5856de80 ths
    prom_set(index++, env->kernel_filename);
466 5856de80 ths
    if (initrd_size > 0)
467 44cbbf18 ths
        prom_set(index++, "rd_start=0x" TLSZ " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);
468 5856de80 ths
    else
469 5856de80 ths
        prom_set(index++, env->kernel_cmdline);
470 5856de80 ths
471 5856de80 ths
    /* Setup minimum environment variables */
472 5856de80 ths
    prom_set(index++, "memsize");
473 5856de80 ths
    prom_set(index++, "%i", env->ram_size);
474 5856de80 ths
    prom_set(index++, "modetty0");
475 5856de80 ths
    prom_set(index++, "38400n8r");
476 5856de80 ths
    prom_set(index++, NULL);
477 5856de80 ths
478 5856de80 ths
    return kernel_addr;
479 5856de80 ths
}
480 5856de80 ths
481 5856de80 ths
static void main_cpu_reset(void *opaque)
482 5856de80 ths
{
483 5856de80 ths
    CPUState *env = opaque;
484 5856de80 ths
    cpu_reset(env);
485 5856de80 ths
486 5856de80 ths
    /* The bootload does not need to be rewritten as it is located in a
487 5856de80 ths
       read only location. The kernel location and the arguments table
488 5856de80 ths
       location does not change. */
489 5856de80 ths
    if (env->kernel_filename)
490 5856de80 ths
        load_kernel (env);
491 5856de80 ths
}
492 5856de80 ths
493 70705261 ths
static
494 5856de80 ths
void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
495 5856de80 ths
                      DisplayState *ds, const char **fd_filename, int snapshot,
496 5856de80 ths
                      const char *kernel_filename, const char *kernel_cmdline,
497 5856de80 ths
                      const char *initrd_filename)
498 5856de80 ths
{
499 5856de80 ths
    char buf[1024];
500 5856de80 ths
    unsigned long bios_offset;
501 5856de80 ths
    int64_t kernel_addr;
502 5856de80 ths
    PCIBus *pci_bus;
503 5856de80 ths
    CPUState *env;
504 5856de80 ths
    RTCState *rtc_state;
505 f1770b3e ths
    /* fdctrl_t *floppy_controller; */
506 5856de80 ths
    MaltaFPGAState *malta_fpga;
507 5856de80 ths
    int ret;
508 5856de80 ths
509 5856de80 ths
    env = cpu_init();
510 5856de80 ths
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
511 5856de80 ths
    qemu_register_reset(main_cpu_reset, env);
512 5856de80 ths
513 5856de80 ths
    /* allocate RAM */
514 5856de80 ths
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
515 5856de80 ths
516 5856de80 ths
    /* Map the bios at two physical locations, as on the real board */
517 5856de80 ths
    bios_offset = ram_size + vga_ram_size;
518 5856de80 ths
    cpu_register_physical_memory(0x1e000000LL,
519 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
520 5856de80 ths
    cpu_register_physical_memory(0x1fc00000LL,
521 5856de80 ths
                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
522 5856de80 ths
523 5856de80 ths
    /* Load a BIOS image except if a kernel image has been specified. In
524 5856de80 ths
       the later case, just write a small bootloader to the flash
525 5856de80 ths
       location. */
526 5856de80 ths
    if (kernel_filename) {
527 5856de80 ths
        env->ram_size = ram_size;
528 5856de80 ths
        env->kernel_filename = kernel_filename;
529 5856de80 ths
        env->kernel_cmdline = kernel_cmdline;
530 5856de80 ths
        env->initrd_filename = initrd_filename;
531 5856de80 ths
        kernel_addr = load_kernel(env);
532 5856de80 ths
        write_bootloader(env, bios_offset, kernel_addr);
533 5856de80 ths
    } else {
534 5856de80 ths
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
535 5856de80 ths
        ret = load_image(buf, phys_ram_base + bios_offset);
536 5856de80 ths
        if (ret != BIOS_SIZE) {
537 5856de80 ths
            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
538 5856de80 ths
                    buf);
539 5856de80 ths
            exit(1);
540 5856de80 ths
        }
541 5856de80 ths
    }
542 5856de80 ths
543 5856de80 ths
    /* Board ID = 0x420 (Malta Board with CoreLV)
544 5856de80 ths
       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
545 5856de80 ths
       map to the board ID. */
546 5856de80 ths
    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
547 5856de80 ths
548 5856de80 ths
    /* Init internal devices */
549 5856de80 ths
    cpu_mips_clock_init(env);
550 5856de80 ths
    cpu_mips_irqctrl_init();
551 5856de80 ths
552 5856de80 ths
    /* FPGA */
553 5856de80 ths
    malta_fpga = malta_fpga_init(0x1f000000LL);
554 5856de80 ths
555 5856de80 ths
    /* Interrupt controller */
556 5856de80 ths
    isa_pic = pic_init(pic_irq_request, env);
557 5856de80 ths
558 5856de80 ths
    /* Northbridge */
559 5856de80 ths
    pci_bus = pci_gt64120_init(isa_pic);
560 5856de80 ths
561 5856de80 ths
    /* Southbridge */
562 5856de80 ths
    piix4_init(pci_bus, 80);
563 5856de80 ths
    pci_piix3_ide_init(pci_bus, bs_table, 81);
564 5856de80 ths
    usb_uhci_init(pci_bus, 82);
565 5856de80 ths
    piix4_pm_init(pci_bus, 83);
566 5856de80 ths
    pit = pit_init(0x40, 0);
567 5856de80 ths
    DMA_init(0);
568 5856de80 ths
569 5856de80 ths
    /* Super I/O */
570 5856de80 ths
    kbd_init();
571 5856de80 ths
    rtc_state = rtc_init(0x70, 8);
572 5856de80 ths
    serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
573 5856de80 ths
    parallel_init(0x378, 7, parallel_hds[0]);
574 5856de80 ths
    /* XXX: The floppy controller does not work correctly, something is
575 f1770b3e ths
       probably wrong.
576 f1770b3e ths
    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */
577 5856de80 ths
578 5856de80 ths
    /* Sound card */
579 5856de80 ths
#ifdef HAS_AUDIO
580 5856de80 ths
    audio_init(pci_bus);
581 5856de80 ths
#endif
582 5856de80 ths
583 5856de80 ths
    /* Network card */
584 5856de80 ths
    network_init(pci_bus);
585 5856de80 ths
}
586 5856de80 ths
587 5856de80 ths
QEMUMachine mips_malta_machine = {
588 5856de80 ths
    "malta",
589 5856de80 ths
    "MIPS Malta Core LV",
590 5856de80 ths
    mips_malta_init,
591 5856de80 ths
};