Blame view

hw/sun4u.c 21.7 KB
bellard authored
1
/*
2
 * QEMU Sun4u/Sun4v System Emulator
3
 *
bellard authored
4
 * Copyright (c) 2005 Fabrice Bellard
5
 *
bellard authored
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.
 */
pbrook authored
24
25
26
27
28
29
30
31
32
#include "hw.h"
#include "pci.h"
#include "pc.h"
#include "nvram.h"
#include "fdc.h"
#include "net.h"
#include "qemu-timer.h"
#include "sysemu.h"
#include "boards.h"
33
#include "firmware_abi.h"
34
#include "fw_cfg.h"
35
#include "sysbus.h"
bellard authored
36
37
38
39
//#define DEBUG_IRQ

#ifdef DEBUG_IRQ
40
41
#define DPRINTF(fmt, ...)                                       \
    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
42
#else
43
#define DPRINTF(fmt, ...)
44
45
#endif
bellard authored
46
47
48
#define KERNEL_LOAD_ADDR     0x00404000
#define CMDLINE_ADDR         0x003ff000
#define INITRD_LOAD_ADDR     0x00300000
49
#define PROM_SIZE_MAX        (4 * 1024 * 1024)
blueswir1 authored
50
#define PROM_VADDR           0x000ffd00000ULL
bellard authored
51
#define APB_SPECIAL_BASE     0x1fe00000000ULL
blueswir1 authored
52
53
54
#define APB_MEM_BASE         0x1ff00000000ULL
#define VGA_BASE             (APB_MEM_BASE + 0x400000ULL)
#define PROM_FILENAME        "openbios-sparc64"
bellard authored
55
#define NVRAM_SIZE           0x2000
56
#define MAX_IDE_BUS          2
57
#define BIOS_CFG_IOPORT      0x510
bellard authored
58
59
60
#define MAX_PILS 16
61
62
63
#define TICK_INT_DIS         0x8000000000000000ULL
#define TICK_MAX             0x7fffffffffffffffULL
64
65
struct hwdef {
    const char * const default_cpu_model;
66
    uint16_t machine_id;
67
68
    uint64_t prom_addr;
    uint64_t console_serial_base;
69
70
};
bellard authored
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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) {}
void DMA_init (int high_page_enable) {}
void DMA_register_channel (int nchan,
                           DMA_transfer_handler transfer_handler,
                           void *opaque)
{
}
93
static int fw_cfg_boot_set(void *opaque, const char *boot_device)
94
{
95
    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
96
97
98
    return 0;
}
99
static int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
100
                                   const char *arch,
blueswir1 authored
101
102
                                   ram_addr_t RAM_size,
                                   const char *boot_devices,
103
104
105
106
                                   uint32_t kernel_image, uint32_t kernel_size,
                                   const char *cmdline,
                                   uint32_t initrd_image, uint32_t initrd_size,
                                   uint32_t NVRAM_image,
blueswir1 authored
107
108
                                   int width, int height, int depth,
                                   const uint8_t *macaddr)
