sun4m.c 43.8 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.
 */
24
#include "hw/sysbus.h"
25
#include "qemu/error-report.h"
26
#include "qemu/timer.h"
P
Paolo Bonzini 已提交
27 28 29 30
#include "hw/sparc/sun4m.h"
#include "hw/timer/m48t59.h"
#include "hw/sparc/sparc32_dma.h"
#include "hw/block/fdc.h"
31
#include "sysemu/sysemu.h"
P
Paolo Bonzini 已提交
32
#include "net/net.h"
33
#include "hw/boards.h"
34
#include "hw/nvram/openbios_firmware_abi.h"
P
Paolo Bonzini 已提交
35 36 37 38 39
#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"
40 41
#include "hw/empty_slot.h"
#include "hw/loader.h"
B
Blue Swirl 已提交
42
#include "elf.h"
43
#include "sysemu/blockdev.h"
44
#include "trace.h"
45

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

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

B
bellard 已提交
73
#define MAX_CPUS 16
74
#define MAX_PILS 16
75
#define MAX_VSIMMS 4
76

77 78
#define ESCC_CLOCK 4915200

79
struct sun4m_hwdef {
A
Avi Kivity 已提交
80 81 82 83 84 85
    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;
86
    struct {
A
Avi Kivity 已提交
87
        hwaddr reg_base, vram_base;
88
    } vsimm[MAX_VSIMMS];
A
Avi Kivity 已提交
89
    hwaddr ecc_base;
90 91
    uint64_t max_mem;
    const char * const default_cpu_model;
92 93 94 95
    uint32_t ecc_version;
    uint32_t iommu_version;
    uint16_t machine_id;
    uint8_t nvram_machine_id;
96 97
};

B
bellard 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
int DMA_get_channel_mode (int nchan)
{
    return 0;
}
int DMA_read_memory (int nchan, void *buf, int pos, int size)
{
    return 0;
}
int DMA_write_memory (int nchan, void *buf, int pos, int size)
{
    return 0;
}
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(int nchan) {}
B
Blue Swirl 已提交
113 114 115 116 117

void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
{
}

B
bellard 已提交
118 119 120 121 122 123
void DMA_register_channel (int nchan,
                           DMA_transfer_handler transfer_handler,
                           void *opaque)
{
}

124
static int fw_cfg_boot_set(void *opaque, const char *boot_device)
B
blueswir1 已提交
125
{
126
    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
B
blueswir1 已提交
127 128 129
    return 0;
}

130 131 132
static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
                       const char *cmdline, const char *boot_devices,
                       ram_addr_t RAM_size, uint32_t kernel_size,
B
blueswir1 已提交
133
                       int width, int height, int depth,
134
                       int nvram_machine_id, const char *arch)
B
bellard 已提交
135
{
B
blueswir1 已提交
136
    unsigned int i;
B
blueswir1 已提交
137
    uint32_t start, end;
B
blueswir1 已提交
138 139 140 141
    uint8_t image[0x1ff0];
    struct OpenBIOS_nvpart_v1 *part_header;

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

143
    start = 0;
B
bellard 已提交
144

B
blueswir1 已提交
145 146
    // OpenBIOS nvram variables
    // Variable partition
B
blueswir1 已提交
147 148
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_SYSTEM;
B
blueswir1 已提交
149
    pstrcpy(part_header->name, sizeof(part_header->name), "system");
B
blueswir1 已提交
150

B
blueswir1 已提交
151
    end = start + sizeof(struct OpenBIOS_nvpart_v1);
B
blueswir1 已提交
152
    for (i = 0; i < nb_prom_envs; i++)
B
blueswir1 已提交
153 154 155 156
        end = OpenBIOS_set_var(image, end, prom_envs[i]);

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

    end = start + ((end - start + 15) & ~15);
B
blueswir1 已提交
159
    OpenBIOS_finish_partition(part_header, end - start);
B
blueswir1 已提交
160 161 162

    // free partition
    start = end;
B
blueswir1 已提交
163 164
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_FREE;
B
blueswir1 已提交
165
    pstrcpy(part_header->name, sizeof(part_header->name), "free");
B
blueswir1 已提交
166 167

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

170 171
    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
                    nvram_machine_id);
B
blueswir1 已提交
172 173 174

    for (i = 0; i < sizeof(image); i++)
        m48t59_write(nvram, i, image[i]);
