Statistics
| Branch: | Revision:

root / hw / sun4m.c @ 92d88ecb

History | View | Annotate | Download (15.3 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 m48t59_t *nvram;
121

    
122
extern int nographic;
123

    
124
static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
125
                       int boot_device, uint32_t RAM_size,
126
                       uint32_t kernel_size,
127
                       int width, int height, int depth,
128
                       int machine_id)
129
{
130
    unsigned char tmp = 0;
131
    int i, j;
132

    
133
    // Try to match PPC NVRAM
134
    nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
135
    nvram_set_lword(nvram,  0x10, 0x00000001); /* structure v1 */
136
    // NVRAM_size, arch not applicable
137
    m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
138
    m48t59_write(nvram, 0x2E, 0);
139
    m48t59_write(nvram, 0x2F, nographic & 0xff);
140
    nvram_set_lword(nvram,  0x30, RAM_size);
141
    m48t59_write(nvram, 0x34, boot_device & 0xff);
142
    nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
143
    nvram_set_lword(nvram,  0x3C, kernel_size);
144
    if (cmdline) {
145
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
146
        nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
147
        nvram_set_lword(nvram,  0x44, strlen(cmdline));
148
    }
149
    // initrd_image, initrd_size passed differently
150
    nvram_set_word(nvram,   0x54, width);
151
    nvram_set_word(nvram,   0x56, height);
152
    nvram_set_word(nvram,   0x58, depth);
153

    
154
    // Sun4m specific use
155
    i = 0x1fd8;
156
    m48t59_write(nvram, i++, 0x01);
157
    m48t59_write(nvram, i++, machine_id);
158
    j = 0;
159
    m48t59_write(nvram, i++, macaddr[j++]);
160
    m48t59_write(nvram, i++, macaddr[j++]);
161
    m48t59_write(nvram, i++, macaddr[j++]);
162
    m48t59_write(nvram, i++, macaddr[j++]);
163
    m48t59_write(nvram, i++, macaddr[j++]);
164
    m48t59_write(nvram, i, macaddr[j]);
165

    
166
    /* Calculate checksum */
167
    for (i = 0x1fd8; i < 0x1fe7; i++) {
168
        tmp ^= m48t59_read(nvram, i);
169
    }
170
    m48t59_write(nvram, 0x1fe7, tmp);
171
}
172

    
173
static void *slavio_intctl;
174

    
175
void pic_info()
176
{
177
    slavio_pic_info(slavio_intctl);
178
}
179

    
180
void irq_info()
181
{
182
    slavio_irq_info(slavio_intctl);
183
}
184

    
185
static void *slavio_misc;
186

    
187
void qemu_system_powerdown(void)
188
{
189
    slavio_set_power_fail(slavio_misc, 1);
190
}
191

    
192
static void main_cpu_reset(void *opaque)
193
{
194
    CPUState *env = opaque;
195
    cpu_reset(env);
196
}
197

    
198
static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
199
                          DisplayState *ds, const char *cpu_model)
200

    
201
{
202
    CPUState *env, *envs[MAX_CPUS];
203
    unsigned int i;
204
    void *iommu, *dma, *main_esp, *main_lance = NULL;
205
    const sparc_def_t *def;
206
    qemu_irq *slavio_irq;
207

    
208
    /* init CPUs */
209
    sparc_find_by_name(cpu_model, &def);
210
    if (def == NULL) {
211
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
212
        exit(1);
213
    }
214
    for(i = 0; i < smp_cpus; i++) {
215
        env = cpu_init();
216
        cpu_sparc_register(env, def);
217
        envs[i] = env;
218
        if (i != 0)
219
            env->halted = 1;
220
        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
221
        qemu_register_reset(main_cpu_reset, env);
222
    }
223
    /* allocate RAM */
224
    cpu_register_physical_memory(0, ram_size, 0);
225

    
226
    iommu = iommu_init(hwdef->iommu_base);
227
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
228
                                       hwdef->intctl_base + 0x10000,
229
                                       &hwdef->intbit_to_level[0],
230
                                       &slavio_irq);
231
    for(i = 0; i < smp_cpus; i++) {
232
        slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
233
    }
234
    dma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
235
                           slavio_irq[hwdef->le_irq], iommu);
