sun4m.c 44.5 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 299 300
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "iommu");
    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;
}

A
Avi Kivity 已提交
309
static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
B
Bob Breuer 已提交
310
                              void *iommu, qemu_irq *dev_irq, int is_ledma)
311 312 313 314
{
    DeviceState *dev;
    SysBusDevice *s;

315
    dev = qdev_create(NULL, "sparc32-dma-device");
316
    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
B
Bob Breuer 已提交
317
    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
M
Markus Armbruster 已提交
318
    qdev_init_nofail(dev);
319
    s = SYS_BUS_DEVICE(dev);
320 321 322 323 324 325 326
    sysbus_connect_irq(s, 0, parent_irq);
    *dev_irq = qdev_get_gpio_in(dev, 0);
    sysbus_mmio_map(s, 0, daddr);

    return s;
}

A
Avi Kivity 已提交
327
static void lance_init(NICInfo *nd, hwaddr leaddr,
328
                       void *dma_opaque, qemu_irq irq)
P
Paul Brook 已提交
329 330 331
{
    DeviceState *dev;
    SysBusDevice *s;
332
    qemu_irq reset;
P
Paul Brook 已提交
333 334 335 336

    qemu_check_nic_model(&nd_table[0], "lance");

    dev = qdev_create(NULL, "lance");
337
    qdev_set_nic_properties(dev, nd);
B
Blue Swirl 已提交
338
    qdev_prop_set_ptr(dev, "dma", dma_opaque);
M
Markus Armbruster 已提交
339
    qdev_init_nofail(dev);
340
    s = SYS_BUS_DEVICE(dev);
P
Paul Brook 已提交
341 342
    sysbus_mmio_map(s, 0, leaddr);
    sysbus_connect_irq(s, 0, irq);
343 344
    reset = qdev_get_gpio_in(dev, 0);
    qdev_connect_gpio_out(dma_opaque, 0, reset);
P
Paul Brook 已提交
345 346
}

A
Avi Kivity 已提交
347 348
static DeviceState *slavio_intctl_init(hwaddr addr,
                                       hwaddr addrg,
B
Blue Swirl 已提交
349
                                       qemu_irq **parent_irq)
350 351 352 353 354 355
{
    DeviceState *dev;
    SysBusDevice *s;
    unsigned int i, j;

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

358
    s = SYS_BUS_DEVICE(dev);
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

    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 已提交
376
static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
377 378 379 380 381 382 383 384
                                  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 已提交
385
    qdev_init_nofail(dev);
386
    s = SYS_BUS_DEVICE(dev);
387 388 389 390
    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 已提交
391
        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
392 393 394 395
        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
    }
}

396 397 398 399 400 401 402 403 404 405 406
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
};

407 408 409 410 411 412
#define MISC_LEDS 0x01600000
#define MISC_CFG  0x01800000
#define MISC_DIAG 0x01a00000
#define MISC_MDM  0x01b00000
#define MISC_SYS  0x01f00000

A
Avi Kivity 已提交
413 414 415
static void slavio_misc_init(hwaddr base,
                             hwaddr aux1_base,
                             hwaddr aux2_base, qemu_irq irq,
416
                             qemu_irq fdc_tc)
417 418 419 420 421
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "slavio_misc");
M
Markus Armbruster 已提交
422
    qdev_init_nofail(dev);
423
    s = SYS_BUS_DEVICE(dev);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
    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);
449 450
    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
451 452
}

A
Avi Kivity 已提交
453
static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
454 455 456 457 458 459
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "eccmemctl");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
460
    qdev_init_nofail(dev);
461
    s = SYS_BUS_DEVICE(dev);
462 463 464 465 466 467 468
    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 已提交
469
static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
470 471 472 473 474
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "apc");
M
Markus Armbruster 已提交
475
    qdev_init_nofail(dev);
476
    s = SYS_BUS_DEVICE(dev);
477 478 479 480 481
    /* Power management (APC) XXX: not a Slavio device */
    sysbus_mmio_map(s, 0, power_base);
    sysbus_connect_irq(s, 0, cpu_halt);
}