B
bellard 已提交
175 176
}

177
static DeviceState *slavio_intctl;
B
bellard 已提交
178

179
void sun4m_pic_info(Monitor *mon, const QDict *qdict)
B
bellard 已提交
180
{
181
    if (slavio_intctl)
A
aliguori 已提交
182
        slavio_pic_info(mon, slavio_intctl);
B
bellard 已提交
183 184
}

185
void sun4m_irq_info(Monitor *mon, const QDict *qdict)
B
bellard 已提交
186
{
187
    if (slavio_intctl)
A
aliguori 已提交
188
        slavio_irq_info(mon, slavio_intctl);
B
bellard 已提交
189 190
}

A
Andreas Färber 已提交
191
void cpu_check_irqs(CPUSPARCState *env)
B
blueswir1 已提交
192
{
193 194
    CPUState *cs;

B
blueswir1 已提交
195 196 197 198 199 200 201 202 203
    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;
204
                if (old_interrupt != env->interrupt_index) {
205
                    cs = CPU(sparc_env_get_cpu(env));
206
                    trace_sun4m_cpu_interrupt(i);
207
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
208
                }
B
blueswir1 已提交
209 210 211 212
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
213
        cs = CPU(sparc_env_get_cpu(env));
214
        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
B
blueswir1 已提交
215
        env->interrupt_index = 0;
216
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
B
blueswir1 已提交
217 218 219
    }
}

220
static void cpu_kick_irq(SPARCCPU *cpu)
221
{
222
    CPUSPARCState *env = &cpu->env;
223
    CPUState *cs = CPU(cpu);
224

225
    cs->halted = 0;
226
    cpu_check_irqs(env);
227
    qemu_cpu_kick(cs);
228 229
}

230 231
static void cpu_set_irq(void *opaque, int irq, int level)
{
232 233
    SPARCCPU *cpu = opaque;
    CPUSPARCState *env = &cpu->env;
234 235

    if (level) {
236
        trace_sun4m_cpu_set_irq_raise(irq);
B
blueswir1 已提交
237
        env->pil_in |= 1 << irq;
238
        cpu_kick_irq(cpu);
239
    } else {
240
        trace_sun4m_cpu_set_irq_lower(irq);
B
blueswir1 已提交
241 242
        env->pil_in &= ~(1 << irq);
        cpu_check_irqs(env);
243 244 245 246 247 248 249
    }
}

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

B
bellard 已提交
250 251
static void main_cpu_reset(void *opaque)
{
252
    SPARCCPU *cpu = opaque;
253
    CPUState *cs = CPU(cpu);
254

255 256
    cpu_reset(cs);
    cs->halted = 0;
257 258 259 260
}

static void secondary_cpu_reset(void *opaque)
{
261
    SPARCCPU *cpu = opaque;
262
    CPUState *cs = CPU(cpu);
263

264 265
    cpu_reset(cs);
    cs->halted = 1;
B
bellard 已提交
266 267
}

B
blueswir1 已提交
268 269
static void cpu_halt_signal(void *opaque, int irq, int level)
{
270 271
    if (level && current_cpu) {
        cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT);
272
    }
B
blueswir1 已提交
273 274
}

275 276 277 278 279
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
    return addr - 0xf0000000ULL;
}

280
static unsigned long sun4m_load_kernel(const char *kernel_filename,
281
                                       const char *initrd_filename,
A
Anthony Liguori 已提交
282
                                       ram_addr_t RAM_size)
283 284 285 286
{
    int linux_boot;
    unsigned int i;
    long initrd_size, kernel_size;
287
    uint8_t *ptr;
288 289 290 291 292

    linux_boot = (kernel_filename != NULL);

    kernel_size = 0;
    if (linux_boot) {
B
Blue Swirl 已提交
293 294 295 296 297 298 299
        int bswap_needed;

#ifdef BSWAP_NEEDED
        bswap_needed = 1;
#else
        bswap_needed = 0;
#endif
300 301
        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
                               NULL, NULL, NULL, 1, ELF_MACHINE, 0);
302
        if (kernel_size < 0)
303
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
B
Blue Swirl 已提交
304 305
                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
                                    TARGET_PAGE_SIZE);
306
        if (kernel_size < 0)
