sun4m.c 45.6 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"
38
#include "hw/nvram/openbios_firmware_abi.h"
P
Paolo Bonzini 已提交
39 40 41 42 43
#include "hw/scsi/esp.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/char/escc.h"
44 45
#include "hw/empty_slot.h"
#include "hw/loader.h"
B
Blue Swirl 已提交
46
#include "elf.h"
47
#include "sysemu/block-backend.h"
48
#include "trace.h"
49
#include "qemu/cutils.h"
50

51 52 53 54
/*
 * Sun4m architecture was used in the following machines:
 *
 * SPARCserver 6xxMP/xx
B
blueswir1 已提交
55 56
 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
 * SPARCclassic X (4/10)
57 58 59 60 61 62 63 64 65 66
 * 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
 */

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

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

82 83
#define ESCC_CLOCK 4915200

84
struct sun4m_hwdef {
A
Avi Kivity 已提交
85 86 87 88 89 90
    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;
91
    struct {
A
Avi Kivity 已提交
92
        hwaddr reg_base, vram_base;
93
    } vsimm[MAX_VSIMMS];
A
Avi Kivity 已提交
94
    hwaddr ecc_base;
95 96
    uint64_t max_mem;
    const char * const default_cpu_model;
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;
B
blueswir1 已提交
120
    uint32_t start, end;
B
blueswir1 已提交
121 122
    uint8_t image[0x1ff0];
    struct OpenBIOS_nvpart_v1 *part_header;
123
    NvramClass *k = NVRAM_GET_CLASS(nvram);
B
blueswir1 已提交
124 125

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

127
    start = 0;
B
bellard 已提交
128

B
blueswir1 已提交
129 130
    // OpenBIOS nvram variables
    // Variable partition
B
blueswir1 已提交
131 132
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_SYSTEM;
B
blueswir1 已提交
133
    pstrcpy(part_header->name, sizeof(part_header->name), "system");
B
blueswir1 已提交
134

B
blueswir1 已提交
135
    end = start + sizeof(struct OpenBIOS_nvpart_v1);
B
blueswir1 已提交
136
    for (i = 0; i < nb_prom_envs; i++)
B
blueswir1 已提交
137 138 139 140
        end = OpenBIOS_set_var(image, end, prom_envs[i]);

    // End marker
    image[end++] = '\0';
B
blueswir1 已提交
141 142

    end = start + ((end - start + 15) & ~15);
B
blueswir1 已提交
143
    OpenBIOS_finish_partition(part_header, end - start);
B
blueswir1 已提交
144 145 146

    // free partition
    start = end;
B
blueswir1 已提交
147 148
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_FREE;
B
blueswir1 已提交
149
    pstrcpy(part_header->name, sizeof(part_header->name), "free");
B
blueswir1 已提交
150 151

    end = 0x1fd0;
B
blueswir1 已提交
152 153
    OpenBIOS_finish_partition(part_header, end - start);

154 155
    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
                    nvram_machine_id);
B
blueswir1 已提交
156

157 158 159
    for (i = 0; i < sizeof(image); i++) {
        (k->write)(nvram, i, image[i]);
    }
B
bellard 已提交
160 161
}

A
Andreas Färber 已提交
162
void cpu_check_irqs(CPUSPARCState *env)
B
blueswir1 已提交
163
{
164 165
    CPUState *cs;

B
blueswir1 已提交
166 167 168 169 170 171 172 173 174
    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;
175
                if (old_interrupt != env->interrupt_index) {
176
                    cs = CPU(sparc_env_get_cpu(env));
177
                    trace_sun4m_cpu_interrupt(i);
178
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
179
                }
B
blueswir1 已提交
180 181 182 183
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
184
        cs = CPU(sparc_env_get_cpu(env));
185
        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
B
blueswir1 已提交
186
        env->interrupt_index = 0;
187
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
B
blueswir1 已提交
188 189 190
    }
}

191
static void cpu_kick_irq(SPARCCPU *cpu)
192
{
193
    CPUSPARCState *env = &cpu->env;
194
    CPUState *cs = CPU(cpu);
195

196
    cs->halted = 0;
197
    cpu_check_irqs(env);
198
    qemu_cpu_kick(cs);
199 200
}

201 202
static void cpu_set_irq(void *opaque, int irq, int level)
{
203 204
    SPARCCPU *cpu = opaque;
    CPUSPARCState *env = &cpu->env;
205 206

    if (level) {
207
        trace_sun4m_cpu_set_irq_raise(irq);
B
blueswir1 已提交
208
        env->pil_in |= 1 << irq;
209
        cpu_kick_irq(cpu);
210
    } else {
211
        trace_sun4m_cpu_set_irq_lower(irq);
B
blueswir1 已提交
212 213
        env->pil_in &= ~(1 << irq);
        cpu_check_irqs(env);
214 215 216 217 218 219 220
    }
}

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

