sun4m.c 44.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.
 */
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/block-backend.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 125
static void fw_cfg_boot_set(void *opaque, const char *boot_device,
                            Error **errp)
B
blueswir1 已提交
126
{
127
    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
B
blueswir1 已提交
128 129
}

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_hmp_info_pic(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_hmp_info_irq(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);
}

530
static void tcx_init(hwaddr addr, qemu_irq irq, 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

    /* 10/ROM : FCode ROM */
546
    sysbus_mmio_map(s, 0, addr);
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
    /* 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);
562
    } else {
563
        sysbus_mmio_map(s, 7, addr + 0x00301000ULL);
564
    }
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
    /* 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);
581 582
}

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
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 已提交
608
/* NCR89C100/MACIO Internal ID register */
609 610 611

#define TYPE_MACIO_ID_REGISTER "macio_idreg"

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

A
Avi Kivity 已提交
614
static void idreg_init(hwaddr addr)
B
Blue Swirl 已提交
615 616 617 618
{
    DeviceState *dev;
    SysBusDevice *s;

619
    dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
M
Markus Armbruster 已提交
620
    qdev_init_nofail(dev);
621
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
622 623

    sysbus_mmio_map(s, 0, addr);
624 625
    cpu_physical_memory_write_rom(&address_space_memory,
                                  addr, idreg_data, sizeof(idreg_data));
B
Blue Swirl 已提交
626 627
}

628 629 630
#define MACIO_ID_REGISTER(obj) \
    OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)

A
Avi Kivity 已提交
631
typedef struct IDRegState {
632 633
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
634 635 636
    MemoryRegion mem;
} IDRegState;

637
static int idreg_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
638
{
639
    IDRegState *s = MACIO_ID_REGISTER(dev);
B
Blue Swirl 已提交
640

641
    memory_region_init_ram(&s->mem, OBJECT(s),
642
                           "sun4m.idreg", sizeof(idreg_data), &error_abort);
643
    vmstate_register_ram_global(&s->mem);
A
Avi Kivity 已提交
644
    memory_region_set_readonly(&s->mem, true);
645
    sysbus_init_mmio(dev, &s->mem);
646
    return 0;
B
Blue Swirl 已提交
647 648
}

649 650 651 652 653 654 655
static void idreg_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = idreg_init1;
}

656
static const TypeInfo idreg_info = {
657
    .name          = TYPE_MACIO_ID_REGISTER,
658 659 660
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IDRegState),
    .class_init    = idreg_class_init,
B
Blue Swirl 已提交
661 662
};

663 664 665
#define TYPE_TCX_AFX "tcx_afx"
#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)

A
Avi Kivity 已提交
666
typedef struct AFXState {
667 668
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
669 670 671
    MemoryRegion mem;
} AFXState;

A
Artyom Tarasenko 已提交
672
/* SS-5 TCX AFX register */
A
Avi Kivity 已提交
673
static void afx_init(hwaddr addr)
A
Artyom Tarasenko 已提交
674 675 676 677
{
    DeviceState *dev;
    SysBusDevice *s;

678
    dev = qdev_create(NULL, TYPE_TCX_AFX);
A
Artyom Tarasenko 已提交
679
    qdev_init_nofail(dev);
680
    s = SYS_BUS_DEVICE(dev);
A
Artyom Tarasenko 已提交
681 682 683 684 685 686

    sysbus_mmio_map(s, 0, addr);
}

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

689
    memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4, &error_abort);
690
    vmstate_register_ram_global(&s->mem);
691
    sysbus_init_mmio(dev, &s->mem);
A
Artyom Tarasenko 已提交
692 693 694
    return 0;
}

695 696 697 698 699 700 701
static void afx_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = afx_init1;
}

702
static const TypeInfo afx_info = {
703
    .name          = TYPE_TCX_AFX,
704 705 706
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AFXState),
    .class_init    = afx_class_init,
A
Artyom Tarasenko 已提交
707 708
};

709 710 711
#define TYPE_OPENPROM "openprom"
#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)

A
Avi Kivity 已提交
712
typedef struct PROMState {
713 714
    SysBusDevice parent_obj;

A
Avi Kivity 已提交
715 716 717
    MemoryRegion prom;
} PROMState;