307 308 309
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              RAM_size - KERNEL_LOAD_ADDR);
310 311 312 313 314 315 316 317 318
        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) {
319 320 321
            initrd_size = load_image_targphys(initrd_filename,
                                              INITRD_LOAD_ADDR,
                                              RAM_size - INITRD_LOAD_ADDR);
322 323 324 325 326 327 328 329
            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) {
330 331 332 333
                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);
334 335 336 337 338 339 340 341
                    break;
                }
            }
        }
    }
    return kernel_size;
}

A
Avi Kivity 已提交
342
static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
343 344 345 346 347 348
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "iommu");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
349
    qdev_init_nofail(dev);
350
    s = SYS_BUS_DEVICE(dev);
351 352 353 354 355 356
    sysbus_connect_irq(s, 0, irq);
    sysbus_mmio_map(s, 0, addr);

    return s;
}

A
Avi Kivity 已提交
357
static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
B
Bob Breuer 已提交
358
                              void *iommu, qemu_irq *dev_irq, int is_ledma)
359 360 361 362 363 364
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "sparc32_dma");
    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
B
Bob Breuer 已提交
365
    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
M
Markus Armbruster 已提交
366
    qdev_init_nofail(dev);
367
    s = SYS_BUS_DEVICE(dev);
368 369 370 371 372 373 374
    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 已提交
375
static void lance_init(NICInfo *nd, hwaddr leaddr,
376
                       void *dma_opaque, qemu_irq irq)
P
Paul Brook 已提交
377 378 379
{
    DeviceState *dev;
    SysBusDevice *s;
380
    qemu_irq reset;
P
Paul Brook 已提交
381 382 383 384

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

    dev = qdev_create(NULL, "lance");
385
    qdev_set_nic_properties(dev, nd);
B
Blue Swirl 已提交
386
    qdev_prop_set_ptr(dev, "dma", dma_opaque);
M
Markus Armbruster 已提交
387
    qdev_init_nofail(dev);
388
    s = SYS_BUS_DEVICE(dev);
P
Paul Brook 已提交
389 390
    sysbus_mmio_map(s, 0, leaddr);
    sysbus_connect_irq(s, 0, irq);
391 392
    reset = qdev_get_gpio_in(dev, 0);
    qdev_connect_gpio_out(dma_opaque, 0, reset);
P
Paul Brook 已提交
393 394
}

A
Avi Kivity 已提交
395 396
static DeviceState *slavio_intctl_init(hwaddr addr,
                                       hwaddr addrg,
B
Blue Swirl 已提交
397
                                       qemu_irq **parent_irq)
398 399 400 401 402 403
{
    DeviceState *dev;
    SysBusDevice *s;
    unsigned int i, j;

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

406
    s = SYS_BUS_DEVICE(dev);
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423

    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 已提交
424
static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
425 426 427 428 429 430 431 432
                                  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 已提交
433
    qdev_init_nofail(dev);
434
    s = SYS_BUS_DEVICE(dev);
435 436 437 438
    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 已提交
439
        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
440 441 442 443
        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
    }
}

444 445 446 447 448 449 450 451 452 453 454
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
};

455 456 457 458 459 460
#define MISC_LEDS 0x01600000
#define MISC_CFG  0x01800000
#define MISC_DIAG 0x01a00000
#define MISC_MDM  0x01b00000
#define MISC_SYS  0x01f00000

A
Avi Kivity 已提交
461 462 463
static void slavio_misc_init(hwaddr base,
                             hwaddr aux1_base,
                             hwaddr aux2_base, qemu_irq irq,
464
                             qemu_irq fdc_tc)
465 466 467 468 469
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "slavio_misc");
M
Markus Armbruster 已提交
470
    qdev_init_nofail(dev);
471
    s = SYS_BUS_DEVICE(dev);
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
    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);
497 498
    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
499 500
}

A
Avi Kivity 已提交
501
static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
502 503 504 505 506 507
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "eccmemctl");
    qdev_prop_set_uint32(dev, "version", version);
M
Markus Armbruster 已提交
508
    qdev_init_nofail(dev);
509
    s = SYS_BUS_DEVICE(dev);
510 511 512 513 514 515 516
    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 已提交
517
static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
518 519 520 521 522
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "apc");
M
Markus Armbruster 已提交
523
    qdev_init_nofail(dev);
524
    s = SYS_BUS_DEVICE(dev);