B
bellard 已提交
221 222
static void main_cpu_reset(void *opaque)
{
223
    SPARCCPU *cpu = opaque;
224
    CPUState *cs = CPU(cpu);
225

226 227
    cpu_reset(cs);
    cs->halted = 0;
228 229 230 231
}

static void secondary_cpu_reset(void *opaque)
{
232
    SPARCCPU *cpu = opaque;
233
    CPUState *cs = CPU(cpu);
234

235 236
    cpu_reset(cs);
    cs->halted = 1;
B
bellard 已提交
237 238
}

B
blueswir1 已提交
239 240
static void cpu_halt_signal(void *opaque, int irq, int level)
{
241 242
    if (level && current_cpu) {
        cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT);
243
    }
B
blueswir1 已提交
244 245
}

246 247 248 249 250
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
    return addr - 0xf0000000ULL;
}

251
static unsigned long sun4m_load_kernel(const char *kernel_filename,
252
                                       const char *initrd_filename,
A
Anthony Liguori 已提交
253
                                       ram_addr_t RAM_size)
254 255 256 257
{
    int linux_boot;
    unsigned int i;
    long initrd_size, kernel_size;
258
    uint8_t *ptr;
259 260 261 262 263

    linux_boot = (kernel_filename != NULL);

    kernel_size = 0;
    if (linux_boot) {
B
Blue Swirl 已提交
264 265 266 267 268 269 270
        int bswap_needed;

#ifdef BSWAP_NEEDED
        bswap_needed = 1;
#else
        bswap_needed = 0;
#endif
271
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
272
                               NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
273
        if (kernel_size < 0)
274
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
B
Blue Swirl 已提交
275 276
                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                                    TARGET_PAGE_SIZE);
277
        if (kernel_size < 0)
278 279 280
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              RAM_size - KERNEL_LOAD_ADDR);
281 282 283 284 285 286 287 288 289
        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) {
290 291 292
            initrd_size = load_image_targphys(initrd_filename,
                                              INITRD_LOAD_ADDR,
                                              RAM_size - INITRD_LOAD_ADDR);
293 294 295 296 297 298 299 300
            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) {
301 302 303 304
                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);
305 306 307 308 309 310 311 312
                    break;
                }
            }
        }
    }
    return kernel_size;
}

A
Avi Kivity 已提交
313
static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
314 315 316 317 318 319
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "iommu");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
320
    qdev_init_nofail(dev);
321
    s = SYS_BUS_DEVICE(dev);
322 323 324 325 326 327
    sysbus_connect_irq(s, 0, irq);
    sysbus_mmio_map(s, 0, addr);

    return s;
}

A
Avi Kivity 已提交
328
static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
B
Bob Breuer 已提交
329
                              void *iommu, qemu_irq *dev_irq, int is_ledma)
330 331 332 333 334 335
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "sparc32_dma");
    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
B
Bob Breuer 已提交
336
    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
M
Markus Armbruster 已提交
337
    qdev_init_nofail(dev);
338
    s = SYS_BUS_DEVICE(dev);
339 340 341 342 343 344 345
    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 已提交
346
static void lance_init(NICInfo *nd, hwaddr leaddr,
347
                       void *dma_opaque, qemu_irq irq)
P
Paul Brook 已提交
348 349 350
{
    DeviceState *dev;
    SysBusDevice *s;
351
    qemu_irq reset;
P
Paul Brook 已提交
352 353 354 355

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

    dev = qdev_create(NULL, "lance");
356
    qdev_set_nic_properties(dev, nd);
B
Blue Swirl 已提交
357
    qdev_prop_set_ptr(dev, "dma", dma_opaque);
M
Markus Armbruster 已提交
358
    qdev_init_nofail(dev);
359
    s = SYS_BUS_DEVICE(dev);
P
Paul Brook 已提交
360 361
    sysbus_mmio_map(s, 0, leaddr);
    sysbus_connect_irq(s, 0, irq);
362 363
    reset = qdev_get_gpio_in(dev, 0);
    qdev_connect_gpio_out(dma_opaque, 0, reset);
P
Paul Brook 已提交
364 365
}

A
Avi Kivity 已提交
366 367
static DeviceState *slavio_intctl_init(hwaddr addr,
                                       hwaddr addrg,
B
Blue Swirl 已提交
368
                                       qemu_irq **parent_irq)
369 370 371 372 373 374
{
    DeviceState *dev;
    SysBusDevice *s;
    unsigned int i, j;

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

377
    s = SYS_BUS_DEVICE(dev);
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

    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 已提交
395
static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
396 397 398 399 400 401 402 403
                                  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 已提交
404
    qdev_init_nofail(dev);
405
    s = SYS_BUS_DEVICE(dev);
406 407 408 409
    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 已提交
410
        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
411 412 413 414
        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
    }
}