B
Blue Swirl 已提交
718
/* Boot PROM (OpenBIOS) */
719 720
static uint64_t translate_prom_address(void *opaque, uint64_t addr)
{
A
Avi Kivity 已提交
721
    hwaddr *base_addr = (hwaddr *)opaque;
722 723 724
    return addr + *base_addr - PROM_VADDR;
}

A
Avi Kivity 已提交
725
static void prom_init(hwaddr addr, const char *bios_name)
B
Blue Swirl 已提交
726 727 728 729 730 731
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

732
    dev = qdev_create(NULL, TYPE_OPENPROM);
M
Markus Armbruster 已提交
733
    qdev_init_nofail(dev);
734
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
735 736 737 738 739 740 741 742 743

    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) {
744 745
        ret = load_elf(filename, translate_prom_address, &addr, NULL,
                       NULL, NULL, 1, ELF_MACHINE, 0);
B
Blue Swirl 已提交
746 747 748
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
749
        g_free(filename);
B
Blue Swirl 已提交
750 751 752 753 754 755 756 757 758
    } else {
        ret = -1;
    }
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
        exit(1);
    }
}

759
static int prom_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
760
{
761
    PROMState *s = OPENPROM(dev);
B
Blue Swirl 已提交
762

763 764
    memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX,
                           &error_abort);
765
    vmstate_register_ram_global(&s->prom);
A
Avi Kivity 已提交
766
    memory_region_set_readonly(&s->prom, true);
767
    sysbus_init_mmio(dev, &s->prom);
768
    return 0;
B
Blue Swirl 已提交
769 770
}

771 772 773 774 775 776
static Property prom_properties[] = {
    {/* end of property list */},
};

static void prom_class_init(ObjectClass *klass, void *data)
{
777
    DeviceClass *dc = DEVICE_CLASS(klass);
778 779 780
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = prom_init1;
781
    dc->props = prom_properties;
782 783
}

784
static const TypeInfo prom_info = {
785
    .name          = TYPE_OPENPROM,
786 787 788
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PROMState),
    .class_init    = prom_class_init,
B
Blue Swirl 已提交
789 790
};

791 792 793 794 795 796
#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 已提交
797
    MemoryRegion ram;
798
    uint64_t size;
G
Gerd Hoffmann 已提交
799 800
} RamDevice;

B
Blue Swirl 已提交
801
/* System RAM */
802
static int ram_init1(SysBusDevice *dev)
B
Blue Swirl 已提交
803
{
804
    RamDevice *d = SUN4M_RAM(dev);
B
Blue Swirl 已提交
805

806 807
    memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size,
                           &error_abort);
808
    vmstate_register_ram_global(&d->ram);
809
    sysbus_init_mmio(dev, &d->ram);
810
    return 0;
B
Blue Swirl 已提交
811 812
}

A
Avi Kivity 已提交
813
static void ram_init(hwaddr addr, ram_addr_t RAM_size,
B
Blue Swirl 已提交
814 815 816 817
                     uint64_t max_mem)
{
    DeviceState *dev;
    SysBusDevice *s;
G
Gerd Hoffmann 已提交
818
    RamDevice *d;
B
Blue Swirl 已提交
819 820 821 822 823 824 825 826 827 828

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

831
    d = SUN4M_RAM(dev);
G
Gerd Hoffmann 已提交
832
    d->size = RAM_size;
M
Markus Armbruster 已提交
833
    qdev_init_nofail(dev);
G
Gerd Hoffmann 已提交
834

B
Blue Swirl 已提交
835 836 837
    sysbus_mmio_map(s, 0, addr);
}

838 839 840 841 842 843 844
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)
{
845
    DeviceClass *dc = DEVICE_CLASS(klass);
846 847 848
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = ram_init1;
849
    dc->props = ram_properties;
850 851
}

852
static const TypeInfo ram_info = {
853
    .name          = TYPE_SUN4M_MEMORY,
854 855 856
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(RamDevice),
    .class_init    = ram_class_init,
B
Blue Swirl 已提交
857 858
};

859 860
static void cpu_devinit(const char *cpu_model, unsigned int id,
                        uint64_t prom_addr, qemu_irq **cpu_irqs)