525 526 527 528 529
    /* Power management (APC) XXX: not a Slavio device */
    sysbus_mmio_map(s, 0, power_base);
    sysbus_connect_irq(s, 0, cpu_halt);
}

A
Avi Kivity 已提交
530
static void tcx_init(hwaddr addr, int vram_size, int width,
531 532 533 534 535 536 537 538 539 540
                     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);
541
    qdev_prop_set_uint64(dev, "prom_addr", addr);
M
Markus Armbruster 已提交
542
    qdev_init_nofail(dev);
543
    s = SYS_BUS_DEVICE(dev);
544 545
    /* FCode ROM */
    sysbus_mmio_map(s, 0, addr);
546
    /* 8-bit plane */
547
    sysbus_mmio_map(s, 1, addr + 0x00800000ULL);
548
    /* DAC */
549
    sysbus_mmio_map(s, 2, addr + 0x00200000ULL);
550
    /* TEC (dummy) */
551
    sysbus_mmio_map(s, 3, addr + 0x00700000ULL);
552
    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
553
    sysbus_mmio_map(s, 4, addr + 0x00301000ULL);
554 555
    if (depth == 24) {
        /* 24-bit plane */
556
        sysbus_mmio_map(s, 5, addr + 0x02000000ULL);
557
        /* Control plane */
558
        sysbus_mmio_map(s, 6, addr + 0x0a000000ULL);
559 560
    } else {
        /* THC 8 bit (dummy) */
561
        sysbus_mmio_map(s, 5, addr + 0x00300000ULL);
562 563 564
    }
}

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
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 已提交
590
/* NCR89C100/MACIO Internal ID register */
591 592 593

#define TYPE_MACIO_ID_REGISTER "macio_idreg"

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

A
Avi Kivity 已提交
596
static void idreg_init(hwaddr addr)
B
Blue Swirl 已提交
597 598 599 600
{
    DeviceState *dev;
    SysBusDevice *s;

601
    dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
M
Markus Armbruster 已提交
602
    qdev_init_nofail(dev);
603
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
604 605

    sysbus_mmio_map(s, 0, addr);
606 607
    cpu_physical_memory_write_rom(&address_space_memory,
                                  addr, idreg_data, sizeof(idreg_data));
B
Blue Swirl 已提交
608 609
}

610 611 612
#define MACIO_ID_REGISTER(obj) \
    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)

A
Avi Kivity 已提交
613
typedef struct IDRegState {
614 615
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
616 617 618
    MemoryRegion mem;
} IDRegState;

619
static int idreg_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
620
{
621
    IDRegState *s = MACIO_ID_REGISTER(dev);
B
Blue Swirl 已提交
622

623 624
    memory_region_init_ram(&s->mem, OBJECT(s),
                           "sun4m.idreg", sizeof(idreg_data));
625
    vmstate_register_ram_global(&s->mem);
A
Avi Kivity 已提交
626
    memory_region_set_readonly(&s->mem, true);
627
    sysbus_init_mmio(dev, &s->mem);
628
    return 0;
B
Blue Swirl 已提交
629 630
}

631 632 633 634 635 636 637
static void idreg_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = idreg_init1;
}

638
static const TypeInfo idreg_info = {
639
    .name          = TYPE_MACIO_ID_REGISTER,
640 641 642
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IDRegState),
    .class_init    = idreg_class_init,
B
Blue Swirl 已提交
643 644
};

645 646 647
#define TYPE_TCX_AFX "tcx_afx"
#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)

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

A
Avi Kivity 已提交
651 652 653
    MemoryRegion mem;
} AFXState;

A
Artyom Tarasenko 已提交
654
/* SS-5 TCX AFX register */
A
Avi Kivity 已提交
655
static void afx_init(hwaddr addr)
A
Artyom Tarasenko 已提交
656 657 658 659
{
    DeviceState *dev;
    SysBusDevice *s;

660
    dev = qdev_create(NULL, TYPE_TCX_AFX);
A
Artyom Tarasenko 已提交
661
    qdev_init_nofail(dev);
662
    s = SYS_BUS_DEVICE(dev);
A
Artyom Tarasenko 已提交
663 664 665 666 667 668

    sysbus_mmio_map(s, 0, addr);
}

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

671
    memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4);
672
    vmstate_register_ram_global(&s->mem);