bellard authored
109
{
110
111
    unsigned int i;
    uint32_t start, end;
112
113
114
115
116
    uint8_t image[0x1ff0];
    struct OpenBIOS_nvpart_v1 *part_header;

    memset(image, '\0', sizeof(image));
117
    start = 0;
bellard authored
118
119
120
    // OpenBIOS nvram variables
    // Variable partition
121
122
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_SYSTEM;
123
    pstrcpy(part_header->name, sizeof(part_header->name), "system");
124
125
    end = start + sizeof(struct OpenBIOS_nvpart_v1);
126
    for (i = 0; i < nb_prom_envs; i++)
127
128
129
130
        end = OpenBIOS_set_var(image, end, prom_envs[i]);

    // End marker
    image[end++] = '\0';
131
132

    end = start + ((end - start + 15) & ~15);
133
    OpenBIOS_finish_partition(part_header, end - start);
134
135
136

    // free partition
    start = end;
137
138
    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
    part_header->signature = OPENBIOS_PART_FREE;
139
    pstrcpy(part_header->name, sizeof(part_header->name), "free");
140
141

    end = 0x1fd0;
142
143
    OpenBIOS_finish_partition(part_header, end - start);
blueswir1 authored
144
145
    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
146
147
    for (i = 0; i < sizeof(image); i++)
        m48t59_write(nvram, i, image[i]);
148
bellard authored
149
    return 0;
bellard authored
150
}
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
static unsigned long sun4u_load_kernel(const char *kernel_filename,
                                       const char *initrd_filename,
                                       ram_addr_t RAM_size, long *initrd_size)
{
    int linux_boot;
    unsigned int i;
    long kernel_size;

    linux_boot = (kernel_filename != NULL);

    kernel_size = 0;
    if (linux_boot) {
        kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL);
        if (kernel_size < 0)
            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
                                    RAM_size - KERNEL_LOAD_ADDR);
        if (kernel_size < 0)
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              RAM_size - KERNEL_LOAD_ADDR);
        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) {
            *initrd_size = load_image_targphys(initrd_filename,
                                               INITRD_LOAD_ADDR,
                                               RAM_size - INITRD_LOAD_ADDR);
            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) {
                if (ldl_phys(KERNEL_LOAD_ADDR + i) == 0x48647253) { // HdrS
                    stl_phys(KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
                    stl_phys(KERNEL_LOAD_ADDR + i + 20, *initrd_size);
                    break;
                }
            }
        }
    }
    return kernel_size;
}
bellard authored
201
202
void pic_info(Monitor *mon)
bellard authored
203
204
205
{
}
206
void irq_info(Monitor *mon)
bellard authored
207
208
209
{
}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
void cpu_check_irqs(CPUState *env)
{
    uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) |
        ((env->softint & SOFTINT_TIMER) << 14);

    if (pil && (env->interrupt_index == 0 ||
                (env->interrupt_index & ~15) == TT_EXTINT)) {
        unsigned int i;

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

                env->interrupt_index = TT_EXTINT | i;
                if (old_interrupt != env->interrupt_index) {
                    DPRINTF("Set CPU IRQ %d\n", i);
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) {
        DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15);
        env->interrupt_index = 0;
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}

static void cpu_set_irq(void *opaque, int irq, int level)
{
    CPUState *env = opaque;

    if (level) {
        DPRINTF("Raise CPU IRQ %d\n", irq);
        env->halted = 0;
        env->pil_in |= 1 << irq;
        cpu_check_irqs(env);
    } else {
        DPRINTF("Lower CPU IRQ %d\n", irq);
        env->pil_in &= ~(1 << irq);
        cpu_check_irqs(env);
    }
}
bellard authored
254
void qemu_system_powerdown(void)
bellard authored
255
256
257
{
}
258
259
260
261
262
typedef struct ResetData {
    CPUState *env;
    uint64_t reset_addr;
} ResetData;
bellard authored
263
264
static void main_cpu_reset(void *opaque)
{
265
266
    ResetData *s = (ResetData *)opaque;
    CPUState *env = s->env;
267
bellard authored
268
    cpu_reset(env);
269
270
    env->tick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->tick, TICK_MAX, 1);
blueswir1 authored
271
    ptimer_run(env->tick, 1);
272
273
    env->stick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->stick, TICK_MAX, 1);
blueswir1 authored
274
    ptimer_run(env->stick, 1);
275
276
    env->hstick_cmpr = TICK_INT_DIS | 0;
    ptimer_set_limit(env->hstick, TICK_MAX, 1);
blueswir1 authored
277
    ptimer_run(env->hstick, 1);
278
279
280
281
282
    env->gregs[1] = 0; // Memory start
    env->gregs[2] = ram_size; // Memory size
    env->gregs[3] = 0; // Machine description XXX
    env->pc = s->reset_addr;
    env->npc = env->pc + 4;
283
284
}
blueswir1 authored
285
static void tick_irq(void *opaque)
286
287
288
{
    CPUState *env = opaque;
289
290
291
292
    if (!(env->tick_cmpr & TICK_INT_DIS)) {
        env->softint |= SOFTINT_TIMER;
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
    }
293
294
}
blueswir1 authored
295
static void stick_irq(void *opaque)
296
297
298
{
    CPUState *env = opaque;
299
300
301
302
    if (!(env->stick_cmpr & TICK_INT_DIS)) {
        env->softint |= SOFTINT_STIMER;
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
    }
303
304
}
blueswir1 authored
305
static void hstick_irq(void *opaque)
306
307
308
{
    CPUState *env = opaque;
309
310
311
    if (!(env->hstick_cmpr & TICK_INT_DIS)) {
        cpu_interrupt(env, CPU_INTERRUPT_TIMER);
    }
bellard authored
312
313
}
blueswir1 authored
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
void cpu_tick_set_count(void *opaque, uint64_t count)
{
    ptimer_set_count(opaque, -count);
}

