]> git.proxmox.com Git - qemu.git/blame - hw/mips_malta.c
Merge remote branch 'qemu-kvm/uq/master' into staging
[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 33#include "mips.h"
b970ea8f 34#include "mips_cpudevs.h"
87ecb68b 35#include "pci.h"
18e08a55
MT
36#include "usb-uhci.h"
37#include "vmware_vga.h"
87ecb68b
PB
38#include "qemu-char.h"
39#include "sysemu.h"
40#include "audio/audio.h"
41#include "boards.h"
3b3fb322 42#include "qemu-log.h"
bba831e8 43#include "mips-bios.h"
977e1244 44#include "ide.h"
ca20cf32
BS
45#include "loader.h"
46#include "elf.h"
1d914fa0 47#include "mc146818rtc.h"
5856de80 48
c8b153d7
TS
49//#define DEBUG_BOARD_INIT
50
409dbce5 51#define ENVP_ADDR 0x80002000l
5856de80
TS
52#define ENVP_NB_ENTRIES 16
53#define ENVP_ENTRY_SIZE 256
54
e4bcb14c
TS
55#define MAX_IDE_BUS 2
56
5856de80
TS
57typedef struct {
58 uint32_t leds;
59 uint32_t brk;
60 uint32_t gpout;
130751ee 61 uint32_t i2cin;
5856de80
TS
62 uint32_t i2coe;
63 uint32_t i2cout;
64 uint32_t i2csel;
65 CharDriverState *display;
66 char display_text[9];
a4bc3afc 67 SerialState *uart;
5856de80
TS
68} MaltaFPGAState;
69
70static PITState *pit;
71
7df526e3
TS
72static struct _loaderparams {
73 int ram_size;
74 const char *kernel_filename;
75 const char *kernel_cmdline;
76 const char *initrd_filename;
77} loaderparams;
78
5856de80
TS
79/* Malta FPGA */
80static void malta_fpga_update_display(void *opaque)
81{
82 char leds_text[9];
83 int i;
84 MaltaFPGAState *s = opaque;
85
07cf0ba0
TS
86 for (i = 7 ; i >= 0 ; i--) {
87 if (s->leds & (1 << i))
88 leds_text[i] = '#';
89 else
90 leds_text[i] = ' ';
87ee1669 91 }
07cf0ba0
TS
92 leds_text[8] = '\0';
93
94 qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
95 qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
5856de80
TS
96}
97
130751ee
TS
98/*
99 * EEPROM 24C01 / 24C02 emulation.
100 *
101 * Emulation for serial EEPROMs:
102 * 24C01 - 1024 bit (128 x 8)
103 * 24C02 - 2048 bit (256 x 8)
104 *
105 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
106 */
107
108//~ #define DEBUG
109
110#if defined(DEBUG)
001faf32 111# define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
130751ee 112#else
001faf32 113# define logout(fmt, ...) ((void)0)
130751ee
TS
114#endif
115
c227f099 116struct _eeprom24c0x_t {
130751ee
TS
117 uint8_t tick;
118 uint8_t address;
119 uint8_t command;
120 uint8_t ack;
121 uint8_t scl;
122 uint8_t sda;
123 uint8_t data;
124 //~ uint16_t size;
125 uint8_t contents[256];
126};
127
c227f099 128typedef struct _eeprom24c0x_t eeprom24c0x_t;
130751ee 129
c227f099 130static eeprom24c0x_t eeprom = {
284b08f1 131 .contents = {
130751ee
TS
132 /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
133 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
134 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
135 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
136 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
137 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
140 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
145 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
148 },
149};
150
a5f1b965 151static uint8_t eeprom24c0x_read(void)
130751ee
TS
152{
153 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
154 eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
155 return eeprom.sda;
156}
157
158static void eeprom24c0x_write(int scl, int sda)
159{
160 if (eeprom.scl && scl && (eeprom.sda != sda)) {
161 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
162 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
163 if (!sda) {
164 eeprom.tick = 1;
165 eeprom.command = 0;
166 }
167 } else if (eeprom.tick == 0 && !eeprom.ack) {
168 /* Waiting for start. */
169 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
170 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
171 } else if (!eeprom.scl && scl) {
172 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
173 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
174 if (eeprom.ack) {
175 logout("\ti2c ack bit = 0\n");
176 sda = 0;
177 eeprom.ack = 0;
178 } else if (eeprom.sda == sda) {
179 uint8_t bit = (sda != 0);
180 logout("\ti2c bit = %d\n", bit);
181 if (eeprom.tick < 9) {
182 eeprom.command <<= 1;
183 eeprom.command += bit;
184 eeprom.tick++;
185 if (eeprom.tick == 9) {
186 logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
187 eeprom.ack = 1;
188 }
189 } else if (eeprom.tick < 17) {
190 if (eeprom.command & 1) {
191 sda = ((eeprom.data & 0x80) != 0);
192 }
193 eeprom.address <<= 1;
194 eeprom.address += bit;
195 eeprom.tick++;
196 eeprom.data <<= 1;
197 if (eeprom.tick == 17) {
198 eeprom.data = eeprom.contents[eeprom.address];
199 logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
200 eeprom.ack = 1;
201 eeprom.tick = 0;
202 }
203 } else if (eeprom.tick >= 17) {
204 sda = 0;
205 }
206 } else {
207 logout("\tsda changed with raising scl\n");
208 }
209 } else {
210 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
211 }
212 eeprom.scl = scl;
213 eeprom.sda = sda;
214}
215
c227f099 216static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
5856de80
TS
217{
218 MaltaFPGAState *s = opaque;
219 uint32_t val = 0;
220 uint32_t saddr;
221
222 saddr = (addr & 0xfffff);
223
224 switch (saddr) {
225
226 /* SWITCH Register */
227 case 0x00200:
228 val = 0x00000000; /* All switches closed */
593c0d10 229 break;
5856de80
TS
230
231 /* STATUS Register */
232 case 0x00208:
233#ifdef TARGET_WORDS_BIGENDIAN
234 val = 0x00000012;
235#else
236 val = 0x00000010;
237#endif
238 break;
239
240 /* JMPRS Register */
241 case 0x00210:
242 val = 0x00;
243 break;
244
245 /* LEDBAR Register */
246 case 0x00408:
247 val = s->leds;
248 break;
249
250 /* BRKRES Register */
251 case 0x00508:
252 val = s->brk;
253 break;
254
b6dc7ebb 255 /* UART Registers are handled directly by the serial device */
a4bc3afc 256
5856de80
TS
257 /* GPOUT Register */
258 case 0x00a00:
259 val = s->gpout;
260 break;
261
262 /* XXX: implement a real I2C controller */
263
264 /* GPINP Register */
265 case 0x00a08:
266 /* IN = OUT until a real I2C control is implemented */
267 if (s->i2csel)
268 val = s->i2cout;
269 else
270 val = 0x00;
271 break;
272
273 /* I2CINP Register */
274 case 0x00b00:
130751ee 275 val = ((s->i2cin & ~1) | eeprom24c0x_read());
5856de80
TS
276 break;
277
278 /* I2COE Register */
279 case 0x00b08:
280 val = s->i2coe;
281 break;
282
283 /* I2COUT Register */
284 case 0x00b10:
285 val = s->i2cout;
286 break;
287
288 /* I2CSEL Register */
289 case 0x00b18:
130751ee 290 val = s->i2csel;
5856de80
TS
291 break;
292
293 default:
294#if 0
3594c774 295 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
593c0d10 296 addr);
5856de80
TS
297#endif
298 break;
299 }
300 return val;
301}
302
c227f099 303static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
5856de80
TS
304 uint32_t val)
305{
306 MaltaFPGAState *s = opaque;
307 uint32_t saddr;
308
309 saddr = (addr & 0xfffff);
310
311 switch (saddr) {
312
313 /* SWITCH Register */
314 case 0x00200:
315 break;
316
317 /* JMPRS Register */
318 case 0x00210:
319 break;
320
321 /* LEDBAR Register */
322 /* XXX: implement a 8-LED array */
323 case 0x00408:
324 s->leds = val & 0xff;
325 break;
326
327 /* ASCIIWORD Register */
328 case 0x00410:
329 snprintf(s->display_text, 9, "%08X", val);
330 malta_fpga_update_display(s);
331 break;
332
333 /* ASCIIPOS0 to ASCIIPOS7 Registers */
334 case 0x00418:
335 case 0x00420:
336 case 0x00428:
337 case 0x00430:
338 case 0x00438:
339 case 0x00440:
340 case 0x00448:
341 case 0x00450:
342 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
343 malta_fpga_update_display(s);
344 break;
345
346 /* SOFTRES Register */
347 case 0x00500:
348 if (val == 0x42)
349 qemu_system_reset_request ();
350 break;
351
352 /* BRKRES Register */
353 case 0x00508:
354 s->brk = val & 0xff;
355 break;
356
b6dc7ebb 357 /* UART Registers are handled directly by the serial device */
a4bc3afc 358
5856de80
TS
359 /* GPOUT Register */
360 case 0x00a00:
361 s->gpout = val & 0xff;
362 break;
363
364 /* I2COE Register */
365 case 0x00b08:
366 s->i2coe = val & 0x03;
367 break;
368
369 /* I2COUT Register */
370 case 0x00b10:
130751ee
TS
371 eeprom24c0x_write(val & 0x02, val & 0x01);
372 s->i2cout = val;
5856de80
TS
373 break;
374
375 /* I2CSEL Register */
376 case 0x00b18:
130751ee 377 s->i2csel = val & 0x01;
5856de80
TS
378 break;
379
380 default:
381#if 0
3594c774 382 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
593c0d10 383 addr);
5856de80
TS
384#endif
385 break;
386 }
387}
388
d60efc6b 389static CPUReadMemoryFunc * const malta_fpga_read[] = {
5856de80
TS
390 malta_fpga_readl,
391 malta_fpga_readl,
392 malta_fpga_readl
393};
394
d60efc6b 395static CPUWriteMemoryFunc * const malta_fpga_write[] = {
5856de80
TS
396 malta_fpga_writel,
397 malta_fpga_writel,
398 malta_fpga_writel
399};
400
9596ebb7 401static void malta_fpga_reset(void *opaque)
5856de80
TS
402{
403 MaltaFPGAState *s = opaque;
404
405 s->leds = 0x00;
406 s->brk = 0x0a;
407 s->gpout = 0x00;
130751ee 408 s->i2cin = 0x3;
5856de80
TS
409 s->i2coe = 0x0;
410 s->i2cout = 0x3;
411 s->i2csel = 0x1;
412
413 s->display_text[8] = '\0';
414 snprintf(s->display_text, 9, " ");
ceecf1d1
AJ
415}
416
ceecf1d1
AJ
417static void malta_fpga_led_init(CharDriverState *chr)
418{
419 qemu_chr_printf(chr, "\e[HMalta LEDBAR\r\n");
420 qemu_chr_printf(chr, "+--------+\r\n");
421 qemu_chr_printf(chr, "+ +\r\n");
422 qemu_chr_printf(chr, "+--------+\r\n");
423 qemu_chr_printf(chr, "\n");
424 qemu_chr_printf(chr, "Malta ASCII\r\n");
425 qemu_chr_printf(chr, "+--------+\r\n");
426 qemu_chr_printf(chr, "+ +\r\n");
427 qemu_chr_printf(chr, "+--------+\r\n");
5856de80
TS
428}
429
c227f099 430static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
5856de80
TS
431{
432 MaltaFPGAState *s;
433 int malta;
434
435 s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
436
1eed09cb 437 malta = cpu_register_io_memory(malta_fpga_read,
5856de80 438 malta_fpga_write, s);
a4bc3afc 439
b6dc7ebb 440 cpu_register_physical_memory(base, 0x900, malta);
8da3ff18 441 /* 0xa00 is less than a page, so will still get the right offsets. */
b6dc7ebb 442 cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
5856de80 443
ceecf1d1
AJ
444 s->display = qemu_chr_open("fpga", "vc:320x200", malta_fpga_led_init);
445
2d48377a
BS
446#ifdef TARGET_WORDS_BIGENDIAN
447 s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 1);
448#else
449 s->uart = serial_mm_init(base + 0x900, 3, uart_irq, 230400, uart_chr, 1, 0);
450#endif
a4bc3afc 451
5856de80 452 malta_fpga_reset(s);
a08d4367 453 qemu_register_reset(malta_fpga_reset, s);
5856de80
TS
454
455 return s;
456}
457
458/* Audio support */
5856de80
TS
459static void audio_init (PCIBus *pci_bus)
460{
461 struct soundhw *c;
462 int audio_enabled = 0;
463
464 for (c = soundhw; !audio_enabled && c->name; ++c) {
465 audio_enabled = c->enabled;
466 }
467
468 if (audio_enabled) {
0d9acba8
PB
469 for (c = soundhw; c->name; ++c) {
470 if (c->enabled) {
22d83b14 471 c->init.init_pci(pci_bus);
5856de80
TS
472 }
473 }
474 }
475}
5856de80
TS
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
07caea31 490 pci_nic_init_nofail(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
c938ada2 656static void prom_set(uint32_t* prom_buf, int index, const char *string, ...)
5856de80
TS
657{
658 va_list ap;
3ddd0065 659 int32_t table_addr;
5856de80
TS
660
661 if (index >= ENVP_NB_ENTRIES)
662 return;
663
5856de80 664 if (string == NULL) {
c938ada2 665 prom_buf[index] = 0;
5856de80
TS
666 return;
667 }
668
c938ada2
AJ
669 table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
670 prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
5856de80
TS
671
672 va_start(ap, string);
c938ada2 673 vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
5856de80
TS
674 va_end(ap);
675}
676
677/* Kernel */
e16ad5b0 678static int64_t load_kernel (void)
5856de80 679{
409dbce5 680 int64_t kernel_entry, kernel_high;
5856de80 681 long initrd_size;
c227f099 682 ram_addr_t initrd_offset;
ca20cf32 683 int big_endian;
c938ada2
AJ
684 uint32_t *prom_buf;
685 long prom_size;
686 int prom_index = 0;
ca20cf32
BS
687
688#ifdef TARGET_WORDS_BIGENDIAN
689 big_endian = 1;
690#else
691 big_endian = 0;
692#endif
5856de80 693
409dbce5
AJ
694 if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
695 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
696 big_endian, ELF_MACHINE, 1) < 0) {
5856de80 697 fprintf(stderr, "qemu: could not load kernel '%s'\n",
7df526e3 698 loaderparams.kernel_filename);
acdf72bb 699 exit(1);
5856de80
TS
700 }
701
702 /* load initrd */
703 initrd_size = 0;
74287114 704 initrd_offset = 0;
7df526e3
TS
705 if (loaderparams.initrd_filename) {
706 initrd_size = get_image_size (loaderparams.initrd_filename);
74287114
TS
707 if (initrd_size > 0) {
708 initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
7df526e3 709 if (initrd_offset + initrd_size > ram_size) {
74287114
TS
710 fprintf(stderr,
711 "qemu: memory too small for initial ram disk '%s'\n",
7df526e3 712 loaderparams.initrd_filename);
74287114
TS
713 exit(1);
714 }
dcac9679
PB
715 initrd_size = load_image_targphys(loaderparams.initrd_filename,
716 initrd_offset,
717 ram_size - initrd_offset);
74287114 718 }
5856de80
TS
719 if (initrd_size == (target_ulong) -1) {
720 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
7df526e3 721 loaderparams.initrd_filename);
5856de80
TS
722 exit(1);
723 }
724 }
725
c938ada2
AJ
726 /* Setup prom parameters. */
727 prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
728 prom_buf = qemu_malloc(prom_size);
729
730 prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
731 if (initrd_size > 0) {
409dbce5
AJ
732 prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
733 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
7df526e3 734 loaderparams.kernel_cmdline);
c938ada2
AJ
735 } else {
736 prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
737 }
738
739 prom_set(prom_buf, prom_index++, "memsize");
740 prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
741 prom_set(prom_buf, prom_index++, "modetty0");
742 prom_set(prom_buf, prom_index++, "38400n8r");
743 prom_set(prom_buf, prom_index++, NULL);
744
745 rom_add_blob_fixed("prom", prom_buf, prom_size,
409dbce5 746 cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
5856de80 747
74287114 748 return kernel_entry;
5856de80
TS
749}
750
751static void main_cpu_reset(void *opaque)
752{
753 CPUState *env = opaque;
754 cpu_reset(env);
755
5c43485f 756 /* The bootloader does not need to be rewritten as it is located in a
5856de80
TS
757 read only location. The kernel location and the arguments table
758 location does not change. */
7df526e3 759 if (loaderparams.kernel_filename) {
fb82fea0 760 env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
fb82fea0 761 }
5856de80
TS
762}
763
4556bd8b
BS
764static void cpu_request_exit(void *opaque, int irq, int level)
765{
766 CPUState *env = cpu_single_env;
767
768 if (env && level) {
769 cpu_exit(env);
770 }
771}
772
70705261 773static
c227f099 774void mips_malta_init (ram_addr_t ram_size,
3023f332 775 const char *boot_device,
5856de80 776 const char *kernel_filename, const char *kernel_cmdline,
94fc95cd 777 const char *initrd_filename, const char *cpu_model)
5856de80 778{
5cea8590 779 char *filename;
c227f099
AL
780 ram_addr_t ram_offset;
781 ram_addr_t bios_offset;
c8b153d7 782 target_long bios_size;
74287114 783 int64_t kernel_entry;
5856de80 784 PCIBus *pci_bus;
ae027ad3 785 ISADevice *isa_dev;
5856de80 786 CPUState *env;
1d914fa0 787 ISADevice *rtc_state;
5c02c033 788 FDCtrl *floppy_controller;
5856de80 789 MaltaFPGAState *malta_fpga;
d537cf6c 790 qemu_irq *i8259;
4556bd8b 791 qemu_irq *cpu_exit_irq;
7b717336
TS
792 int piix4_devfn;
793 uint8_t *eeprom_buf;
794 i2c_bus *smbus;
795 int i;
751c6a17 796 DriveInfo *dinfo;
f455e98c 797 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
fd8014e1 798 DriveInfo *fd[MAX_FD];
c8b153d7
TS
799 int fl_idx = 0;
800 int fl_sectors = 0;
3d08ff69 801 int be;
5856de80 802
ffabf037
AJ
803 /* Make sure the first 3 serial ports are associated with a device. */
804 for(i = 0; i < 3; i++) {
805 if (!serial_hds[i]) {
806 char label[32];
807 snprintf(label, sizeof(label), "serial%d", i);
808 serial_hds[i] = qemu_chr_open(label, "null", NULL);
809 }
810 }
811
33d68b5f
TS
812 /* init CPUs */
813 if (cpu_model == NULL) {
60aa19ab 814#ifdef TARGET_MIPS64
c9c1a064 815 cpu_model = "20Kc";
33d68b5f 816#else
1c32f43e 817 cpu_model = "24Kf";
33d68b5f
TS
818#endif
819 }
aaed909a
FB
820 env = cpu_init(cpu_model);
821 if (!env) {
822 fprintf(stderr, "Unable to find CPU definition\n");
823 exit(1);
824 }
a08d4367 825 qemu_register_reset(main_cpu_reset, env);
5856de80
TS
826
827 /* allocate RAM */
0ccff151
AJ
828 if (ram_size > (256 << 20)) {
829 fprintf(stderr,
830 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
831 ((unsigned int)ram_size / (1 << 20)));
832 exit(1);
833 }
1724f049
AW
834 ram_offset = qemu_ram_alloc(NULL, "mips_malta.ram", ram_size);
835 bios_offset = qemu_ram_alloc(NULL, "mips_malta.bios", BIOS_SIZE);
dcac9679
PB
836
837
838 cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
5856de80 839
c8b153d7 840 /* Map the bios at two physical locations, as on the real board. */
5856de80
TS
841 cpu_register_physical_memory(0x1e000000LL,
842 BIOS_SIZE, bios_offset | IO_MEM_ROM);
843 cpu_register_physical_memory(0x1fc00000LL,
844 BIOS_SIZE, bios_offset | IO_MEM_ROM);
845
3d08ff69
BS
846#ifdef TARGET_WORDS_BIGENDIAN
847 be = 1;
848#else
849 be = 0;
850#endif
070ce5ed 851 /* FPGA */
470d86b7 852 malta_fpga = malta_fpga_init(0x1f000000LL, env->irq[2], serial_hds[2]);
070ce5ed 853
c8b153d7
TS
854 /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
855 if (kernel_filename) {
856 /* Write a small bootloader to the flash location. */
857 loaderparams.ram_size = ram_size;
858 loaderparams.kernel_filename = kernel_filename;
859 loaderparams.kernel_cmdline = kernel_cmdline;
860 loaderparams.initrd_filename = initrd_filename;
e16ad5b0 861 kernel_entry = load_kernel();
d7585251 862 write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
c8b153d7 863 } else {
751c6a17
GH
864 dinfo = drive_get(IF_PFLASH, 0, fl_idx);
865 if (dinfo) {
c8b153d7
TS
866 /* Load firmware from flash. */
867 bios_size = 0x400000;
868 fl_sectors = bios_size >> 16;
869#ifdef DEBUG_BOARD_INIT
870 printf("Register parallel flash %d size " TARGET_FMT_lx " at "
871 "offset %08lx addr %08llx '%s' %x\n",
872 fl_idx, bios_size, bios_offset, 0x1e000000LL,
751c6a17 873 bdrv_get_device_name(dinfo->bdrv), fl_sectors);
c8b153d7
TS
874#endif
875 pflash_cfi01_register(0x1e000000LL, bios_offset,
751c6a17 876 dinfo->bdrv, 65536, fl_sectors,
3d08ff69 877 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
c8b153d7
TS
878 fl_idx++;
879 } else {
880 /* Load a BIOS image. */
881 if (bios_name == NULL)
882 bios_name = BIOS_FILENAME;
5cea8590
PB
883 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
884 if (filename) {
885 bios_size = load_image_targphys(filename, 0x1fc00000LL,
886 BIOS_SIZE);
887 qemu_free(filename);
888 } else {
889 bios_size = -1;
890 }
c8b153d7
TS
891 if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
892 fprintf(stderr,
893 "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
5cea8590 894 bios_name);
c8b153d7
TS
895 exit(1);
896 }
070ce5ed 897 }
3187ef03
TS
898 /* In little endian mode the 32bit words in the bios are swapped,
899 a neat trick which allows bi-endian firmware. */
900#ifndef TARGET_WORDS_BIGENDIAN
901 {
d7585251
PB
902 uint32_t *addr = qemu_get_ram_ptr(bios_offset);;
903 uint32_t *end = addr + bios_size;
904 while (addr < end) {
905 bswap32s(addr);
3187ef03
TS
906 }
907 }
908#endif
070ce5ed
TS
909 }
910
5856de80
TS
911 /* Board ID = 0x420 (Malta Board with CoreLV)
912 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
913 map to the board ID. */
d7585251 914 stl_phys(0x1fc00010LL, 0x00000420);
5856de80
TS
915
916 /* Init internal devices */
d537cf6c 917 cpu_mips_irq_init_cpu(env);
5856de80 918 cpu_mips_clock_init(env);
5856de80 919
5856de80 920 /* Interrupt controller */
d537cf6c
PB
921 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
922 i8259 = i8259_init(env->irq[2]);
5856de80
TS
923
924 /* Northbridge */
d537cf6c 925 pci_bus = pci_gt64120_init(i8259);
5856de80
TS
926
927 /* Southbridge */
e4bcb14c
TS
928
929 if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
930 fprintf(stderr, "qemu: too many IDE bus\n");
931 exit(1);
932 }
933
934 for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
f455e98c 935 hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
e4bcb14c
TS
936 }
937
7b717336 938 piix4_devfn = piix4_init(pci_bus, 80);
ae027ad3
SW
939 isa_bus_irqs(i8259);
940 pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
afcc3cdf 941 usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
53b67b30
BS
942 smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_reserve_irq(9),
943 NULL, NULL, 0);
7b717336
TS
944 eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
945 for (i = 0; i < 8; i++) {
946 /* TODO: Populate SPD eeprom data. */
1ea96673 947 DeviceState *eeprom;
02e2da45 948 eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
5b7f5327 949 qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
ee6847d1 950 qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
e23a1b33 951 qdev_init_nofail(eeprom);
7b717336 952 }
ae027ad3 953 pit = pit_init(0x40, isa_reserve_irq(0));
4556bd8b
BS
954 cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
955 DMA_init(0, cpu_exit_irq);
5856de80
TS
956
957 /* Super I/O */
2e15e23b 958 isa_dev = isa_create_simple("i8042");
ae027ad3 959
7d932dfd 960 rtc_state = rtc_init(2000, NULL);
ac0be998
GH
961 serial_isa_init(0, serial_hds[0]);
962 serial_isa_init(1, serial_hds[1]);
7bcc17dc 963 if (parallel_hds[0])
021f0674 964 parallel_init(0, parallel_hds[0]);
e4bcb14c 965 for(i = 0; i < MAX_FD; i++) {
fd8014e1 966 fd[i] = drive_get(IF_FLOPPY, 0, i);
e4bcb14c 967 }
86c86157 968 floppy_controller = fdctrl_init_isa(fd);
5856de80
TS
969
970 /* Sound card */
5856de80 971 audio_init(pci_bus);
5856de80
TS
972
973 /* Network card */
5607c388 974 network_init();
11f29511
TS
975
976 /* Optional PCI video card */
1f605a76 977 if (cirrus_vga_enabled) {
fbe1b595 978 pci_cirrus_vga_init(pci_bus);
1f605a76 979 } else if (vmsvga_enabled) {
fbe1b595 980 pci_vmsvga_init(pci_bus);
1f605a76 981 } else if (std_vga_enabled) {
fbe1b595 982 pci_vga_init(pci_bus, 0, 0);
1f605a76 983 }
5856de80
TS
984}
985
f80f9ec9 986static QEMUMachine mips_malta_machine = {
eec2743e
TS
987 .name = "malta",
988 .desc = "MIPS Malta Core LV",
989 .init = mips_malta_init,
0c257437 990 .is_default = 1,
5856de80 991};
f80f9ec9
AL
992
993static void mips_malta_machine_init(void)
994{
995 qemu_register_machine(&mips_malta_machine);
996}
997
998machine_init(mips_malta_machine_init);