673
    sysbus_init_mmio(dev, &s->mem);
A
Artyom Tarasenko 已提交
674 675 676
    return 0;
}

677 678 679 680 681 682 683
static void afx_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = afx_init1;
}

684
static const TypeInfo afx_info = {
685
    .name          = TYPE_TCX_AFX,
686 687 688
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AFXState),
    .class_init    = afx_class_init,
A
Artyom Tarasenko 已提交
689 690
};

691 692 693
#define TYPE_OPENPROM "openprom"
#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)

A
Avi Kivity 已提交
694
typedef struct PROMState {
695 696
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
697 698 699
    MemoryRegion prom;
} PROMState;

B
Blue Swirl 已提交
700
/* Boot PROM (OpenBIOS) */
701 702
static uint64_t translate_prom_address(void *opaque, uint64_t addr)
{
A
Avi Kivity 已提交
703
    hwaddr *base_addr = (hwaddr *)opaque;
704 705 706
    return addr + *base_addr - PROM_VADDR;
}

A
Avi Kivity 已提交
707
static void prom_init(hwaddr addr, const char *bios_name)
B
Blue Swirl 已提交
708 709 710 711 712 713
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

714
    dev = qdev_create(NULL, TYPE_OPENPROM);
M
Markus Armbruster 已提交
715
    qdev_init_nofail(dev);
716
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
717 718 719 720 721 722 723 724 725

    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) {
726 727
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
                       NULL, NULL, 1, ELF_MACHINE, 0);
B
Blue Swirl 已提交
728 729 730
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
731
        g_free(filename);
B
Blue Swirl 已提交
732 733 734 735 736 737 738 739 740
    } else {
        ret = -1;
    }
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
        exit(1);
    }
}

741
static int prom_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
742
{
743
    PROMState *s = OPENPROM(dev);
B
Blue Swirl 已提交
744

745
    memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX);
746
    vmstate_register_ram_global(&s->prom);
A
Avi Kivity 已提交
747
    memory_region_set_readonly(&s->prom, true);
748
    sysbus_init_mmio(dev, &s->prom);
749
    return 0;
B
Blue Swirl 已提交
750 751
}

752 753 754 755 756 757
static Property prom_properties[] = {
    {/* end of property list */},
};

static void prom_class_init(ObjectClass *klass, void *data)
{
758
    DeviceClass *dc = DEVICE_CLASS(klass);
759 760 761
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = prom_init1;
762
    dc->props = prom_properties;
763 764
}

765
static const TypeInfo prom_info = {
766
    .name          = TYPE_OPENPROM,
767 768 769
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PROMState),
    .class_init    = prom_class_init,
B
Blue Swirl 已提交
770 771
};

772 773 774 775 776 777
#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 已提交
778
    MemoryRegion ram;
779
    uint64_t size;
G
Gerd Hoffmann 已提交
780 781
} RamDevice;

B
Blue Swirl 已提交
782
/* System RAM */
783
static int ram_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
784
{
785
    RamDevice *d = SUN4M_RAM(dev);
B
Blue Swirl 已提交
786

787
    memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size);
788
    vmstate_register_ram_global(&d->ram);
789
    sysbus_init_mmio(dev, &d->ram);
790
    return 0;
B
Blue Swirl 已提交
791 792
}

A
Avi Kivity 已提交
793
static void ram_init(hwaddr addr, ram_addr_t RAM_size,
B
Blue Swirl 已提交
794 795 796 797
                     uint64_t max_mem)
{
    DeviceState *dev;
    SysBusDevice *s;
G
Gerd Hoffmann 已提交
798
    RamDevice *d;
B
Blue Swirl 已提交
799 800 801 802 803 804 805 806 807 808

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

811
    d = SUN4M_RAM(dev);
G
Gerd Hoffmann 已提交
812
    d->size = RAM_size;
M
Markus Armbruster 已提交
813
    qdev_init_nofail(dev);
G
Gerd Hoffmann 已提交
814

B
Blue Swirl 已提交
815 816 817
    sysbus_mmio_map(s, 0, addr);
}

818 819 820 821 822 823 824
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)
{
825
    DeviceClass *dc = DEVICE_CLASS(klass);
826 827 828
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = ram_init1;
829
    dc->props = ram_properties;
830 831
}

