sun4m.c 44.2 KB
Newer Older
1
/*
B
blueswir1 已提交
2
 * QEMU Sun4m & Sun4d & Sun4c System Emulator
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
Peter Maydell 已提交
24
#include "qemu/osdep.h"
25
#include "qapi/error.h"
26 27
#include "qemu-common.h"
#include "cpu.h"
28
#include "hw/sysbus.h"
29
#include "qemu/error-report.h"
30
#include "qemu/timer.h"
P
Paolo Bonzini 已提交
31 32 33 34
#include "hw/sparc/sun4m.h"
#include "hw/timer/m48t59.h"
#include "hw/sparc/sparc32_dma.h"
#include "hw/block/fdc.h"
35
#include "sysemu/sysemu.h"
P
Paolo Bonzini 已提交
36
#include "net/net.h"
37
#include "hw/boards.h"
P
Paolo Bonzini 已提交
38 39 40
#include "hw/scsi/esp.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
41
#include "hw/nvram/sun_nvram.h"
42
#include "hw/nvram/chrp_nvram.h"
P
Paolo Bonzini 已提交
43 44
#include "hw/nvram/fw_cfg.h"
#include "hw/char/escc.h"
45 46
#include "hw/empty_slot.h"
#include "hw/loader.h"
B
Blue Swirl 已提交
47
#include "elf.h"
48
#include "sysemu/block-backend.h"
49
#include "trace.h"
50
#include "qemu/cutils.h"
51

52 53 54 55
/*
 * Sun4m architecture was used in the following machines:
 *
 * SPARCserver 6xxMP/xx
B
blueswir1 已提交
56 57
 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
 * SPARCclassic X (4/10)
58 59 60 61 62 63 64 65 66 67
 * SPARCstation LX/ZX (4/30)
 * SPARCstation Voyager
 * SPARCstation 10/xx, SPARCserver 10/xx
 * SPARCstation 5, SPARCserver 5
 * SPARCstation 20/xx, SPARCserver 20
 * SPARCstation 4
 *
 * See for example: http://www.sunhelp.org/faq/sunref1.html
 */

68
#define KERNEL_LOAD_ADDR     0x00004000
B
bellard 已提交
69
#define CMDLINE_ADDR         0x007ff000
B
bellard 已提交
70
#define INITRD_LOAD_ADDR     0x00800000
71
#define PROM_SIZE_MAX        (1024 * 1024)
B
blueswir1 已提交
72
#define PROM_VADDR           0xffd00000
B
blueswir1 已提交
73
#define PROM_FILENAME        "openbios-sparc32"
74
#define CFG_ADDR             0xd00000510ULL
75
#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
76 77
#define FW_CFG_SUN4M_WIDTH   (FW_CFG_ARCH_LOCAL + 0x01)
#define FW_CFG_SUN4M_HEIGHT  (FW_CFG_ARCH_LOCAL + 0x02)
78

B
bellard 已提交
79
#define MAX_CPUS 16
80
#define MAX_PILS 16
81
#define MAX_VSIMMS 4
82

83 84
#define ESCC_CLOCK 4915200

85
struct sun4m_hwdef {
A
Avi Kivity 已提交
86 87 88 89 90 91
    hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
    hwaddr serial_base, fd_base;
    hwaddr afx_base, idreg_base, dma_base, esp_base, le_base;
    hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base;
    hwaddr bpp_base, dbri_base, sx_base;
92
    struct {
A
Avi Kivity 已提交
93
        hwaddr reg_base, vram_base;
94
    } vsimm[MAX_VSIMMS];
A
Avi Kivity 已提交
95
    hwaddr ecc_base;
96
    uint64_t max_mem;
97 98 99 100
    uint32_t ecc_version;
    uint32_t iommu_version;
    uint16_t machine_id;
    uint8_t nvram_machine_id;
101 102
};

103
void DMA_init(ISABus *bus, int high_page_enable)
B
Blue Swirl 已提交
104 105 106
{
}

107 108
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
                            Error **errp)
B
blueswir1 已提交
109
{
110
    fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
B
blueswir1 已提交
111 112
}

113
static void nvram_init(Nvram *nvram, uint8_t *macaddr,
114 115
                       const char *cmdline, const char *boot_devices,
                       ram_addr_t RAM_size, uint32_t kernel_size,
B
blueswir1 已提交
116
                       int width, int height, int depth,
117
                       int nvram_machine_id, const char *arch)
B
bellard 已提交
118
{
B
blueswir1 已提交
119
    unsigned int i;
120
    int sysp_end;
B
blueswir1 已提交
121
    uint8_t image[0x1ff0];
122
    NvramClass *k = NVRAM_GET_CLASS(nvram);
B
blueswir1 已提交
123 124

    memset(image, '\0', sizeof(image));
B
bellard 已提交
125

126 127
    /* OpenBIOS nvram variables partition */
    sysp_end = chrp_nvram_create_system_partition(image, 0);
B
bellard 已提交
128

129 130
    /* Free space partition */
    chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end);
B
blueswir1 已提交
131

132 133
    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
                    nvram_machine_id);
B
blueswir1 已提交
134

135 136 137
    for (i = 0; i < sizeof(image); i++) {
        (k->write)(nvram, i, image[i]);
    }
B
bellard 已提交
138 139
}