236

    
237
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + ram_size, ram_size,
238
             hwdef->vram_size, graphic_width, graphic_height);
239
    if (nd_table[0].vlan) {
240
        if (nd_table[0].model == NULL
241
            || strcmp(nd_table[0].model, "lance") == 0) {
242
            main_lance = lance_init(&nd_table[0], hwdef->le_base, dma,
243
                                    slavio_irq[hwdef->le_irq]);
244
        } else {
245
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
246
            exit (1);
247
        }
248
    }
249
    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
250
                        hwdef->nvram_size, 8);
251
    for (i = 0; i < MAX_CPUS; i++) {
252
        slavio_timer_init(hwdef->counter_base + i * TARGET_PAGE_SIZE,
253
                          hwdef->clock_irq, 0, i, slavio_intctl);
254
    }
255
    slavio_timer_init(hwdef->counter_base + 0x10000, hwdef->clock1_irq, 2,
256
                      (unsigned int)-1, slavio_intctl);
257
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
258
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
259
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
260
    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
261
                       serial_hds[1], serial_hds[0]);
262
    fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
263
    main_esp = esp_init(bs_table, hwdef->esp_base, dma);
264

    
265
    for (i = 0; i < MAX_DISKS; i++) {
266
        if (bs_table[i]) {
267
            esp_scsi_attach(main_esp, bs_table[i], i);
268
        }
269
    }
270

    
271
    slavio_misc = slavio_misc_init(hwdef->slavio_base, 
272
                                   slavio_irq[hwdef->me_irq]);
273
    if (hwdef->cs_base != (target_ulong)-1)
274
        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
275
    sparc32_dma_set_reset_data(dma, main_esp, main_lance);
276
}
277

    
278
static void sun4m_load_kernel(long vram_size, int ram_size, int boot_device,
279
                              const char *kernel_filename,
280
                              const char *kernel_cmdline,
281
                              const char *initrd_filename,
282
                              int machine_id)
283
{
284
    int ret, linux_boot;
285
    char buf[1024];
286
    unsigned int i;
287
    long prom_offset, initrd_size, kernel_size;
288

    
289
    linux_boot = (kernel_filename != NULL);
290

    
291
    prom_offset = ram_size + vram_size;
292
    cpu_register_physical_memory(PROM_ADDR, 
293
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK, 
294
                                 prom_offset | IO_MEM_ROM);
295

    
296
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
297
    ret = load_elf(buf, 0, NULL, NULL, NULL);
298
    if (ret < 0) {
299
        fprintf(stderr, "qemu: could not load prom '%s'\n", 
300
                buf);
301
        exit(1);
302
    }
303

    
304
    kernel_size = 0;
305
    if (linux_boot) {
306
        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
307
        if (kernel_size < 0)
308
            kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
309
        if (kernel_size < 0)
310
            kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
311
        if (kernel_size < 0) {
312
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
313
                    kernel_filename);
314
            exit(1);
315
        }
316

    
317
        /* load initrd */
318
        initrd_size = 0;
319
        if (initrd_filename) {
320
            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
321
            if (initrd_size < 0) {
322
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
323
                        initrd_filename);
324
                exit(1);
325
            }
326
        }
327
        if (initrd_size > 0) {
328
            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
329
                if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
330
                    == 0x48647253) { // HdrS
331
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
332
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
333
                    break;
334
                }
335
            }
336
        }
337
    }
338
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
339
               boot_device, ram_size, kernel_size, graphic_width,
340
               graphic_height, graphic_depth, machine_id);
