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