A
Andreas Färber 已提交
140
void cpu_check_irqs(CPUSPARCState *env)
B
blueswir1 已提交
141
{
142 143
    CPUState *cs;

144 145 146
    /* We should be holding the BQL before we mess with IRQs */
    g_assert(qemu_mutex_iothread_locked());

B
blueswir1 已提交
147 148 149 150 151 152 153 154 155
    if (env->pil_in && (env->interrupt_index == 0 ||
                        (env->interrupt_index & ~15) == TT_EXTINT)) {
        unsigned int i;

        for (i = 15; i > 0; i--) {
            if (env->pil_in & (1 << i)) {
                int old_interrupt = env->interrupt_index;

                env->interrupt_index = TT_EXTINT | i;
156
                if (old_interrupt != env->interrupt_index) {
157
                    cs = CPU(sparc_env_get_cpu(env));
158
                    trace_sun4m_cpu_interrupt(i);
159
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
160
                }
B
blueswir1 已提交
161 162 163 164
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
165
        cs = CPU(sparc_env_get_cpu(env));
166
        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
B
blueswir1 已提交
167
        env->interrupt_index = 0;
168
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
B
blueswir1 已提交
169 170 171
    }
}

172
static void cpu_kick_irq(SPARCCPU *cpu)
173
{
174
    CPUSPARCState *env = &cpu->env;
175
    CPUState *cs = CPU(cpu);
176

177
    cs->halted = 0;
178
    cpu_check_irqs(env);
179
    qemu_cpu_kick(cs);
180 181
}

182 183
static void cpu_set_irq(void *opaque, int irq, int level)
{
184 185
    SPARCCPU *cpu = opaque;
    CPUSPARCState *env = &cpu->env;
186 187

    if (level) {
188
        trace_sun4m_cpu_set_irq_raise(irq);
B
blueswir1 已提交
189
        env->pil_in |= 1 << irq;
190
        cpu_kick_irq(cpu);
191
    } else {
192
        trace_sun4m_cpu_set_irq_lower(irq);
B
blueswir1 已提交
193 194
        env->pil_in &= ~(1 << irq);
        cpu_check_irqs(env);
195 196 197 198 199 200 201
    }
}

static void dummy_cpu_set_irq(void *opaque, int irq, int level)
{
}

B
bellard 已提交
202 203
static void main_cpu_reset(void *opaque)
{
204
    SPARCCPU *cpu = opaque;
205
    CPUState *cs = CPU(cpu);
206

207 208
    cpu_reset(cs);
    cs->halted = 0;
209 210 211 212
}

static void secondary_cpu_reset(void *opaque)
{
213
    SPARCCPU *cpu = opaque;
214
    CPUState *cs = CPU(cpu);
215

216 217
    cpu_reset(cs);
    cs->halted = 1;
B
bellard 已提交
218 219
}

B
blueswir1 已提交
220 221
static void cpu_halt_signal(void *opaque, int irq, int level)
{
222 223
    if (level && current_cpu) {
        cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT);
224
    }
B
blueswir1 已提交
225 226
}

227 228 229 230 231
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
    return addr - 0xf0000000ULL;
}

232
static unsigned long sun4m_load_kernel(const char *kernel_filename,
233
                                       const char *initrd_filename,
A
Anthony Liguori 已提交
234
                                       ram_addr_t RAM_size)
235 236 237 238
{
    int linux_boot;
    unsigned int i;
    long initrd_size, kernel_size;
239
    uint8_t *ptr;
240 241 242 243 244

    linux_boot = (kernel_filename != NULL);

    kernel_size = 0;
    if (linux_boot) {
B
Blue Swirl 已提交
245 246 247 248 249 250 251
        int bswap_needed;

#ifdef BSWAP_NEEDED
        bswap_needed = 1;
#else
        bswap_needed = 0;
#endif
252
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
253
                               NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
254
        if (kernel_size < 0)
255
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
B
Blue Swirl 已提交
256 257
                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                                    TARGET_PAGE_SIZE);
258
        if (kernel_size < 0)
259 260 261
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              RAM_size - KERNEL_LOAD_ADDR);
262 263 264 265 266 267 268 269 270
        if (kernel_size < 0) {
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }

        /* load initrd */
        initrd_size = 0;
        if (initrd_filename) {
271 272 273
            initrd_size = load_image_targphys(initrd_filename,
                                              INITRD_LOAD_ADDR,
                                              RAM_size - INITRD_LOAD_ADDR);
274 275 276 277 278 279 280 281
            if (initrd_size < 0) {
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                        initrd_filename);
                exit(1);
            }
        }
        if (initrd_size > 0) {
            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
282 283 284 285
                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
                if (ldl_p(ptr) == 0x48647253) { // HdrS
                    stl_p(ptr + 16, INITRD_LOAD_ADDR);
                    stl_p(ptr + 20, initrd_size);
286 287 288 289 290 291 292 293
                    break;
                }
            }
        }
    }
    return kernel_size;
}

A
Avi Kivity 已提交
294
static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
295 296 297 298
{
    DeviceState *dev;
    SysBusDevice *s;

299
    dev = qdev_create(NULL, TYPE_SUN4M_IOMMU);
300
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
301
    qdev_init_nofail(dev);
302
    s = SYS_BUS_DEVICE(dev);
303 304 305 306 307 308
    sysbus_connect_irq(s, 0, irq);
    sysbus_mmio_map(s, 0, addr);

    return s;
}

309
static void *sparc32_dma_init(hwaddr daddr, void *iommu, int is_ledma)
310 311 312 313
{
    DeviceState *dev;
    SysBusDevice *s;

314
    dev = qdev_create(NULL, is_ledma ? "sparc32-ledma" : "sparc32-espdma");
315
    object_property_set_link(OBJECT(dev), OBJECT(iommu), "iommu", &error_abort);
M
Markus Armbruster 已提交
316
    qdev_init_nofail(dev);
317
    s = SYS_BUS_DEVICE(dev);
318 319 320 321 322
    sysbus_mmio_map(s, 0, daddr);

    return s;
}

A
Avi Kivity 已提交
323 324
static DeviceState *slavio_intctl_init(hwaddr addr,
                                       hwaddr addrg,
B
Blue Swirl 已提交
325
                                       qemu_irq **parent_irq)
326 327 328 329 330 331
{
    DeviceState *dev;
    SysBusDevice *s;
    unsigned int i, j;

    dev = qdev_create(NULL, "slavio_intctl");
M
Markus Armbruster 已提交
332
    qdev_init_nofail(dev);
333

334
    s = SYS_BUS_DEVICE(dev);
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

    for (i = 0; i < MAX_CPUS; i++) {
        for (j = 0; j < MAX_PILS; j++) {
            sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
        }
    }
    sysbus_mmio_map(s, 0, addrg);
    for (i = 0; i < MAX_CPUS; i++) {
        sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
    }

    return dev;
}

#define SYS_TIMER_OFFSET      0x10000ULL
#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)

A
Avi Kivity 已提交
352
static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
353 354 355 356 357 358 359 360
                                  qemu_irq *cpu_irqs, unsigned int num_cpus)
{
    DeviceState *dev;
    SysBusDevice *s;
    unsigned int i;

    dev = qdev_create(NULL, "slavio_timer");
    qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
M
Markus Armbruster 已提交
361
    qdev_init_nofail(dev);
362
    s = SYS_BUS_DEVICE(dev);
363 364 365 366
    sysbus_connect_irq(s, 0, master_irq);
    sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);

    for (i = 0; i < MAX_CPUS; i++) {
A
Avi Kivity 已提交
367
        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
368 369 370 371
        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
    }
}

372 373 374 375 376 377 378 379 380 381 382
static qemu_irq  slavio_system_powerdown;

static void slavio_powerdown_req(Notifier *n, void *opaque)
{
    qemu_irq_raise(slavio_system_powerdown);
}