B
Blue Swirl 已提交
861
{
862
    CPUState *cs;
863
    SPARCCPU *cpu;
A
Andreas Färber 已提交
864
    CPUSPARCState *env;
B
Blue Swirl 已提交
865

866 867
    cpu = cpu_sparc_init(cpu_model);
    if (cpu == NULL) {
B
Blue Swirl 已提交
868 869 870
        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
        exit(1);
    }
871
    env = &cpu->env;
B
Blue Swirl 已提交
872 873 874

    cpu_sparc_set_id(env, id);
    if (id == 0) {
875
        qemu_register_reset(main_cpu_reset, cpu);
B
Blue Swirl 已提交
876
    } else {
877
        qemu_register_reset(secondary_cpu_reset, cpu);
878 879
        cs = CPU(cpu);
        cs->halted = 1;
B
Blue Swirl 已提交
880
    }
881
    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
B
Blue Swirl 已提交
882 883 884
    env->prom_addr = prom_addr;
}

B
Blue Swirl 已提交
885 886 887 888
static void dummy_fdc_tc(void *opaque, int irq, int level)
{
}

889
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
890
                          MachineState *machine)
891
{
892
    const char *cpu_model = machine->cpu_model;
B
bellard 已提交
893
    unsigned int i;
P
Paul Brook 已提交
894
    void *iommu, *espdma, *ledma, *nvram;
895
    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
896
        espdma_irq, ledma_irq;
897
    qemu_irq esp_reset, dma_enable;
898
    qemu_irq fdc_tc;
B
blueswir1 已提交
899
    qemu_irq *cpu_halt;
B
blueswir1 已提交
900
    unsigned long kernel_size;
G
Gerd Hoffmann 已提交
901
    DriveInfo *fd[MAX_FD];
L
Laszlo Ersek 已提交
902
    FWCfgState *fw_cfg;
903
    unsigned int num_vsimms;
904

B
bellard 已提交
905
    /* init CPUs */
906 907
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;
908

B
bellard 已提交
909
    for(i = 0; i < smp_cpus; i++) {
910
        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
B
bellard 已提交
911
    }
912 913 914 915

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

916 917

    /* set up devices */
918
    ram_init(0, machine->ram_size, hwdef->max_mem);
919 920
    /* models without ECC don't trap when missing ram is accessed */
    if (!hwdef->ecc_base) {
921
        empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size);
922
    }
B
Blue Swirl 已提交
923

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

926 927
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
                                       hwdef->intctl_base + 0x10000ULL,
B
Blue Swirl 已提交
928
                                       cpu_irqs);
929 930

    for (i = 0; i < 32; i++) {
931
        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
932 933
    }
    for (i = 0; i < MAX_CPUS; i++) {
934
        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
935
    }
936

937
    if (hwdef->idreg_base) {
B
Blue Swirl 已提交
938
        idreg_init(hwdef->idreg_base);
B
blueswir1 已提交
939 940
    }

A
Artyom Tarasenko 已提交
941 942 943 944
    if (hwdef->afx_base) {
        afx_init(hwdef->afx_base);
    }

945
    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
946
                       slavio_irq[30]);
947

948 949 950 951 952 953 954 955
    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);
    }

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

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

B
blueswir1 已提交
962
    if (graphic_depth != 8 && graphic_depth != 24) {
963
        error_report("Unsupported depth: %d", graphic_depth);
B
blueswir1 已提交
964 965
        exit (1);
    }
966 967
    num_vsimms = 0;
    if (num_vsimms == 0) {
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
        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);
            }

997 998
            tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000,
                     graphic_width, graphic_height, graphic_depth);
999
        }
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
    }

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

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

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

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

1019
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
1020
                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
S
Stefan Weil 已提交
1021 1022
    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
1023
    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
A
aurel32 已提交
1024
              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
B
blueswir1 已提交
1025

B
blueswir1 已提交
1026
    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
1027 1028 1029
    if (hwdef->apc_base) {
        apc_init(hwdef->apc_base, cpu_halt[0]);
    }
B
blueswir1 已提交
1030

1031
    if (hwdef->fd_base) {
T
ths 已提交
1032
        /* there is zero or one floppy drive */
1033
        memset(fd, 0, sizeof(fd));
G
Gerd Hoffmann 已提交
1034
        fd[0] = drive_get(IF_FLOPPY, 0, 0);
1035
        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
1036
                          &fdc_tc);