uint64_t cpu_tick_get_count(void *opaque)
{
    return -ptimer_get_count(opaque);
}

void cpu_tick_set_limit(void *opaque, uint64_t limit)
{
    ptimer_set_limit(opaque, -limit, 0);
}
bellard authored
329
330
331
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
bellard authored
332
bellard authored
333
334
335
336
337
338
339
static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };

static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };

static fdctrl_t *floppy_controller;
bellard authored
340
blueswir1 authored
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
                              uint32_t addr, uint32_t size, int type)
{
    DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
    switch (region_num) {
    case 0:
        isa_mmio_init(addr, 0x1000000);
        break;
    case 1:
        isa_mmio_init(addr, 0x800000);
        break;
    }
}

/* EBUS (Eight bit bus) bridge */
static void
pci_ebus_init(PCIBus *bus, int devfn)
{
359
360
    pci_create_simple(bus, devfn, "ebus");
}
blueswir1 authored
361
362
363
364
static void
pci_ebus_init1(PCIDevice *s)
{
365
366
    pci_config_set_vendor_id(s->config, PCI_VENDOR_ID_SUN);
    pci_config_set_device_id(s->config, PCI_DEVICE_ID_SUN_EBUS);
blueswir1 authored
367
368
369
370
371
372
    s->config[0x04] = 0x06; // command = bus master, pci mem
    s->config[0x05] = 0x00;
    s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
    s->config[0x07] = 0x03; // status = medium devsel
    s->config[0x08] = 0x01; // revision
    s->config[0x09] = 0x00; // programming i/f
373
    pci_config_set_class(s->config, PCI_CLASS_BRIDGE_OTHER);
blueswir1 authored
374
    s->config[0x0D] = 0x0a; // latency_timer
Isaku Yamahata authored
375
    s->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
blueswir1 authored
376
377
    pci_register_bar(s, 0, 0x1000000, PCI_ADDRESS_SPACE_MEM,
blueswir1 authored
378
                           ebus_mmio_mapfunc);
379
    pci_register_bar(s, 1, 0x800000,  PCI_ADDRESS_SPACE_MEM,
blueswir1 authored
380
381
382
                           ebus_mmio_mapfunc);
}
383
384
385
386
387
388
389
390
391
392
393
394
395
static PCIDeviceInfo ebus_info = {
    .qdev.name = "ebus",
    .qdev.size = sizeof(PCIDevice),
    .init = pci_ebus_init1,
};

static void pci_ebus_register(void)
{
    pci_qdev_register(&ebus_info);
}

device_init(pci_ebus_register);
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
/* Boot PROM (OpenBIOS) */
static void prom_init(target_phys_addr_t addr, const char *bios_name)
{
    DeviceState *dev;
    SysBusDevice *s;
    char *filename;
    int ret;

    dev = qdev_create(NULL, "openprom");
    qdev_init(dev);
    s = sysbus_from_qdev(dev);

    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) {
        ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL);
        if (ret < 0 || ret > PROM_SIZE_MAX) {
            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
        }
        qemu_free(filename);
    } else {
        ret = -1;
    }
    if (ret < 0 || ret > PROM_SIZE_MAX) {
        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
        exit(1);
    }
}

static void prom_init1(SysBusDevice *dev)
{
    ram_addr_t prom_offset;

    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
    sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
}

static SysBusDeviceInfo prom_info = {
    .init = prom_init1,
    .qdev.name  = "openprom",
    .qdev.size  = sizeof(SysBusDevice),
    .qdev.props = (Property[]) {
        {/* end of property list */}
    }
};

static void prom_register_devices(void)
{
    sysbus_register_withprop(&prom_info);
}

device_init(prom_register_devices);
454
455
456
457

typedef struct RamDevice
{
    SysBusDevice busdev;
458
    uint64_t size;
459
460
461
462
463
464
465
466
467
468
469
470
471
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
} RamDevice;

/* System RAM */
static void ram_init1(SysBusDevice *dev)
{
    ram_addr_t RAM_size, ram_offset;
    RamDevice *d = FROM_SYSBUS(RamDevice, dev);

    RAM_size = d->size;

    ram_offset = qemu_ram_alloc(RAM_size);
    sysbus_init_mmio(dev, RAM_size, ram_offset);
}

static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size)
{
    DeviceState *dev;
    SysBusDevice *s;
    RamDevice *d;

    /* allocate RAM */
    dev = qdev_create(NULL, "memory");
    s = sysbus_from_qdev(dev);

    d = FROM_SYSBUS(RamDevice, s);
    d->size = RAM_size;
    qdev_init(dev);

    sysbus_mmio_map(s, 0, addr);
}