static Notifier slavio_system_powerdown_notifier = {
    .notify = slavio_powerdown_req
};

383 384 385 386 387 388
#define MISC_LEDS 0x01600000
#define MISC_CFG  0x01800000
#define MISC_DIAG 0x01a00000
#define MISC_MDM  0x01b00000
#define MISC_SYS  0x01f00000

A
Avi Kivity 已提交
389 390 391
static void slavio_misc_init(hwaddr base,
                             hwaddr aux1_base,
                             hwaddr aux2_base, qemu_irq irq,
392
                             qemu_irq fdc_tc)
393 394 395 396 397
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "slavio_misc");
M
Markus Armbruster 已提交
398
    qdev_init_nofail(dev);
399
    s = SYS_BUS_DEVICE(dev);
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    if (base) {
        /* 8 bit registers */
        /* Slavio control */
        sysbus_mmio_map(s, 0, base + MISC_CFG);
        /* Diagnostics */
        sysbus_mmio_map(s, 1, base + MISC_DIAG);
        /* Modem control */
        sysbus_mmio_map(s, 2, base + MISC_MDM);
        /* 16 bit registers */
        /* ss600mp diag LEDs */
        sysbus_mmio_map(s, 3, base + MISC_LEDS);
        /* 32 bit registers */
        /* System control */
        sysbus_mmio_map(s, 4, base + MISC_SYS);
    }
    if (aux1_base) {
        /* AUX 1 (Misc System Functions) */
        sysbus_mmio_map(s, 5, aux1_base);
    }
    if (aux2_base) {
        /* AUX 2 (Software Powerdown Control) */
        sysbus_mmio_map(s, 6, aux2_base);
    }
    sysbus_connect_irq(s, 0, irq);
    sysbus_connect_irq(s, 1, fdc_tc);
425 426
    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
427 428
}

A
Avi Kivity 已提交
429
static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
430 431 432 433 434 435
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "eccmemctl");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
436
    qdev_init_nofail(dev);
437
    s = SYS_BUS_DEVICE(dev);
438 439 440 441 442 443 444
    sysbus_connect_irq(s, 0, irq);
    sysbus_mmio_map(s, 0, base);
    if (version == 0) { // SS-600MP only
        sysbus_mmio_map(s, 1, base + 0x1000);
    }
}

A
Avi Kivity 已提交
445
static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
446 447 448 449 450
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "apc");
M
Markus Armbruster 已提交
451
    qdev_init_nofail(dev);
452
    s = SYS_BUS_DEVICE(dev);
453 454 455 456 457
    /* Power management (APC) XXX: not a Slavio device */
    sysbus_mmio_map(s, 0, power_base);
    sysbus_connect_irq(s, 0, cpu_halt);
}

458
static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width,
459 460 461 462 463 464 465 466 467 468
                     int height, int depth)
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "SUNW,tcx");
    qdev_prop_set_uint32(dev, "vram_size", vram_size);
    qdev_prop_set_uint16(dev, "width", width);
    qdev_prop_set_uint16(dev, "height", height);
    qdev_prop_set_uint16(dev, "depth", depth);
M
Markus Armbruster 已提交
469
    qdev_init_nofail(dev);
470
    s = SYS_BUS_DEVICE(dev);
471 472

    /* 10/ROM : FCode ROM */
473
    sysbus_mmio_map(s, 0, addr);
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
    /* 2/STIP : Stipple */
    sysbus_mmio_map(s, 1, addr + 0x04000000ULL);
    /* 3/BLIT : Blitter */
    sysbus_mmio_map(s, 2, addr + 0x06000000ULL);
    /* 5/RSTIP : Raw Stipple */
    sysbus_mmio_map(s, 3, addr + 0x0c000000ULL);
    /* 6/RBLIT : Raw Blitter */
    sysbus_mmio_map(s, 4, addr + 0x0e000000ULL);
    /* 7/TEC : Transform Engine */
    sysbus_mmio_map(s, 5, addr + 0x00700000ULL);
    /* 8/CMAP  : DAC */
    sysbus_mmio_map(s, 6, addr + 0x00200000ULL);
    /* 9/THC : */
    if (depth == 8) {
        sysbus_mmio_map(s, 7, addr + 0x00300000ULL);
489
    } else {
490
        sysbus_mmio_map(s, 7, addr + 0x00301000ULL);
491
    }
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
    /* 11/DHC : */
    sysbus_mmio_map(s, 8, addr + 0x00240000ULL);
    /* 12/ALT : */
    sysbus_mmio_map(s, 9, addr + 0x00280000ULL);
    /* 0/DFB8 : 8-bit plane */
    sysbus_mmio_map(s, 10, addr + 0x00800000ULL);
    /* 1/DFB24 : 24bit plane */
    sysbus_mmio_map(s, 11, addr + 0x02000000ULL);
    /* 4/RDFB32: Raw framebuffer. Control plane */
    sysbus_mmio_map(s, 12, addr + 0x0a000000ULL);
    /* 9/THC24bits : NetBSD writes here even with 8-bit display: dummy */
    if (depth == 8) {
        sysbus_mmio_map(s, 13, addr + 0x00301000ULL);
    }

    sysbus_connect_irq(s, 0, irq);
508 509
}

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533
static void cg3_init(hwaddr addr, qemu_irq irq, int vram_size, int width,
                     int height, int depth)
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "cgthree");
    qdev_prop_set_uint32(dev, "vram-size", vram_size);
    qdev_prop_set_uint16(dev, "width", width);
    qdev_prop_set_uint16(dev, "height", height);
    qdev_prop_set_uint16(dev, "depth", depth);
    qdev_init_nofail(dev);
    s = SYS_BUS_DEVICE(dev);

    /* FCode ROM */
    sysbus_mmio_map(s, 0, addr);
    /* DAC */
    sysbus_mmio_map(s, 1, addr + 0x400000ULL);
    /* 8-bit plane */
    sysbus_mmio_map(s, 2, addr + 0x800000ULL);

    sysbus_connect_irq(s, 0, irq);
}

B
Blue Swirl 已提交
534
/* NCR89C100/MACIO Internal ID register */
535 536 537

#define TYPE_MACIO_ID_REGISTER "macio_idreg"

B
Blue Swirl 已提交
538 539
static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };

A
Avi Kivity 已提交
540
static void idreg_init(hwaddr addr)
B
Blue Swirl 已提交
541 542 543 544
{
    DeviceState *dev;
    SysBusDevice *s;

545
    dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
M
Markus Armbruster 已提交
546
    qdev_init_nofail(dev);
547
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
548 549

    sysbus_mmio_map(s, 0, addr);
550 551
    cpu_physical_memory_write_rom(&address_space_memory,
                                  addr, idreg_data, sizeof(idreg_data));
B
Blue Swirl 已提交
552 553
}

