Statistics
| Branch: | Revision:

root / hw / sun4m.c @ beb811bd

History | View | Annotate | Download (15.2 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
void pic_set_irq(int irq, int level)
186
{
187
    pic_set_irq_new(slavio_intctl, irq, level);
188
}
189

    
190
static void *slavio_misc;
191

    
192
void qemu_system_powerdown(void)
193
{
194
    slavio_set_power_fail(slavio_misc, 1);
195
}
196

    
197
static void main_cpu_reset(void *opaque)
198
{
199
    CPUState *env = opaque;
200
    cpu_reset(env);
201
}
202

    
203
static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
204
                          DisplayState *ds, const char *cpu_model)
205

    
206
{
207
    CPUState *env, *envs[MAX_CPUS];
208
    unsigned int i;
209
    void *iommu, *dma, *main_esp, *main_lance = NULL;
210
    const sparc_def_t *def;
211

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

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

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

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

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

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

    
291
    linux_boot = (kernel_filename != NULL);
292

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

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

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

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

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

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

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

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

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

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

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