Blame view

hw/sun4m.c 19.3 KB
1
2
3
/*
 * QEMU Sun4m System Emulator
 * 
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
24
 * 
 * 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.
 */
#include "vl.h"
25
//#define DEBUG_IRQ
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * Sun4m architecture was used in the following machines:
 *
 * SPARCserver 6xxMP/xx
 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), SPARCclassic X (4/10)
 * 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
 */
42
43
44
45
46
47
48
#ifdef DEBUG_IRQ
#define DPRINTF(fmt, args...)                           \
    do { printf("CPUIRQ: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
49
#define KERNEL_LOAD_ADDR     0x00004000
bellard authored
50
#define CMDLINE_ADDR         0x007ff000
bellard authored
51
#define INITRD_LOAD_ADDR     0x00800000
bellard authored
52
#define PROM_SIZE_MAX        (256 * 1024)
bellard authored
53
#define PROM_ADDR	     0xffd00000
54
#define PROM_FILENAME	     "openbios-sparc32"
55
56
#define MAX_CPUS 16
57
#define MAX_PILS 16
58
59
struct hwdef {
60
61
62
63
64
    target_phys_addr_t iommu_base, slavio_base;
    target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base;
    target_phys_addr_t serial_base, fd_base;
    target_phys_addr_t dma_base, esp_base, le_base;
    target_phys_addr_t tcx_base, cs_base, power_base;
65
66
67
    long vram_size, nvram_size;
    // IRQ numbers are not PIL ones, but master interrupt controller register
    // bit numbers
68
    int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq;
69
70
    int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq;
    int machine_id; // For NVRAM
71
    uint32_t intbit_to_level[32];
72
73
};
74
75
76
77
78
79
80
/* TSC handling */

uint64_t cpu_get_tsc()
{
    return qemu_get_clock(vm_clock);
}
bellard authored
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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_run (void) {}
void DMA_init (int high_page_enable) {}
void DMA_register_channel (int nchan,
                           DMA_transfer_handler transfer_handler,
                           void *opaque)
{
}
104
static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
bellard authored
105
{
106
107
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
    m48t59_write(nvram, addr++, value & 0xff);
bellard authored
108
109
}
110
static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
bellard authored
111
{
112
113
114
115
    m48t59_write(nvram, addr++, value >> 24);
    m48t59_write(nvram, addr++, (value >> 16) & 0xff);
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
    m48t59_write(nvram, addr++, value & 0xff);
bellard authored
116
117
}
118
static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
bellard authored
119
120
121
122
123
                       const unsigned char *str, uint32_t max)
{
    unsigned int i;

    for (i = 0; i < max && str[i] != '\0'; i++) {
124
        m48t59_write(nvram, addr + i, str[i]);
bellard authored
125
    }
126
    m48t59_write(nvram, addr + max - 1, '\0');
bellard authored
127
}
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
                                const unsigned char *str)
{
    uint32_t len;

    len = strlen(str) + 1;
    nvram_set_string(nvram, addr, str, len);

    return addr + len;
}

static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
                                    uint32_t end)
{
    unsigned int i, sum;

    // Length divided by 16
    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
    // Checksum
    sum = m48t59_read(nvram, start);
    for (i = 0; i < 14; i++) {
        sum += m48t59_read(nvram, start + 2 + i);
        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
    }
    m48t59_write(nvram, start + 1, sum & 0xff);
}
bellard authored
157
158
extern int nographic;
159
static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
bellard authored
160
161
		       int boot_device, uint32_t RAM_size,
		       uint32_t kernel_size,
162
163
		       int width, int height, int depth,
                       int machine_id)