482
static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width,
483 484 485 486 487 488 489 490 491 492
                     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 已提交
493
    qdev_init_nofail(dev);
494
    s = SYS_BUS_DEVICE(dev);
495 496

    /* 10/ROM : FCode ROM */
497
    sysbus_mmio_map(s, 0, addr);
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
    /* 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);
513
    } else {
514
        sysbus_mmio_map(s, 7, addr + 0x00301000ULL);
515
    }
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
    /* 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);
532 533
}

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
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 已提交
558
/* NCR89C100/MACIO Internal ID register */
559 560 561

#define TYPE_MACIO_ID_REGISTER "macio_idreg"

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

A
Avi Kivity 已提交
564
static void idreg_init(hwaddr addr)
B
Blue Swirl 已提交
565 566 567 568
{
    DeviceState *dev;
    SysBusDevice *s;

569
    dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
M
Markus Armbruster 已提交
570
    qdev_init_nofail(dev);
571
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
572 573

    sysbus_mmio_map(s, 0, addr);
574 575
    cpu_physical_memory_write_rom(&address_space_memory,
                                  addr, idreg_data, sizeof(idreg_data));
B
Blue Swirl 已提交
576 577
}

578 579 580
#define MACIO_ID_REGISTER(obj) \
    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)

A
Avi Kivity 已提交
581
typedef struct IDRegState {
582 583
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
584 585 586
    MemoryRegion mem;
} IDRegState;

X
xiaoqiang zhao 已提交
587
static void idreg_init1(Object *obj)
B
Blue Swirl 已提交
588
{
X
xiaoqiang zhao 已提交
589 590
    IDRegState *s = MACIO_ID_REGISTER(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
B
Blue Swirl 已提交
591

592
    memory_region_init_ram_nomigrate(&s->mem, obj,
593
                           "sun4m.idreg", sizeof(idreg_data), &error_fatal);
594
    vmstate_register_ram_global(&s->mem);
A
Avi Kivity 已提交
595
    memory_region_set_readonly(&s->mem, true);
596
    sysbus_init_mmio(dev, &s->mem);
597 598
}

599
static const TypeInfo idreg_info = {
600
    .name          = TYPE_MACIO_ID_REGISTER,
601 602
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IDRegState),
X
xiaoqiang zhao 已提交
603
    .instance_init = idreg_init1,
B
Blue Swirl 已提交
604 605
};

606 607 608
#define TYPE_TCX_AFX "tcx_afx"
#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)

A
Avi Kivity 已提交
609
typedef struct AFXState {
610 611
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
612 613 614
    MemoryRegion mem;
} AFXState;

A
Artyom Tarasenko 已提交
615
/* SS-5 TCX AFX register */
A
Avi Kivity 已提交
616
static void afx_init(hwaddr addr)
A
Artyom Tarasenko 已提交
617 618 619 620
{
    DeviceState *dev;
    SysBusDevice *s;

621
    dev = qdev_create(NULL, TYPE_TCX_AFX);
A
Artyom Tarasenko 已提交
622
    qdev_init_nofail(dev);
623
    s = SYS_BUS_DEVICE(dev);
A
Artyom Tarasenko 已提交
624 625 626 627

    sysbus_mmio_map(s, 0, addr);
}

X
xiaoqiang zhao 已提交
628
static void afx_init1(Object *obj)
A
Artyom Tarasenko 已提交
629
{
X
xiaoqiang zhao 已提交
630 631
    AFXState *s = TCX_AFX(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
A
Artyom Tarasenko 已提交
632

633
    memory_region_init_ram_nomigrate(&s->mem, obj, "sun4m.afx", 4, &error_fatal);
634
    vmstate_register_ram_global(&s->mem);
635
    sysbus_init_mmio(dev, &s->mem);
636 637
}

638
static const TypeInfo afx_info = {
639
    .name          = TYPE_TCX_AFX,
640 641
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AFXState),
X
xiaoqiang zhao 已提交
642
    .instance_init = afx_init1,
A
Artyom Tarasenko 已提交
643 644
};

