Statistics
| Branch: | Revision:

root / hw / sun4m.c @ 565d2895

History | View | Annotate | Download (16.9 kB)

1
/*
2
 * QEMU Sun4m System Emulator
3
 * 
4
 * Copyright (c) 2003-2005 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
/*
27
 * Sun4m architecture was used in the following machines:
28
 *
29
 * SPARCserver 6xxMP/xx
30
 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), SPARCclassic X (4/10)
31
 * SPARCstation LX/ZX (4/30)
32
 * SPARCstation Voyager
33
 * SPARCstation 10/xx, SPARCserver 10/xx
34
 * SPARCstation 5, SPARCserver 5
35
 * SPARCstation 20/xx, SPARCserver 20
36
 * SPARCstation 4
37
 *
38
 * See for example: http://www.sunhelp.org/faq/sunref1.html
39
 */
40

    
41
#define KERNEL_LOAD_ADDR     0x00004000
42
#define CMDLINE_ADDR         0x007ff000
43
#define INITRD_LOAD_ADDR     0x00800000
44
#define PROM_SIZE_MAX        (256 * 1024)
45
#define PROM_ADDR             0xffd00000
46
#define PROM_FILENAME             "openbios-sparc32"
47

    
48
#define MAX_CPUS 16
49

    
50
struct hwdef {
51
    target_ulong iommu_base, slavio_base;
52
    target_ulong intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
53
    target_ulong fd_base;
54
    target_ulong dma_base, esp_base, le_base;
55
    target_ulong tcx_base, cs_base;
56
    long vram_size, nvram_size;
57
    // IRQ numbers are not PIL ones, but master interrupt controller register
58
    // bit numbers
59
    int intctl_g_intr, esp_irq, le_irq, cpu_irq, clock_irq, clock1_irq;
60
    int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq;
61
    int machine_id; // For NVRAM
62
    uint32_t intbit_to_level[32];
63
};
64

    
65
/* TSC handling */
66

    
67
uint64_t cpu_get_tsc()
68
{
69
    return qemu_get_clock(vm_clock);
70
}
71

    
72
int DMA_get_channel_mode (int nchan)
73
{
74
    return 0;
75
}
76
int DMA_read_memory (int nchan, void *buf, int pos, int size)
77
{
78
    return 0;
79
}
80
int DMA_write_memory (int nchan, void *buf, int pos, int size)
81
{
82
    return 0;
83
}
84
void DMA_hold_DREQ (int nchan) {}
85
void DMA_release_DREQ (int nchan) {}
86
void DMA_schedule(int nchan) {}
87
void DMA_run (void) {}
88
void DMA_init (int high_page_enable) {}
89
void DMA_register_channel (int nchan,
90
                           DMA_transfer_handler transfer_handler,
91
                           void *opaque)
92
{
93
}
94

    
95
static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
96
{
97
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
98
    m48t59_write(nvram, addr++, value & 0xff);
99
}
100

    
101
static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
102
{
103
    m48t59_write(nvram, addr++, value >> 24);
104
    m48t59_write(nvram, addr++, (value >> 16) & 0xff);
105
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
106
    m48t59_write(nvram, addr++, value & 0xff);
107
}
108

    
109
static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
110
                       const unsigned char *str, uint32_t max)
111
{
112
    unsigned int i;
113

    
114
    for (i = 0; i < max && str[i] != '\0'; i++) {
115
        m48t59_write(nvram, addr + i, str[i]);
116
    }
117
    m48t59_write(nvram, addr + max - 1, '\0');
118
}
119

    
120
static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
121
                                const unsigned char *str)
122
{
123
    uint32_t len;
124

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

    
128
    return addr + len;
129
}
130

    
131
static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
132
                                    uint32_t end)
133
{
134
    unsigned int i, sum;
135

    
136
    // Length divided by 16
137
    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
138
    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
139
    // Checksum
140
    sum = m48t59_read(nvram, start);
141
    for (i = 0; i < 14; i++) {
142
        sum += m48t59_read(nvram, start + 2 + i);
143
        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
144
    }
145
    m48t59_write(nvram, start + 1, sum & 0xff);
146
}
147

    
148
static m48t59_t *nvram;
149

    
150
extern int nographic;
151

    
152
static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
153
                       int boot_device, uint32_t RAM_size,
154
                       uint32_t kernel_size,