341
}
342

    
343
static const struct hwdef hwdefs[] = {
344
    /* SS-5 */
345
    {
346
        .iommu_base   = 0x10000000,
347
        .tcx_base     = 0x50000000,
348
        .cs_base      = 0x6c000000,
349
        .slavio_base  = 0x71000000,
350
        .ms_kb_base   = 0x71000000,
351
        .serial_base  = 0x71100000,
352
        .nvram_base   = 0x71200000,
353
        .fd_base      = 0x71400000,
354
        .counter_base = 0x71d00000,
355
        .intctl_base  = 0x71e00000,
356
        .dma_base     = 0x78400000,
357
        .esp_base     = 0x78800000,
358
        .le_base      = 0x78c00000,
359
        .vram_size    = 0x00100000,
360
        .nvram_size   = 0x2000,
361
        .esp_irq = 18,
362
        .le_irq = 16,
363
        .clock_irq = 7,
364
        .clock1_irq = 19,
365
        .ms_kb_irq = 14,
366
        .ser_irq = 15,
367
        .fd_irq = 22,
368
        .me_irq = 30,
369
        .cs_irq = 5,
370
        .machine_id = 0x80,
371
        .intbit_to_level = {
372
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
373
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
374
        },
375
    },
376
    /* SS-10 */
377
    {
378
        .iommu_base   = 0xe0000000, // XXX Actually at 0xfe0000000ULL (36 bits)
379
        .tcx_base     = 0x20000000, // 0xe20000000ULL,
380
        .cs_base      = -1,
381
        .slavio_base  = 0xf1000000, // 0xff1000000ULL,
382
        .ms_kb_base   = 0xf1000000, // 0xff1000000ULL,
383
        .serial_base  = 0xf1100000, // 0xff1100000ULL,
384
        .nvram_base   = 0xf1200000, // 0xff1200000ULL,
385
        .fd_base      = 0xf1700000, // 0xff1700000ULL,
386
        .counter_base = 0xf1300000, // 0xff1300000ULL,
387
        .intctl_base  = 0xf1400000, // 0xff1400000ULL,
388
        .dma_base     = 0xf0400000, // 0xef0400000ULL,
389
        .esp_base     = 0xf0800000, // 0xef0800000ULL,
390
        .le_base      = 0xf0c00000, // 0xef0c00000ULL,
391
        .vram_size    = 0x00100000,
392
        .nvram_size   = 0x2000,
393
        .esp_irq = 18,
394
        .le_irq = 16,
395
        .clock_irq = 7,
396
        .clock1_irq = 19,
397
        .ms_kb_irq = 14,
398
        .ser_irq = 15,
399
        .fd_irq = 22,
400
        .me_irq = 30,
401
        .cs_irq = -1,
402
        .machine_id = 0x72,
403
        .intbit_to_level = {
404
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
405
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
406
        },
407
    },
408
};
409

    
410
static void sun4m_common_init(int ram_size, int boot_device, DisplayState *ds,
411
                              const char *kernel_filename, const char *kernel_cmdline,
412
                              const char *initrd_filename, const char *cpu_model,
413
                              unsigned int machine)
414
{
415
    sun4m_hw_init(&hwdefs[machine], ram_size, ds, cpu_model);
416

    
417
    sun4m_load_kernel(hwdefs[machine].vram_size, ram_size, boot_device,
418
                      kernel_filename, kernel_cmdline, initrd_filename,
419
                      hwdefs[machine].machine_id);
420
}
421

    
422
/* SPARCstation 5 hardware initialisation */
423
static void ss5_init(int ram_size, int vga_ram_size, int boot_device,
424
                       DisplayState *ds, const char **fd_filename, int snapshot,
425
                       const char *kernel_filename, const char *kernel_cmdline,
426
                       const char *initrd_filename, const char *cpu_model)
427
{
428
    if (cpu_model == NULL)
429
        cpu_model = "Fujitsu MB86904";
430
    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
431
                      kernel_cmdline, initrd_filename, cpu_model,
432
                      0);
433
}
434

    
435
/* SPARCstation 10 hardware initialisation */
436
static void ss10_init(int ram_size, int vga_ram_size, int boot_device,
437
                            DisplayState *ds, const char **fd_filename, int snapshot,
438
                            const char *kernel_filename, const char *kernel_cmdline,
439
                            const char *initrd_filename, const char *cpu_model)
440
{
441
    if (cpu_model == NULL)
442
        cpu_model = "TI SuperSparc II";
443
    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
444
                      kernel_cmdline, initrd_filename, cpu_model,
445
                      1);
446
}
447

    
448
QEMUMachine ss5_machine = {
449
    "SS-5",
450
    "Sun4m platform, SPARCstation 5",
451
    ss5_init,
452
};
453

    
454
QEMUMachine ss10_machine = {
455
    "SS-10",
456
    "Sun4m platform, SPARCstation 10",
457
    ss10_init,
458
};