832
static const TypeInfo ram_info = {
833
    .name          = TYPE_SUN4M_MEMORY,
834 835 836
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(RamDevice),
    .class_init    = ram_class_init,
B
Blue Swirl 已提交
837 838
};

839 840
static void cpu_devinit(const char *cpu_model, unsigned int id,
                        uint64_t prom_addr, qemu_irq **cpu_irqs)
B
Blue Swirl 已提交
841
{
842
    CPUState *cs;
843
    SPARCCPU *cpu;
A
Andreas Färber 已提交
844
    CPUSPARCState *env;
B
Blue Swirl 已提交
845

846 847
    cpu = cpu_sparc_init(cpu_model);
    if (cpu == NULL) {
B
Blue Swirl 已提交
848 849 850
        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
        exit(1);
    }
851
    env = &cpu->env;
B
Blue Swirl 已提交
852 853 854

    cpu_sparc_set_id(env, id);
    if (id == 0) {
855
        qemu_register_reset(main_cpu_reset, cpu);
B
Blue Swirl 已提交
856
    } else {
857
        qemu_register_reset(secondary_cpu_reset, cpu);
858 859
        cs = CPU(cpu);
        cs->halted = 1;
B
Blue Swirl 已提交
860
    }
861
    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
B
Blue Swirl 已提交
862 863 864
    env->prom_addr = prom_addr;
}

B
Blue Swirl 已提交
865 866 867 868
static void dummy_fdc_tc(void *opaque, int irq, int level)
{
}

869 870
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
                          QEMUMachineInitArgs *args)
871
{
872
    const char *cpu_model = args->cpu_model;
B
bellard 已提交
873
    unsigned int i;
P
Paul Brook 已提交
874
    void *iommu, *espdma, *ledma, *nvram;
875
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
876
        espdma_irq, ledma_irq;
877
    qemu_irq esp_reset, dma_enable;
878
    qemu_irq fdc_tc;
B
blueswir1 已提交
879
    qemu_irq *cpu_halt;
B
blueswir1 已提交
880
    unsigned long kernel_size;
G
Gerd Hoffmann 已提交
881
    DriveInfo *fd[MAX_FD];
L
Laszlo Ersek 已提交
882
    FWCfgState *fw_cfg;
883
    unsigned int num_vsimms;
884

B
bellard 已提交
885
    /* init CPUs */
886 887
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;
888

B
bellard 已提交
889
    for(i = 0; i < smp_cpus; i++) {
890
        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
B
bellard 已提交
891
    }
892 893 894 895

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

896 897

    /* set up devices */
898
    ram_init(0, args->ram_size, hwdef->max_mem);
899 900
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
901
        empty_slot_init(args->ram_size, hwdef->max_mem - args->ram_size);
902
    }
B
Blue Swirl 已提交
903

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

906 907
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
B
Blue Swirl 已提交
908
                                       cpu_irqs);
909 910

    for (i = 0; i < 32; i++) {
911
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
912 913
    }
    for (i = 0; i < MAX_CPUS; i++) {
914
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
915
    }
916

917
    if (hwdef->idreg_base) {
B
Blue Swirl 已提交
918
        idreg_init(hwdef->idreg_base);
B
blueswir1 已提交
919 920
    }

A
Artyom Tarasenko 已提交
921 922 923 924
    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

925
    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
926
                       slavio_irq[30]);
927

928 929 930 931 932 933 934 935
    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);
    }

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

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

B
blueswir1 已提交
942
    if (graphic_depth != 8 && graphic_depth != 24) {
943
        error_report("Unsupported depth: %d", graphic_depth);
B
blueswir1 已提交
944 945
        exit (1);
    }
946 947
    num_vsimms = 0;
    if (num_vsimms == 0) {
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
        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);
            }

            tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
                     graphic_depth);
        }
980 981 982 983 984 985 986 987 988 989 990 991
    }

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

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

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

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

999
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
1000
                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
S
Stefan Weil 已提交
1001 1002
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
1003
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
A
aurel32 已提交
1004
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
B
blueswir1 已提交
1005

B
blueswir1 已提交
1006
    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
1007 1008 1009
    if (hwdef->apc_base) {
        apc_init(hwdef->apc_base, cpu_halt[0]);
    }
B
blueswir1 已提交
1010