155
                       int width, int height, int depth,
156
                       int machine_id)
157
{
158
    unsigned char tmp = 0;
159
    unsigned int i, j;
160
    uint32_t start, end;
161

    
162
    // Try to match PPC NVRAM
163
    nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
164
    nvram_set_lword(nvram,  0x10, 0x00000001); /* structure v1 */
165
    // NVRAM_size, arch not applicable
166
    m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
167
    m48t59_write(nvram, 0x2E, 0);
168
    m48t59_write(nvram, 0x2F, nographic & 0xff);
169
    nvram_set_lword(nvram,  0x30, RAM_size);
170
    m48t59_write(nvram, 0x34, boot_device & 0xff);
171
    nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
172
    nvram_set_lword(nvram,  0x3C, kernel_size);
173
    if (cmdline) {
174
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
175
        nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
176
        nvram_set_lword(nvram,  0x44, strlen(cmdline));
177
    }
178
    // initrd_image, initrd_size passed differently
179
    nvram_set_word(nvram,   0x54, width);
180
    nvram_set_word(nvram,   0x56, height);
181
    nvram_set_word(nvram,   0x58, depth);
182

    
183
    // OpenBIOS nvram variables
184
    // Variable partition
185
    start = 252;
186
    m48t59_write(nvram, start, 0x70);
187
    nvram_set_string(nvram, start + 4, "system", 12);
188

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

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

    
197
    // free partition
198
    start = end;
199
    m48t59_write(nvram, start, 0x7f);
200
    nvram_set_string(nvram, start + 4, "free", 12);
201

    
202
    end = 0x1fd0;
203
    nvram_finish_partition(nvram, start, end);
204

    
205
    // Sun4m specific use
206
    start = i = 0x1fd8;
207
    m48t59_write(nvram, i++, 0x01);
208
    m48t59_write(nvram, i++, machine_id);
209
    j = 0;
210
    m48t59_write(nvram, i++, macaddr[j++]);
211
    m48t59_write(nvram, i++, macaddr[j++]);
212
    m48t59_write(nvram, i++, macaddr[j++]);
213
    m48t59_write(nvram, i++, macaddr[j++]);
214
    m48t59_write(nvram, i++, macaddr[j++]);
215
    m48t59_write(nvram, i, macaddr[j]);
216

    
217
    /* Calculate checksum */
218
    for (i = start; i < start + 15; i++) {
219
        tmp ^= m48t59_read(nvram, i);
220
    }
221
    m48t59_write(nvram, start + 15, tmp);
222
}
223

    
224
static void *slavio_intctl;
225

    
226
void pic_info()
227
{
228
    slavio_pic_info(slavio_intctl);
229
}
230

    
231
void irq_info()
232
{
233
    slavio_irq_info(slavio_intctl);
234
}
235

    
236
static void *slavio_misc;
237

    
238
void qemu_system_powerdown(void)
239
{
240
    slavio_set_power_fail(slavio_misc, 1);
241
}
242

    
243
static void main_cpu_reset(void *opaque)
244
{
245
    CPUState *env = opaque;
246
    cpu_reset(env);
247
}
248

    
249
static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
250
                          DisplayState *ds, const char *cpu_model)
251

    
252
{
253
    CPUState *env, *envs[MAX_CPUS];
254
    unsigned int i;
255
    void *iommu, *dma, *main_esp, *main_lance = NULL;
256
    const sparc_def_t *def;
257
    qemu_irq *slavio_irq;
258

    
259
    /* init CPUs */
260
    sparc_find_by_name(cpu_model, &def);
261
    if (def == NULL) {
262
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
263
        exit(1);
264
    }
265
    for(i = 0; i < smp_cpus; i++) {
266
        env = cpu_init();
267
        cpu_sparc_register(env, def);
268
        envs[i] = env;
269
        if (i != 0)
270
            env->halted = 1;
271
        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
272
        qemu_register_reset(main_cpu_reset, env);
273
    }
274
    /* allocate RAM */
275
    cpu_register_physical_memory(0, ram_size, 0);
276

    
277
    iommu = iommu_init(hwdef->iommu_base);
278
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
279
                                       hwdef->intctl_base + 0x10000,
280
                                       &hwdef->intbit_to_level[0],
281
                                       &slavio_irq);