static SysBusDeviceInfo ram_info = {
    .init = ram_init1,
    .qdev.name  = "memory",
    .qdev.size  = sizeof(RamDevice),
    .qdev.props = (Property[]) {
        {
            .name = "size",
497
            .info = &qdev_prop_uint64,
498
499
500
501
502
503
504
505
506
507
508
509
510
            .offset = offsetof(RamDevice, size),
        },
        {/* end of property list */}
    }
};

static void ram_register_devices(void)
{
    sysbus_register_withprop(&ram_info);
}

device_init(ram_register_devices);
511
static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
bellard authored
512
{
bellard authored
513
    CPUState *env;
514
    QEMUBH *bh;
515
    ResetData *reset_info;
bellard authored
516
517
518
    if (!cpu_model)
        cpu_model = hwdef->default_cpu_model;
519
520
    env = cpu_init(cpu_model);
    if (!env) {
blueswir1 authored
521
522
523
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
        exit(1);
    }
524
525
526
527
528
529
530
531
532
533
534
    bh = qemu_bh_new(tick_irq, env);
    env->tick = ptimer_init(bh);
    ptimer_set_period(env->tick, 1ULL);

    bh = qemu_bh_new(stick_irq, env);
    env->stick = ptimer_init(bh);
    ptimer_set_period(env->stick, 1ULL);

    bh = qemu_bh_new(hstick_irq, env);
    env->hstick = ptimer_init(bh);
    ptimer_set_period(env->hstick, 1ULL);
535
536
537
538

    reset_info = qemu_mallocz(sizeof(ResetData));
    reset_info->env = env;
    reset_info->reset_addr = hwdef->prom_addr + 0x40ULL;
539
    qemu_register_reset(main_cpu_reset, reset_info);
540
541
542
543
    main_cpu_reset(reset_info);
    // Override warm reset address with cold start address
    env->pc = hwdef->prom_addr + 0x20ULL;
    env->npc = env->pc + 4;
bellard authored
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
    return env;
}

static void sun4uv_init(ram_addr_t RAM_size,
                        const char *boot_devices,
                        const char *kernel_filename, const char *kernel_cmdline,
                        const char *initrd_filename, const char *cpu_model,
                        const struct hwdef *hwdef)
{
    CPUState *env;
    m48t59_t *nvram;
    unsigned int i;
    long initrd_size, kernel_size;
    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
    qemu_irq *irq;
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BlockDriverState *fd[MAX_FD];
    void *fw_cfg;
Gerd Hoffmann authored
563
    DriveInfo *dinfo;
564
565
566
567

    /* init CPUs */
    env = cpu_devinit(cpu_model, hwdef);
568
569
    /* set up devices */
    ram_init(0, RAM_size);
bellard authored
570
571
    prom_init(hwdef->prom_addr, bios_name);
bellard authored
572
573
574
575

    irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
blueswir1 authored
576
                           &pci_bus3);
bellard authored
577
    isa_mem_base = VGA_BASE;
Paul Brook authored
578
    pci_vga_init(pci_bus, 0, 0);
bellard authored
579
blueswir1 authored
580
581
582
    // XXX Should be pci_bus3
    pci_ebus_init(pci_bus, -1);
583
584
585
586
587
588
589
    i = 0;
    if (hwdef->console_serial_base) {
        serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
                       serial_hds[i], 1);
        i++;
    }
    for(; i < MAX_SERIAL_PORTS; i++) {
bellard authored
590
        if (serial_hds[i]) {
591
592
            serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200,
                        serial_hds[i]);
bellard authored
593
594
595
596
597
        }
    }

    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
        if (parallel_hds[i]) {
blueswir1 authored
598
599
            parallel_init(parallel_io[i], NULL/*parallel_irq[i]*/,
                          parallel_hds[i]);
bellard authored
600
601
602
        }
    }
603
    for(i = 0; i < nb_nics; i++)
604
        pci_nic_init(&nd_table[i], "ne2k_pci", NULL);
bellard authored
605
606
607
608
609
610
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
Gerd Hoffmann authored
611
612
613
        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS,
                          i % MAX_IDE_DEVS);
        hd[i] = dinfo ? dinfo->bdrv : NULL;
614
615
    }
blueswir1 authored
616
617
    pci_cmd646_ide_init(pci_bus, hd, 1);