415 416 417 418 419 420 421 422 423 424 425
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
};

426 427 428 429 430 431
#define MISC_LEDS 0x01600000
#define MISC_CFG  0x01800000
#define MISC_DIAG 0x01a00000
#define MISC_MDM  0x01b00000
#define MISC_SYS  0x01f00000

A
Avi Kivity 已提交
432 433 434
static void slavio_misc_init(hwaddr base,
                             hwaddr aux1_base,
                             hwaddr aux2_base, qemu_irq irq,
435
                             qemu_irq fdc_tc)
436 437 438 439 440
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "slavio_misc");
M
Markus Armbruster 已提交
441
    qdev_init_nofail(dev);
442
    s = SYS_BUS_DEVICE(dev);
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
    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);
468 469
    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
470 471
}

A
Avi Kivity 已提交
472
static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
473 474 475 476 477 478
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "eccmemctl");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
479
    qdev_init_nofail(dev);
480
    s = SYS_BUS_DEVICE(dev);
481 482 483 484 485 486 487
    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 已提交
488
static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
489 490 491 492 493
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "apc");
M
Markus Armbruster 已提交
494
    qdev_init_nofail(dev);
495
    s = SYS_BUS_DEVICE(dev);
496 497 498 499 500
    /* Power management (APC) XXX: not a Slavio device */
    sysbus_mmio_map(s, 0, power_base);
    sysbus_connect_irq(s, 0, cpu_halt);
}

501
static void tcx_init(hwaddr addr, qemu_irq irq, int vram_size, int width,
502 503 504 505 506 507 508 509 510 511
                     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);
512
    qdev_prop_set_uint64(dev, "prom_addr", addr);
M
Markus Armbruster 已提交
513
    qdev_init_nofail(dev);
514
    s = SYS_BUS_DEVICE(dev);
515 516

    /* 10/ROM : FCode ROM */
517
    sysbus_mmio_map(s, 0, addr);
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    /* 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);
533
    } else {
534
        sysbus_mmio_map(s, 7, addr + 0x00301000ULL);
535
    }
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
    /* 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);
552 553
}

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
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_prop_set_uint64(dev, "prom-addr", addr);
    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 已提交
579
/* NCR89C100/MACIO Internal ID register */
580 581 582

#define TYPE_MACIO_ID_REGISTER "macio_idreg"

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

A
Avi Kivity 已提交
585
static void idreg_init(hwaddr addr)
B
Blue Swirl 已提交
586 587 588 589
{
    DeviceState *dev;
    SysBusDevice *s;

590
    dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
M
Markus Armbruster 已提交
591
    qdev_init_nofail(dev);
592
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
593 594

    sysbus_mmio_map(s, 0, addr);
595 596
    cpu_physical_memory_write_rom(&address_space_memory,
                                  addr, idreg_data, sizeof(idreg_data));
B
Blue Swirl 已提交
597 598
}

599 600 601
#define MACIO_ID_REGISTER(obj) \
    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)

A
Avi Kivity 已提交
602
typedef struct IDRegState {
603 604
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
605 606 607
    MemoryRegion mem;
} IDRegState;

608
static int idreg_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
609
{
610
    IDRegState *s = MACIO_ID_REGISTER(dev);
B
Blue Swirl 已提交
611

612
    memory_region_init_ram(&s->mem, OBJECT(s),
613
                           "sun4m.idreg", sizeof(idreg_data), &error_fatal);
614
    vmstate_register_ram_global(&s->mem);
A
Avi Kivity 已提交
615
    memory_region_set_readonly(&s->mem, true);
616
    sysbus_init_mmio(dev, &s->mem);
617
    return 0;
B
Blue Swirl 已提交
618 619
}

620 621 622 623 624 625 626
static void idreg_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = idreg_init1;
}

627
static const TypeInfo idreg_info = {
628
    .name          = TYPE_MACIO_ID_REGISTER,
629 630 631
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IDRegState),
    .class_init    = idreg_class_init,
B
Blue Swirl 已提交
632 633
};

634 635 636
#define TYPE_TCX_AFX "tcx_afx"
#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)

A
Avi Kivity 已提交
637
typedef struct AFXState {
638 639
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
640 641 642
    MemoryRegion mem;
} AFXState;

A
Artyom Tarasenko 已提交
643
/* SS-5 TCX AFX register */
A
Avi Kivity 已提交
644
static void afx_init(hwaddr addr)
A
Artyom Tarasenko 已提交
645 646 647 648
{
    DeviceState *dev;
    SysBusDevice *s;

649
    dev = qdev_create(NULL, TYPE_TCX_AFX);
A
Artyom Tarasenko 已提交
650
    qdev_init_nofail(dev);
651
    s = SYS_BUS_DEVICE(dev);
A
Artyom Tarasenko 已提交
652 653 654 655 656 657

    sysbus_mmio_map(s, 0, addr);
}

