| 1 | /* |
| 2 | * QEMU MIPS Jazz support |
| 3 | * |
| 4 | * Copyright (c) 2007-2008 Hervé Poussineau |
| 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 | |
| 25 | #include "qemu/osdep.h" |
| 26 | #include "qemu/datadir.h" |
| 27 | #include "hw/core/clock.h" |
| 28 | #include "hw/mips/mips.h" |
| 29 | #include "hw/intc/i8259.h" |
| 30 | #include "hw/dma/i8257.h" |
| 31 | #include "hw/char/serial-mm.h" |
| 32 | #include "hw/char/parallel.h" |
| 33 | #include "hw/isa/isa.h" |
| 34 | #include "hw/block/fdc.h" |
| 35 | #include "system/system.h" |
| 36 | #include "hw/core/boards.h" |
| 37 | #include "net/net.h" |
| 38 | #include "hw/scsi/esp.h" |
| 39 | #include "hw/core/loader.h" |
| 40 | #include "hw/rtc/mc146818rtc.h" |
| 41 | #include "hw/timer/i8254.h" |
| 42 | #include "hw/display/vga.h" |
| 43 | #include "hw/display/bochs-vbe.h" |
| 44 | #include "hw/audio/pcspk.h" |
| 45 | #include "hw/input/i8042.h" |
| 46 | #include "hw/core/sysbus.h" |
| 47 | #include "system/qtest.h" |
| 48 | #include "system/reset.h" |
| 49 | #include "qapi/error.h" |
| 50 | #include "qemu/error-report.h" |
| 51 | #include "qemu/help_option.h" |
| 52 | #ifdef CONFIG_TCG |
| 53 | #include "accel/tcg/cpu-ops.h" |
| 54 | #endif /* CONFIG_TCG */ |
| 55 | #include "target/mips/cpu.h" |
| 56 | |
| 57 | enum jazz_model_e { |
| 58 | JAZZ_MAGNUM, |
| 59 | JAZZ_PICA61, |
| 60 | }; |
| 61 | |
| 62 | static void main_cpu_reset(void *opaque) |
| 63 | { |
| 64 | MIPSCPU *cpu = opaque; |
| 65 | |
| 66 | cpu_reset(CPU(cpu)); |
| 67 | } |
| 68 | |
| 69 | static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size) |
| 70 | { |
| 71 | uint8_t val; |
| 72 | address_space_read(&address_space_memory, 0x90000071, |
| 73 | MEMTXATTRS_UNSPECIFIED, &val, 1); |
| 74 | return val; |
| 75 | } |
| 76 | |
| 77 | static void rtc_write(void *opaque, hwaddr addr, |
| 78 | uint64_t val, unsigned size) |
| 79 | { |
| 80 | uint8_t buf = val & 0xff; |
| 81 | address_space_write(&address_space_memory, 0x90000071, |
| 82 | MEMTXATTRS_UNSPECIFIED, &buf, 1); |
| 83 | } |
| 84 | |
| 85 | static const MemoryRegionOps rtc_ops = { |
| 86 | .read = rtc_read, |
| 87 | .write = rtc_write, |
| 88 | .endianness = DEVICE_NATIVE_ENDIAN, |
| 89 | }; |
| 90 | |
| 91 | static uint64_t dma_dummy_read(void *opaque, hwaddr addr, |
| 92 | unsigned size) |
| 93 | { |
| 94 | /* |
| 95 | * Nothing to do. That is only to ensure that |
| 96 | * the current DMA acknowledge cycle is completed. |
| 97 | */ |
| 98 | return 0xff; |
| 99 | } |
| 100 | |
| 101 | static void dma_dummy_write(void *opaque, hwaddr addr, |
| 102 | uint64_t val, unsigned size) |
| 103 | { |
| 104 | /* |
| 105 | * Nothing to do. That is only to ensure that |
| 106 | * the current DMA acknowledge cycle is completed. |
| 107 | */ |
| 108 | } |
| 109 | |
| 110 | static const MemoryRegionOps dma_dummy_ops = { |
| 111 | .read = dma_dummy_read, |
| 112 | .write = dma_dummy_write, |
| 113 | .endianness = DEVICE_NATIVE_ENDIAN, |
| 114 | }; |
| 115 | |
| 116 | static void mips_jazz_init_net(IOMMUMemoryRegion *rc4030_dma_mr, |
| 117 | DeviceState *rc4030, MemoryRegion *dp8393x_prom) |
| 118 | { |
| 119 | DeviceState *dev; |
| 120 | SysBusDevice *sysbus; |
| 121 | int checksum, i; |
| 122 | uint8_t *prom; |
| 123 | NICInfo *nd; |
| 124 | |
| 125 | nd = qemu_find_nic_info("dp8393x", true, "dp83932"); |
| 126 | if (!nd) { |
| 127 | return; |
| 128 | } |
| 129 | |
| 130 | dev = qdev_new("dp8393x"); |
| 131 | qdev_set_nic_properties(dev, nd); |
| 132 | qdev_prop_set_uint8(dev, "it_shift", 2); |
| 133 | qdev_prop_set_bit(dev, "big_endian", TARGET_BIG_ENDIAN); |
| 134 | object_property_set_link(OBJECT(dev), "dma_mr", |
| 135 | OBJECT(rc4030_dma_mr), &error_abort); |
| 136 | sysbus = SYS_BUS_DEVICE(dev); |
| 137 | sysbus_realize_and_unref(sysbus, &error_fatal); |
| 138 | sysbus_mmio_map(sysbus, 0, 0x80001000); |
| 139 | sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4)); |
| 140 | |
| 141 | /* Add MAC address with valid checksum to PROM */ |
| 142 | prom = memory_region_get_ram_ptr(dp8393x_prom); |
| 143 | checksum = 0; |
| 144 | for (i = 0; i < 6; i++) { |
| 145 | prom[i] = nd->macaddr.a[i]; |
| 146 | checksum += prom[i]; |
| 147 | if (checksum > 0xff) { |
| 148 | checksum = (checksum + 1) & 0xff; |
| 149 | } |
| 150 | } |
| 151 | prom[7] = 0xff - checksum; |
| 152 | } |
| 153 | |
| 154 | #define BIOS_SIZE (4 * MiB) |
| 155 | |
| 156 | #define MAGNUM_BIOS_SIZE_MAX 0x7e000 |
| 157 | #define MAGNUM_BIOS_SIZE \ |
| 158 | (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX) |
| 159 | |
| 160 | #define SONIC_PROM_SIZE 0x1000 |
| 161 | |
| 162 | static void mips_jazz_init(MachineState *machine, |
| 163 | enum jazz_model_e jazz_model) |
| 164 | { |
| 165 | const char *bios_name = TARGET_BIG_ENDIAN ? "mips_bios.bin" |
| 166 | : "mipsel_bios.bin"; |
| 167 | MemoryRegion *address_space = get_system_memory(); |
| 168 | char *filename; |
| 169 | int bios_size, n; |
| 170 | Clock *cpuclk; |
| 171 | MIPSCPU *cpu; |
| 172 | MIPSCPUClass *mcc; |
| 173 | CPUMIPSState *env; |
| 174 | qemu_irq *i8259; |
| 175 | rc4030_dma *dmas; |
| 176 | IOMMUMemoryRegion *rc4030_dma_mr; |
| 177 | MemoryRegion *isa_mem = g_new(MemoryRegion, 1); |
| 178 | MemoryRegion *isa_io = g_new(MemoryRegion, 1); |
| 179 | MemoryRegion *rtc = g_new(MemoryRegion, 1); |
| 180 | MemoryRegion *dma_dummy = g_new(MemoryRegion, 1); |
| 181 | MemoryRegion *dp8393x_prom = g_new(MemoryRegion, 1); |
| 182 | DeviceState *dev, *rc4030; |
| 183 | MMIOKBDState *i8042; |
| 184 | SysBusDevice *sysbus; |
| 185 | ISABus *isa_bus; |
| 186 | ISADevice *pit; |
| 187 | ISADevice *pcspk; |
| 188 | DriveInfo *fds[MAX_FD]; |
| 189 | MemoryRegion *bios = g_new(MemoryRegion, 1); |
| 190 | MemoryRegion *bios2 = g_new(MemoryRegion, 1); |
| 191 | SysBusESPState *sysbus_esp; |
| 192 | ESPState *esp; |
| 193 | static const struct { |
| 194 | unsigned freq_hz; |
| 195 | unsigned pll_mult; |
| 196 | } ext_clk[] = { |
| 197 | [JAZZ_MAGNUM] = {50000000, 2}, |
| 198 | [JAZZ_PICA61] = {33333333, 4}, |
| 199 | }; |
| 200 | |
| 201 | if (machine->ram_size > 256 * MiB) { |
| 202 | error_report("RAM size more than 256Mb is not supported"); |
| 203 | exit(EXIT_FAILURE); |
| 204 | } |
| 205 | |
| 206 | cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); |
| 207 | clock_set_hz(cpuclk, ext_clk[jazz_model].freq_hz |
| 208 | * ext_clk[jazz_model].pll_mult); |
| 209 | |
| 210 | /* init CPUs */ |
| 211 | cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk, |
| 212 | TARGET_BIG_ENDIAN); |
| 213 | env = &cpu->env; |
| 214 | qemu_register_reset(main_cpu_reset, cpu); |
| 215 | |
| 216 | /* |
| 217 | * Chipset returns 0 in invalid reads and do not raise data exceptions. |
| 218 | * However, we can't simply add a global memory region to catch |
| 219 | * everything, as this would make all accesses including instruction |
| 220 | * accesses be ignored and not raise exceptions. |
| 221 | * |
| 222 | * NOTE: this behaviour of raising exceptions for bad instruction |
| 223 | * fetches but not bad data accesses was added in commit 54e755588cf1e9 |
| 224 | * to restore behaviour broken by c658b94f6e8c206, but it is not clear |
| 225 | * whether the real hardware behaves this way. It is possible that |
| 226 | * real hardware ignores bad instruction fetches as well -- if so then |
| 227 | * we could replace this hijacking of CPU methods with a simple global |
| 228 | * memory region that catches all memory accesses, as we do on Malta. |
| 229 | */ |
| 230 | mcc = MIPS_CPU_GET_CLASS(cpu); |
| 231 | mcc->no_data_aborts = true; |
| 232 | |
| 233 | /* allocate RAM */ |
| 234 | memory_region_add_subregion(address_space, 0, machine->ram); |
| 235 | |
| 236 | memory_region_init_rom(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE, |
| 237 | &error_fatal); |
| 238 | memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios, |
| 239 | 0, MAGNUM_BIOS_SIZE); |
| 240 | memory_region_add_subregion(address_space, 0x1fc00000LL, bios); |
| 241 | memory_region_add_subregion(address_space, 0xfff00000LL, bios2); |
| 242 | |
| 243 | /* load the BIOS image. */ |
| 244 | filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, |
| 245 | machine->firmware ?: bios_name); |
| 246 | if (filename) { |
| 247 | bios_size = load_image_targphys(filename, 0xfff00000LL, |
| 248 | MAGNUM_BIOS_SIZE, NULL); |
| 249 | g_free(filename); |
| 250 | } else { |
| 251 | bios_size = -1; |
| 252 | } |
| 253 | if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) |
| 254 | && machine->firmware && !qtest_enabled()) { |
| 255 | error_report("Could not load MIPS bios '%s'", machine->firmware); |
| 256 | exit(1); |
| 257 | } |
| 258 | |
| 259 | /* Init CPU internal devices */ |
| 260 | cpu_mips_irq_init_cpu(cpu); |
| 261 | cpu_mips_clock_init(cpu); |
| 262 | |
| 263 | /* Chipset */ |
| 264 | rc4030 = rc4030_init(&dmas, &rc4030_dma_mr); |
| 265 | sysbus = SYS_BUS_DEVICE(rc4030); |
| 266 | sysbus_connect_irq(sysbus, 0, env->irq[6]); |
| 267 | sysbus_connect_irq(sysbus, 1, env->irq[3]); |
| 268 | memory_region_add_subregion(address_space, 0x80000000, |
| 269 | sysbus_mmio_get_region(sysbus, 0)); |
| 270 | memory_region_add_subregion(address_space, 0xf0000000, |
| 271 | sysbus_mmio_get_region(sysbus, 1)); |
| 272 | memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, |
| 273 | NULL, "dummy_dma", 0x1000); |
| 274 | memory_region_add_subregion(address_space, 0x8000d000, dma_dummy); |
| 275 | |
| 276 | memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-jazz.prom", |
| 277 | SONIC_PROM_SIZE, &error_fatal); |
| 278 | memory_region_add_subregion(address_space, 0x8000b000, dp8393x_prom); |
| 279 | |
| 280 | /* ISA bus: IO space at 0x90000000, mem space at 0x91000000 */ |
| 281 | memory_region_init(isa_io, NULL, "isa-io", 0x00010000); |
| 282 | memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); |
| 283 | memory_region_add_subregion(address_space, 0x90000000, isa_io); |
| 284 | memory_region_add_subregion(address_space, 0x91000000, isa_mem); |
| 285 | isa_bus = isa_bus_new(NULL, isa_mem, isa_io, &error_abort); |
| 286 | |
| 287 | /* ISA devices */ |
| 288 | i8259 = i8259_init(isa_bus, env->irq[4]); |
| 289 | isa_bus_register_input_irqs(isa_bus, i8259); |
| 290 | i8257_dma_init(OBJECT(rc4030), isa_bus, 0); |
| 291 | pit = i8254_pit_init(isa_bus, 0x40, 0, NULL); |
| 292 | pcspk = isa_new(TYPE_PC_SPEAKER); |
| 293 | object_property_set_link(OBJECT(pcspk), "pit", OBJECT(pit), &error_fatal); |
| 294 | isa_realize_and_unref(pcspk, isa_bus, &error_fatal); |
| 295 | |
| 296 | /* Video card */ |
| 297 | switch (jazz_model) { |
| 298 | case JAZZ_MAGNUM: |
| 299 | dev = qdev_new("sysbus-g364"); |
| 300 | sysbus = SYS_BUS_DEVICE(dev); |
| 301 | sysbus_realize_and_unref(sysbus, &error_fatal); |
| 302 | sysbus_mmio_map(sysbus, 0, 0x60080000); |
| 303 | sysbus_mmio_map(sysbus, 1, 0x40000000); |
| 304 | sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 3)); |
| 305 | { |
| 306 | /* Simple ROM, so user doesn't have to provide one */ |
| 307 | MemoryRegion *rom_mr = g_new(MemoryRegion, 1); |
| 308 | memory_region_init_rom(rom_mr, NULL, "g364fb.rom", 0x80000, |
| 309 | &error_fatal); |
| 310 | uint8_t *rom = memory_region_get_ram_ptr(rom_mr); |
| 311 | memory_region_add_subregion(address_space, 0x60000000, rom_mr); |
| 312 | rom[0] = 0x10; /* Mips G364 */ |
| 313 | } |
| 314 | break; |
| 315 | case JAZZ_PICA61: |
| 316 | dev = qdev_new(TYPE_VGA_MMIO); |
| 317 | qdev_prop_set_uint8(dev, "it_shift", 0); |
| 318 | sysbus = SYS_BUS_DEVICE(dev); |
| 319 | sysbus_realize_and_unref(sysbus, &error_fatal); |
| 320 | sysbus_mmio_map(sysbus, 0, 0x60000000); |
| 321 | sysbus_mmio_map(sysbus, 1, 0x400a0000); |
| 322 | sysbus_mmio_map(sysbus, 2, VBE_DISPI_LFB_PHYSICAL_ADDRESS); |
| 323 | break; |
| 324 | default: |
| 325 | break; |
| 326 | } |
| 327 | |
| 328 | /* Network controller */ |
| 329 | mips_jazz_init_net(rc4030_dma_mr, rc4030, dp8393x_prom); |
| 330 | |
| 331 | /* SCSI adapter */ |
| 332 | dev = qdev_new(TYPE_SYSBUS_ESP); |
| 333 | sysbus_esp = SYSBUS_ESP(dev); |
| 334 | esp = &sysbus_esp->esp; |
| 335 | esp->dma_memory_read = rc4030_dma_read; |
| 336 | esp->dma_memory_write = rc4030_dma_write; |
| 337 | esp->dma_opaque = dmas[0]; |
| 338 | sysbus_esp->it_shift = 0; |
| 339 | /* XXX for now until rc4030 has been changed to use DMA enable signal */ |
| 340 | esp->dma_enabled = 1; |
| 341 | |
| 342 | sysbus = SYS_BUS_DEVICE(dev); |
| 343 | sysbus_realize_and_unref(sysbus, &error_fatal); |
| 344 | sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 5)); |
| 345 | sysbus_mmio_map(sysbus, 0, 0x80002000); |
| 346 | |
| 347 | scsi_bus_legacy_handle_cmdline(&esp->bus); |
| 348 | |
| 349 | /* Floppy */ |
| 350 | for (n = 0; n < MAX_FD; n++) { |
| 351 | fds[n] = drive_get(IF_FLOPPY, 0, n); |
| 352 | } |
| 353 | /* FIXME: we should enable DMA with a custom IsaDma device */ |
| 354 | fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), 0x80003000, fds); |
| 355 | |
| 356 | /* Real time clock */ |
| 357 | mc146818_rtc_init(isa_bus, 1980, NULL); |
| 358 | memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000); |
| 359 | memory_region_add_subregion(address_space, 0x80004000, rtc); |
| 360 | |
| 361 | /* Keyboard (i8042) */ |
| 362 | i8042 = I8042_MMIO(qdev_new(TYPE_I8042_MMIO)); |
| 363 | qdev_prop_set_uint64(DEVICE(i8042), "mask", 1); |
| 364 | qdev_prop_set_uint32(DEVICE(i8042), "size", 0x1000); |
| 365 | sysbus_realize_and_unref(SYS_BUS_DEVICE(i8042), &error_fatal); |
| 366 | |
| 367 | qdev_connect_gpio_out(DEVICE(i8042), I8042_KBD_IRQ, |
| 368 | qdev_get_gpio_in(rc4030, 6)); |
| 369 | qdev_connect_gpio_out(DEVICE(i8042), I8042_MOUSE_IRQ, |
| 370 | qdev_get_gpio_in(rc4030, 7)); |
| 371 | |
| 372 | memory_region_add_subregion(address_space, 0x80005000, |
| 373 | sysbus_mmio_get_region(SYS_BUS_DEVICE(i8042), |
| 374 | 0)); |
| 375 | |
| 376 | /* Serial ports */ |
| 377 | serial_mm_init(address_space, 0x80006000, 0, |
| 378 | qdev_get_gpio_in(rc4030, 8), 8000000 / 16, |
| 379 | serial_hd(0), DEVICE_NATIVE_ENDIAN); |
| 380 | serial_mm_init(address_space, 0x80007000, 0, |
| 381 | qdev_get_gpio_in(rc4030, 9), 8000000 / 16, |
| 382 | serial_hd(1), DEVICE_NATIVE_ENDIAN); |
| 383 | |
| 384 | /* Parallel port */ |
| 385 | if (parallel_hds[0]) |
| 386 | parallel_mm_init(address_space, 0x80008000, 0, |
| 387 | qdev_get_gpio_in(rc4030, 0), parallel_hds[0]); |
| 388 | |
| 389 | /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */ |
| 390 | |
| 391 | /* NVRAM */ |
| 392 | dev = qdev_new("ds1225y"); |
| 393 | sysbus = SYS_BUS_DEVICE(dev); |
| 394 | sysbus_realize_and_unref(sysbus, &error_fatal); |
| 395 | sysbus_mmio_map(sysbus, 0, 0x80009000); |
| 396 | |
| 397 | /* LED indicator */ |
| 398 | sysbus_create_simple("jazz-led", 0x8000f000, NULL); |
| 399 | |
| 400 | g_free(dmas); |
| 401 | } |
| 402 | |
| 403 | static |
| 404 | void mips_magnum_init(MachineState *machine) |
| 405 | { |
| 406 | mips_jazz_init(machine, JAZZ_MAGNUM); |
| 407 | } |
| 408 | |
| 409 | static |
| 410 | void mips_pica61_init(MachineState *machine) |
| 411 | { |
| 412 | mips_jazz_init(machine, JAZZ_PICA61); |
| 413 | } |
| 414 | |
| 415 | static void mips_magnum_class_init(ObjectClass *oc, const void *data) |
| 416 | { |
| 417 | MachineClass *mc = MACHINE_CLASS(oc); |
| 418 | |
| 419 | mc->desc = "MIPS Magnum"; |
| 420 | mc->init = mips_magnum_init; |
| 421 | mc->block_default_type = IF_SCSI; |
| 422 | mc->default_cpu_type = MIPS_CPU_TYPE_NAME("R4000"); |
| 423 | mc->default_ram_id = "mips_jazz.ram"; |
| 424 | } |
| 425 | |
| 426 | static const TypeInfo mips_magnum_type = { |
| 427 | .name = MACHINE_TYPE_NAME("magnum"), |
| 428 | .parent = TYPE_MACHINE, |
| 429 | .class_init = mips_magnum_class_init, |
| 430 | }; |
| 431 | |
| 432 | static void mips_pica61_class_init(ObjectClass *oc, const void *data) |
| 433 | { |
| 434 | MachineClass *mc = MACHINE_CLASS(oc); |
| 435 | |
| 436 | mc->desc = "Acer Pica 61"; |
| 437 | mc->init = mips_pica61_init; |
| 438 | mc->block_default_type = IF_SCSI; |
| 439 | mc->default_cpu_type = MIPS_CPU_TYPE_NAME("R4000"); |
| 440 | mc->default_ram_id = "mips_jazz.ram"; |
| 441 | } |
| 442 | |
| 443 | static const TypeInfo mips_pica61_type = { |
| 444 | .name = MACHINE_TYPE_NAME("pica61"), |
| 445 | .parent = TYPE_MACHINE, |
| 446 | .class_init = mips_pica61_class_init, |
| 447 | }; |
| 448 | |
| 449 | static void mips_jazz_machine_init(void) |
| 450 | { |
| 451 | type_register_static(&mips_magnum_type); |
| 452 | type_register_static(&mips_pica61_type); |
| 453 | } |
| 454 | |
| 455 | type_init(mips_jazz_machine_init) |