282
    for(i = 0; i < smp_cpus; i++) {
283
        slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
284
    }
285
    dma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
286
                           slavio_irq[hwdef->le_irq], iommu);
287

    
288
    if (graphic_depth != 8 && graphic_depth != 24) {
289
        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
290
        exit (1);
291
    }
292
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + ram_size, ram_size,
293
             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
294
    if (nd_table[0].vlan) {
295
        if (nd_table[0].model == NULL
296
            || strcmp(nd_table[0].model, "lance") == 0) {
297
            main_lance = lance_init(&nd_table[0], hwdef->le_base, dma,
298
                                    slavio_irq[hwdef->le_irq]);
299
        } else {
300
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
301
            exit (1);
302
        }
303
    }
304
    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
305
                        hwdef->nvram_size, 8);
306
    for (i = 0; i < MAX_CPUS; i++) {
307
        slavio_timer_init(hwdef->counter_base + i * TARGET_PAGE_SIZE,
308
                          hwdef->clock_irq, 0, i, slavio_intctl);
309
    }
310
    slavio_timer_init(hwdef->counter_base + 0x10000, hwdef->clock1_irq, 2,
311
                      (unsigned int)-1, slavio_intctl);
312
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
313
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
314
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
315
    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
316
                       serial_hds[1], serial_hds[0]);
317
    fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
318
    main_esp = esp_init(bs_table, hwdef->esp_base, dma);
319

    
320
    for (i = 0; i < MAX_DISKS; i++) {
321
        if (bs_table[i]) {
322
            esp_scsi_attach(main_esp, bs_table[i], i);
323
        }
324
    }
325

    
326
    slavio_misc = slavio_misc_init(hwdef->slavio_base, 
327
                                   slavio_irq[hwdef->me_irq]);
328
    if (hwdef->cs_base != (target_ulong)-1)
329
        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
330
    sparc32_dma_set_reset_data(dma, main_esp, main_lance);
331
}
332

    
333
static void sun4m_load_kernel(long vram_size, int ram_size, int boot_device,
334
                              const char *kernel_filename,
335
                              const char *kernel_cmdline,
336
                              const char *initrd_filename,
337
                              int machine_id)
338
{
339
    int ret, linux_boot;
340
    char buf[1024];
341
    unsigned int i;
342
    long prom_offset, initrd_size, kernel_size;
343

    
344
    linux_boot = (kernel_filename != NULL);
345

    
346
    prom_offset = ram_size + vram_size;
347
    cpu_register_physical_memory(PROM_ADDR, 
348
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK, 
349
                                 prom_offset | IO_MEM_ROM);
350

    
351
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
352
    ret = load_elf(buf, 0, NULL, NULL, NULL);
353
    if (ret < 0) {
354
        fprintf(stderr, "qemu: could not load prom '%s'\n", 
355
                buf);
356
        exit(1);
357
    }
358

    
359
    kernel_size = 0;
360
    if (linux_boot) {
361
        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
362
        if (kernel_size < 0)
363
            kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
364
        if (kernel_size < 0)
365
            kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
366
        if (kernel_size < 0) {
367
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
368
                    kernel_filename);
369
            exit(1);
370
        }
371

    
372
        /* load initrd */
373
        initrd_size = 0;
374
        if (initrd_filename) {
375
            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
376
            if (initrd_size < 0) {
377
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
378
                        initrd_filename);
379
                exit(1);
380
            }
381
        }
382
        if (initrd_size > 0) {
383
            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
384
                if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
385
                    == 0x48647253) { // HdrS
386
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
387
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
388
                    break;
389
                }
390
            }
391
        }
392
    }
393
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
394
               boot_device, ram_size, kernel_size, graphic_width,
395
               graphic_height, graphic_depth, machine_id);