bellard authored
164
165
{
    unsigned char tmp = 0;
166
167
    unsigned int i, j;
    uint32_t start, end;
bellard authored
168
bellard authored
169
170
171
172
    // Try to match PPC NVRAM
    nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
    nvram_set_lword(nvram,  0x10, 0x00000001); /* structure v1 */
    // NVRAM_size, arch not applicable
173
174
    m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
    m48t59_write(nvram, 0x2E, 0);
175
    m48t59_write(nvram, 0x2F, nographic & 0xff);
bellard authored
176
    nvram_set_lword(nvram,  0x30, RAM_size);
177
    m48t59_write(nvram, 0x34, boot_device & 0xff);
bellard authored
178
179
    nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
    nvram_set_lword(nvram,  0x3C, kernel_size);
bellard authored
180
181
    if (cmdline) {
	strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
bellard authored
182
183
	nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
        nvram_set_lword(nvram,  0x44, strlen(cmdline));
bellard authored
184
    }
bellard authored
185
186
187
188
    // initrd_image, initrd_size passed differently
    nvram_set_word(nvram,   0x54, width);
    nvram_set_word(nvram,   0x56, height);
    nvram_set_word(nvram,   0x58, depth);
bellard authored
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    // OpenBIOS nvram variables
    // Variable partition
    start = 252;
    m48t59_write(nvram, start, 0x70);
    nvram_set_string(nvram, start + 4, "system", 12);

    end = start + 16;
    for (i = 0; i < nb_prom_envs; i++)
        end = nvram_set_var(nvram, end, prom_envs[i]);

    m48t59_write(nvram, end++ , 0);
    end = start + ((end - start + 15) & ~15);
    nvram_finish_partition(nvram, start, end);

    // free partition
    start = end;
    m48t59_write(nvram, start, 0x7f);
    nvram_set_string(nvram, start + 4, "free", 12);

    end = 0x1fd0;
    nvram_finish_partition(nvram, start, end);
bellard authored
212
    // Sun4m specific use
213
    start = i = 0x1fd8;
214
    m48t59_write(nvram, i++, 0x01);
215
    m48t59_write(nvram, i++, machine_id);
bellard authored
216
    j = 0;
217
218
219
220
221
222
    m48t59_write(nvram, i++, macaddr[j++]);
    m48t59_write(nvram, i++, macaddr[j++]);
    m48t59_write(nvram, i++, macaddr[j++]);
    m48t59_write(nvram, i++, macaddr[j++]);
    m48t59_write(nvram, i++, macaddr[j++]);
    m48t59_write(nvram, i, macaddr[j]);
bellard authored
223
224

    /* Calculate checksum */
225
226
    for (i = start; i < start + 15; i++) {
        tmp ^= m48t59_read(nvram, i);
bellard authored
227
    }
228
    m48t59_write(nvram, start + 15, tmp);
bellard authored
229
230
231
232
233
234
235
236
237
238
239
240
241
242
}

static void *slavio_intctl;

void pic_info()
{
    slavio_pic_info(slavio_intctl);
}

void irq_info()
{
    slavio_irq_info(slavio_intctl);
}
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
void cpu_check_irqs(CPUState *env)
{
    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;
                if (old_interrupt != env->interrupt_index)
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
        env->interrupt_index = 0;
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
265
266
267
268
269
270
271
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;
272
273
        env->pil_in |= 1 << irq;
        cpu_check_irqs(env);
274
275
    } else {
        DPRINTF("Lower CPU IRQ %d\n", irq);
276
277
        env->pil_in &= ~(1 << irq);
        cpu_check_irqs(env);
278
279
280
281
282
283
284
    }
}

static void dummy_cpu_set_irq(void *opaque, int irq, int level)
{
}
bellard authored
285
286
287
288
289
290
291
static void *slavio_misc;

void qemu_system_powerdown(void)
{
    slavio_set_power_fail(slavio_misc, 1);
}
bellard authored
292
293
294
static void main_cpu_reset(void *opaque)
{
    CPUState *env = opaque;
295
296
297
298
299
300
301
302
303

    cpu_reset(env);
    env->halted = 0;
}

static void secondary_cpu_reset(void *opaque)
{
    CPUState *env = opaque;
bellard authored
304
    cpu_reset(env);
305
    env->halted = 1;
bellard authored
306
307
}
308
309
static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size,
                           DisplayState *ds, const char *cpu_model)
310
311
{
312
    CPUState *env, *envs[MAX_CPUS];
bellard authored
313
    unsigned int i;
314
    void *iommu, *espdma, *ledma, *main_esp, *nvram;
blueswir1 authored
315
    const sparc_def_t *def;
316
    qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,
317
        *espdma_irq, *ledma_irq;
318
    qemu_irq *esp_reset, *le_reset;
319
320
    /* init CPUs */
blueswir1 authored
321
322
323
324
325
    sparc_find_by_name(cpu_model, &def);
    if (def == NULL) {
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
        exit(1);
    }
326
327
328
    for(i = 0; i < smp_cpus; i++) {
        env = cpu_init();
blueswir1 authored
329
        cpu_sparc_register(env, def);
330
        envs[i] = env;
331
332
333
334
        if (i == 0) {
            qemu_register_reset(main_cpu_reset, env);
        } else {
            qemu_register_reset(secondary_cpu_reset, env);
335
            env->halted = 1;
336
        }
337
        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
338
        cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
339
    }
340
341
342
343

    for (i = smp_cpus; i < MAX_CPUS; i++)
        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
344
    /* allocate RAM */
345
    cpu_register_physical_memory(0, RAM_size, 0);
346
347
348
    iommu = iommu_init(hwdef->iommu_base);
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
349
                                       hwdef->intctl_base + 0x10000ULL,
pbrook authored
350
                                       &hwdef->intbit_to_level[0],
351
                                       &slavio_irq, &slavio_cpu_irq,
352
                                       cpu_irqs,
353
                                       hwdef->clock_irq);