1011
    if (hwdef->fd_base) {
T
ths 已提交
1012
        /* there is zero or one floppy drive */
1013
        memset(fd, 0, sizeof(fd));
G
Gerd Hoffmann 已提交
1014
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
1015
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
1016
                          &fdc_tc);
B
Blue Swirl 已提交
1017 1018
    } else {
        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
T
ths 已提交
1019 1020
    }

B
Blue Swirl 已提交
1021 1022 1023
    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

T
ths 已提交
1024 1025 1026 1027 1028
    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

P
Paul Brook 已提交
1029 1030
    esp_init(hwdef->esp_base, 2,
             espdma_memory_read, espdma_memory_write,
1031
             espdma, espdma_irq, &esp_reset, &dma_enable);
1032

1033 1034
    qdev_connect_gpio_out(espdma, 0, esp_reset);
    qdev_connect_gpio_out(espdma, 1, dma_enable);
1035

B
Blue Swirl 已提交
1036 1037
    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
1038
                             slavio_irq[5]);
B
Blue Swirl 已提交
1039
    }
1040

1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
    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);
    }

1054 1055 1056
    kernel_size = sun4m_load_kernel(args->kernel_filename,
                                    args->initrd_filename,
                                    args->ram_size);
1057

1058
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, args->kernel_cmdline,
1059
               args->boot_order, args->ram_size, kernel_size, graphic_width,
1060 1061
               graphic_height, graphic_depth, hwdef->nvram_machine_id,
               "Sun4m");
1062

1063
    if (hwdef->ecc_base)
1064
        ecc_init(hwdef->ecc_base, slavio_irq[28],
1065
                 hwdef->ecc_version);
1066 1067

    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
1068
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
1069
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
1070 1071
    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);
1072
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
1073 1074
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
1075 1076
    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);
1077
    if (args->kernel_cmdline) {
1078
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1079 1080 1081
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
                         args->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, args->kernel_cmdline);
B
Blue Swirl 已提交
1082
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
1083
                       strlen(args->kernel_cmdline) + 1);
1084 1085
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
B
Blue Swirl 已提交
1086
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1087 1088 1089
    }
    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
1090
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, args->boot_order[0]);
1091
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1092 1093
}

1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
enum {
    ss5_id = 32,
    vger_id,
    lx_id,
    ss4_id,
    scls_id,
    sbook_id,
    ss10_id = 64,
    ss20_id,
    ss600mp_id,
};

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

/* SPARCstation 5 hardware initialisation */
1352
static void ss5_init(QEMUMachineInitArgs *args)
1353
{
1354
    sun4m_hw_init(&sun4m_hwdefs[0], args);
1355
}
B
bellard 已提交
1356

B
blueswir1 已提交
1357
/* SPARCstation 10 hardware initialisation */
1358
static void ss10_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1359
{
1360
    sun4m_hw_init(&sun4m_hwdefs[1], args);
B
blueswir1 已提交
1361 1362
}

1363
/* SPARCserver 600MP hardware initialisation */
1364
static void ss600mp_init(QEMUMachineInitArgs *args)
1365
{
1366
    sun4m_hw_init(&sun4m_hwdefs[2], args);
1367 1368
}

1369
/* SPARCstation 20 hardware initialisation */
1370
static void ss20_init(QEMUMachineInitArgs *args)
1371
{
1372
    sun4m_hw_init(&sun4m_hwdefs[3], args);
B
blueswir1 已提交
1373 1374
}

B
blueswir1 已提交
1375
/* SPARCstation Voyager hardware initialisation */
1376
static void vger_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1377
{
1378
    sun4m_hw_init(&sun4m_hwdefs[4], args);
B
blueswir1 已提交
1379 1380 1381
}

/* SPARCstation LX hardware initialisation */
1382
static void ss_lx_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1383
{
1384
    sun4m_hw_init(&sun4m_hwdefs[5], args);
B
blueswir1 已提交
1385 1386 1387
}

/* SPARCstation 4 hardware initialisation */
1388
static void ss4_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1389
{
1390
    sun4m_hw_init(&sun4m_hwdefs[6], args);
B
blueswir1 已提交
1391 1392 1393
}

/* SPARCClassic hardware initialisation */
1394
static void scls_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1395
{
1396
    sun4m_hw_init(&sun4m_hwdefs[7], args);
B
blueswir1 已提交
1397 1398 1399
}