396
}
397

    
398
static const struct hwdef hwdefs[] = {
399
    /* SS-5 */
400
    {
401
        .iommu_base   = 0x10000000,
402
        .tcx_base     = 0x50000000,
403
        .cs_base      = 0x6c000000,
404
        .slavio_base  = 0x70000000,
405
        .ms_kb_base   = 0x71000000,
406
        .serial_base  = 0x71100000,
407
        .nvram_base   = 0x71200000,
408
        .fd_base      = 0x71400000,
409
        .counter_base = 0x71d00000,
410
        .intctl_base  = 0x71e00000,
411
        .dma_base     = 0x78400000,
412
        .esp_base     = 0x78800000,
413
        .le_base      = 0x78c00000,
414
        .vram_size    = 0x00100000,
415
        .nvram_size   = 0x2000,
416
        .esp_irq = 18,
417
        .le_irq = 16,
418
        .clock_irq = 7,
419
        .clock1_irq = 19,
420
        .ms_kb_irq = 14,
421
        .ser_irq = 15,
422
        .fd_irq = 22,
423
        .me_irq = 30,
424
        .cs_irq = 5,
425
        .machine_id = 0x80,
426
        .intbit_to_level = {
427
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
428
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
429
        },
430
    },
431
    /* SS-10 */
432
    {
433
        .iommu_base   = 0xe0000000, // XXX Actually at 0xfe0000000ULL (36 bits)
434
        .tcx_base     = 0x20000000, // 0xe20000000ULL,
435
        .cs_base      = -1,
436
        .slavio_base  = 0xf0000000, // 0xff0000000ULL,
437
        .ms_kb_base   = 0xf1000000, // 0xff1000000ULL,
438
        .serial_base  = 0xf1100000, // 0xff1100000ULL,
439
        .nvram_base   = 0xf1200000, // 0xff1200000ULL,
440
        .fd_base      = 0xf1700000, // 0xff1700000ULL,
441
        .counter_base = 0xf1300000, // 0xff1300000ULL,
442
        .intctl_base  = 0xf1400000, // 0xff1400000ULL,
443
        .dma_base     = 0xf0400000, // 0xef0400000ULL,
444
        .esp_base     = 0xf0800000, // 0xef0800000ULL,
445
        .le_base      = 0xf0c00000, // 0xef0c00000ULL,
446
        .vram_size    = 0x00100000,
447
        .nvram_size   = 0x2000,
448
        .esp_irq = 18,
449
        .le_irq = 16,
450
        .clock_irq = 7,
451
        .clock1_irq = 19,
452
        .ms_kb_irq = 14,
453
        .ser_irq = 15,
454
        .fd_irq = 22,
455
        .me_irq = 30,
456
        .cs_irq = -1,
457
        .machine_id = 0x72,
458
        .intbit_to_level = {
459
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
460
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
461
        },
462
    },
463
};
464

    
465
static void sun4m_common_init(int ram_size, int boot_device, DisplayState *ds,
466
                              const char *kernel_filename, const char *kernel_cmdline,
467
                              const char *initrd_filename, const char *cpu_model,
468
                              unsigned int machine)
469
{
470
    sun4m_hw_init(&hwdefs[machine], ram_size, ds, cpu_model);
471

    
472
    sun4m_load_kernel(hwdefs[machine].vram_size, ram_size, boot_device,
473
                      kernel_filename, kernel_cmdline, initrd_filename,
474
                      hwdefs[machine].machine_id);
475
}
476

    
477
/* SPARCstation 5 hardware initialisation */
478
static void ss5_init(int ram_size, int vga_ram_size, int boot_device,
479
                       DisplayState *ds, const char **fd_filename, int snapshot,
480
                       const char *kernel_filename, const char *kernel_cmdline,
481
                       const char *initrd_filename, const char *cpu_model)
482
{
483
    if (cpu_model == NULL)
484
        cpu_model = "Fujitsu MB86904";
485
    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
486
                      kernel_cmdline, initrd_filename, cpu_model,
487
                      0);
488
}
489

    
490
/* SPARCstation 10 hardware initialisation */
491
static void ss10_init(int ram_size, int vga_ram_size, int boot_device,
492
                            DisplayState *ds, const char **fd_filename, int snapshot,
493
                            const char *kernel_filename, const char *kernel_cmdline,
494
                            const char *initrd_filename, const char *cpu_model)
495
{
496
    if (cpu_model == NULL)
497
        cpu_model = "TI SuperSparc II";
498
    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
499
                      kernel_cmdline, initrd_filename, cpu_model,
500
                      1);
501
}
502

    
503
QEMUMachine ss5_machine = {
504
    "SS-5",
505
    "Sun4m platform, SPARCstation 5",
506
    ss5_init,
507
};
508

    
509
QEMUMachine ss10_machine = {
510
    "SS-10",
511
    "Sun4m platform, SPARCstation 10",
512
    ss10_init,
513
};