]> git.proxmox.com Git - mirror_qemu.git/blame - hw/mips_malta.c
Compile qemu-config only once
[mirror_qemu.git] / hw / mips_malta.c
CommitLineData
5856de80
TS
1/*
2 * QEMU Malta board support
3 *
4 * Copyright (c) 2006 Aurelien Jarno
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
87ecb68b
PB
25#include "hw.h"
26#include "pc.h"
ded7ba9c 27#include "fdc.h"
87ecb68b
PB
28#include "net.h"
29#include "boards.h"
30#include "smbus.h"
c8b153d7
TS
31#include "block.h"
32#include "flash.h"
87ecb68b
PB
33#include "mips.h"
34#include "pci.h"
35#include "qemu-char.h"
36#include "sysemu.h"
37#include "audio/audio.h"
38#include "boards.h"
3b3fb322 39#include "qemu-log.h"
bba831e8 40#include "mips-bios.h"
977e1244 41#include "ide.h"
5856de80 42
c8b153d7
TS
43//#define DEBUG_BOARD_INIT
44
60aa19ab 45#ifdef TARGET_MIPS64
74287114 46#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
5856de80 47#else
74287114 48#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
5856de80
TS
49#endif
50
74287114
TS
51#define ENVP_ADDR (int32_t)0x80002000
52#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
5856de80
TS
53
54#define ENVP_NB_ENTRIES 16
55#define ENVP_ENTRY_SIZE 256
56
e4bcb14c
TS
57#define MAX_IDE_BUS 2
58
5856de80
TS
59typedef struct {
60 uint32_t leds;
61 uint32_t brk;
62 uint32_t gpout;
130751ee 63 uint32_t i2cin;
5856de80
TS
64 uint32_t i2coe;
65 uint32_t i2cout;
66 uint32_t i2csel;
67 CharDriverState *display;
68 char display_text[9];
a4bc3afc 69 SerialState *uart;
5856de80
TS
70} MaltaFPGAState;
71
72static PITState *pit;
73
7df526e3
TS
74static struct _loaderparams {
75 int ram_size;
76 const char *kernel_filename;
77 const char *kernel_cmdline;
78 const char *initrd_filename;
79} loaderparams;
80
5856de80
TS
81/* Malta FPGA */
82static void malta_fpga_update_display(void *opaque)
83{
84 char leds_text[9];
85 int i;
86 MaltaFPGAState *s = opaque;
87
07cf0ba0
TS
88 for (i = 7 ; i >= 0 ; i--) {
89 if (s->leds & (1 << i))
90 leds_text[i] = '#';
91 else
92 leds_text[i] = ' ';
87ee1669 93 }
07cf0ba0
TS
94 leds_text[8] = '\0';
95
96 qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
97 qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
5856de80
TS
98}
99
130751ee
TS
100/*
101 * EEPROM 24C01 / 24C02 emulation.
102 *
103 * Emulation for serial EEPROMs:
104 * 24C01 - 1024 bit (128 x 8)
105 * 24C02 - 2048 bit (256 x 8)
106 *
107 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
108 */
109
110//~ #define DEBUG
111
112#if defined(DEBUG)
001faf32 113# define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
130751ee 114#else
001faf32 115# define logout(fmt, ...) ((void)0)
130751ee
TS
116#endif
117
118struct _eeprom24c0x_t {
119 uint8_t tick;
120 uint8_t address;
121 uint8_t command;
122 uint8_t ack;
123 uint8_t scl;
124 uint8_t sda;
125 uint8_t data;
126 //~ uint16_t size;
127 uint8_t contents[256];
128};
129
130typedef struct _eeprom24c0x_t eeprom24c0x_t;
131
132static eeprom24c0x_t eeprom = {
133 contents: {
134 /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
135 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
136 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
137 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
138 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
139 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
142 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
150 },
151};
152
a5f1b965 153static uint8_t eeprom24c0x_read(void)
130751ee
TS
154{
155 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
156 eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
157 return eeprom.sda;
158}
159
160static void eeprom24c0x_write(int scl, int sda)
161{
162 if (eeprom.scl && scl && (eeprom.sda != sda)) {
163 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
164 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
165 if (!sda) {
166 eeprom.tick = 1;
167 eeprom.command = 0;
168 }
169 } else if (eeprom.tick == 0 && !eeprom.ack) {
170 /* Waiting for start. */
171 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
172 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
173 } else if (!eeprom.scl && scl) {
174 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
175 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
176 if (eeprom.ack) {
177 logout("\ti2c ack bit = 0\n");
178 sda = 0;
179 eeprom.ack = 0;
180 } else if (eeprom.sda == sda) {
181 uint8_t bit = (sda != 0);
182 logout("\ti2c bit = %d\n", bit);
183 if (eeprom.tick < 9) {
184 eeprom.command <<= 1;
185 eeprom.command += bit;
186 eeprom.tick++;
187 if (eeprom.tick == 9) {
188 logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
189 eeprom.ack = 1;
190 }
191 } else if (eeprom.tick < 17) {
192 if (eeprom.command & 1) {
193 sda = ((eeprom.data & 0x80) != 0);
194 }
195 eeprom.address <<= 1;
196 eeprom.address += bit;
197 eeprom.tick++;
198 eeprom.data <<= 1;
199 if (eeprom.tick == 17) {
200 eeprom.data = eeprom.contents[eeprom.address];
201 logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
202 eeprom.ack = 1;
203 eeprom.tick = 0;
204 }
205 } else if (eeprom.tick >= 17) {
206 sda = 0;
207 }
208 } else {
209 logout("\tsda changed with raising scl\n");
210 }
211 } else {
212 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
213 }
214 eeprom.scl = scl;
215 eeprom.sda = sda;
216}
217
5856de80
TS
218static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
219{
220 MaltaFPGAState *s = opaque;
221 uint32_t val = 0;
222 uint32_t saddr;
223
224 saddr = (addr & 0xfffff);
225
226 switch (saddr) {
227
228 /* SWITCH Register */
229 case 0x00200:
230 val = 0x00000000; /* All switches closed */
231 break;
232
233 /* STATUS Register */
234 case 0x00208:
235#ifdef TARGET_WORDS_BIGENDIAN
236 val = 0x00000012;
237#else
238 val = 0x00000010;
239#endif
240 break;
241
242 /* JMPRS Register */
243 case 0x00210:
244 val = 0x00;
245 break;
246
247 /* LEDBAR Register */
248 case 0x00408:
249 val = s->leds;
250 break;
251
252 /* BRKRES Register */
253 case 0x00508:
254 val = s->brk;
255 break;
256
b6dc7ebb 257 /* UART Registers are handled directly by the serial device */
a4bc3afc 258
5856de80
TS
259 /* GPOUT Register */
260 case 0x00a00:
261 val = s->gpout;
262 break;
263
264 /* XXX: implement a real I2C controller */
265
266 /* GPINP Register */
267 case 0x00a08:
268 /* IN = OUT until a real I2C control is implemented */
269 if (s->i2csel)
270 val = s->i2cout;
271 else
272 val = 0x00;
273 break;
274
275 /* I2CINP Register */
276 case 0x00b00:
130751ee 277 val = ((s->i2cin & ~1) | eeprom24c0x_read());
5856de80
TS
278 break;
279
280 /* I2COE Register */
281 case 0x00b08:
282 val = s->i2coe;
283 break;
284
285 /* I2COUT Register */
286 case 0x00b10:
287 val = s->i2cout;
288 break;
289
290 /* I2CSEL Register */
291 case 0x00b18:
130751ee 292 val = s->i2csel;
5856de80
TS
293 break;
294
295 default:
296#if 0
3594c774 297 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
44cbbf18 298 addr);
5856de80
TS
299#endif
300 break;
301 }
302 return val;
303}
304
305static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
306 uint32_t val)
307{
308 MaltaFPGAState *s = opaque;
309 uint32_t saddr;
310
311 saddr = (addr & 0xfffff);
312
313 switch (saddr) {
314
315 /* SWITCH Register */
316 case 0x00200:
317 break;
318
319 /* JMPRS Register */
320 case 0x00210:
321 break;
322
323 /* LEDBAR Register */
324 /* XXX: implement a 8-LED array */
325 case 0x00408:
326 s->leds = val & 0xff;
327 break;
328
329 /* ASCIIWORD Register */
330 case 0x00410:
331 snprintf(s->display_text, 9, "%08X", val);
332 malta_fpga_update_display(s);
333 break;
334
335 /* ASCIIPOS0 to ASCIIPOS7 Registers */
336 case 0x00418:
337 case 0x00420:
338 case 0x00428:
339 case 0x00430:
340 case 0x00438:
341 case 0x00440:
342 case 0x00448:
343 case 0x00450:
344 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
345 malta_fpga_update_display(s);
346 break;
347
348 /* SOFTRES Register */
349 case 0x00500:
350 if (val == 0x42)
351 qemu_system_reset_request ();
352 break;
353
354 /* BRKRES Register */
355 case 0x00508:
356 s->brk = val & 0xff;
357 break;
358
b6dc7ebb 359 /* UART Registers are handled directly by the serial device */
a4bc3afc 360
5856de80
TS
361 /* GPOUT Register */
362 case 0x00a00:
363 s->gpout = val & 0xff;
364 break;
365
366 /* I2COE Register */
367 case 0x00b08:
368 s->i2coe = val & 0x03;
369 break;
370
371 /* I2COUT Register */
372 case 0x00b10:
130751ee
TS
373 eeprom24c0x_write(val & 0x02, val & 0x01);
374 s->i2cout = val;
5856de80
TS
375 break;
376
377 /* I2CSEL Register */
378 case 0x00b18:
130751ee 379 s->i2csel = val & 0x01;
5856de80
TS
380 break;
381
382 default:
383#if 0
3594c774 384 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
44cbbf18 385 addr);
5856de80
TS
386#endif
387 break;
388 }
389}
390
d60efc6b 391static CPUReadMemoryFunc * const malta_fpga_read[] = {
5856de80
TS
392 malta_fpga_readl,
393 malta_fpga_readl,
394 malta_fpga_readl
395};
396
d60efc6b 397static CPUWriteMemoryFunc * const malta_fpga_write[] = {
5856de80
TS
398 malta_fpga_writel,
399 malta_fpga_writel,
400 malta_fpga_writel
401};
402
9596ebb7 403static void malta_fpga_reset(void *opaque)
5856de80
TS
404{
405 MaltaFPGAState *s = opaque;
406
407 s->leds = 0x00;
408 s->brk = 0x0a;
409 s->gpout = 0x00;
130751ee 410 s->i2cin = 0x3;
5856de80
TS
411 s->i2coe = 0x0;
412 s->i2cout = 0x3;
413 s->i2csel = 0x1;
414
415 s->display_text[8] = '\0';
416 snprintf(s->display_text, 9, " ");
ceecf1d1
AJ
417}
418
ceecf1d1
AJ
419static void malta_fpga_led_init(CharDriverState *chr)
420{
421 qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
422 qemu_chr_printf(chr, "+--------+\r\n");
423 qemu_chr_printf(chr, "+ +\r\n");
424 qemu_chr_printf(chr, "+--------+\r\n");
425 qemu_chr_printf(chr, "\n");
426 qemu_chr_printf(chr, "Malta ASCII\r\n");
427 qemu_chr_printf(chr, "+--------+\r\n");
428 qemu_chr_printf(chr, "+ +\r\n");
429 qemu_chr_printf(chr, "+--------+\r\n");
5856de80
TS
430}
431
470d86b7 432static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
5856de80
TS
433{
434 MaltaFPGAState *s;
435 int malta;
436
437 s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
438
1eed09cb 439 malta = cpu_register_io_memory(malta_fpga_read,
5856de80 440 malta_fpga_write, s);
a4bc3afc 441
b6dc7ebb 442 cpu_register_physical_memory(base, 0x900, malta);
8da3ff18 443 /* 0xa00 is less than a page, so will still get the right offsets. */
b6dc7ebb 444 cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
5856de80 445
ceecf1d1
AJ
446 s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
447
470d86b7 448 s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1);
a4bc3afc 449
5856de80 450 malta_fpga_reset(s);
a08d4367 451 qemu_register_reset(malta_fpga_reset, s);
5856de80
TS
452
453 return s;
454}
455
456/* Audio support */
457#ifdef HAS_AUDIO
458static void audio_init (PCIBus *pci_bus)
459{
460 struct soundhw *c;
461 int audio_enabled = 0;
462
463 for (c = soundhw; !audio_enabled && c->name; ++c) {
464 audio_enabled = c->enabled;
465 }
466
467 if (audio_enabled) {
0d9acba8
PB
468 for (c = soundhw; c->name; ++c) {
469 if (c->enabled) {
22d83b14 470 c->init.init_pci(pci_bus);
5856de80
TS
471 }
472 }
473 }
474}
475#endif
476
477/* Network support */
5607c388 478static void network_init(void)
5856de80
TS
479{
480 int i;
5856de80
TS
481
482 for(i = 0; i < nb_nics; i++) {
cb457d76 483 NICInfo *nd = &nd_table[i];
5607c388 484 const char *default_devaddr = NULL;
cb457d76
AL
485
486 if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
5856de80 487 /* The malta board has a PCNet card using PCI SLOT 11 */
5607c388 488 default_devaddr = "0b";
cb457d76 489
5607c388 490 pci_nic_init(nd, "pcnet", default_devaddr);
5856de80
TS
491 }
492}
493
494/* ROM and pseudo bootloader
495
496 The following code implements a very very simple bootloader. It first
497 loads the registers a0 to a3 to the values expected by the OS, and
498 then jump at the kernel address.
499
500 The bootloader should pass the locations of the kernel arguments and
501 environment variables tables. Those tables contain the 32-bit address
502 of NULL terminated strings. The environment variables table should be
503 terminated by a NULL address.
504
505 For a simpler implementation, the number of kernel arguments is fixed
506 to two (the name of the kernel and the command line), and the two
507 tables are actually the same one.
508
509 The registers a0 to a3 should contain the following values:
510 a0 - number of kernel arguments
511 a1 - 32-bit address of the kernel arguments table
512 a2 - 32-bit address of the environment variables table
513 a3 - RAM size in bytes
514*/
515
d7585251
PB
516static void write_bootloader (CPUState *env, uint8_t *base,
517 int64_t kernel_entry)
5856de80
TS
518{
519 uint32_t *p;
520
521 /* Small bootloader */
d7585251 522 p = (uint32_t *)base;
26ea0918 523 stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */
3ddd0065 524 stl_raw(p++, 0x00000000); /* nop */
5856de80 525
26ea0918 526 /* YAMON service vector */
d7585251
PB
527 stl_raw(base + 0x500, 0xbfc00580); /* start: */
528 stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */
529 stl_raw(base + 0x520, 0xbfc00580); /* start: */
530 stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */
531 stl_raw(base + 0x534, 0xbfc00808); /* print: */
532 stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */
533 stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */
534 stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */
535 stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */
536 stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */
537 stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */
538 stl_raw(base + 0x550, 0xbfc00800); /* getchar: */
539 stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */
26ea0918
TS
540
541
5856de80 542 /* Second part of the bootloader */
d7585251 543 p = (uint32_t *) (base + 0x580);
d52fff71
TS
544 stl_raw(p++, 0x24040002); /* addiu a0, zero, 2 */
545 stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
471ea271 546 stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
3ddd0065 547 stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
471ea271 548 stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
3ddd0065
TS
549 stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
550 stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
7df526e3
TS
551 stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
552 stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
2802bfe3
TS
553
554 /* Load BAR registers as done by YAMON */
a0a8793e
TS
555 stl_raw(p++, 0x3c09b400); /* lui t1, 0xb400 */
556
557#ifdef TARGET_WORDS_BIGENDIAN
558 stl_raw(p++, 0x3c08df00); /* lui t0, 0xdf00 */
559#else
560 stl_raw(p++, 0x340800df); /* ori t0, r0, 0x00df */
561#endif
562 stl_raw(p++, 0xad280068); /* sw t0, 0x0068(t1) */
563
2802bfe3
TS
564 stl_raw(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
565
566#ifdef TARGET_WORDS_BIGENDIAN
567 stl_raw(p++, 0x3c08c000); /* lui t0, 0xc000 */
568#else
569 stl_raw(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */
570#endif
571 stl_raw(p++, 0xad280048); /* sw t0, 0x0048(t1) */
572#ifdef TARGET_WORDS_BIGENDIAN
573 stl_raw(p++, 0x3c084000); /* lui t0, 0x4000 */
574#else
575 stl_raw(p++, 0x34080040); /* ori t0, r0, 0x0040 */
576#endif
577 stl_raw(p++, 0xad280050); /* sw t0, 0x0050(t1) */
578
579#ifdef TARGET_WORDS_BIGENDIAN
580 stl_raw(p++, 0x3c088000); /* lui t0, 0x8000 */
581#else
582 stl_raw(p++, 0x34080080); /* ori t0, r0, 0x0080 */
583#endif
584 stl_raw(p++, 0xad280058); /* sw t0, 0x0058(t1) */
585#ifdef TARGET_WORDS_BIGENDIAN
586 stl_raw(p++, 0x3c083f00); /* lui t0, 0x3f00 */
587#else
588 stl_raw(p++, 0x3408003f); /* ori t0, r0, 0x003f */
589#endif
590 stl_raw(p++, 0xad280060); /* sw t0, 0x0060(t1) */
591
592#ifdef TARGET_WORDS_BIGENDIAN
593 stl_raw(p++, 0x3c08c100); /* lui t0, 0xc100 */
594#else
595 stl_raw(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */
596#endif
597 stl_raw(p++, 0xad280080); /* sw t0, 0x0080(t1) */
598#ifdef TARGET_WORDS_BIGENDIAN
599 stl_raw(p++, 0x3c085e00); /* lui t0, 0x5e00 */
600#else
601 stl_raw(p++, 0x3408005e); /* ori t0, r0, 0x005e */
602#endif
603 stl_raw(p++, 0xad280088); /* sw t0, 0x0088(t1) */
604
605 /* Jump to kernel code */
74287114
TS
606 stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
607 stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
3ddd0065
TS
608 stl_raw(p++, 0x03e00008); /* jr ra */
609 stl_raw(p++, 0x00000000); /* nop */
26ea0918
TS
610
611 /* YAMON subroutines */
d7585251 612 p = (uint32_t *) (base + 0x800);
26ea0918
TS
613 stl_raw(p++, 0x03e00008); /* jr ra */
614 stl_raw(p++, 0x24020000); /* li v0,0 */
615 /* 808 YAMON print */
616 stl_raw(p++, 0x03e06821); /* move t5,ra */
617 stl_raw(p++, 0x00805821); /* move t3,a0 */
618 stl_raw(p++, 0x00a05021); /* move t2,a1 */
619 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
620 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
621 stl_raw(p++, 0x10800005); /* beqz a0,834 */
622 stl_raw(p++, 0x00000000); /* nop */
623 stl_raw(p++, 0x0ff0021c); /* jal 870 */
624 stl_raw(p++, 0x00000000); /* nop */
625 stl_raw(p++, 0x08000205); /* j 814 */
626 stl_raw(p++, 0x00000000); /* nop */
627 stl_raw(p++, 0x01a00008); /* jr t5 */
628 stl_raw(p++, 0x01602021); /* move a0,t3 */
629 /* 0x83c YAMON print_count */
630 stl_raw(p++, 0x03e06821); /* move t5,ra */
631 stl_raw(p++, 0x00805821); /* move t3,a0 */
632 stl_raw(p++, 0x00a05021); /* move t2,a1 */
633 stl_raw(p++, 0x00c06021); /* move t4,a2 */
634 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
635 stl_raw(p++, 0x0ff0021c); /* jal 870 */
636 stl_raw(p++, 0x00000000); /* nop */
637 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
638 stl_raw(p++, 0x258cffff); /* addiu t4,t4,-1 */
639 stl_raw(p++, 0x1580fffa); /* bnez t4,84c */
640 stl_raw(p++, 0x00000000); /* nop */
641 stl_raw(p++, 0x01a00008); /* jr t5 */
642 stl_raw(p++, 0x01602021); /* move a0,t3 */
643 /* 0x870 */
644 stl_raw(p++, 0x3c08b800); /* lui t0,0xb400 */
645 stl_raw(p++, 0x350803f8); /* ori t0,t0,0x3f8 */
646 stl_raw(p++, 0x91090005); /* lbu t1,5(t0) */
647 stl_raw(p++, 0x00000000); /* nop */
648 stl_raw(p++, 0x31290040); /* andi t1,t1,0x40 */
649 stl_raw(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
650 stl_raw(p++, 0x00000000); /* nop */
651 stl_raw(p++, 0x03e00008); /* jr ra */
652 stl_raw(p++, 0xa1040000); /* sb a0,0(t0) */
653
5856de80
TS
654}
655
656static void prom_set(int index, const char *string, ...)
657{
d7585251
PB
658 char buf[ENVP_ENTRY_SIZE];
659 target_phys_addr_t p;
5856de80 660 va_list ap;
3ddd0065 661 int32_t table_addr;
5856de80
TS
662
663 if (index >= ENVP_NB_ENTRIES)
664 return;
665
d7585251 666 p = ENVP_ADDR + VIRT_TO_PHYS_ADDEND + index * 4;
5856de80
TS
667
668 if (string == NULL) {
d7585251 669 stl_phys(p, 0);
5856de80
TS
670 return;
671 }
672
d7585251 673 table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES
39303672
AJ
674 + index * ENVP_ENTRY_SIZE;
675 stl_phys(p, table_addr);
5856de80
TS
676
677 va_start(ap, string);
d7585251 678 vsnprintf(buf, ENVP_ENTRY_SIZE, string, ap);
5856de80 679 va_end(ap);
39303672 680 pstrcpy_targphys(table_addr + VIRT_TO_PHYS_ADDEND, ENVP_ENTRY_SIZE, buf);
5856de80
TS
681}
682
683/* Kernel */
684static int64_t load_kernel (CPUState *env)
685{
74287114 686 int64_t kernel_entry, kernel_low, kernel_high;
5856de80
TS
687 int index = 0;
688 long initrd_size;
74287114 689 ram_addr_t initrd_offset;
5856de80 690
7df526e3 691 if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
b55266b5
BS
692 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
693 (uint64_t *)&kernel_high) < 0) {
5856de80 694 fprintf(stderr, "qemu: could not load kernel '%s'\n",
7df526e3 695 loaderparams.kernel_filename);
acdf72bb 696 exit(1);
5856de80
TS
697 }
698
699 /* load initrd */
700 initrd_size = 0;
74287114 701 initrd_offset = 0;
7df526e3
TS
702 if (loaderparams.initrd_filename) {
703 initrd_size = get_image_size (loaderparams.initrd_filename);
74287114
TS
704 if (initrd_size > 0) {
705 initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
7df526e3 706 if (initrd_offset + initrd_size > ram_size) {
74287114
TS
707 fprintf(stderr,
708 "qemu: memory too small for initial ram disk '%s'\n",
7df526e3 709 loaderparams.initrd_filename);
74287114
TS
710 exit(1);
711 }
dcac9679
PB
712 initrd_size = load_image_targphys(loaderparams.initrd_filename,
713 initrd_offset,
714 ram_size - initrd_offset);
74287114 715 }
5856de80
TS
716 if (initrd_size == (target_ulong) -1) {
717 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
7df526e3 718 loaderparams.initrd_filename);
5856de80
TS
719 exit(1);
720 }
721 }
722
723 /* Store command line. */
7df526e3 724 prom_set(index++, loaderparams.kernel_filename);
5856de80 725 if (initrd_size > 0)
74287114
TS
726 prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
727 PHYS_TO_VIRT(initrd_offset), initrd_size,
7df526e3 728 loaderparams.kernel_cmdline);
5856de80 729 else
7df526e3 730 prom_set(index++, loaderparams.kernel_cmdline);
5856de80
TS
731
732 /* Setup minimum environment variables */
733 prom_set(index++, "memsize");
7df526e3 734 prom_set(index++, "%i", loaderparams.ram_size);
5856de80
TS
735 prom_set(index++, "modetty0");
736 prom_set(index++, "38400n8r");
737 prom_set(index++, NULL);
738
74287114 739 return kernel_entry;
5856de80
TS
740}
741
742static void main_cpu_reset(void *opaque)
743{
744 CPUState *env = opaque;
745 cpu_reset(env);
746
747 /* The bootload does not need to be rewritten as it is located in a
748 read only location. The kernel location and the arguments table
749 location does not change. */
7df526e3 750 if (loaderparams.kernel_filename) {
fb82fea0 751 env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
5856de80 752 load_kernel (env);
fb82fea0 753 }
5856de80
TS
754}
755
70705261 756static
fbe1b595 757void mips_malta_init (ram_addr_t ram_size,
3023f332 758 const char *boot_device,
5856de80 759 const char *kernel_filename, const char *kernel_cmdline,
94fc95cd 760 const char *initrd_filename, const char *cpu_model)
5856de80 761{
5cea8590 762 char *filename;
dcac9679 763 ram_addr_t ram_offset;
dcac9679 764 ram_addr_t bios_offset;
c8b153d7 765 target_long bios_size;
74287114 766 int64_t kernel_entry;
5856de80 767 PCIBus *pci_bus;
ae027ad3 768 ISADevice *isa_dev;
5856de80
TS
769 CPUState *env;
770 RTCState *rtc_state;
ded7ba9c 771 fdctrl_t *floppy_controller;
5856de80 772 MaltaFPGAState *malta_fpga;
d537cf6c 773 qemu_irq *i8259;
7b717336
TS
774 int piix4_devfn;
775 uint8_t *eeprom_buf;
776 i2c_bus *smbus;
777 int i;
751c6a17 778 DriveInfo *dinfo;
f455e98c 779 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
e4bcb14c 780 BlockDriverState *fd[MAX_FD];
c8b153d7
TS
781 int fl_idx = 0;
782 int fl_sectors = 0;
5856de80 783
ffabf037
AJ
784 /* Make sure the first 3 serial ports are associated with a device. */
785 for(i = 0; i < 3; i++) {
786 if (!serial_hds[i]) {
787 char label[32];
788 snprintf(label, sizeof(label), "serial%d", i);
789 serial_hds[i] = qemu_chr_open(label, "null", NULL);
790 }
791 }
792
33d68b5f
TS
793 /* init CPUs */
794 if (cpu_model == NULL) {
60aa19ab 795#ifdef TARGET_MIPS64
c9c1a064 796 cpu_model = "20Kc";
33d68b5f 797#else
1c32f43e 798 cpu_model = "24Kf";
33d68b5f
TS
799#endif
800 }
aaed909a
FB
801 env = cpu_init(cpu_model);
802 if (!env) {
803 fprintf(stderr, "Unable to find CPU definition\n");
804 exit(1);
805 }
a08d4367 806 qemu_register_reset(main_cpu_reset, env);
5856de80
TS
807
808 /* allocate RAM */
0ccff151
AJ
809 if (ram_size > (256 << 20)) {
810 fprintf(stderr,
811 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
812 ((unsigned int)ram_size / (1 << 20)));
813 exit(1);
814 }
dcac9679 815 ram_offset = qemu_ram_alloc(ram_size);
dcac9679
PB
816 bios_offset = qemu_ram_alloc(BIOS_SIZE);
817
818
819 cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
5856de80 820
c8b153d7 821 /* Map the bios at two physical locations, as on the real board. */
5856de80
TS
822 cpu_register_physical_memory(0x1e000000LL,
823 BIOS_SIZE, bios_offset | IO_MEM_ROM);
824 cpu_register_physical_memory(0x1fc00000LL,
825 BIOS_SIZE, bios_offset | IO_MEM_ROM);
826
070ce5ed 827 /* FPGA */
470d86b7 828 malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
070ce5ed 829
c8b153d7
TS
830 /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
831 if (kernel_filename) {
832 /* Write a small bootloader to the flash location. */
833 loaderparams.ram_size = ram_size;
834 loaderparams.kernel_filename = kernel_filename;
835 loaderparams.kernel_cmdline = kernel_cmdline;
836 loaderparams.initrd_filename = initrd_filename;
837 kernel_entry = load_kernel(env);
838 env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
d7585251 839 write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
c8b153d7 840 } else {
751c6a17
GH
841 dinfo = drive_get(IF_PFLASH, 0, fl_idx);
842 if (dinfo) {
c8b153d7
TS
843 /* Load firmware from flash. */
844 bios_size = 0x400000;
845 fl_sectors = bios_size >> 16;
846#ifdef DEBUG_BOARD_INIT
847 printf("Register parallel flash %d size " TARGET_FMT_lx " at "
848 "offset %08lx addr %08llx '%s' %x\n",
849 fl_idx, bios_size, bios_offset, 0x1e000000LL,
751c6a17 850 bdrv_get_device_name(dinfo->bdrv), fl_sectors);
c8b153d7
TS
851#endif
852 pflash_cfi01_register(0x1e000000LL, bios_offset,
751c6a17 853 dinfo->bdrv, 65536, fl_sectors,
c8b153d7
TS
854 4, 0x0000, 0x0000, 0x0000, 0x0000);
855 fl_idx++;
856 } else {
857 /* Load a BIOS image. */
858 if (bios_name == NULL)
859 bios_name = BIOS_FILENAME;
5cea8590
PB
860 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
861 if (filename) {
862 bios_size = load_image_targphys(filename, 0x1fc00000LL,
863 BIOS_SIZE);
864 qemu_free(filename);
865 } else {
866 bios_size = -1;
867 }
c8b153d7
TS
868 if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
869 fprintf(stderr,
870 "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
5cea8590 871 bios_name);
c8b153d7
TS
872 exit(1);
873 }
070ce5ed 874 }
3187ef03
TS
875 /* In little endian mode the 32bit words in the bios are swapped,
876 a neat trick which allows bi-endian firmware. */
877#ifndef TARGET_WORDS_BIGENDIAN
878 {
d7585251
PB
879 uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
880 uint32_t *end = addr + bios_size;
881 while (addr < end) {
882 bswap32s(addr);
3187ef03
TS
883 }
884 }
885#endif
070ce5ed
TS
886 }
887
5856de80
TS
888 /* Board ID = 0x420 (Malta Board with CoreLV)
889 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
890 map to the board ID. */
d7585251 891 stl_phys(0x1fc00010LL, 0x00000420);
5856de80
TS
892
893 /* Init internal devices */
d537cf6c 894 cpu_mips_irq_init_cpu(env);
5856de80 895 cpu_mips_clock_init(env);
5856de80 896
5856de80 897 /* Interrupt controller */
d537cf6c
PB
898 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
899 i8259 = i8259_init(env->irq[2]);
5856de80
TS
900
901 /* Northbridge */
d537cf6c 902 pci_bus = pci_gt64120_init(i8259);
5856de80
TS
903
904 /* Southbridge */
e4bcb14c
TS
905
906 if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
907 fprintf(stderr, "qemu: too many IDE bus\n");
908 exit(1);
909 }
910
911 for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
f455e98c 912 hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
e4bcb14c
TS
913 }
914
7b717336 915 piix4_devfn = piix4_init(pci_bus, 80);
ae027ad3
SW
916 isa_bus_irqs(i8259);
917 pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
afcc3cdf 918 usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
ae027ad3 919 smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9));
7b717336
TS
920 eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
921 for (i = 0; i < 8; i++) {
922 /* TODO: Populate SPD eeprom data. */
1ea96673 923 DeviceState *eeprom;
02e2da45 924 eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
ee6847d1
GH
925 qdev_prop_set_uint32(eeprom, "address", 0x50 + i);
926 qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
1ea96673 927 qdev_init(eeprom);
7b717336 928 }
ae027ad3 929 pit = pit_init(0x40, isa_reserve_irq(0));
5856de80
TS
930 DMA_init(0);
931
932 /* Super I/O */
2e15e23b 933 isa_dev = isa_create_simple("i8042");
ae027ad3 934
32e0c826 935 rtc_state = rtc_init(2000);
ae027ad3
SW
936 serial_init(0x3f8, isa_reserve_irq(4), 115200, serial_hds[0]);
937 serial_init(0x2f8, isa_reserve_irq(3), 115200, serial_hds[1]);
7bcc17dc 938 if (parallel_hds[0])
ae027ad3 939 parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]);
e4bcb14c 940 for(i = 0; i < MAX_FD; i++) {
751c6a17
GH
941 dinfo = drive_get(IF_FLOPPY, 0, i);
942 fd[i] = dinfo ? dinfo->bdrv : NULL;
e4bcb14c 943 }
86c86157 944 floppy_controller = fdctrl_init_isa(fd);
5856de80
TS
945
946 /* Sound card */
947#ifdef HAS_AUDIO
948 audio_init(pci_bus);
949#endif
950
951 /* Network card */
5607c388 952 network_init();
11f29511
TS
953
954 /* Optional PCI video card */
1f605a76 955 if (cirrus_vga_enabled) {
fbe1b595 956 pci_cirrus_vga_init(pci_bus);
1f605a76 957 } else if (vmsvga_enabled) {
fbe1b595 958 pci_vmsvga_init(pci_bus);
1f605a76 959 } else if (std_vga_enabled) {
fbe1b595 960 pci_vga_init(pci_bus, 0, 0);
1f605a76 961 }
5856de80
TS
962}
963
f80f9ec9 964static QEMUMachine mips_malta_machine = {
eec2743e
TS
965 .name = "malta",
966 .desc = "MIPS Malta Core LV",
967 .init = mips_malta_init,
0c257437 968 .is_default = 1,
5856de80 969};
f80f9ec9
AL
970
971static void mips_malta_machine_init(void)
972{
973 qemu_register_machine(&mips_malta_machine);
974}
975
976machine_init(mips_malta_machine_init);