554 555 556
#define MACIO_ID_REGISTER(obj) \
    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)

A
Avi Kivity 已提交
557
typedef struct IDRegState {
558 559
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
560 561 562
    MemoryRegion mem;
} IDRegState;

X
xiaoqiang zhao 已提交
563
static void idreg_init1(Object *obj)
B
Blue Swirl 已提交
564
{
X
xiaoqiang zhao 已提交
565 566
    IDRegState *s = MACIO_ID_REGISTER(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
B
Blue Swirl 已提交
567

568
    memory_region_init_ram_nomigrate(&s->mem, obj,
569
                           "sun4m.idreg", sizeof(idreg_data), &error_fatal);
570
    vmstate_register_ram_global(&s->mem);
A
Avi Kivity 已提交
571
    memory_region_set_readonly(&s->mem, true);
572
    sysbus_init_mmio(dev, &s->mem);
573 574
}

575
static const TypeInfo idreg_info = {
576
    .name          = TYPE_MACIO_ID_REGISTER,
577 578
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IDRegState),
X
xiaoqiang zhao 已提交
579
    .instance_init = idreg_init1,
B
Blue Swirl 已提交
580 581
};

582 583 584
#define TYPE_TCX_AFX "tcx_afx"
#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)

A
Avi Kivity 已提交
585
typedef struct AFXState {
586 587
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
588 589 590
    MemoryRegion mem;
} AFXState;

A
Artyom Tarasenko 已提交
591
/* SS-5 TCX AFX register */
A
Avi Kivity 已提交
592
static void afx_init(hwaddr addr)
A
Artyom Tarasenko 已提交
593 594 595 596
{
    DeviceState *dev;
    SysBusDevice *s;

597
    dev = qdev_create(NULL, TYPE_TCX_AFX);
A
Artyom Tarasenko 已提交
598
    qdev_init_nofail(dev);
599
    s = SYS_BUS_DEVICE(dev);
A
Artyom Tarasenko 已提交
600 601 602 603

    sysbus_mmio_map(s, 0, addr);
}

X
xiaoqiang zhao 已提交
604
static void afx_init1(Object *obj)
A
Artyom Tarasenko 已提交
605
{
X
xiaoqiang zhao 已提交
606 607
    AFXState *s = TCX_AFX(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
A
Artyom Tarasenko 已提交
608

609
    memory_region_init_ram_nomigrate(&s->mem, obj, "sun4m.afx", 4, &error_fatal);
610
    vmstate_register_ram_global(&s->mem);
611
    sysbus_init_mmio(dev, &s->mem);
612 613
}

614
static const TypeInfo afx_info = {
615
    .name          = TYPE_TCX_AFX,
616 617
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AFXState),
X
xiaoqiang zhao 已提交
618
    .instance_init = afx_init1,
A
Artyom Tarasenko 已提交
619 620
};

621 622 623
#define TYPE_OPENPROM "openprom"
#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)

A
Avi Kivity 已提交
624
typedef struct PROMState {
625 626
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
627 628 629
    MemoryRegion prom;
} PROMState;

B
Blue Swirl 已提交
630
/* Boot PROM (OpenBIOS) */
631 632
static uint64_t translate_prom_address(void *opaque, uint64_t addr)
{
A
Avi Kivity 已提交
633
    hwaddr *base_addr = (hwaddr *)opaque;
634 635 636
    return addr + *base_addr - PROM_VADDR;
}

A
Avi Kivity 已提交
637
static void prom_init(hwaddr addr, const char *bios_name)
B
Blue Swirl 已提交
638 639 640 641 642 643
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

644
    dev = qdev_create(NULL, TYPE_OPENPROM);
M
Markus Armbruster 已提交
645
    qdev_init_nofail(dev);
646
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
647 648 649 650 651 652 653 654 655

    sysbus_mmio_map(s, 0, addr);

    /* load boot prom */
    if (bios_name == NULL) {
        bios_name = PROM_FILENAME;
    }
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
656
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
657
                       NULL, NULL, 1, EM_SPARC, 0, 0);
B
Blue Swirl 已提交
658 659 660
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
661
        g_free(filename);
B
Blue Swirl 已提交
662 663 664 665 666 667 668 669 670
    } else {
        ret = -1;
    }
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
        exit(1);
    }
}

X
xiaoqiang zhao 已提交
671
static void prom_init1(Object *obj)
B
Blue Swirl 已提交
672
{
X
xiaoqiang zhao 已提交
673 674
    PROMState *s = OPENPROM(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
B
Blue Swirl 已提交
675

676
    memory_region_init_ram_nomigrate(&s->prom, obj, "sun4m.prom", PROM_SIZE_MAX,
677
                           &error_fatal);
678
    vmstate_register_ram_global(&s->prom);
A
Avi Kivity 已提交
679
    memory_region_set_readonly(&s->prom, true);
680
    sysbus_init_mmio(dev, &s->prom);
B
Blue Swirl 已提交
681 682
}

683 684 685 686 687 688
static Property prom_properties[] = {
    {/* end of property list */},
};

static void prom_class_init(ObjectClass *klass, void *data)
{
689
    DeviceClass *dc = DEVICE_CLASS(klass);
690

691
    dc->props = prom_properties;
692 693
}

694
static const TypeInfo prom_info = {
695
    .name          = TYPE_OPENPROM,
696 697 698
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PROMState),
    .class_init    = prom_class_init,
X
xiaoqiang zhao 已提交
699
    .instance_init = prom_init1,
B
Blue Swirl 已提交
700 701
};

702 703 704 705 706 707
#define TYPE_SUN4M_MEMORY "memory"
#define SUN4M_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4M_MEMORY)

typedef struct RamDevice {
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
708
    MemoryRegion ram;
709
    uint64_t size;
G
Gerd Hoffmann 已提交
710 711
} RamDevice;

B
Blue Swirl 已提交
712
/* System RAM */
X
xiaoqiang zhao 已提交
713
static void ram_realize(DeviceState *dev, Error **errp)
B
Blue Swirl 已提交
714
{
715
    RamDevice *d = SUN4M_RAM(dev);
X
xiaoqiang zhao 已提交
716
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
717

718 719
    memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram",
                                         d->size);
X
xiaoqiang zhao 已提交
720
    sysbus_init_mmio(sbd, &d->ram);
B
Blue Swirl 已提交
721 722
}