pbrook authored
618
619
    /* FIXME: wire up interrupts.  */
    i8042_init(NULL/*1*/, NULL/*12*/, 0x60);
620
    for(i = 0; i < MAX_FD; i++) {
Gerd Hoffmann authored
621
622
        dinfo = drive_get(IF_FLOPPY, 0, i);
        fd[i] = dinfo ? dinfo->bdrv : NULL;
623
624
    }
    floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd);
pbrook authored
625
    nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
626
627
628
629
630

    initrd_size = 0;
    kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
                                    ram_size, &initrd_size);
blueswir1 authored
631
    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
blueswir1 authored
632
633
634
635
636
637
638
                           KERNEL_LOAD_ADDR, kernel_size,
                           kernel_cmdline,
                           INITRD_LOAD_ADDR, initrd_size,
                           /* XXX: need an option to load a NVRAM image */
                           0,
                           graphic_width, graphic_height, graphic_depth,
                           (uint8_t *)&nd_table[0].macaddr);
bellard authored
639
640
641
    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
642
643
    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);
644
645
646
647
648
649
650
651
652
653
654
655
    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);
    if (kernel_cmdline) {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
        pstrcpy_targphys(CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
    } else {
        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
    }
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
bellard authored
656
657
}
658
659
660
enum {
    sun4u_id = 0,
    sun4v_id = 64,
661
    niagara_id,
662
663
};
664
665
666
667
static const struct hwdef hwdefs[] = {
    /* Sun4u generic PC-like machine */
    {
        .default_cpu_model = "TI UltraSparc II",
668
        .machine_id = sun4u_id,
669
670
        .prom_addr = 0x1fff0000000ULL,
        .console_serial_base = 0,
671
672
673
674
    },
    /* Sun4v generic PC-like machine */
    {
        .default_cpu_model = "Sun UltraSparc T1",
675
        .machine_id = sun4v_id,
676
677
678
679
680
681
682
683
684
        .prom_addr = 0x1fff0000000ULL,
        .console_serial_base = 0,
    },
    /* Sun4v generic Niagara machine */
    {
        .default_cpu_model = "Sun UltraSparc T1",
        .machine_id = niagara_id,
        .prom_addr = 0xfff0000000ULL,
        .console_serial_base = 0xfff0c2c000ULL,
685
686
687
688
    },
};

/* Sun4u hardware initialisation */
Paul Brook authored
689
static void sun4u_init(ram_addr_t RAM_size,
690
                       const char *boot_devices,
691
692
693
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, const char *cpu_model)
{
Paul Brook authored
694
    sun4uv_init(RAM_size, boot_devices, kernel_filename,
695
696
697
698
                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
}

/* Sun4v hardware initialisation */
Paul Brook authored
699
static void sun4v_init(ram_addr_t RAM_size,
700
                       const char *boot_devices,
701
702
703
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, const char *cpu_model)
{
Paul Brook authored
704
    sun4uv_init(RAM_size, boot_devices, kernel_filename,
705
706
707
                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
}
708
/* Niagara hardware initialisation */
Paul Brook authored
709
static void niagara_init(ram_addr_t RAM_size,
710
                         const char *boot_devices,
711
712
713
                         const char *kernel_filename, const char *kernel_cmdline,
                         const char *initrd_filename, const char *cpu_model)
{
Paul Brook authored
714
    sun4uv_init(RAM_size, boot_devices, kernel_filename,
715
716
717
                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
}
718
static QEMUMachine sun4u_machine = {
blueswir1 authored
719
720
721
    .name = "sun4u",
    .desc = "Sun4u platform",
    .init = sun4u_init,
blueswir1 authored
722
    .max_cpus = 1, // XXX for now
723
    .is_default = 1,
bellard authored
724
};
725
726
static QEMUMachine sun4v_machine = {
blueswir1 authored
727
728
729
    .name = "sun4v",
    .desc = "Sun4v platform",
    .init = sun4v_init,
blueswir1 authored
730
    .max_cpus = 1, // XXX for now
731
};
732
733
static QEMUMachine niagara_machine = {
734
735
736
    .name = "Niagara",
    .desc = "Sun4v platform, Niagara",
    .init = niagara_init,
blueswir1 authored
737
    .max_cpus = 1, // XXX for now
738
};
739
740
741
742
743
744
745
746
747

static void sun4u_machine_init(void)
{
    qemu_register_machine(&sun4u_machine);
    qemu_register_machine(&sun4v_machine);
    qemu_register_machine(&niagara_machine);
}

machine_init(sun4u_machine_init);