645 646 647
#define TYPE_OPENPROM "openprom"
#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)

A
Avi Kivity 已提交
648
typedef struct PROMState {
649 650
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
651 652 653
    MemoryRegion prom;
} PROMState;

B
Blue Swirl 已提交
654
/* Boot PROM (OpenBIOS) */
655 656
static uint64_t translate_prom_address(void *opaque, uint64_t addr)
{
A
Avi Kivity 已提交
657
    hwaddr *base_addr = (hwaddr *)opaque;
658 659 660
    return addr + *base_addr - PROM_VADDR;
}

A
Avi Kivity 已提交
661
static void prom_init(hwaddr addr, const char *bios_name)
B
Blue Swirl 已提交
662 663 664 665 666 667
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

668
    dev = qdev_create(NULL, TYPE_OPENPROM);
M
Markus Armbruster 已提交
669
    qdev_init_nofail(dev);
670
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
671 672 673 674 675 676 677 678 679

    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) {
680
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
681
                       NULL, NULL, 1, EM_SPARC, 0, 0);
B
Blue Swirl 已提交
682 683 684
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
685
        g_free(filename);
B
Blue Swirl 已提交
686 687 688 689 690 691 692 693 694
    } 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 已提交
695
static void prom_init1(Object *obj)
B
Blue Swirl 已提交
696
{
X
xiaoqiang zhao 已提交
697 698
    PROMState *s = OPENPROM(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
B
Blue Swirl 已提交
699

700
    memory_region_init_ram_nomigrate(&s->prom, obj, "sun4m.prom", PROM_SIZE_MAX,
701
                           &error_fatal);
702
    vmstate_register_ram_global(&s->prom);
A
Avi Kivity 已提交
703
    memory_region_set_readonly(&s->prom, true);
704
    sysbus_init_mmio(dev, &s->prom);
B
Blue Swirl 已提交
705 706
}

707 708 709 710 711 712
static Property prom_properties[] = {
    {/* end of property list */},
};

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

715
    dc->props = prom_properties;
716 717
}

718
static const TypeInfo prom_info = {
719
    .name          = TYPE_OPENPROM,
720 721 722
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PROMState),
    .class_init    = prom_class_init,
X
xiaoqiang zhao 已提交
723
    .instance_init = prom_init1,
B
Blue Swirl 已提交
724 725
};

726 727 728 729 730 731
#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 已提交
732
    MemoryRegion ram;
733
    uint64_t size;
G
Gerd Hoffmann 已提交
734 735
} RamDevice;

B
Blue Swirl 已提交
736
/* System RAM */
X
xiaoqiang zhao 已提交
737
static void ram_realize(DeviceState *dev, Error **errp)
B
Blue Swirl 已提交
738
{
739
    RamDevice *d = SUN4M_RAM(dev);
X
xiaoqiang zhao 已提交
740
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
741

742 743
    memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram",
                                         d->size);
X
xiaoqiang zhao 已提交
744
    sysbus_init_mmio(sbd, &d->ram);
B
Blue Swirl 已提交
745 746
}

