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