/* SPARCbook hardware initialisation */
1400
static void sbook_init(QEMUMachineInitArgs *args)
B
blueswir1 已提交
1401
{
1402
    sun4m_hw_init(&sun4m_hwdefs[8], args);
B
blueswir1 已提交
1403 1404
}

1405
static QEMUMachine ss5_machine = {
B
blueswir1 已提交
1406 1407 1408
    .name = "SS-5",
    .desc = "Sun4m platform, SPARCstation 5",
    .init = ss5_init,
1409
    .block_default_type = IF_SCSI,
1410
    .is_default = 1,
1411
    .default_boot_order = "c",
B
bellard 已提交
1412
};
B
blueswir1 已提交
1413

1414
static QEMUMachine ss10_machine = {
B
blueswir1 已提交
1415 1416 1417
    .name = "SS-10",
    .desc = "Sun4m platform, SPARCstation 10",
    .init = ss10_init,
1418
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1419
    .max_cpus = 4,
1420
    .default_boot_order = "c",
B
blueswir1 已提交
1421
};
1422

1423
static QEMUMachine ss600mp_machine = {
B
blueswir1 已提交
1424 1425 1426
    .name = "SS-600MP",
    .desc = "Sun4m platform, SPARCserver 600MP",
    .init = ss600mp_init,
1427
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1428
    .max_cpus = 4,
1429
    .default_boot_order = "c",
1430
};
1431

1432
static QEMUMachine ss20_machine = {
B
blueswir1 已提交
1433 1434 1435
    .name = "SS-20",
    .desc = "Sun4m platform, SPARCstation 20",
    .init = ss20_init,
1436
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1437
    .max_cpus = 4,
1438
    .default_boot_order = "c",
1439 1440
};

1441
static QEMUMachine voyager_machine = {
B
blueswir1 已提交
1442 1443 1444
    .name = "Voyager",
    .desc = "Sun4m platform, SPARCstation Voyager",
    .init = vger_init,
1445
    .block_default_type = IF_SCSI,
1446
    .default_boot_order = "c",
B
blueswir1 已提交
1447 1448
};

1449
static QEMUMachine ss_lx_machine = {
B
blueswir1 已提交
1450 1451 1452
    .name = "LX",
    .desc = "Sun4m platform, SPARCstation LX",
    .init = ss_lx_init,
1453
    .block_default_type = IF_SCSI,
1454
    .default_boot_order = "c",
B
blueswir1 已提交
1455 1456
};

1457
static QEMUMachine ss4_machine = {
B
blueswir1 已提交
1458 1459 1460
    .name = "SS-4",
    .desc = "Sun4m platform, SPARCstation 4",
    .init = ss4_init,
1461
    .block_default_type = IF_SCSI,
1462
    .default_boot_order = "c",
B
blueswir1 已提交
1463 1464
};

1465
static QEMUMachine scls_machine = {
B
blueswir1 已提交
1466 1467 1468
    .name = "SPARCClassic",
    .desc = "Sun4m platform, SPARCClassic",
    .init = scls_init,
1469
    .block_default_type = IF_SCSI,
1470
    .default_boot_order = "c",
B
blueswir1 已提交
1471 1472
};

1473
static QEMUMachine sbook_machine = {
B
blueswir1 已提交
1474 1475 1476
    .name = "SPARCbook",
    .desc = "Sun4m platform, SPARCbook",
    .init = sbook_init,
1477
    .block_default_type = IF_SCSI,
1478
    .default_boot_order = "c",
B
blueswir1 已提交
1479 1480
};

A
Andreas Färber 已提交
1481 1482 1483 1484 1485 1486 1487 1488
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);
}

B
Blue Swirl 已提交
1489
static void sun4m_machine_init(void)
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
{
    qemu_register_machine(&ss5_machine);
    qemu_register_machine(&ss10_machine);
    qemu_register_machine(&ss600mp_machine);
    qemu_register_machine(&ss20_machine);
    qemu_register_machine(&voyager_machine);
    qemu_register_machine(&ss_lx_machine);
    qemu_register_machine(&ss4_machine);
    qemu_register_machine(&scls_machine);
    qemu_register_machine(&sbook_machine);
}

A
Andreas Färber 已提交
1502
type_init(sun4m_register_types)
B
Blue Swirl 已提交
1503
machine_init(sun4m_machine_init);