A
Avi Kivity 已提交
747
static void ram_init(hwaddr addr, ram_addr_t RAM_size,
B
Blue Swirl 已提交
748 749 750 751
                     uint64_t max_mem)
{
    DeviceState *dev;
    SysBusDevice *s;
G
Gerd Hoffmann 已提交
752
    RamDevice *d;
B
Blue Swirl 已提交
753 754 755 756 757 758 759 760 761 762

    /* 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");
763
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
764

765
    d = SUN4M_RAM(dev);
G
Gerd Hoffmann 已提交
766
    d->size = RAM_size;
M
Markus Armbruster 已提交
767
    qdev_init_nofail(dev);
G
Gerd Hoffmann 已提交
768

B
Blue Swirl 已提交
769 770 771
    sysbus_mmio_map(s, 0, addr);
}

772 773 774 775 776 777 778
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)
{
779
    DeviceClass *dc = DEVICE_CLASS(klass);
780

X
xiaoqiang zhao 已提交
781
    dc->realize = ram_realize;
782
    dc->props = ram_properties;
783 784
}

785
static const TypeInfo ram_info = {
786
    .name          = TYPE_SUN4M_MEMORY,
787 788 789
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(RamDevice),
    .class_init    = ram_class_init,
B
Blue Swirl 已提交
790 791
};

792
static void cpu_devinit(const char *cpu_type, unsigned int id,
793
                        uint64_t prom_addr, qemu_irq **cpu_irqs)
B
Blue Swirl 已提交
794
{
795
    CPUState *cs;
796
    SPARCCPU *cpu;
A
Andreas Färber 已提交
797
    CPUSPARCState *env;
B
Blue Swirl 已提交
798

799
    cpu = SPARC_CPU(cpu_create(cpu_type));
800
    env = &cpu->env;
B
Blue Swirl 已提交
801 802 803

    cpu_sparc_set_id(env, id);
    if (id == 0) {
804
        qemu_register_reset(main_cpu_reset, cpu);
B
Blue Swirl 已提交
805
    } else {
806
        qemu_register_reset(secondary_cpu_reset, cpu);
807 808
        cs = CPU(cpu);
        cs->halted = 1;
B
Blue Swirl 已提交
809
    }
810
    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
B
Blue Swirl 已提交
811 812 813
    env->prom_addr = prom_addr;
}

B
Blue Swirl 已提交
814 815 816 817
static void dummy_fdc_tc(void *opaque, int irq, int level)
{
}

818
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
819
                          MachineState *machine)
820
{
821
    DeviceState *slavio_intctl;
B
bellard 已提交
822
    unsigned int i;
P
Paul Brook 已提交
823
    void *iommu, *espdma, *ledma, *nvram;
824
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
825
        espdma_irq, ledma_irq;
826
    qemu_irq esp_reset, dma_enable;
827
    qemu_irq fdc_tc;
B
blueswir1 已提交
828
    unsigned long kernel_size;
G
Gerd Hoffmann 已提交
829
    DriveInfo *fd[MAX_FD];
L
Laszlo Ersek 已提交
830
    FWCfgState *fw_cfg;
831
    unsigned int num_vsimms;
832

B
bellard 已提交
833 834
    /* init CPUs */
    for(i = 0; i < smp_cpus; i++) {
835
        cpu_devinit(machine->cpu_type, i, hwdef->slavio_base, &cpu_irqs[i]);
B
bellard 已提交
836
    }
837 838 839 840

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

841 842

    /* set up devices */
843
    ram_init(0, machine->ram_size, hwdef->max_mem);
844 845
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
846
        empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size);
847
    }
B
Blue Swirl 已提交
848

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

851 852
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
B
Blue Swirl 已提交
853
                                       cpu_irqs);
854 855

    for (i = 0; i < 32; i++) {
856
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
857 858
    }
    for (i = 0; i < MAX_CPUS; i++) {
859
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
860
    }
861

862
    if (hwdef->idreg_base) {
B
Blue Swirl 已提交
863
        idreg_init(hwdef->idreg_base);
B
blueswir1 已提交
864 865
    }

A
Artyom Tarasenko 已提交
866 867 868 869
    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

870
    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
871
                       slavio_irq[30]);
872

873 874 875 876 877 878 879 880
    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);
    }

881
    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
B
Bob Breuer 已提交
882
                              iommu, &espdma_irq, 0);
883

B
blueswir1 已提交
884
    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
B
Bob Breuer 已提交
885
                             slavio_irq[16], iommu, &ledma_irq, 1);
B
bellard 已提交
886

B
blueswir1 已提交
887
    if (graphic_depth != 8 && graphic_depth != 24) {
888
        error_report("Unsupported depth: %d", graphic_depth);
B
blueswir1 已提交
889 890
        exit (1);
    }
891 892
    num_vsimms = 0;
    if (num_vsimms == 0) {
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
        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);
            }

922 923
            tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
924
        }
925 926 927 928 929 930 931 932 933 934 935 936
    }

    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);
    }