A
Avi Kivity 已提交
723
static void ram_init(hwaddr addr, ram_addr_t RAM_size,
B
Blue Swirl 已提交
724 725 726 727
                     uint64_t max_mem)
{
    DeviceState *dev;
    SysBusDevice *s;
G
Gerd Hoffmann 已提交
728
    RamDevice *d;
B
Blue Swirl 已提交
729 730 731 732 733 734 735 736 737 738

    /* allocate RAM */
    if ((uint64_t)RAM_size > max_mem) {
        fprintf(stderr,
                "qemu: Too much memory for this machine: %d, maximum %d\n",
                (unsigned int)(RAM_size / (1024 * 1024)),
                (unsigned int)(max_mem / (1024 * 1024)));
        exit(1);
    }
    dev = qdev_create(NULL, "memory");
739
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
740

741
    d = SUN4M_RAM(dev);
G
Gerd Hoffmann 已提交
742
    d->size = RAM_size;
M
Markus Armbruster 已提交
743
    qdev_init_nofail(dev);
G
Gerd Hoffmann 已提交
744

B
Blue Swirl 已提交
745 746 747
    sysbus_mmio_map(s, 0, addr);
}

748 749 750 751 752 753 754
static Property ram_properties[] = {
    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
    DEFINE_PROP_END_OF_LIST(),
};

static void ram_class_init(ObjectClass *klass, void *data)
{
755
    DeviceClass *dc = DEVICE_CLASS(klass);
756

X
xiaoqiang zhao 已提交
757
    dc->realize = ram_realize;
758
    dc->props = ram_properties;
759 760
}

761
static const TypeInfo ram_info = {
762
    .name          = TYPE_SUN4M_MEMORY,
763 764 765
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(RamDevice),
    .class_init    = ram_class_init,
B
Blue Swirl 已提交
766 767
};

768
static void cpu_devinit(const char *cpu_type, unsigned int id,
769
                        uint64_t prom_addr, qemu_irq **cpu_irqs)
B
Blue Swirl 已提交
770
{
771
    CPUState *cs;
772
    SPARCCPU *cpu;
A
Andreas Färber 已提交
773
    CPUSPARCState *env;
B
Blue Swirl 已提交
774

775
    cpu = SPARC_CPU(cpu_create(cpu_type));
776
    env = &cpu->env;
B
Blue Swirl 已提交
777 778 779

    cpu_sparc_set_id(env, id);
    if (id == 0) {
780
        qemu_register_reset(main_cpu_reset, cpu);
B
Blue Swirl 已提交
781
    } else {
782
        qemu_register_reset(secondary_cpu_reset, cpu);
783 784
        cs = CPU(cpu);
        cs->halted = 1;
B
Blue Swirl 已提交
785
    }
786
    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
B
Blue Swirl 已提交
787 788 789
    env->prom_addr = prom_addr;
}

B
Blue Swirl 已提交
790 791 792 793
static void dummy_fdc_tc(void *opaque, int irq, int level)
{
}

794
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
795
                          MachineState *machine)
796
{
797
    DeviceState *slavio_intctl;
B
bellard 已提交
798
    unsigned int i;
799
    void *iommu, *nvram;
800
    DeviceState *espdma, *esp, *ledma, *lance;
801 802
    SysBusDevice *sbd;
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS];
803
    qemu_irq fdc_tc;
B
blueswir1 已提交
804
    unsigned long kernel_size;
G
Gerd Hoffmann 已提交
805
    DriveInfo *fd[MAX_FD];
L
Laszlo Ersek 已提交
806
    FWCfgState *fw_cfg;
807
    unsigned int num_vsimms;
808

B
bellard 已提交
809 810
    /* init CPUs */
    for(i = 0; i < smp_cpus; i++) {
811
        cpu_devinit(machine->cpu_type, i, hwdef->slavio_base, &cpu_irqs[i]);
B
bellard 已提交
812
    }
813 814 815 816

    for (i = smp_cpus; i < MAX_CPUS; i++)
        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);

817 818

    /* set up devices */
819
    ram_init(0, machine->ram_size, hwdef->max_mem);
820 821
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
822
        empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size);
823
    }
B
Blue Swirl 已提交
824

B
Blue Swirl 已提交
825 826
    prom_init(hwdef->slavio_base, bios_name);

827 828
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
B
Blue Swirl 已提交
829
                                       cpu_irqs);
830 831

    for (i = 0; i < 32; i++) {
832
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
833 834
    }
    for (i = 0; i < MAX_CPUS; i++) {
835
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
836
    }
837

838
    if (hwdef->idreg_base) {
B
Blue Swirl 已提交
839
        idreg_init(hwdef->idreg_base);
B
blueswir1 已提交
840 841
    }

A
Artyom Tarasenko 已提交
842 843 844 845
    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

846
    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
847
                       slavio_irq[30]);
848

849 850 851 852 853 854 855 856
    if (hwdef->iommu_pad_base) {
        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
           Software shouldn't use aliased addresses, neither should it crash
           when does. Using empty_slot instead of aliasing can help with
           debugging such accesses */
        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
    }

857 858 859
    espdma = sparc32_dma_init(hwdef->dma_base, iommu, 0);
    sbd = SYS_BUS_DEVICE(espdma);
    sysbus_connect_irq(sbd, 0, slavio_irq[18]);
860

861 862 863 864 865 866 867
    esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp"));
    sbd = SYS_BUS_DEVICE(esp);
    sysbus_mmio_map(sbd, 0, hwdef->esp_base);
    sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(espdma, 0));
    qdev_connect_gpio_out(espdma, 0, qdev_get_gpio_in(esp, 0));
    qdev_connect_gpio_out(espdma, 1, qdev_get_gpio_in(esp, 1));

868 869 870
    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, iommu, 1);
    sbd = SYS_BUS_DEVICE(ledma);
    sysbus_connect_irq(sbd, 0, slavio_irq[16]);
B
bellard 已提交
871

872 873 874 875 876 877
    lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance"));
    sbd = SYS_BUS_DEVICE(lance);
    sysbus_mmio_map(sbd, 0, hwdef->le_base);
    sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(ledma, 0));
    qdev_connect_gpio_out(ledma, 0, qdev_get_gpio_in(lance, 0));

B
blueswir1 已提交
878
    if (graphic_depth != 8 && graphic_depth != 24) {
879
        error_report("Unsupported depth: %d", graphic_depth);
B
blueswir1 已提交
880 881
        exit (1);
    }