B
Blue Swirl 已提交
1037 1038
    } else {
        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
T
ths 已提交
1039 1040
    }

B
Blue Swirl 已提交
1041 1042 1043
    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
                     slavio_irq[30], fdc_tc);

T
ths 已提交
1044 1045 1046 1047 1048
    if (drive_get_max_bus(IF_SCSI) > 0) {
        fprintf(stderr, "qemu: too many SCSI bus\n");
        exit(1);
    }

P
Paul Brook 已提交
1049 1050
    esp_init(hwdef->esp_base, 2,
             espdma_memory_read, espdma_memory_write,
1051
             espdma, espdma_irq, &esp_reset, &dma_enable);
1052

1053 1054
    qdev_connect_gpio_out(espdma, 0, esp_reset);
    qdev_connect_gpio_out(espdma, 1, dma_enable);
1055

B
Blue Swirl 已提交
1056 1057
    if (hwdef->cs_base) {
        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
1058
                             slavio_irq[5]);
B
Blue Swirl 已提交
1059
    }
1060

1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
    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);
    }

1074 1075 1076
    kernel_size = sun4m_load_kernel(machine->kernel_filename,
                                    machine->initrd_filename,
                                    machine->ram_size);
1077

1078 1079 1080 1081
    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");
1082

1083
    if (hwdef->ecc_base)
1084
        ecc_init(hwdef->ecc_base, slavio_irq[28],
1085
                 hwdef->ecc_version);
1086

1087
    fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
1088
    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
1089
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
1090 1091
    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);
1092
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
1093 1094
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
1095 1096
    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);
1097
    if (machine->kernel_cmdline) {
1098
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
1099
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
1100 1101
                         machine->kernel_cmdline);
        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline);
B
Blue Swirl 已提交
1102
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
1103
                       strlen(machine->kernel_cmdline) + 1);
1104 1105
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
B
Blue Swirl 已提交
1106
        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
1107 1108 1109
    }
    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
1110
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]);
1111
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
1112 1113
}

1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
enum {
    ss5_id = 32,
    vger_id,
    lx_id,
    ss4_id,
    scls_id,
    sbook_id,
    ss10_id = 64,
    ss20_id,
    ss600mp_id,
};

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

/* SPARCstation 5 hardware initialisation */
1372
static void ss5_init(MachineState *machine)
1373
{
1374
    sun4m_hw_init(&sun4m_hwdefs[0], machine);
1375
}
B
bellard 已提交
1376

B
blueswir1 已提交
1377
/* SPARCstation 10 hardware initialisation */
1378
static void ss10_init(MachineState *machine)
B
blueswir1 已提交
1379
{
1380
    sun4m_hw_init(&sun4m_hwdefs[1], machine);
B
blueswir1 已提交
1381 1382
}

1383
/* SPARCserver 600MP hardware initialisation */
1384
static void ss600mp_init(MachineState *machine)
1385
{
1386
    sun4m_hw_init(&sun4m_hwdefs[2], machine);
1387 1388
}

1389
/* SPARCstation 20 hardware initialisation */
1390
static void ss20_init(MachineState *machine)
1391
{
1392
    sun4m_hw_init(&sun4m_hwdefs[3], machine);
B
blueswir1 已提交
1393 1394
}

B
blueswir1 已提交
1395
/* SPARCstation Voyager hardware initialisation */
1396
static void vger_init(MachineState *machine)
B
blueswir1 已提交
1397
{
1398
    sun4m_hw_init(&sun4m_hwdefs[4], machine);
B
blueswir1 已提交
1399 1400 1401
}

/* SPARCstation LX hardware initialisation */
1402
static void ss_lx_init(MachineState *machine)
B
blueswir1 已提交
1403
{
1404
    sun4m_hw_init(&sun4m_hwdefs[5], machine);
B
blueswir1 已提交
1405 1406 1407
}

/* SPARCstation 4 hardware initialisation */
1408
static void ss4_init(MachineState *machine)
B
blueswir1 已提交
1409
{
1410
    sun4m_hw_init(&sun4m_hwdefs[6], machine);
B
blueswir1 已提交
1411 1412 1413
}