937

938
    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
939

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

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

944
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
945
                              !machine->enable_graphics, ESCC_CLOCK, 1);
S
Stefan Weil 已提交
946 947
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
948
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
A
aurel32 已提交
949
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
B
blueswir1 已提交
950

951
    if (hwdef->apc_base) {
952
        apc_init(hwdef->apc_base, qemu_allocate_irq(cpu_halt_signal, NULL, 0));
953
    }
B
blueswir1 已提交
954

955
    if (hwdef->fd_base) {
T
ths 已提交
956
        /* there is zero or one floppy drive */
957
        memset(fd, 0, sizeof(fd));
G
Gerd Hoffmann 已提交
958
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
959
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
960
                          &fdc_tc);
B
Blue Swirl 已提交
961
    } else {
962
        fdc_tc = qemu_allocate_irq(dummy_fdc_tc, NULL, 0);
T
ths 已提交
963 964
    }

B
Blue Swirl 已提交
965 966 967
    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

P
Paul Brook 已提交
968 969
    esp_init(hwdef->esp_base, 2,
             espdma_memory_read, espdma_memory_write,
970
             espdma, espdma_irq, &esp_reset, &dma_enable);
971

972 973
    qdev_connect_gpio_out(espdma, 0, esp_reset);
    qdev_connect_gpio_out(espdma, 1, dma_enable);
974

B
Blue Swirl 已提交
975 976
    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
977
                             slavio_irq[5]);
B
Blue Swirl 已提交
978
    }
979

980 981 982 983 984 985 986 987 988 989 990 991 992
    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);
    }

993 994 995
    kernel_size = sun4m_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    machine->ram_size);
996

997 998 999 1000
    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");
1001

1002
    if (hwdef->ecc_base)
1003
        ecc_init(hwdef->ecc_base, slavio_irq[28],
1004
                 hwdef->ecc_version);
1005

1006
    fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
1007
    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
1008
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
1009 1010
    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);
1011
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
1012 1013
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
1014 1015
    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);
1016
    if (machine->kernel_cmdline) {
1017
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1018
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
1019 1020
                         machine->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
B
Blue Swirl 已提交
1021
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
1022
                       strlen(machine->kernel_cmdline) + 1);
1023 1024
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
B
Blue Swirl 已提交
1025
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1026 1027 1028
    }
    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
1029
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
1030
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1031 1032
}

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
enum {
    ss5_id = 32,
    vger_id,
    lx_id,
    ss4_id,
    scls_id,
    sbook_id,
    ss10_id = 64,
    ss20_id,
    ss600mp_id,
};

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

/* SPARCstation 5 hardware initialisation */
1282
static void ss5_init(MachineState *machine)
1283
{
1284
    sun4m_hw_init(&sun4m_hwdefs[0], machine);
1285
}
B
bellard 已提交
1286

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

1293
/* SPARCserver 600MP hardware initialisation */
1294
static void ss600mp_init(MachineState *machine)
1295
{
1296
    sun4m_hw_init(&sun4m_hwdefs[2], machine);
1297 1298
}

1299
/* SPARCstation 20 hardware initialisation */
1300
static void ss20_init(MachineState *machine)
1301
{
1302
    sun4m_hw_init(&sun4m_hwdefs[3], machine);
B
blueswir1 已提交
1303 1304
}

B
blueswir1 已提交
1305
/* SPARCstation Voyager hardware initialisation */
1306
static void vger_init(MachineState *machine)
B
blueswir1 已提交
1307
{
1308
    sun4m_hw_init(&sun4m_hwdefs[4], machine);
B
blueswir1 已提交
1309 1310 1311
}

/* SPARCstation LX hardware initialisation */
1312
static void ss_lx_init(MachineState *machine)
B
blueswir1 已提交
1313
{
1314
    sun4m_hw_init(&sun4m_hwdefs[5], machine);
B
blueswir1 已提交
1315 1316 1317
}

