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