static int afx_init1(SysBusDevice *dev)
{
658
    AFXState *s = TCX_AFX(dev);
A
Artyom Tarasenko 已提交
659

660
    memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4, &error_fatal);
661
    vmstate_register_ram_global(&s->mem);
662
    sysbus_init_mmio(dev, &s->mem);
A
Artyom Tarasenko 已提交
663 664 665
    return 0;
}

666 667 668 669 670 671 672
static void afx_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = afx_init1;
}

673
static const TypeInfo afx_info = {
674
    .name          = TYPE_TCX_AFX,
675 676 677
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AFXState),
    .class_init    = afx_class_init,
A
Artyom Tarasenko 已提交
678 679
};

680 681 682
#define TYPE_OPENPROM "openprom"
#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)

A
Avi Kivity 已提交
683
typedef struct PROMState {
684 685
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
686 687 688
    MemoryRegion prom;
} PROMState;

B
Blue Swirl 已提交
689
/* Boot PROM (OpenBIOS) */
690 691
static uint64_t translate_prom_address(void *opaque, uint64_t addr)
{
A
Avi Kivity 已提交
692
    hwaddr *base_addr = (hwaddr *)opaque;
693 694 695
    return addr + *base_addr - PROM_VADDR;
}

A
Avi Kivity 已提交
696
static void prom_init(hwaddr addr, const char *bios_name)
B
Blue Swirl 已提交
697 698 699 700 701 702
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

703
    dev = qdev_create(NULL, TYPE_OPENPROM);
M
Markus Armbruster 已提交
704
    qdev_init_nofail(dev);
705
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
706 707 708 709 710 711 712 713 714

    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) {
715
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
716
                       NULL, NULL, 1, EM_SPARC, 0, 0);
B
Blue Swirl 已提交
717 718 719
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
720
        g_free(filename);
B
Blue Swirl 已提交
721 722 723 724 725 726 727 728 729
    } else {
        ret = -1;
    }
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
        exit(1);
    }
}

730
static int prom_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
731
{
732
    PROMState *s = OPENPROM(dev);
B
Blue Swirl 已提交
733

734
    memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX,
735
                           &error_fatal);
736
    vmstate_register_ram_global(&s->prom);
A
Avi Kivity 已提交
737
    memory_region_set_readonly(&s->prom, true);
738
    sysbus_init_mmio(dev, &s->prom);
739
    return 0;
B
Blue Swirl 已提交
740 741
}

742 743 744 745 746 747
static Property prom_properties[] = {
    {/* end of property list */},
};

static void prom_class_init(ObjectClass *klass, void *data)
{
748
    DeviceClass *dc = DEVICE_CLASS(klass);
749 750 751
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = prom_init1;
752
    dc->props = prom_properties;
753 754
}

755
static const TypeInfo prom_info = {
756
    .name          = TYPE_OPENPROM,
757 758 759
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PROMState),
    .class_init    = prom_class_init,
B
Blue Swirl 已提交
760 761
};

762 763 764 765 766 767
#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 已提交
768
    MemoryRegion ram;
769
    uint64_t size;
G
Gerd Hoffmann 已提交
770 771
} RamDevice;

B
Blue Swirl 已提交
772
/* System RAM */
773
static int ram_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
774
{
775
    RamDevice *d = SUN4M_RAM(dev);
B
Blue Swirl 已提交
776

777 778
    memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram",
                                         d->size);
779
    sysbus_init_mmio(dev, &d->ram);
780
    return 0;
B
Blue Swirl 已提交
781 782
}

A
Avi Kivity 已提交
783
static void ram_init(hwaddr addr, ram_addr_t RAM_size,
B
Blue Swirl 已提交
784 785 786 787
                     uint64_t max_mem)
{
    DeviceState *dev;
    SysBusDevice *s;
G
Gerd Hoffmann 已提交
788
    RamDevice *d;
B
Blue Swirl 已提交
789 790 791 792 793 794 795 796 797 798

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

801
    d = SUN4M_RAM(dev);
G
Gerd Hoffmann 已提交
802
    d->size = RAM_size;
M
Markus Armbruster 已提交
803
    qdev_init_nofail(dev);
G
Gerd Hoffmann 已提交
804

B
Blue Swirl 已提交
805 806 807
    sysbus_mmio_map(s, 0, addr);
}

808 809 810 811 812 813 814
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)
{
815
    DeviceClass *dc = DEVICE_CLASS(klass);
816 817 818
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = ram_init1;
819
    dc->props = ram_properties;
820 821
}