354
355
    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
356
357
                              iommu, &espdma_irq, &esp_reset);
358
    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
359
360
                             slavio_irq[hwdef->le_irq], iommu, &ledma_irq,
                             &le_reset);
361
blueswir1 authored
362
363
364
365
    if (graphic_depth != 8 && graphic_depth != 24) {
        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
        exit (1);
    }
366
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
blueswir1 authored
367
             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
368
369
370

    if (nd_table[0].model == NULL
        || strcmp(nd_table[0].model, "lance") == 0) {
371
        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
372
373
374
    } else if (strcmp(nd_table[0].model, "?") == 0) {
        fprintf(stderr, "qemu: Supported NICs: lance\n");
        exit (1);
375
376
377
    } else {
        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
        exit (1);
378
    }
379
pbrook authored
380
381
    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
                        hwdef->nvram_size, 8);
382
    for (i = 0; i < MAX_CPUS; i++) {
383
384
        slavio_timer_init(hwdef->counter_base +
                          (target_phys_addr_t)(i * TARGET_PAGE_SIZE),
385
                           slavio_cpu_irq[i], 0);
386
    }
387
388
    slavio_timer_init(hwdef->counter_base + 0x10000ULL,
                      slavio_irq[hwdef->clock1_irq], 2);
pbrook authored
389
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
390
391
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
pbrook authored
392
393
394
    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
                       serial_hds[1], serial_hds[0]);
    fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
395
396
397

    main_esp = esp_init(bs_table, hwdef->esp_base, espdma, *espdma_irq,
                        esp_reset);
398
399
400
401
402
403
404

    for (i = 0; i < MAX_DISKS; i++) {
        if (bs_table[i]) {
            esp_scsi_attach(main_esp, bs_table[i], i);
        }
    }
405
    slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->power_base,
pbrook authored
406
                                   slavio_irq[hwdef->me_irq]);
407
    if (hwdef->cs_base != (target_phys_addr_t)-1)
408
        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
409
410

    return nvram;
411
412
}
413
static void sun4m_load_kernel(long vram_size, int RAM_size, int boot_device,
414
415
416
                              const char *kernel_filename,
                              const char *kernel_cmdline,
                              const char *initrd_filename,
417
418
                              int machine_id,
                              void *nvram)
419
420
421
422
423
424
425
{
    int ret, linux_boot;
    char buf[1024];
    unsigned int i;
    long prom_offset, initrd_size, kernel_size;

    linux_boot = (kernel_filename != NULL);
426
427
    prom_offset = RAM_size + vram_size;
bellard authored
428
429
430
    cpu_register_physical_memory(PROM_ADDR, 
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK, 
                                 prom_offset | IO_MEM_ROM);
bellard authored
431
432
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
433
    ret = load_elf(buf, 0, NULL, NULL, NULL);
bellard authored
434
435
436
437
438
439
    if (ret < 0) {
	fprintf(stderr, "qemu: could not load prom '%s'\n", 
		buf);
	exit(1);
    }
bellard authored
440
    kernel_size = 0;
bellard authored
441
    if (linux_boot) {
442
        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
bellard authored
443
444
445
446
447
        if (kernel_size < 0)
	    kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
	if (kernel_size < 0)
	    kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
        if (kernel_size < 0) {
448
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
bellard authored
449
450
                    kernel_filename);
	    exit(1);
451
        }
bellard authored
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472

        /* load initrd */
        initrd_size = 0;
        if (initrd_filename) {
            initrd_size = load_image(initrd_filename, phys_ram_base + 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_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
		    == 0x48647253) { // HdrS
		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
		    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
		    break;
		}
	    }
        }
473
    }
474
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
475
               boot_device, RAM_size, kernel_size, graphic_width,
476
477
478
479
480
481
482
483
484
               graphic_height, graphic_depth, machine_id);
}