/* SPARCstation 4 hardware initialisation */
1318
static void ss4_init(MachineState *machine)
B
blueswir1 已提交
1319
{
1320
    sun4m_hw_init(&sun4m_hwdefs[6], machine);
B
blueswir1 已提交
1321 1322 1323
}

/* SPARCClassic hardware initialisation */
1324
static void scls_init(MachineState *machine)
B
blueswir1 已提交
1325
{
1326
    sun4m_hw_init(&sun4m_hwdefs[7], machine);
B
blueswir1 已提交
1327 1328 1329
}

/* SPARCbook hardware initialisation */
1330
static void sbook_init(MachineState *machine)
B
blueswir1 已提交
1331
{
1332
    sun4m_hw_init(&sun4m_hwdefs[8], machine);
B
blueswir1 已提交
1333 1334
}

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

1339 1340 1341 1342 1343
    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";
1344
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1345
}
B
blueswir1 已提交
1346

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

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

1357 1358 1359 1360 1361
    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";
1362
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1363
}
1364

1365 1366 1367 1368 1369
static const TypeInfo ss10_type = {
    .name = MACHINE_TYPE_NAME("SS-10"),
    .parent = TYPE_MACHINE,
    .class_init = ss10_class_init,
};
1370

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

1375 1376 1377 1378 1379
    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";
1380
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1381
}
B
blueswir1 已提交
1382

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

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

1393 1394 1395 1396 1397
    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";
1398
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-SuperSparc-II");
1399
}
B
blueswir1 已提交
1400

1401 1402 1403 1404 1405
static const TypeInfo ss20_type = {
    .name = MACHINE_TYPE_NAME("SS-20"),
    .parent = TYPE_MACHINE,
    .class_init = ss20_class_init,
};
B
blueswir1 已提交
1406

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

1411 1412 1413 1414
    mc->desc = "Sun4m platform, SPARCstation Voyager";
    mc->init = vger_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1415
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1416 1417
}

1418 1419 1420 1421 1422
static const TypeInfo voyager_type = {
    .name = MACHINE_TYPE_NAME("Voyager"),
    .parent = TYPE_MACHINE,
    .class_init = voyager_class_init,
};
1423

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

1428 1429 1430 1431
    mc->desc = "Sun4m platform, SPARCstation LX";
    mc->init = ss_lx_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1432
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I");
1433 1434
}

1435 1436 1437 1438 1439
static const TypeInfo ss_lx_type = {
    .name = MACHINE_TYPE_NAME("LX"),
    .parent = TYPE_MACHINE,
    .class_init = ss_lx_class_init,
};
1440

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

1445 1446 1447 1448
    mc->desc = "Sun4m platform, SPARCstation 4";
    mc->init = ss4_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1449
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("Fujitsu-MB86904");
1450 1451
}

1452 1453 1454 1455 1456
static const TypeInfo ss4_type = {
    .name = MACHINE_TYPE_NAME("SS-4"),
    .parent = TYPE_MACHINE,
    .class_init = ss4_class_init,
};
1457

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

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

1469 1470 1471 1472 1473
static const TypeInfo scls_type = {
    .name = MACHINE_TYPE_NAME("SPARCClassic"),
    .parent = TYPE_MACHINE,
    .class_init = scls_class_init,
};
1474

1475
static void sbook_class_init(ObjectClass *oc, void *data)
1476
{
1477 1478
    MachineClass *mc = MACHINE_CLASS(oc);

1479 1480 1481 1482
    mc->desc = "Sun4m platform, SPARCbook";
    mc->init = sbook_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
1483
    mc->default_cpu_type = SPARC_CPU_TYPE_NAME("TI-MicroSparc-I");
1484 1485
}

1486 1487 1488 1489 1490
static const TypeInfo sbook_type = {
    .name = MACHINE_TYPE_NAME("SPARCbook"),
    .parent = TYPE_MACHINE,
    .class_init = sbook_class_init,
};
B
blueswir1 已提交
1491

A
Andreas Färber 已提交
1492 1493 1494 1495 1496 1497 1498
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);

1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
    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 已提交
1510
type_init(sun4m_register_types)