822
static const TypeInfo ram_info = {
823
    .name          = TYPE_SUN4M_MEMORY,
824 825 826
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(RamDevice),
    .class_init    = ram_class_init,
B
Blue Swirl 已提交
827 828
};

829 830
static void cpu_devinit(const char *cpu_model, unsigned int id,
                        uint64_t prom_addr, qemu_irq **cpu_irqs)
B
Blue Swirl 已提交
831
{
832
    CPUState *cs;
833
    SPARCCPU *cpu;
A
Andreas Färber 已提交
834
    CPUSPARCState *env;
B
Blue Swirl 已提交
835

836 837
    cpu = cpu_sparc_init(cpu_model);
    if (cpu == NULL) {
B
Blue Swirl 已提交
838 839 840
        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
        exit(1);
    }
841
    env = &cpu->env;
B
Blue Swirl 已提交
842 843 844

    cpu_sparc_set_id(env, id);
    if (id == 0) {
845
        qemu_register_reset(main_cpu_reset, cpu);
B
Blue Swirl 已提交
846
    } else {
847
        qemu_register_reset(secondary_cpu_reset, cpu);
848 849
        cs = CPU(cpu);
        cs->halted = 1;
B
Blue Swirl 已提交
850
    }
851
    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
B
Blue Swirl 已提交
852 853 854
    env->prom_addr = prom_addr;
}

B
Blue Swirl 已提交
855 856 857 858
static void dummy_fdc_tc(void *opaque, int irq, int level)
{
}

859
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
860
                          MachineState *machine)
861
{
862
    DeviceState *slavio_intctl;
863
    const char *cpu_model = machine->cpu_model;
B
bellard 已提交
864
    unsigned int i;
P
Paul Brook 已提交
865
    void *iommu, *espdma, *ledma, *nvram;
866
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
867
        espdma_irq, ledma_irq;
868
    qemu_irq esp_reset, dma_enable;
869
    qemu_irq fdc_tc;
B
blueswir1 已提交
870
    unsigned long kernel_size;
G
Gerd Hoffmann 已提交
871
    DriveInfo *fd[MAX_FD];
L
Laszlo Ersek 已提交
872
    FWCfgState *fw_cfg;
873
    unsigned int num_vsimms;
874

B
bellard 已提交
875
    /* init CPUs */
876 877
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;
878

B
bellard 已提交
879
    for(i = 0; i < smp_cpus; i++) {
880
        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
B
bellard 已提交
881
    }
882 883 884 885

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

886 887

    /* set up devices */
888
    ram_init(0, machine->ram_size, hwdef->max_mem);
889 890
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
891
        empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size);
892
    }
B
Blue Swirl 已提交
893

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

896 897
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
B
Blue Swirl 已提交
898
                                       cpu_irqs);
899 900

    for (i = 0; i < 32; i++) {
901
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
902 903
    }
    for (i = 0; i < MAX_CPUS; i++) {
904
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
905
    }
906

907
    if (hwdef->idreg_base) {
B
Blue Swirl 已提交
908
        idreg_init(hwdef->idreg_base);
B
blueswir1 已提交
909 910
    }

A
Artyom Tarasenko 已提交
911 912 913 914
    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

915
    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
916
                       slavio_irq[30]);
917

918 919 920 921 922 923 924 925
    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);
    }

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

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

B
blueswir1 已提交
932
    if (graphic_depth != 8 && graphic_depth != 24) {
933
        error_report("Unsupported depth: %d", graphic_depth);
B
blueswir1 已提交
934 935
        exit (1);
    }
936 937
    num_vsimms = 0;
    if (num_vsimms == 0) {
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
        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);
            }

967 968
            tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
969
        }
970 971 972 973 974 975 976 977 978 979 980 981
    }

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

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

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

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

989
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
990
                              !machine->enable_graphics, ESCC_CLOCK, 1);
S
Stefan Weil 已提交
991 992
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
993
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
A
aurel32 已提交
994
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
B
blueswir1 已提交
995

996
    if (hwdef->apc_base) {
997
        apc_init(hwdef->apc_base, qemu_allocate_irq(cpu_halt_signal, NULL, 0));
998
    }
B
blueswir1 已提交
999

1000
    if (hwdef->fd_base) {
T
ths 已提交
1001
        /* there is zero or one floppy drive */
1002
        memset(fd, 0, sizeof(fd));
G
Gerd Hoffmann 已提交
1003
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
1004
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
1005
                          &fdc_tc);
B
Blue Swirl 已提交
1006
    } else {
1007
        fdc_tc = qemu_allocate_irq(dummy_fdc_tc, NULL, 0);
T
ths 已提交
1008 1009
    }