static const struct hwdef hwdefs[] = {
    /* SS-5 */
    {
        .iommu_base   = 0x10000000,
        .tcx_base     = 0x50000000,
        .cs_base      = 0x6c000000,
blueswir1 authored
485
        .slavio_base  = 0x70000000,
486
487
488
489
490
491
492
493
494
        .ms_kb_base   = 0x71000000,
        .serial_base  = 0x71100000,
        .nvram_base   = 0x71200000,
        .fd_base      = 0x71400000,
        .counter_base = 0x71d00000,
        .intctl_base  = 0x71e00000,
        .dma_base     = 0x78400000,
        .esp_base     = 0x78800000,
        .le_base      = 0x78c00000,
495
        .power_base   = 0x7a000000,
496
497
498
499
500
501
502
503
504
505
506
507
        .vram_size    = 0x00100000,
        .nvram_size   = 0x2000,
        .esp_irq = 18,
        .le_irq = 16,
        .clock_irq = 7,
        .clock1_irq = 19,
        .ms_kb_irq = 14,
        .ser_irq = 15,
        .fd_irq = 22,
        .me_irq = 30,
        .cs_irq = 5,
        .machine_id = 0x80,
508
509
510
511
512
513
514
        .intbit_to_level = {
            2, 3, 5, 7, 9, 11, 0, 14,	3, 5, 7, 9, 11, 13, 12, 12,
            6, 0, 4, 10, 8, 0, 11, 0,	0, 0, 0, 0, 15, 0, 15, 0,
        },
    },
    /* SS-10 */
    {
515
516
        .iommu_base   = 0xfe0000000ULL,
        .tcx_base     = 0xe20000000ULL,
517
        .cs_base      = -1,
518
519
520
521
522
523
524
525
526
527
528
        .slavio_base  = 0xff0000000ULL,
        .ms_kb_base   = 0xff1000000ULL,
        .serial_base  = 0xff1100000ULL,
        .nvram_base   = 0xff1200000ULL,
        .fd_base      = 0xff1700000ULL,
        .counter_base = 0xff1300000ULL,
        .intctl_base  = 0xff1400000ULL,
        .dma_base     = 0xef0400000ULL,
        .esp_base     = 0xef0800000ULL,
        .le_base      = 0xef0c00000ULL,
        .power_base   = 0xefa000000ULL,
529
530
531
532
533
534
535
536
537
538
        .vram_size    = 0x00100000,
        .nvram_size   = 0x2000,
        .esp_irq = 18,
        .le_irq = 16,
        .clock_irq = 7,
        .clock1_irq = 19,
        .ms_kb_irq = 14,
        .ser_irq = 15,
        .fd_irq = 22,
        .me_irq = 30,
539
540
        .cs_irq = -1,
        .machine_id = 0x72,
541
542
543
544
        .intbit_to_level = {
            2, 3, 5, 7, 9, 11, 0, 14,	3, 5, 7, 9, 11, 13, 12, 12,
            6, 0, 4, 10, 8, 0, 11, 0,	0, 0, 0, 0, 15, 0, 15, 0,
        },
545
546
547
    },
};
548
static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
549
550
                              const char *kernel_filename, const char *kernel_cmdline,
                              const char *initrd_filename, const char *cpu_model,
551
                              unsigned int machine, int max_ram)
552
{
553
554
555
    void *nvram;

    if ((unsigned int)RAM_size > (unsigned int)max_ram) {
556
        fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
557
                (unsigned int)RAM_size / (1024 * 1024),
558
                (unsigned int)max_ram / (1024 * 1024));
559
560
        exit(1);
    }
561
    nvram = sun4m_hw_init(&hwdefs[machine], RAM_size, ds, cpu_model);
562
563
    sun4m_load_kernel(hwdefs[machine].vram_size, RAM_size, boot_device,
564
                      kernel_filename, kernel_cmdline, initrd_filename,
565
                      hwdefs[machine].machine_id, nvram);
566
567
568
}

/* SPARCstation 5 hardware initialisation */
569
static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
570
571
572
573
574
575
                       DisplayState *ds, const char **fd_filename, int snapshot,
                       const char *kernel_filename, const char *kernel_cmdline,
                       const char *initrd_filename, const char *cpu_model)
{
    if (cpu_model == NULL)
        cpu_model = "Fujitsu MB86904";
576
    sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
577
                      kernel_cmdline, initrd_filename, cpu_model,
578
                      0, 0x10000000);
579
}
bellard authored
580
581
/* SPARCstation 10 hardware initialisation */
582
static void ss10_init(int RAM_size, int vga_ram_size, int boot_device,
583
584
585
586
587
588
                            DisplayState *ds, const char **fd_filename, int snapshot,
                            const char *kernel_filename, const char *kernel_cmdline,
                            const char *initrd_filename, const char *cpu_model)
{
    if (cpu_model == NULL)
        cpu_model = "TI SuperSparc II";
589
    sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
590
                      kernel_cmdline, initrd_filename, cpu_model,
591
                      1, PROM_ADDR); // XXX prom overlap, actually first 4GB ok
592
593
}
594
595
596
597
QEMUMachine ss5_machine = {
    "SS-5",
    "Sun4m platform, SPARCstation 5",
    ss5_init,
bellard authored
598
};
599
600
601
602
603
604

QEMUMachine ss10_machine = {
    "SS-10",
    "Sun4m platform, SPARCstation 10",
    ss10_init,
};