]> git.proxmox.com Git - mirror_qemu.git/blame - hw/mips_malta.c
usb: the big rename
[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 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"
0dfa5ef9 40#include "arch_init.h"
87ecb68b 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"
b1277b03 48#include "i8254.h"
2446333c 49#include "blockdev.h"
cfe5f011 50#include "exec-memory.h"
e9b40fd3 51#include "sysbus.h" /* SysBusDevice */
5856de80 52
c8b153d7
TS
53//#define DEBUG_BOARD_INIT
54
409dbce5 55#define ENVP_ADDR 0x80002000l
5856de80
TS
56#define ENVP_NB_ENTRIES 16
57#define ENVP_ENTRY_SIZE 256
58
e4bcb14c
TS
59#define MAX_IDE_BUS 2
60
5856de80 61typedef struct {
ea85df72
AK
62 MemoryRegion iomem;
63 MemoryRegion iomem_lo; /* 0 - 0x900 */
64 MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
5856de80
TS
65 uint32_t leds;
66 uint32_t brk;
67 uint32_t gpout;
130751ee 68 uint32_t i2cin;
5856de80
TS
69 uint32_t i2coe;
70 uint32_t i2cout;
71 uint32_t i2csel;
72 CharDriverState *display;
73 char display_text[9];
a4bc3afc 74 SerialState *uart;
5856de80
TS
75} MaltaFPGAState;
76
e9b40fd3
SW
77typedef struct {
78 SysBusDevice busdev;
79 qemu_irq *i8259;
80} MaltaState;
81
64d7e9a4 82static ISADevice *pit;
5856de80 83
7df526e3
TS
84static struct _loaderparams {
85 int ram_size;
86 const char *kernel_filename;
87 const char *kernel_cmdline;
88 const char *initrd_filename;
89} loaderparams;
90
5856de80
TS
91/* Malta FPGA */
92static void malta_fpga_update_display(void *opaque)
93{
94 char leds_text[9];
95 int i;
96 MaltaFPGAState *s = opaque;
97
07cf0ba0
TS
98 for (i = 7 ; i >= 0 ; i--) {
99 if (s->leds & (1 << i))
100 leds_text[i] = '#';
101 else
102 leds_text[i] = ' ';
87ee1669 103 }
07cf0ba0
TS
104 leds_text[8] = '\0';
105
e7e71b0e
AL
106 qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
107 qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
5856de80
TS
108}
109
130751ee
TS
110/*
111 * EEPROM 24C01 / 24C02 emulation.
112 *
113 * Emulation for serial EEPROMs:
114 * 24C01 - 1024 bit (128 x 8)
115 * 24C02 - 2048 bit (256 x 8)
116 *
117 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
118 */
119
120//~ #define DEBUG
121
122#if defined(DEBUG)
001faf32 123# define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
130751ee 124#else
001faf32 125# define logout(fmt, ...) ((void)0)
130751ee
TS
126#endif
127
c227f099 128struct _eeprom24c0x_t {
130751ee
TS
129 uint8_t tick;
130 uint8_t address;
131 uint8_t command;
132 uint8_t ack;
133 uint8_t scl;
134 uint8_t sda;
135 uint8_t data;
136 //~ uint16_t size;
137 uint8_t contents[256];
138};
139
c227f099 140typedef struct _eeprom24c0x_t eeprom24c0x_t;
130751ee 141
c227f099 142static eeprom24c0x_t eeprom = {
284b08f1 143 .contents = {
130751ee
TS
144 /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
145 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
146 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
147 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
148 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
149 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
152 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
153 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
154 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
155 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
156 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
157 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
158 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
159 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
160 },
161};
162
a5f1b965 163static uint8_t eeprom24c0x_read(void)
130751ee
TS
164{
165 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
166 eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
167 return eeprom.sda;
168}
169
170static void eeprom24c0x_write(int scl, int sda)
171{
172 if (eeprom.scl && scl && (eeprom.sda != sda)) {
173 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
174 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
175 if (!sda) {
176 eeprom.tick = 1;
177 eeprom.command = 0;
178 }
179 } else if (eeprom.tick == 0 && !eeprom.ack) {
180 /* Waiting for start. */
181 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
182 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
183 } else if (!eeprom.scl && scl) {
184 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
185 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
186 if (eeprom.ack) {
187 logout("\ti2c ack bit = 0\n");
188 sda = 0;
189 eeprom.ack = 0;
190 } else if (eeprom.sda == sda) {
191 uint8_t bit = (sda != 0);
192 logout("\ti2c bit = %d\n", bit);
193 if (eeprom.tick < 9) {
194 eeprom.command <<= 1;
195 eeprom.command += bit;
196 eeprom.tick++;
197 if (eeprom.tick == 9) {
198 logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
199 eeprom.ack = 1;
200 }
201 } else if (eeprom.tick < 17) {
202 if (eeprom.command & 1) {
203 sda = ((eeprom.data & 0x80) != 0);
204 }
205 eeprom.address <<= 1;
206 eeprom.address += bit;
207 eeprom.tick++;
208 eeprom.data <<= 1;
209 if (eeprom.tick == 17) {
210 eeprom.data = eeprom.contents[eeprom.address];
211 logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
212 eeprom.ack = 1;
213 eeprom.tick = 0;
214 }
215 } else if (eeprom.tick >= 17) {
216 sda = 0;
217 }
218 } else {
219 logout("\tsda changed with raising scl\n");
220 }
221 } else {
222 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
223 }
224 eeprom.scl = scl;
225 eeprom.sda = sda;
226}
227
ea85df72
AK
228static uint64_t malta_fpga_read(void *opaque, target_phys_addr_t addr,
229 unsigned size)
5856de80
TS
230{
231 MaltaFPGAState *s = opaque;
232 uint32_t val = 0;
233 uint32_t saddr;
234
235 saddr = (addr & 0xfffff);
236
237 switch (saddr) {
238
239 /* SWITCH Register */
240 case 0x00200:
241 val = 0x00000000; /* All switches closed */
593c0d10 242 break;
5856de80
TS
243
244 /* STATUS Register */
245 case 0x00208:
246#ifdef TARGET_WORDS_BIGENDIAN
247 val = 0x00000012;
248#else
249 val = 0x00000010;
250#endif
251 break;
252
253 /* JMPRS Register */
254 case 0x00210:
255 val = 0x00;
256 break;
257
258 /* LEDBAR Register */
259 case 0x00408:
260 val = s->leds;
261 break;
262
263 /* BRKRES Register */
264 case 0x00508:
265 val = s->brk;
266 break;
267
b6dc7ebb 268 /* UART Registers are handled directly by the serial device */
a4bc3afc 269
5856de80
TS
270 /* GPOUT Register */
271 case 0x00a00:
272 val = s->gpout;
273 break;
274
275 /* XXX: implement a real I2C controller */
276
277 /* GPINP Register */
278 case 0x00a08:
279 /* IN = OUT until a real I2C control is implemented */
280 if (s->i2csel)
281 val = s->i2cout;
282 else
283 val = 0x00;
284 break;
285
286 /* I2CINP Register */
287 case 0x00b00:
130751ee 288 val = ((s->i2cin & ~1) | eeprom24c0x_read());
5856de80
TS
289 break;
290
291 /* I2COE Register */
292 case 0x00b08:
293 val = s->i2coe;
294 break;
295
296 /* I2COUT Register */
297 case 0x00b10:
298 val = s->i2cout;
299 break;
300
301 /* I2CSEL Register */
302 case 0x00b18:
130751ee 303 val = s->i2csel;
5856de80
TS
304 break;
305
306 default:
307#if 0
3594c774 308 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
593c0d10 309 addr);
5856de80
TS
310#endif
311 break;
312 }
313 return val;
314}
315
ea85df72
AK
316static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
317 uint64_t val, unsigned size)
5856de80
TS
318{
319 MaltaFPGAState *s = opaque;
320 uint32_t saddr;
321
322 saddr = (addr & 0xfffff);
323
324 switch (saddr) {
325
326 /* SWITCH Register */
327 case 0x00200:
328 break;
329
330 /* JMPRS Register */
331 case 0x00210:
332 break;
333
334 /* LEDBAR Register */
335 /* XXX: implement a 8-LED array */
336 case 0x00408:
337 s->leds = val & 0xff;
338 break;
339
340 /* ASCIIWORD Register */
341 case 0x00410:
ea85df72 342 snprintf(s->display_text, 9, "%08X", (uint32_t)val);
5856de80
TS
343 malta_fpga_update_display(s);
344 break;
345
346 /* ASCIIPOS0 to ASCIIPOS7 Registers */
347 case 0x00418:
348 case 0x00420:
349 case 0x00428:
350 case 0x00430:
351 case 0x00438:
352 case 0x00440:
353 case 0x00448:
354 case 0x00450:
355 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
356 malta_fpga_update_display(s);
357 break;
358
359 /* SOFTRES Register */
360 case 0x00500:
361 if (val == 0x42)
362 qemu_system_reset_request ();
363 break;
364
365 /* BRKRES Register */
366 case 0x00508:
367 s->brk = val & 0xff;
368 break;
369
b6dc7ebb 370 /* UART Registers are handled directly by the serial device */
a4bc3afc 371
5856de80
TS
372 /* GPOUT Register */
373 case 0x00a00:
374 s->gpout = val & 0xff;
375 break;
376
377 /* I2COE Register */
378 case 0x00b08:
379 s->i2coe = val & 0x03;
380 break;
381
382 /* I2COUT Register */
383 case 0x00b10:
130751ee
TS
384 eeprom24c0x_write(val & 0x02, val & 0x01);
385 s->i2cout = val;
5856de80
TS
386 break;
387
388 /* I2CSEL Register */
389 case 0x00b18:
130751ee 390 s->i2csel = val & 0x01;
5856de80
TS
391 break;
392
393 default:
394#if 0
3594c774 395 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
593c0d10 396 addr);
5856de80
TS
397#endif
398 break;
399 }
400}
401
ea85df72
AK
402static const MemoryRegionOps malta_fpga_ops = {
403 .read = malta_fpga_read,
404 .write = malta_fpga_write,
405 .endianness = DEVICE_NATIVE_ENDIAN,
5856de80
TS
406};
407
9596ebb7 408static void malta_fpga_reset(void *opaque)
5856de80
TS
409{
410 MaltaFPGAState *s = opaque;
411
412 s->leds = 0x00;
413 s->brk = 0x0a;
414 s->gpout = 0x00;
130751ee 415 s->i2cin = 0x3;
5856de80
TS
416 s->i2coe = 0x0;
417 s->i2cout = 0x3;
418 s->i2csel = 0x1;
419
420 s->display_text[8] = '\0';
421 snprintf(s->display_text, 9, " ");
ceecf1d1
AJ
422}
423
ceecf1d1
AJ
424static void malta_fpga_led_init(CharDriverState *chr)
425{
e7e71b0e
AL
426 qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
427 qemu_chr_fe_printf(chr, "+--------+\r\n");
428 qemu_chr_fe_printf(chr, "+ +\r\n");
429 qemu_chr_fe_printf(chr, "+--------+\r\n");
430 qemu_chr_fe_printf(chr, "\n");
431 qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
432 qemu_chr_fe_printf(chr, "+--------+\r\n");
433 qemu_chr_fe_printf(chr, "+ +\r\n");
434 qemu_chr_fe_printf(chr, "+--------+\r\n");
5856de80
TS
435}
436
ea85df72
AK
437static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
438 target_phys_addr_t base, qemu_irq uart_irq, CharDriverState *uart_chr)
5856de80
TS
439{
440 MaltaFPGAState *s;
5856de80 441
7267c094 442 s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
5856de80 443
ea85df72
AK
444 memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
445 "malta-fpga", 0x100000);
446 memory_region_init_alias(&s->iomem_lo, "malta-fpga",
447 &s->iomem, 0, 0x900);
448 memory_region_init_alias(&s->iomem_hi, "malta-fpga",
449 &s->iomem, 0xa00, 0x10000-0xa00);
a4bc3afc 450
ea85df72
AK
451 memory_region_add_subregion(address_space, base, &s->iomem_lo);
452 memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
5856de80 453
27143a44 454 s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
ceecf1d1 455
39186d8a
RH
456 s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
457 230400, uart_chr, DEVICE_NATIVE_ENDIAN);
a4bc3afc 458
5856de80 459 malta_fpga_reset(s);
a08d4367 460 qemu_register_reset(malta_fpga_reset, s);
5856de80
TS
461
462 return s;
463}
464
5856de80 465/* Network support */
5607c388 466static void network_init(void)
5856de80
TS
467{
468 int i;
5856de80
TS
469
470 for(i = 0; i < nb_nics; i++) {
cb457d76 471 NICInfo *nd = &nd_table[i];
5607c388 472 const char *default_devaddr = NULL;
cb457d76
AL
473
474 if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
5856de80 475 /* The malta board has a PCNet card using PCI SLOT 11 */
5607c388 476 default_devaddr = "0b";
cb457d76 477
07caea31 478 pci_nic_init_nofail(nd, "pcnet", default_devaddr);
5856de80
TS
479 }
480}
481
482/* ROM and pseudo bootloader
483
484 The following code implements a very very simple bootloader. It first
485 loads the registers a0 to a3 to the values expected by the OS, and
486 then jump at the kernel address.
487
488 The bootloader should pass the locations of the kernel arguments and
489 environment variables tables. Those tables contain the 32-bit address
490 of NULL terminated strings. The environment variables table should be
491 terminated by a NULL address.
492
493 For a simpler implementation, the number of kernel arguments is fixed
494 to two (the name of the kernel and the command line), and the two
495 tables are actually the same one.
496
497 The registers a0 to a3 should contain the following values:
498 a0 - number of kernel arguments
499 a1 - 32-bit address of the kernel arguments table
500 a2 - 32-bit address of the environment variables table
501 a3 - RAM size in bytes
502*/
503
d7585251
PB
504static void write_bootloader (CPUState *env, uint8_t *base,
505 int64_t kernel_entry)
5856de80
TS
506{
507 uint32_t *p;
508
509 /* Small bootloader */
d7585251 510 p = (uint32_t *)base;
26ea0918 511 stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */
3ddd0065 512 stl_raw(p++, 0x00000000); /* nop */
5856de80 513
26ea0918 514 /* YAMON service vector */
d7585251
PB
515 stl_raw(base + 0x500, 0xbfc00580); /* start: */
516 stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */
517 stl_raw(base + 0x520, 0xbfc00580); /* start: */
518 stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */
519 stl_raw(base + 0x534, 0xbfc00808); /* print: */
520 stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */
521 stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */
522 stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */
523 stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */
524 stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */
525 stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */
526 stl_raw(base + 0x550, 0xbfc00800); /* getchar: */
527 stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */
26ea0918
TS
528
529
5856de80 530 /* Second part of the bootloader */
d7585251 531 p = (uint32_t *) (base + 0x580);
d52fff71
TS
532 stl_raw(p++, 0x24040002); /* addiu a0, zero, 2 */
533 stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
471ea271 534 stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
3ddd0065 535 stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
471ea271 536 stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
3ddd0065
TS
537 stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
538 stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
7df526e3
TS
539 stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
540 stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
2802bfe3
TS
541
542 /* Load BAR registers as done by YAMON */
a0a8793e
TS
543 stl_raw(p++, 0x3c09b400); /* lui t1, 0xb400 */
544
545#ifdef TARGET_WORDS_BIGENDIAN
546 stl_raw(p++, 0x3c08df00); /* lui t0, 0xdf00 */
547#else
548 stl_raw(p++, 0x340800df); /* ori t0, r0, 0x00df */
549#endif
550 stl_raw(p++, 0xad280068); /* sw t0, 0x0068(t1) */
551
2802bfe3
TS
552 stl_raw(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
553
554#ifdef TARGET_WORDS_BIGENDIAN
555 stl_raw(p++, 0x3c08c000); /* lui t0, 0xc000 */
556#else
557 stl_raw(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */
558#endif
559 stl_raw(p++, 0xad280048); /* sw t0, 0x0048(t1) */
560#ifdef TARGET_WORDS_BIGENDIAN
561 stl_raw(p++, 0x3c084000); /* lui t0, 0x4000 */
562#else
563 stl_raw(p++, 0x34080040); /* ori t0, r0, 0x0040 */
564#endif
565 stl_raw(p++, 0xad280050); /* sw t0, 0x0050(t1) */
566
567#ifdef TARGET_WORDS_BIGENDIAN
568 stl_raw(p++, 0x3c088000); /* lui t0, 0x8000 */
569#else
570 stl_raw(p++, 0x34080080); /* ori t0, r0, 0x0080 */
571#endif
572 stl_raw(p++, 0xad280058); /* sw t0, 0x0058(t1) */
573#ifdef TARGET_WORDS_BIGENDIAN
574 stl_raw(p++, 0x3c083f00); /* lui t0, 0x3f00 */
575#else
576 stl_raw(p++, 0x3408003f); /* ori t0, r0, 0x003f */
577#endif
578 stl_raw(p++, 0xad280060); /* sw t0, 0x0060(t1) */
579
580#ifdef TARGET_WORDS_BIGENDIAN
581 stl_raw(p++, 0x3c08c100); /* lui t0, 0xc100 */
582#else
583 stl_raw(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */
584#endif
585 stl_raw(p++, 0xad280080); /* sw t0, 0x0080(t1) */
586#ifdef TARGET_WORDS_BIGENDIAN
587 stl_raw(p++, 0x3c085e00); /* lui t0, 0x5e00 */
588#else
589 stl_raw(p++, 0x3408005e); /* ori t0, r0, 0x005e */
590#endif
591 stl_raw(p++, 0xad280088); /* sw t0, 0x0088(t1) */
592
593 /* Jump to kernel code */
74287114
TS
594 stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
595 stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
3ddd0065
TS
596 stl_raw(p++, 0x03e00008); /* jr ra */
597 stl_raw(p++, 0x00000000); /* nop */
26ea0918
TS
598
599 /* YAMON subroutines */
d7585251 600 p = (uint32_t *) (base + 0x800);
26ea0918
TS
601 stl_raw(p++, 0x03e00008); /* jr ra */
602 stl_raw(p++, 0x24020000); /* li v0,0 */
603 /* 808 YAMON print */
604 stl_raw(p++, 0x03e06821); /* move t5,ra */
605 stl_raw(p++, 0x00805821); /* move t3,a0 */
606 stl_raw(p++, 0x00a05021); /* move t2,a1 */
607 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
608 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
609 stl_raw(p++, 0x10800005); /* beqz a0,834 */
610 stl_raw(p++, 0x00000000); /* nop */
611 stl_raw(p++, 0x0ff0021c); /* jal 870 */
612 stl_raw(p++, 0x00000000); /* nop */
613 stl_raw(p++, 0x08000205); /* j 814 */
614 stl_raw(p++, 0x00000000); /* nop */
615 stl_raw(p++, 0x01a00008); /* jr t5 */
616 stl_raw(p++, 0x01602021); /* move a0,t3 */
617 /* 0x83c YAMON print_count */
618 stl_raw(p++, 0x03e06821); /* move t5,ra */
619 stl_raw(p++, 0x00805821); /* move t3,a0 */
620 stl_raw(p++, 0x00a05021); /* move t2,a1 */
621 stl_raw(p++, 0x00c06021); /* move t4,a2 */
622 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
623 stl_raw(p++, 0x0ff0021c); /* jal 870 */
624 stl_raw(p++, 0x00000000); /* nop */
625 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
626 stl_raw(p++, 0x258cffff); /* addiu t4,t4,-1 */
627 stl_raw(p++, 0x1580fffa); /* bnez t4,84c */
628 stl_raw(p++, 0x00000000); /* nop */
629 stl_raw(p++, 0x01a00008); /* jr t5 */
630 stl_raw(p++, 0x01602021); /* move a0,t3 */
631 /* 0x870 */
632 stl_raw(p++, 0x3c08b800); /* lui t0,0xb400 */
633 stl_raw(p++, 0x350803f8); /* ori t0,t0,0x3f8 */
634 stl_raw(p++, 0x91090005); /* lbu t1,5(t0) */
635 stl_raw(p++, 0x00000000); /* nop */
636 stl_raw(p++, 0x31290040); /* andi t1,t1,0x40 */
637 stl_raw(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
638 stl_raw(p++, 0x00000000); /* nop */
639 stl_raw(p++, 0x03e00008); /* jr ra */
640 stl_raw(p++, 0xa1040000); /* sb a0,0(t0) */
641
5856de80
TS
642}
643
8b7968f7
SW
644static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
645 const char *string, ...)
5856de80
TS
646{
647 va_list ap;
3ddd0065 648 int32_t table_addr;
5856de80
TS
649
650 if (index >= ENVP_NB_ENTRIES)
651 return;
652
5856de80 653 if (string == NULL) {
c938ada2 654 prom_buf[index] = 0;
5856de80
TS
655 return;
656 }
657
c938ada2
AJ
658 table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
659 prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
5856de80
TS
660
661 va_start(ap, string);
c938ada2 662 vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
5856de80
TS
663 va_end(ap);
664}
665
666/* Kernel */
e16ad5b0 667static int64_t load_kernel (void)
5856de80 668{
409dbce5 669 int64_t kernel_entry, kernel_high;
5856de80 670 long initrd_size;
c227f099 671 ram_addr_t initrd_offset;
ca20cf32 672 int big_endian;
c938ada2
AJ
673 uint32_t *prom_buf;
674 long prom_size;
675 int prom_index = 0;
ca20cf32
BS
676
677#ifdef TARGET_WORDS_BIGENDIAN
678 big_endian = 1;
679#else
680 big_endian = 0;
681#endif
5856de80 682
409dbce5
AJ
683 if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
684 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
685 big_endian, ELF_MACHINE, 1) < 0) {
5856de80 686 fprintf(stderr, "qemu: could not load kernel '%s'\n",
7df526e3 687 loaderparams.kernel_filename);
acdf72bb 688 exit(1);
5856de80
TS
689 }
690
691 /* load initrd */
692 initrd_size = 0;
74287114 693 initrd_offset = 0;
7df526e3
TS
694 if (loaderparams.initrd_filename) {
695 initrd_size = get_image_size (loaderparams.initrd_filename);
74287114
TS
696 if (initrd_size > 0) {
697 initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
7df526e3 698 if (initrd_offset + initrd_size > ram_size) {
74287114
TS
699 fprintf(stderr,
700 "qemu: memory too small for initial ram disk '%s'\n",
7df526e3 701 loaderparams.initrd_filename);
74287114
TS
702 exit(1);
703 }
dcac9679
PB
704 initrd_size = load_image_targphys(loaderparams.initrd_filename,
705 initrd_offset,
706 ram_size - initrd_offset);
74287114 707 }
5856de80
TS
708 if (initrd_size == (target_ulong) -1) {
709 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
7df526e3 710 loaderparams.initrd_filename);
5856de80
TS
711 exit(1);
712 }
713 }
714
c938ada2
AJ
715 /* Setup prom parameters. */
716 prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
7267c094 717 prom_buf = g_malloc(prom_size);
c938ada2 718
f36d53ef 719 prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
c938ada2 720 if (initrd_size > 0) {
409dbce5
AJ
721 prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
722 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
7df526e3 723 loaderparams.kernel_cmdline);
c938ada2 724 } else {
f36d53ef 725 prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
c938ada2
AJ
726 }
727
728 prom_set(prom_buf, prom_index++, "memsize");
729 prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
730 prom_set(prom_buf, prom_index++, "modetty0");
731 prom_set(prom_buf, prom_index++, "38400n8r");
732 prom_set(prom_buf, prom_index++, NULL);
733
734 rom_add_blob_fixed("prom", prom_buf, prom_size,
409dbce5 735 cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
5856de80 736
74287114 737 return kernel_entry;
5856de80
TS
738}
739
c4cb2578
EI
740static void malta_mips_config(CPUState *env)
741{
742 env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
743 ((smp_cpus * env->nr_threads - 1) << CP0MVPC0_PTC);
744}
745
5856de80
TS
746static void main_cpu_reset(void *opaque)
747{
748 CPUState *env = opaque;
749 cpu_reset(env);
750
5c43485f 751 /* The bootloader does not need to be rewritten as it is located in a
5856de80
TS
752 read only location. The kernel location and the arguments table
753 location does not change. */
7df526e3 754 if (loaderparams.kernel_filename) {
fb82fea0 755 env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
fb82fea0 756 }
c4cb2578
EI
757
758 malta_mips_config(env);
5856de80
TS
759}
760
4556bd8b
BS
761static void cpu_request_exit(void *opaque, int irq, int level)
762{
763 CPUState *env = cpu_single_env;
764
765 if (env && level) {
766 cpu_exit(env);
767 }
768}
769
70705261 770static
c227f099 771void mips_malta_init (ram_addr_t ram_size,
3023f332 772 const char *boot_device,
5856de80 773 const char *kernel_filename, const char *kernel_cmdline,
94fc95cd 774 const char *initrd_filename, const char *cpu_model)
5856de80 775{
5cea8590 776 char *filename;
cfe5f011 777 pflash_t *fl;
cfe5f011 778 MemoryRegion *system_memory = get_system_memory();
ea85df72 779 MemoryRegion *ram = g_new(MemoryRegion, 1);
cfe5f011 780 MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
c8b153d7 781 target_long bios_size;
74287114 782 int64_t kernel_entry;
5856de80 783 PCIBus *pci_bus;
48a18b3c 784 ISABus *isa_bus;
5856de80 785 CPUState *env;
e9b40fd3 786 qemu_irq *isa_irq;
4556bd8b 787 qemu_irq *cpu_exit_irq;
7b717336 788 int piix4_devfn;
7b717336
TS
789 i2c_bus *smbus;
790 int i;
751c6a17 791 DriveInfo *dinfo;
f455e98c 792 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
fd8014e1 793 DriveInfo *fd[MAX_FD];
c8b153d7
TS
794 int fl_idx = 0;
795 int fl_sectors = 0;
01e0451a 796 int be;
5856de80 797
e9b40fd3
SW
798 DeviceState *dev = qdev_create(NULL, "mips-malta");
799 MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
800
801 qdev_init_nofail(dev);
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);
27143a44 808 serial_hds[i] = qemu_chr_new(label, "null", NULL);
ffabf037
AJ
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 }
c4cb2578
EI
820
821 for (i = 0; i < smp_cpus; i++) {
822 env = cpu_init(cpu_model);
823 if (!env) {
824 fprintf(stderr, "Unable to find CPU definition\n");
825 exit(1);
826 }
827 /* Init internal devices */
828 cpu_mips_irq_init_cpu(env);
829 cpu_mips_clock_init(env);
830 qemu_register_reset(main_cpu_reset, env);
aaed909a 831 }
c4cb2578 832 env = first_cpu;
5856de80
TS
833
834 /* allocate RAM */
0ccff151
AJ
835 if (ram_size > (256 << 20)) {
836 fprintf(stderr,
837 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
838 ((unsigned int)ram_size / (1 << 20)));
839 exit(1);
840 }
c5705a77
AK
841 memory_region_init_ram(ram, "mips_malta.ram", ram_size);
842 vmstate_register_ram_global(ram);
ea85df72 843 memory_region_add_subregion(system_memory, 0, ram);
5856de80 844
01e0451a
AL
845#ifdef TARGET_WORDS_BIGENDIAN
846 be = 1;
847#else
848 be = 0;
849#endif
070ce5ed 850 /* FPGA */
ea85df72 851 malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
070ce5ed 852
c8b153d7
TS
853 /* Load firmware in flash / BIOS unless we boot directly into a kernel. */
854 if (kernel_filename) {
855 /* Write a small bootloader to the flash location. */
cfe5f011 856 bios = g_new(MemoryRegion, 1);
c5705a77
AK
857 memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
858 vmstate_register_ram_global(bios);
cfe5f011
AK
859 memory_region_set_readonly(bios, true);
860 memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
861 /* Map the bios at two physical locations, as on the real board. */
862 memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
863 memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
c8b153d7
TS
864 loaderparams.ram_size = ram_size;
865 loaderparams.kernel_filename = kernel_filename;
866 loaderparams.kernel_cmdline = kernel_cmdline;
867 loaderparams.initrd_filename = initrd_filename;
e16ad5b0 868 kernel_entry = load_kernel();
cfe5f011 869 write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
c8b153d7 870 } else {
751c6a17
GH
871 dinfo = drive_get(IF_PFLASH, 0, fl_idx);
872 if (dinfo) {
c8b153d7
TS
873 /* Load firmware from flash. */
874 bios_size = 0x400000;
875 fl_sectors = bios_size >> 16;
876#ifdef DEBUG_BOARD_INIT
877 printf("Register parallel flash %d size " TARGET_FMT_lx " at "
cfe5f011
AK
878 "addr %08llx '%s' %x\n",
879 fl_idx, bios_size, 0x1e000000LL,
751c6a17 880 bdrv_get_device_name(dinfo->bdrv), fl_sectors);
c8b153d7 881#endif
cfe5f011
AK
882 fl = pflash_cfi01_register(0x1e000000LL,
883 NULL, "mips_malta.bios", BIOS_SIZE,
884 dinfo->bdrv, 65536, fl_sectors,
885 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
886 bios = pflash_cfi01_get_memory(fl);
887 /* Map the bios at two physical locations, as on the real board. */
888 memory_region_init_alias(bios_alias, "bios.1fc",
889 bios, 0, BIOS_SIZE);
890 memory_region_add_subregion(system_memory, 0x1fc00000LL,
891 bios_alias);
892 fl_idx++;
c8b153d7 893 } else {
cfe5f011 894 bios = g_new(MemoryRegion, 1);
c5705a77
AK
895 memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
896 vmstate_register_ram_global(bios);
cfe5f011
AK
897 memory_region_set_readonly(bios, true);
898 memory_region_init_alias(bios_alias, "bios.1fc",
899 bios, 0, BIOS_SIZE);
900 /* Map the bios at two physical locations, as on the real board. */
901 memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
902 memory_region_add_subregion(system_memory, 0x1fc00000LL,
903 bios_alias);
c8b153d7
TS
904 /* Load a BIOS image. */
905 if (bios_name == NULL)
906 bios_name = BIOS_FILENAME;
5cea8590
PB
907 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
908 if (filename) {
909 bios_size = load_image_targphys(filename, 0x1fc00000LL,
910 BIOS_SIZE);
7267c094 911 g_free(filename);
5cea8590
PB
912 } else {
913 bios_size = -1;
914 }
c8b153d7
TS
915 if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
916 fprintf(stderr,
917 "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
5cea8590 918 bios_name);
c8b153d7
TS
919 exit(1);
920 }
070ce5ed 921 }
3187ef03
TS
922 /* In little endian mode the 32bit words in the bios are swapped,
923 a neat trick which allows bi-endian firmware. */
924#ifndef TARGET_WORDS_BIGENDIAN
925 {
cfe5f011 926 uint32_t *addr = memory_region_get_ram_ptr(bios);
d7585251
PB
927 uint32_t *end = addr + bios_size;
928 while (addr < end) {
929 bswap32s(addr);
a30cfee5 930 addr++;
3187ef03
TS
931 }
932 }
933#endif
070ce5ed
TS
934 }
935
5856de80
TS
936 /* Board ID = 0x420 (Malta Board with CoreLV)
937 XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
938 map to the board ID. */
cfe5f011 939 stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
5856de80
TS
940
941 /* Init internal devices */
d537cf6c 942 cpu_mips_irq_init_cpu(env);
5856de80 943 cpu_mips_clock_init(env);
5856de80 944
5632ae46
AK
945 /*
946 * We have a circular dependency problem: pci_bus depends on isa_irq,
947 * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
948 * on piix4, and piix4 depends on pci_bus. To stop the cycle we have
949 * qemu_irq_proxy() adds an extra bit of indirection, allowing us
950 * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
951 */
e9b40fd3 952 isa_irq = qemu_irq_proxy(&s->i8259, 16);
5856de80
TS
953
954 /* Northbridge */
5632ae46 955 pci_bus = gt64120_register(isa_irq);
5856de80
TS
956
957 /* Southbridge */
75717903 958 ide_drive_get(hd, MAX_IDE_BUS);
e4bcb14c 959
142e9787 960 piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
5632ae46
AK
961
962 /* Interrupt controller */
963 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
e9b40fd3 964 s->i8259 = i8259_init(isa_bus, env->irq[2]);
5632ae46 965
e9b40fd3 966 isa_bus_irqs(isa_bus, s->i8259);
ae027ad3 967 pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
afcc3cdf 968 usb_uhci_piix4_init(pci_bus, piix4_devfn + 2);
48a18b3c 969 smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
da98c8eb 970 isa_get_irq(NULL, 9), NULL, 0);
a88df0b9
IY
971 /* TODO: Populate SPD eeprom data. */
972 smbus_eeprom_init(smbus, 8, NULL, 0);
319ba9f5 973 pit = pit_init(isa_bus, 0x40, 0, NULL);
4556bd8b
BS
974 cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
975 DMA_init(0, cpu_exit_irq);
5856de80
TS
976
977 /* Super I/O */
48a18b3c 978 isa_create_simple(isa_bus, "i8042");
49a2942d 979
48a18b3c
HP
980 rtc_init(isa_bus, 2000, NULL);
981 serial_isa_init(isa_bus, 0, serial_hds[0]);
982 serial_isa_init(isa_bus, 1, serial_hds[1]);
7bcc17dc 983 if (parallel_hds[0])
48a18b3c 984 parallel_init(isa_bus, 0, parallel_hds[0]);
e4bcb14c 985 for(i = 0; i < MAX_FD; i++) {
fd8014e1 986 fd[i] = drive_get(IF_FLOPPY, 0, i);
e4bcb14c 987 }
48a18b3c 988 fdctrl_init_isa(isa_bus, fd);
5856de80
TS
989
990 /* Sound card */
4a0f031d 991 audio_init(isa_bus, pci_bus);
5856de80
TS
992
993 /* Network card */
5607c388 994 network_init();
11f29511
TS
995
996 /* Optional PCI video card */
1f605a76 997 if (cirrus_vga_enabled) {
fbe1b595 998 pci_cirrus_vga_init(pci_bus);
1f605a76 999 } else if (vmsvga_enabled) {
a369da5f 1000 pci_vmsvga_init(pci_bus);
1f605a76 1001 } else if (std_vga_enabled) {
78895427 1002 pci_vga_init(pci_bus);
1f605a76 1003 }
5856de80
TS
1004}
1005
e9b40fd3
SW
1006static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
1007{
1008 return 0;
1009}
1010
999e12bb
AL
1011static void mips_malta_class_init(ObjectClass *klass, void *data)
1012{
1013 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1014
1015 k->init = mips_malta_sysbus_device_init;
1016}
1017
39bffca2
AL
1018static TypeInfo mips_malta_device = {
1019 .name = "mips-malta",
1020 .parent = TYPE_SYS_BUS_DEVICE,
1021 .instance_size = sizeof(MaltaState),
1022 .class_init = mips_malta_class_init,
e9b40fd3
SW
1023};
1024
f80f9ec9 1025static QEMUMachine mips_malta_machine = {
eec2743e
TS
1026 .name = "malta",
1027 .desc = "MIPS Malta Core LV",
1028 .init = mips_malta_init,
c4cb2578 1029 .max_cpus = 16,
0c257437 1030 .is_default = 1,
5856de80 1031};
f80f9ec9 1032
83f7d43a 1033static void mips_malta_register_types(void)
e9b40fd3 1034{
39bffca2 1035 type_register_static(&mips_malta_device);
e9b40fd3
SW
1036}
1037
f80f9ec9
AL
1038static void mips_malta_machine_init(void)
1039{
1040 qemu_register_machine(&mips_malta_machine);
1041}
1042
83f7d43a 1043type_init(mips_malta_register_types)
f80f9ec9 1044machine_init(mips_malta_machine_init);