B
Blue Swirl 已提交
1010 1011 1012
    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

T
ths 已提交
1013 1014 1015 1016 1017
    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

P
Paul Brook 已提交
1018 1019
    esp_init(hwdef->esp_base, 2,
             espdma_memory_read, espdma_memory_write,
1020
             espdma, espdma_irq, &esp_reset, &dma_enable);
1021

1022 1023
    qdev_connect_gpio_out(espdma, 0, esp_reset);
    qdev_connect_gpio_out(espdma, 1, dma_enable);
1024

B
Blue Swirl 已提交
1025 1026
    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
1027
                             slavio_irq[5]);
B
Blue Swirl 已提交
1028
    }
1029

1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
    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);
    }

1043 1044 1045
    kernel_size = sun4m_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    machine->ram_size);
1046

1047 1048 1049 1050
    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");
1051

1052
    if (hwdef->ecc_base)
1053
        ecc_init(hwdef->ecc_base, slavio_irq[28],
1054
                 hwdef->ecc_version);
1055

1056
    fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
1057
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
1058 1059
    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);
1060
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
1061 1062
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
1063 1064
    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);
1065
    if (machine->kernel_cmdline) {
1066
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1067
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
1068 1069
                         machine->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
B
Blue Swirl 已提交
1070
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
1071
                       strlen(machine->kernel_cmdline) + 1);
1072 1073
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
B
Blue Swirl 已提交
1074
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1075 1076 1077
    }
    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
1078
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
1079
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1080 1081
}

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
enum {
    ss5_id = 32,
    vger_id,
    lx_id,
    ss4_id,
    scls_id,
    sbook_id,
    ss10_id = 64,
    ss20_id,
    ss600mp_id,
};