882 883
    num_vsimms = 0;
    if (num_vsimms == 0) {
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
        if (vga_interface_type == VGA_CG3) {
            if (graphic_depth != 8) {
                error_report("Unsupported depth: %d", graphic_depth);
                exit(1);
            }

            if (!(graphic_width == 1024 && graphic_height == 768) &&
                !(graphic_width == 1152 && graphic_height == 900)) {
                error_report("Unsupported resolution: %d x %d", graphic_width,
                             graphic_height);
                exit(1);
            }

            /* sbus irq 5 */
            cg3_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
        } else {
            /* If no display specified, default to TCX */
            if (graphic_depth != 8 && graphic_depth != 24) {
                error_report("Unsupported depth: %d", graphic_depth);
                exit(1);
            }

            if (!(graphic_width == 1024 && graphic_height == 768)) {
                error_report("Unsupported resolution: %d x %d",
                             graphic_width, graphic_height);
                exit(1);
            }

913 914
            tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
915
        }
916 917 918 919 920 921 922 923 924 925 926 927
    }

    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
        /* vsimm registers probed by OBP */
        if (hwdef->vsimm[i].reg_base) {
            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
        }
    }

    if (hwdef->sx_base) {
        empty_slot_init(hwdef->sx_base, 0x2000);
    }
928

929
    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8);
B
blueswir1 已提交
930

931
    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
B
blueswir1 已提交
932

933
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
934
                              !machine->enable_graphics, ESCC_CLOCK, 1);
S
Stefan Weil 已提交
935 936
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
937
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
A
aurel32 已提交
938
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
B
blueswir1 已提交
939

940
    if (hwdef->apc_base) {
941
        apc_init(hwdef->apc_base, qemu_allocate_irq(cpu_halt_signal, NULL, 0));
942
    }
B
blueswir1 已提交
943

944
    if (hwdef->fd_base) {
T
ths 已提交
945
        /* there is zero or one floppy drive */
946
        memset(fd, 0, sizeof(fd));
G
Gerd Hoffmann 已提交
947
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
948
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
949
                          &fdc_tc);
B
Blue Swirl 已提交
950
    } else {
951
        fdc_tc = qemu_allocate_irq(dummy_fdc_tc, NULL, 0);
T
ths 已提交
952 953
    }

B
Blue Swirl 已提交
954 955 956
    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

B
Blue Swirl 已提交
957 958
    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
959
                             slavio_irq[5]);
B
Blue Swirl 已提交
960
    }
961

962 963 964 965 966 967 968 969 970 971 972 973 974
    if (hwdef->dbri_base) {
        /* ISDN chip with attached CS4215 audio codec */
        /* prom space */
        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
        /* reg space */
        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
    }

    if (hwdef->bpp_base) {
        /* parallel port */
        empty_slot_init(hwdef->bpp_base, 0x20);
    }

975 976 977
    kernel_size = sun4m_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    machine->ram_size);
978

979 980 981 982
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline,
               machine->boot_order, machine->ram_size, kernel_size,
               graphic_width, graphic_height, graphic_depth,
               hwdef->nvram_machine_id, "Sun4m");
983

984
    if (hwdef->ecc_base)
985
        ecc_init(hwdef->ecc_base, slavio_irq[28],
986
                 hwdef->ecc_version);
987

988
    fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
989
    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
990
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
991 992
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
993
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
994 995
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
996 997
    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
998
    if (machine->kernel_cmdline) {
999
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1000
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
1001 1002
                         machine->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
B
Blue Swirl 已提交
1003
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
1004
                       strlen(machine->kernel_cmdline) + 1);
1005 1006
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
B
Blue Swirl 已提交
1007
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1008 1009 1010
    }
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
1011
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
1012
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1013 1014
}

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
enum {
    ss5_id = 32,
    vger_id,
    lx_id,
    ss4_id,
    scls_id,
    sbook_id,
    ss10_id = 64,
    ss20_id,
    ss600mp_id,
};