/* SPARCClassic hardware initialisation */
1414
static void scls_init(MachineState *machine)
B
blueswir1 已提交
1415
{
1416
    sun4m_hw_init(&sun4m_hwdefs[7], machine);
B
blueswir1 已提交
1417 1418 1419
}

/* SPARCbook hardware initialisation */
1420
static void sbook_init(MachineState *machine)
B
blueswir1 已提交
1421
{
1422
    sun4m_hw_init(&sun4m_hwdefs[8], machine);
B
blueswir1 已提交
1423 1424
}

1425
static QEMUMachine ss5_machine = {
B
blueswir1 已提交
1426 1427 1428
    .name = "SS-5",
    .desc = "Sun4m platform, SPARCstation 5",
    .init = ss5_init,
1429
    .block_default_type = IF_SCSI,
1430
    .is_default = 1,
1431
    .default_boot_order = "c",
B
bellard 已提交
1432
};
B
blueswir1 已提交
1433

1434
static QEMUMachine ss10_machine = {
B
blueswir1 已提交
1435 1436 1437
    .name = "SS-10",
    .desc = "Sun4m platform, SPARCstation 10",
    .init = ss10_init,
1438
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1439
    .max_cpus = 4,
1440
    .default_boot_order = "c",
B
blueswir1 已提交
1441
};
1442

1443
static QEMUMachine ss600mp_machine = {
B
blueswir1 已提交
1444 1445 1446
    .name = "SS-600MP",
    .desc = "Sun4m platform, SPARCserver 600MP",
    .init = ss600mp_init,
1447
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1448
    .max_cpus = 4,
1449
    .default_boot_order = "c",
1450
};
1451

1452
static QEMUMachine ss20_machine = {
B
blueswir1 已提交
1453 1454 1455
    .name = "SS-20",
    .desc = "Sun4m platform, SPARCstation 20",
    .init = ss20_init,
1456
    .block_default_type = IF_SCSI,
B
blueswir1 已提交
1457
    .max_cpus = 4,
1458
    .default_boot_order = "c",
1459 1460
};

1461
static QEMUMachine voyager_machine = {
B
blueswir1 已提交
1462 1463 1464
    .name = "Voyager",
    .desc = "Sun4m platform, SPARCstation Voyager",
    .init = vger_init,
1465
    .block_default_type = IF_SCSI,
1466
    .default_boot_order = "c",
B
blueswir1 已提交
1467 1468
};

1469
static QEMUMachine ss_lx_machine = {
B
blueswir1 已提交
1470 1471 1472
    .name = "LX",
    .desc = "Sun4m platform, SPARCstation LX",
    .init = ss_lx_init,
1473
    .block_default_type = IF_SCSI,
1474
    .default_boot_order = "c",
B
blueswir1 已提交
1475 1476
};

1477
static QEMUMachine ss4_machine = {
B
blueswir1 已提交
1478 1479 1480
    .name = "SS-4",
    .desc = "Sun4m platform, SPARCstation 4",
    .init = ss4_init,
1481
    .block_default_type = IF_SCSI,
1482
    .default_boot_order = "c",
B
blueswir1 已提交
1483 1484
};

1485
static QEMUMachine scls_machine = {
B
blueswir1 已提交
1486 1487 1488
    .name = "SPARCClassic",
    .desc = "Sun4m platform, SPARCClassic",
    .init = scls_init,
1489
    .block_default_type = IF_SCSI,
1490
    .default_boot_order = "c",
B
blueswir1 已提交
1491 1492
};

1493
static QEMUMachine sbook_machine = {
B
blueswir1 已提交
1494 1495 1496
    .name = "SPARCbook",
    .desc = "Sun4m platform, SPARCbook",
    .init = sbook_init,
1497
    .block_default_type = IF_SCSI,
1498
    .default_boot_order = "c",
B
blueswir1 已提交
1499 1500
};

A
Andreas Färber 已提交
1501 1502 1503 1504 1505 1506 1507 1508
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 已提交
1509
static void sun4m_machine_init(void)
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
{
    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 已提交
1522
type_init(sun4m_register_types)
B
Blue Swirl 已提交
1523
machine_init(sun4m_machine_init);