1094
static const struct sun4m_hwdef sun4m_hwdefs[] = {
1095 1096 1097
    /* SS-5 */
    {
        .iommu_base   = 0x10000000,
1098 1099
        .iommu_pad_base = 0x10004000,
        .iommu_pad_len  = 0x0fffb000,
1100 1101
        .tcx_base     = 0x50000000,
        .cs_base      = 0x6c000000,
B
blueswir1 已提交
1102
        .slavio_base  = 0x70000000,
1103 1104 1105 1106 1107 1108
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
B
blueswir1 已提交
1109
        .idreg_base   = 0x78000000,
1110 1111 1112
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
1113
        .apc_base     = 0x6a000000,
A
Artyom Tarasenko 已提交
1114
        .afx_base     = 0x6e000000,
1115 1116
        .aux1_base    = 0x71900000,
        .aux2_base    = 0x71910000,
1117 1118
        .nvram_machine_id = 0x80,
        .machine_id = ss5_id,
1119
        .iommu_version = 0x05000000,
1120 1121
        .max_mem = 0x10000000,
        .default_cpu_model = "Fujitsu MB86904",
B
blueswir1 已提交
1122 1123 1124
    },
    /* SS-10 */
    {
1125 1126 1127 1128 1129 1130 1131 1132 1133
        .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 已提交
1134
        .idreg_base   = 0xef0000000ULL,
1135 1136 1137
        .dma_base     = 0xef0400000ULL,
        .esp_base     = 0xef0800000ULL,
        .le_base      = 0xef0c00000ULL,
1138
        .apc_base     = 0xefa000000ULL, // XXX should not exist
1139 1140
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL,
1141 1142
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x10000000, // version 0, implementation 1
1143 1144
        .nvram_machine_id = 0x72,
        .machine_id = ss10_id,
1145
        .iommu_version = 0x03000000,
B
blueswir1 已提交
1146
        .max_mem = 0xf00000000ULL,
1147
        .default_cpu_model = "TI SuperSparc II",
1148
    },
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
    /* 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,
1162
        .apc_base     = 0xefa000000ULL, // XXX should not exist
1163 1164
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
1165 1166
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x00000000, // version 0, implementation 0
1167 1168
        .nvram_machine_id = 0x71,
        .machine_id = ss600mp_id,
1169
        .iommu_version = 0x01000000,
B
blueswir1 已提交
1170
        .max_mem = 0xf00000000ULL,
1171
        .default_cpu_model = "TI SuperSparc II",
1172
    },
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    /* 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 已提交
1184
        .idreg_base   = 0xef0000000ULL,
1185 1186 1187
        .dma_base     = 0xef0400000ULL,
        .esp_base     = 0xef0800000ULL,
        .le_base      = 0xef0c00000ULL,
1188
        .bpp_base     = 0xef4800000ULL,
1189
        .apc_base     = 0xefa000000ULL, // XXX should not exist
B
blueswir1 已提交
1190 1191
        .aux1_base    = 0xff1800000ULL,
        .aux2_base    = 0xff1a01000ULL,
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
        .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
            }
        },
1207 1208
        .ecc_base     = 0xf00000000ULL,
        .ecc_version  = 0x20000000, // version 0, implementation 2
1209 1210
        .nvram_machine_id = 0x72,
        .machine_id = ss20_id,
1211
        .iommu_version = 0x13000000,
B
blueswir1 已提交
1212
        .max_mem = 0xf00000000ULL,
1213 1214
        .default_cpu_model = "TI SuperSparc II",
    },
B
blueswir1 已提交
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
    /* 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,
1233 1234
        .nvram_machine_id = 0x80,
        .machine_id = vger_id,
B
blueswir1 已提交
1235 1236 1237 1238 1239 1240 1241
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
        .default_cpu_model = "Fujitsu MB86904",
    },
    /* LX */
    {
        .iommu_base   = 0x10000000,
1242 1243
        .iommu_pad_base = 0x10004000,
        .iommu_pad_len  = 0x0fffb000,
B
blueswir1 已提交
1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
        .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,
1258 1259
        .nvram_machine_id = 0x80,
        .machine_id = lx_id,
B
blueswir1 已提交
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
        .iommu_version = 0x04000000,
        .max_mem = 0x10000000,
        .default_cpu_model = "TI MicroSparc I",
    },
    /* 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,
1283 1284
        .nvram_machine_id = 0x80,
        .machine_id = ss4_id,
B
blueswir1 已提交
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
        .default_cpu_model = "Fujitsu MB86904",
    },
    /* 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,
1307 1308
        .nvram_machine_id = 0x80,
        .machine_id = scls_id,
B
blueswir1 已提交
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
        .default_cpu_model = "TI MicroSparc I",
    },
    /* 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,
1331 1332
        .nvram_machine_id = 0x80,
        .machine_id = sbook_id,
B
blueswir1 已提交
1333 1334 1335 1336
        .iommu_version = 0x05000000,
        .max_mem = 0x10000000,
        .default_cpu_model = "TI MicroSparc I",
    },
1337 1338 1339
};

/* SPARCstation 5 hardware initialisation */
1340
static void ss5_init(MachineState *machine)
1341
{
1342
    sun4m_hw_init(&sun4m_hwdefs[0], machine);
1343
}
B
bellard 已提交
1344

B
blueswir1 已提交
1345
/* SPARCstation 10 hardware initialisation */
1346
static void ss10_init(MachineState *machine)
B
blueswir1 已提交
1347
{
1348
    sun4m_hw_init(&sun4m_hwdefs[1], machine);
B
blueswir1 已提交
1349 1350
}

1351
/* SPARCserver 600MP hardware initialisation */
1352
static void ss600mp_init(MachineState *machine)
1353
{
1354
    sun4m_hw_init(&sun4m_hwdefs[2], machine);
1355 1356
}

1357
/* SPARCstation 20 hardware initialisation */
1358
static void ss20_init(MachineState *machine)
1359
{
1360
    sun4m_hw_init(&sun4m_hwdefs[3], machine);
B
blueswir1 已提交
1361 1362
}

B
blueswir1 已提交
1363
/* SPARCstation Voyager hardware initialisation */
1364
static void vger_init(MachineState *machine)
B
blueswir1 已提交
1365
{
1366
    sun4m_hw_init(&sun4m_hwdefs[4], machine);
B
blueswir1 已提交
1367 1368 1369
}

/* SPARCstation LX hardware initialisation */
1370
static void ss_lx_init(MachineState *machine)
B
blueswir1 已提交
1371
{
1372
    sun4m_hw_init(&sun4m_hwdefs[5], machine);
B
blueswir1 已提交
1373 1374 1375
}

/* SPARCstation 4 hardware initialisation */
1376
static void ss4_init(MachineState *machine)
B
blueswir1 已提交
1377
{
1378
    sun4m_hw_init(&sun4m_hwdefs[6], machine);
B
blueswir1 已提交
1379 1380 1381
}

/* SPARCClassic hardware initialisation */
1382
static void scls_init(MachineState *machine)
B
blueswir1 已提交
1383
{
1384
    sun4m_hw_init(&sun4m_hwdefs[7], machine);
B
blueswir1 已提交
1385 1386 1387
}

/* SPARCbook hardware initialisation */
1388
static void sbook_init(MachineState *machine)
B
blueswir1 已提交
1389
{
1390
    sun4m_hw_init(&sun4m_hwdefs[8], machine);
B
blueswir1 已提交
1391 1392
}

1393
static void ss5_class_init(ObjectClass *oc, void *data)
1394
{
1395 1396
    MachineClass *mc = MACHINE_CLASS(oc);

1397 1398 1399 1400 1401 1402
    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";
}
B
blueswir1 已提交
1403

1404 1405 1406 1407 1408
static const TypeInfo ss5_type = {
    .name = MACHINE_TYPE_NAME("SS-5"),
    .parent = TYPE_MACHINE,
    .class_init = ss5_class_init,
};
1409

1410
static void ss10_class_init(ObjectClass *oc, void *data)
1411
{
1412 1413
    MachineClass *mc = MACHINE_CLASS(oc);

1414 1415 1416 1417 1418 1419
    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";
}
1420

1421 1422 1423 1424 1425
static const TypeInfo ss10_type = {
    .name = MACHINE_TYPE_NAME("SS-10"),
    .parent = TYPE_MACHINE,
    .class_init = ss10_class_init,
};
1426

1427
static void ss600mp_class_init(ObjectClass *oc, void *data)
1428
{
1429 1430
    MachineClass *mc = MACHINE_CLASS(oc);

1431 1432 1433 1434 1435 1436
    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";
}
B
blueswir1 已提交
1437

1438 1439 1440 1441 1442
static const TypeInfo ss600mp_type = {
    .name = MACHINE_TYPE_NAME("SS-600MP"),
    .parent = TYPE_MACHINE,
    .class_init = ss600mp_class_init,
};
B
blueswir1 已提交
1443

1444
static void ss20_class_init(ObjectClass *oc, void *data)
1445
{
1446 1447
    MachineClass *mc = MACHINE_CLASS(oc);

1448 1449 1450 1451 1452 1453
    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";
}
B
blueswir1 已提交
1454

1455 1456 1457 1458 1459
static const TypeInfo ss20_type = {
    .name = MACHINE_TYPE_NAME("SS-20"),
    .parent = TYPE_MACHINE,
    .class_init = ss20_class_init,
};
B
blueswir1 已提交
1460

1461
static void voyager_class_init(ObjectClass *oc, void *data)
1462
{
1463 1464
    MachineClass *mc = MACHINE_CLASS(oc);

1465 1466 1467 1468 1469 1470
    mc->desc = "Sun4m platform, SPARCstation Voyager";
    mc->init = vger_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
}

1471 1472 1473 1474 1475
static const TypeInfo voyager_type = {
    .name = MACHINE_TYPE_NAME("Voyager"),
    .parent = TYPE_MACHINE,
    .class_init = voyager_class_init,
};
1476

1477
static void ss_lx_class_init(ObjectClass *oc, void *data)
1478
{
1479 1480
    MachineClass *mc = MACHINE_CLASS(oc);

1481 1482 1483 1484 1485 1486
    mc->desc = "Sun4m platform, SPARCstation LX";
    mc->init = ss_lx_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
}

1487 1488 1489 1490 1491
static const TypeInfo ss_lx_type = {
    .name = MACHINE_TYPE_NAME("LX"),
    .parent = TYPE_MACHINE,
    .class_init = ss_lx_class_init,
};
1492

1493
static void ss4_class_init(ObjectClass *oc, void *data)
1494
{
1495 1496
    MachineClass *mc = MACHINE_CLASS(oc);

1497 1498 1499 1500 1501 1502
    mc->desc = "Sun4m platform, SPARCstation 4";
    mc->init = ss4_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
}

1503 1504 1505 1506 1507
static const TypeInfo ss4_type = {
    .name = MACHINE_TYPE_NAME("SS-4"),
    .parent = TYPE_MACHINE,
    .class_init = ss4_class_init,
};
1508

1509
static void scls_class_init(ObjectClass *oc, void *data)
1510
{
1511 1512
    MachineClass *mc = MACHINE_CLASS(oc);

1513 1514 1515 1516 1517 1518
    mc->desc = "Sun4m platform, SPARCClassic";
    mc->init = scls_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
}

1519 1520 1521 1522 1523
static const TypeInfo scls_type = {
    .name = MACHINE_TYPE_NAME("SPARCClassic"),
    .parent = TYPE_MACHINE,
    .class_init = scls_class_init,
};
1524

1525
static void sbook_class_init(ObjectClass *oc, void *data)
1526
{
1527 1528
    MachineClass *mc = MACHINE_CLASS(oc);

1529 1530 1531 1532 1533 1534
    mc->desc = "Sun4m platform, SPARCbook";
    mc->init = sbook_init;
    mc->block_default_type = IF_SCSI;
    mc->default_boot_order = "c";
}

1535 1536 1537 1538 1539
static const TypeInfo sbook_type = {
    .name = MACHINE_TYPE_NAME("SPARCbook"),
    .parent = TYPE_MACHINE,
    .class_init = sbook_class_init,
};
B
blueswir1 已提交
1540

A
Andreas Färber 已提交
1541 1542 1543 1544 1545 1546 1547
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);

1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
    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 已提交
1559
type_init(sun4m_register_types)