1027
static const struct sun4m_hwdef sun4m_hwdefs[] = {
1028 1029 1030
    /* SS-5 */
    {
        .iommu_base   = 0x10000000,
1031 1032
        .iommu_pad_base = 0x10004000,
        .iommu_pad_len  = 0x0fffb000,
1033 1034
        .tcx_base     = 0x50000000,
        .cs_base      = 0x6c000000,
B
blueswir1 已提交
1035
        .slavio_base  = 0x70000000,
1036 1037 1038 1039 1040 1041
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
B
blueswir1 已提交
1042
        .idreg_base   = 0x78000000,
1043 1044 1045
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
1046
        .apc_base     = 0x6a000000,
A
Artyom Tarasenko 已提交
1047
        .afx_base     = 0x6e000000,
1048 1049
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1050 1051
        .nvram_machine_id = 0x80,
        .machine_id = ss5_id,
1052
        .iommu_version = 0x05000000,
1053
        .max_mem = 0x10000000,
B
blueswir1 已提交
1054 1055 1056
    },
    /* SS-10 */
    {
1057 1058 1059 1060 1061 1062 1063 1064 1065
        .iommu_base   = 0xfe0000000ULL,
        .tcx_base     = 0xe20000000ULL,
        .slavio_base  = 0xff0000000ULL,
        .ms_kb_base   = 0xff1000000ULL,
        .serial_base  = 0xff1100000ULL,
        .nvram_base   = 0xff1200000ULL,
        .fd_base      = 0xff1700000ULL,
        .counter_base = 0xff1300000ULL,
        .intctl_base  = 0xff1400000ULL,
B
blueswir1 已提交
1066
        .idreg_base   = 0xef0000000ULL,
1067 1068 1069
        .dma_base     = 0xef0400000ULL,
        .esp_base     = 0xef0800000ULL,
        .le_base      = 0xef0c00000ULL,
1070
        .apc_base     = 0xefa000000ULL, // XXX should not exist
1071 1072
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL,
1073 1074
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x10000000, // version 0, implementation 1
1075 1076
        .nvram_machine_id = 0x72,
        .machine_id = ss10_id,
1077
        .iommu_version = 0x03000000,
B
blueswir1 已提交
1078
        .max_mem = 0xf00000000ULL,
1079
    },
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    /* SS-600MP */
    {
        .iommu_base   = 0xfe0000000ULL,
        .tcx_base     = 0xe20000000ULL,
        .slavio_base  = 0xff0000000ULL,
        .ms_kb_base   = 0xff1000000ULL,
        .serial_base  = 0xff1100000ULL,
        .nvram_base   = 0xff1200000ULL,
        .counter_base = 0xff1300000ULL,
        .intctl_base  = 0xff1400000ULL,
        .dma_base     = 0xef0081000ULL,
        .esp_base     = 0xef0080000ULL,
        .le_base      = 0xef0060000ULL,
1093
        .apc_base     = 0xefa000000ULL, // XXX should not exist
1094 1095
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
1096 1097
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x00000000, // version 0, implementation 0
1098 1099
        .nvram_machine_id = 0x71,
        .machine_id = ss600mp_id,
1100
        .iommu_version = 0x01000000,
B
blueswir1 已提交
1101
        .max_mem = 0xf00000000ULL,
1102
    },
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
    /* SS-20 */
    {
        .iommu_base   = 0xfe0000000ULL,
        .tcx_base     = 0xe20000000ULL,
        .slavio_base  = 0xff0000000ULL,
        .ms_kb_base   = 0xff1000000ULL,
        .serial_base  = 0xff1100000ULL,
        .nvram_base   = 0xff1200000ULL,
        .fd_base      = 0xff1700000ULL,
        .counter_base = 0xff1300000ULL,
        .intctl_base  = 0xff1400000ULL,
B
blueswir1 已提交
1114
        .idreg_base   = 0xef0000000ULL,
1115 1116 1117
        .dma_base     = 0xef0400000ULL,
        .esp_base     = 0xef0800000ULL,
        .le_base      = 0xef0c00000ULL,
1118
        .bpp_base     = 0xef4800000ULL,
1119
        .apc_base     = 0xefa000000ULL, // XXX should not exist
B
blueswir1 已提交
1120 1121
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL,
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
        .dbri_base    = 0xee0000000ULL,
        .sx_base      = 0xf80000000ULL,
        .vsimm        = {
            {
                .reg_base  = 0x9c000000ULL,
                .vram_base = 0xfc000000ULL
            }, {
                .reg_base  = 0x90000000ULL,
                .vram_base = 0xf0000000ULL
            }, {
                .reg_base  = 0x94000000ULL
            }, {
                .reg_base  = 0x98000000ULL
            }
        },
1137 1138
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x20000000, // version 0, implementation 2
1139 1140
        .nvram_machine_id = 0x72,
        .machine_id = ss20_id,
1141
        .iommu_version = 0x13000000,
B
blueswir1 已提交
1142
        .max_mem = 0xf00000000ULL,
1143
    },
B
blueswir1 已提交
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
    /* Voyager */
    {
        .iommu_base   = 0x10000000,
        .tcx_base     = 0x50000000,
        .slavio_base  = 0x70000000,
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .idreg_base   = 0x78000000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
        .apc_base     = 0x71300000, // pmc
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1162 1163
        .nvram_machine_id = 0x80,
        .machine_id = vger_id,
B
blueswir1 已提交
1164 1165 1166 1167 1168 1169
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
    },
    /* LX */
    {
        .iommu_base   = 0x10000000,
1170 1171
        .iommu_pad_base = 0x10004000,
        .iommu_pad_len  = 0x0fffb000,
B
blueswir1 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
        .tcx_base     = 0x50000000,
        .slavio_base  = 0x70000000,
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .idreg_base   = 0x78000000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1186 1187
        .nvram_machine_id = 0x80,
        .machine_id = lx_id,
B
blueswir1 已提交
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
        .iommu_version = 0x04000000,
        .max_mem = 0x10000000,
    },
    /* SS-4 */
    {
        .iommu_base   = 0x10000000,
        .tcx_base     = 0x50000000,
        .cs_base      = 0x6c000000,
        .slavio_base  = 0x70000000,
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .idreg_base   = 0x78000000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
        .apc_base     = 0x6a000000,
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1210 1211
        .nvram_machine_id = 0x80,
        .machine_id = ss4_id,
B
blueswir1 已提交
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
    },
    /* SPARCClassic */
    {
        .iommu_base   = 0x10000000,
        .tcx_base     = 0x50000000,
        .slavio_base  = 0x70000000,
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .idreg_base   = 0x78000000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
        .apc_base     = 0x6a000000,
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1233 1234
        .nvram_machine_id = 0x80,
        .machine_id = scls_id,
B
blueswir1 已提交
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
    },
    /* SPARCbook */
    {
        .iommu_base   = 0x10000000,
        .tcx_base     = 0x50000000, // XXX
        .slavio_base  = 0x70000000,
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .idreg_base   = 0x78000000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
        .apc_base     = 0x6a000000,
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1256 1257
        .nvram_machine_id = 0x80,
        .machine_id = sbook_id,
B
blueswir1 已提交
1258 1259 1260
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
    },
1261 1262 1263
};

/* SPARCstation 5 hardware initialisation */
1264
static void ss5_init(MachineState *machine)
1265
{
1266
    sun4m_hw_init(&sun4m_hwdefs[0], machine);
1267
}
B
bellard 已提交
1268

B
blueswir1 已提交
1269
/* SPARCstation 10 hardware initialisation */
1270
static void ss10_init(MachineState *machine)
B
blueswir1 已提交
1271
{
1272
    sun4m_hw_init(&sun4m_hwdefs[1], machine);
B
blueswir1 已提交
1273 1274
}

1275
/* SPARCserver 600MP hardware initialisation */
1276
static void ss600mp_init(MachineState *machine)
1277
{
1278
    sun4m_hw_init(&sun4m_hwdefs[2], machine);
1279 1280
}

1281
/* SPARCstation 20 hardware initialisation */
1282
static void ss20_init(MachineState *machine)
1283
{
1284
    sun4m_hw_init(&sun4m_hwdefs[3], machine);
B
blueswir1 已提交
1285 1286
}

B
blueswir1 已提交
1287
/* SPARCstation Voyager hardware initialisation */
1288
static void vger_init(MachineState *machine)
B
blueswir1 已提交
1289
{
1290
    sun4m_hw_init(&sun4m_hwdefs[4], machine);
B
blueswir1 已提交
1291 1292 1293
}

/* SPARCstation LX hardware initialisation */
1294
static void ss_lx_init(MachineState *machine)
B
blueswir1 已提交
1295
{
1296
    sun4m_hw_init(&sun4m_hwdefs[5], machine);
B
blueswir1 已提交
1297 1298 1299
}

/* SPARCstation 4 hardware initialisation */
1300
static void ss4_init(MachineState *machine)
B
blueswir1 已提交
1301
{
1302
    sun4m_hw_init(&sun4m_hwdefs[6], machine);
B
blueswir1 已提交
1303 1304 1305
}

/* SPARCClassic hardware initialisation */
1306
static void scls_init(MachineState *machine)
B
blueswir1 已提交
1307
{
1308
    sun4m_hw_init(&sun4m_hwdefs[7], machine);
B
blueswir1 已提交
1309 1310 1311
}

/* SPARCbook hardware initialisation */
1312
static void sbook_init(MachineState *machine)
B
blueswir1 已提交
1313
{
1314
    sun4m_hw_init(&sun4m_hwdefs[8], machine);
B
blueswir1 已提交
1315 1316
}

1317
static void ss5_class_init(ObjectClass *oc, void *data)
1318
{
1319 1320
    MachineClass *mc = MACHINE_CLASS(oc);

1321 1322 1323 1324 1325
    mc->desc = "Sun4m platform, SPARCstation 5";
    mc->init = ss5_init;
    mc->block_default_type = IF_SCSI;
    mc->is_default = 1;
    mc->default_boot_order = "c";
1326
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1327
}
B
blueswir1 已提交
1328

1329 1330 1331 1332 1333
static const TypeInfo ss5_type = {
    .name = MACHINE_TYPE_NAME("SS-5"),
    .parent = TYPE_MACHINE,
    .class_init = ss5_class_init,
};
1334

1335
static void ss10_class_init(ObjectClass *oc, void *data)
1336
{
1337 1338
    MachineClass *mc = MACHINE_CLASS(oc);

1339 1340 1341 1342 1343
    mc->desc = "Sun4m platform, SPARCstation 10";
    mc->init = ss10_init;
    mc->block_default_type = IF_SCSI;
    mc->max_cpus = 4;
    mc->default_boot_order = "c";
1344
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1345
}
1346

1347 1348 1349 1350 1351
static const TypeInfo ss10_type = {
    .name = MACHINE_TYPE_NAME("SS-10"),
    .parent = TYPE_MACHINE,
    .class_init = ss10_class_init,
};
1352

1353
static void ss600mp_class_init(ObjectClass *oc, void *data)
1354
{
1355 1356
    MachineClass *mc = MACHINE_CLASS(oc);

1357 1358 1359 1360 1361
    mc->desc = "Sun4m platform, SPARCserver 600MP";
    mc->init = ss600mp_init;
    mc->block_default_type = IF_SCSI;
    mc->max_cpus = 4;
    mc->default_boot_order = "c";
1362
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1363
}
B
blueswir1 已提交
1364

1365 1366 1367 1368 1369
static const TypeInfo ss600mp_type = {
    .name = MACHINE_TYPE_NAME("SS-600MP"),
    .parent = TYPE_MACHINE,
    .class_init = ss600mp_class_init,
};
B
blueswir1 已提交
1370

1371
static void ss20_class_init(ObjectClass *oc, void *data)
1372
{
1373 1374
    MachineClass *mc = MACHINE_CLASS(oc);

1375 1376 1377 1378 1379
    mc->desc = "Sun4m platform, SPARCstation 20";
    mc->init = ss20_init;
    mc->block_default_type = IF_SCSI;
    mc->max_cpus = 4;
    mc->default_boot_order = "c";
1380
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1381
}
B
blueswir1 已提交
1382

1383 1384 1385 1386 1387
static const TypeInfo ss20_type = {
    .name = MACHINE_TYPE_NAME("SS-20"),
    .parent = TYPE_MACHINE,
    .class_init = ss20_class_init,
};
B
blueswir1 已提交
1388

1389
static void voyager_class_init(ObjectClass *oc, void *data)
1390
{
1391 1392
    MachineClass *mc = MACHINE_CLASS(oc);

1393 1394 1395 1396
    mc->desc = "Sun4m platform, SPARCstation Voyager";
    mc->init = vger_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1397
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1398 1399
}

1400 1401 1402 1403 1404
static const TypeInfo voyager_type = {
    .name = MACHINE_TYPE_NAME("Voyager"),
    .parent = TYPE_MACHINE,
    .class_init = voyager_class_init,
};
1405

1406
static void ss_lx_class_init(ObjectClass *oc, void *data)
1407
{
1408 1409
    MachineClass *mc = MACHINE_CLASS(oc);

1410 1411 1412 1413
    mc->desc = "Sun4m platform, SPARCstation LX";
    mc->init = ss_lx_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1414
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I");
1415 1416
}

1417 1418 1419 1420 1421
static const TypeInfo ss_lx_type = {
    .name = MACHINE_TYPE_NAME("LX"),
    .parent = TYPE_MACHINE,
    .class_init = ss_lx_class_init,
};
1422

1423
static void ss4_class_init(ObjectClass *oc, void *data)
1424
{
1425 1426
    MachineClass *mc = MACHINE_CLASS(oc);

1427 1428 1429 1430
    mc->desc = "Sun4m platform, SPARCstation 4";
    mc->init = ss4_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1431
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1432 1433
}

1434 1435 1436 1437 1438
static const TypeInfo ss4_type = {
    .name = MACHINE_TYPE_NAME("SS-4"),
    .parent = TYPE_MACHINE,
    .class_init = ss4_class_init,
};
1439

1440
static void scls_class_init(ObjectClass *oc, void *data)
1441
{
1442 1443
    MachineClass *mc = MACHINE_CLASS(oc);

1444 1445 1446 1447
    mc->desc = "Sun4m platform, SPARCClassic";
    mc->init = scls_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1448
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I");
1449 1450
}

1451 1452 1453 1454 1455
static const TypeInfo scls_type = {
    .name = MACHINE_TYPE_NAME("SPARCClassic"),
    .parent = TYPE_MACHINE,
    .class_init = scls_class_init,
};
1456

1457
static void sbook_class_init(ObjectClass *oc, void *data)
1458
{
1459 1460
    MachineClass *mc = MACHINE_CLASS(oc);

1461 1462 1463 1464
    mc->desc = "Sun4m platform, SPARCbook";
    mc->init = sbook_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1465
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I");
1466 1467
}

1468 1469 1470 1471 1472
static const TypeInfo sbook_type = {
    .name = MACHINE_TYPE_NAME("SPARCbook"),
    .parent = TYPE_MACHINE,
    .class_init = sbook_class_init,
};
B
blueswir1 已提交
1473

A
Andreas Färber 已提交
1474 1475 1476 1477 1478 1479 1480
static void sun4m_register_types(void)
{
    type_register_static(&idreg_info);
    type_register_static(&afx_info);
    type_register_static(&prom_info);
    type_register_static(&ram_info);

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
    type_register_static(&ss5_type);
    type_register_static(&ss10_type);
    type_register_static(&ss600mp_type);
    type_register_static(&ss20_type);
    type_register_static(&voyager_type);
    type_register_static(&ss_lx_type);
    type_register_static(&ss4_type);
    type_register_static(&scls_type);
    type_register_static(&sbook_type);
}

A
Andreas Färber 已提交
1492
type_init(sun4m_register_types)