Statistics
| Branch: | Revision:

root / hw / sun4m.c @ 5fafdf24

History | View | Annotate | Download (19.3 kB)

1 420557e8 bellard
/*
2 420557e8 bellard
 * QEMU Sun4m System Emulator
3 5fafdf24 ths
 *
4 b81b3b10 bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 420557e8 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 420557e8 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 420557e8 bellard
 * in the Software without restriction, including without limitation the rights
9 420557e8 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 420557e8 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 420557e8 bellard
 * furnished to do so, subject to the following conditions:
12 420557e8 bellard
 *
13 420557e8 bellard
 * The above copyright notice and this permission notice shall be included in
14 420557e8 bellard
 * all copies or substantial portions of the Software.
15 420557e8 bellard
 *
16 420557e8 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 420557e8 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 420557e8 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 420557e8 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 420557e8 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 420557e8 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 420557e8 bellard
 * THE SOFTWARE.
23 420557e8 bellard
 */
24 420557e8 bellard
#include "vl.h"
25 b3a23197 blueswir1
//#define DEBUG_IRQ
26 420557e8 bellard
27 36cd9210 blueswir1
/*
28 36cd9210 blueswir1
 * Sun4m architecture was used in the following machines:
29 36cd9210 blueswir1
 *
30 36cd9210 blueswir1
 * SPARCserver 6xxMP/xx
31 36cd9210 blueswir1
 * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), SPARCclassic X (4/10)
32 36cd9210 blueswir1
 * SPARCstation LX/ZX (4/30)
33 36cd9210 blueswir1
 * SPARCstation Voyager
34 36cd9210 blueswir1
 * SPARCstation 10/xx, SPARCserver 10/xx
35 36cd9210 blueswir1
 * SPARCstation 5, SPARCserver 5
36 36cd9210 blueswir1
 * SPARCstation 20/xx, SPARCserver 20
37 36cd9210 blueswir1
 * SPARCstation 4
38 36cd9210 blueswir1
 *
39 36cd9210 blueswir1
 * See for example: http://www.sunhelp.org/faq/sunref1.html
40 36cd9210 blueswir1
 */
41 36cd9210 blueswir1
42 b3a23197 blueswir1
#ifdef DEBUG_IRQ
43 b3a23197 blueswir1
#define DPRINTF(fmt, args...)                           \
44 b3a23197 blueswir1
    do { printf("CPUIRQ: " fmt , ##args); } while (0)
45 b3a23197 blueswir1
#else
46 b3a23197 blueswir1
#define DPRINTF(fmt, args...)
47 b3a23197 blueswir1
#endif
48 b3a23197 blueswir1
49 420557e8 bellard
#define KERNEL_LOAD_ADDR     0x00004000
50 b6f479d3 bellard
#define CMDLINE_ADDR         0x007ff000
51 713c45fa bellard
#define INITRD_LOAD_ADDR     0x00800000
52 b3783731 bellard
#define PROM_SIZE_MAX        (256 * 1024)
53 e80cfcfc bellard
#define PROM_ADDR             0xffd00000
54 0986ac3b bellard
#define PROM_FILENAME             "openbios-sparc32"
55 b8174937 bellard
56 ba3c64fb bellard
#define MAX_CPUS 16
57 b3a23197 blueswir1
#define MAX_PILS 16
58 420557e8 bellard
59 36cd9210 blueswir1
struct hwdef {
60 5dcb6b91 blueswir1
    target_phys_addr_t iommu_base, slavio_base;
61 5dcb6b91 blueswir1
    target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base;
62 5dcb6b91 blueswir1
    target_phys_addr_t serial_base, fd_base;
63 5dcb6b91 blueswir1
    target_phys_addr_t dma_base, esp_base, le_base;
64 5dcb6b91 blueswir1
    target_phys_addr_t tcx_base, cs_base, power_base;
65 36cd9210 blueswir1
    long vram_size, nvram_size;
66 36cd9210 blueswir1
    // IRQ numbers are not PIL ones, but master interrupt controller register
67 36cd9210 blueswir1
    // bit numbers
68 d7edfd27 blueswir1
    int intctl_g_intr, esp_irq, le_irq, clock_irq, clock1_irq;
69 36cd9210 blueswir1
    int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq;
70 36cd9210 blueswir1
    int machine_id; // For NVRAM
71 e0353fe2 blueswir1
    uint32_t intbit_to_level[32];
72 36cd9210 blueswir1
};
73 36cd9210 blueswir1
74 420557e8 bellard
/* TSC handling */
75 420557e8 bellard
76 420557e8 bellard
uint64_t cpu_get_tsc()
77 420557e8 bellard
{
78 420557e8 bellard
    return qemu_get_clock(vm_clock);
79 420557e8 bellard
}
80 420557e8 bellard
81 6f7e9aec bellard
int DMA_get_channel_mode (int nchan)
82 6f7e9aec bellard
{
83 6f7e9aec bellard
    return 0;
84 6f7e9aec bellard
}
85 6f7e9aec bellard
int DMA_read_memory (int nchan, void *buf, int pos, int size)
86 6f7e9aec bellard
{
87 6f7e9aec bellard
    return 0;
88 6f7e9aec bellard
}
89 6f7e9aec bellard
int DMA_write_memory (int nchan, void *buf, int pos, int size)
90 6f7e9aec bellard
{
91 6f7e9aec bellard
    return 0;
92 6f7e9aec bellard
}
93 6f7e9aec bellard
void DMA_hold_DREQ (int nchan) {}
94 6f7e9aec bellard
void DMA_release_DREQ (int nchan) {}
95 6f7e9aec bellard
void DMA_schedule(int nchan) {}
96 6f7e9aec bellard
void DMA_run (void) {}
97 6f7e9aec bellard
void DMA_init (int high_page_enable) {}
98 6f7e9aec bellard
void DMA_register_channel (int nchan,
99 6f7e9aec bellard
                           DMA_transfer_handler transfer_handler,
100 6f7e9aec bellard
                           void *opaque)
101 6f7e9aec bellard
{
102 6f7e9aec bellard
}
103 6f7e9aec bellard
104 819385c5 bellard
static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
105 6f7e9aec bellard
{
106 819385c5 bellard
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
107 819385c5 bellard
    m48t59_write(nvram, addr++, value & 0xff);
108 6f7e9aec bellard
}
109 6f7e9aec bellard
110 819385c5 bellard
static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
111 6f7e9aec bellard
{
112 819385c5 bellard
    m48t59_write(nvram, addr++, value >> 24);
113 819385c5 bellard
    m48t59_write(nvram, addr++, (value >> 16) & 0xff);
114 819385c5 bellard
    m48t59_write(nvram, addr++, (value >> 8) & 0xff);
115 819385c5 bellard
    m48t59_write(nvram, addr++, value & 0xff);
116 6f7e9aec bellard
}
117 6f7e9aec bellard
118 819385c5 bellard
static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
119 6f7e9aec bellard
                       const unsigned char *str, uint32_t max)
120 6f7e9aec bellard
{
121 6f7e9aec bellard
    unsigned int i;
122 6f7e9aec bellard
123 6f7e9aec bellard
    for (i = 0; i < max && str[i] != '\0'; i++) {
124 819385c5 bellard
        m48t59_write(nvram, addr + i, str[i]);
125 6f7e9aec bellard
    }
126 819385c5 bellard
    m48t59_write(nvram, addr + max - 1, '\0');
127 6f7e9aec bellard
}
128 420557e8 bellard
129 66508601 blueswir1
static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
130 66508601 blueswir1
                                const unsigned char *str)
131 66508601 blueswir1
{
132 66508601 blueswir1
    uint32_t len;
133 66508601 blueswir1
134 66508601 blueswir1
    len = strlen(str) + 1;
135 66508601 blueswir1
    nvram_set_string(nvram, addr, str, len);
136 66508601 blueswir1
137 66508601 blueswir1
    return addr + len;
138 66508601 blueswir1
}
139 66508601 blueswir1
140 66508601 blueswir1
static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
141 66508601 blueswir1
                                    uint32_t end)
142 66508601 blueswir1
{
143 66508601 blueswir1
    unsigned int i, sum;
144 66508601 blueswir1
145 66508601 blueswir1
    // Length divided by 16
146 66508601 blueswir1
    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
147 66508601 blueswir1
    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
148 66508601 blueswir1
    // Checksum
149 66508601 blueswir1
    sum = m48t59_read(nvram, start);
150 66508601 blueswir1
    for (i = 0; i < 14; i++) {
151 66508601 blueswir1
        sum += m48t59_read(nvram, start + 2 + i);
152 66508601 blueswir1
        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
153 66508601 blueswir1
    }
154 66508601 blueswir1
    m48t59_write(nvram, start + 1, sum & 0xff);
155 66508601 blueswir1
}
156 66508601 blueswir1
157 6f7e9aec bellard
extern int nographic;
158 6f7e9aec bellard
159 819385c5 bellard
static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
160 6f7e9aec bellard
                       int boot_device, uint32_t RAM_size,
161 6f7e9aec bellard
                       uint32_t kernel_size,
162 36cd9210 blueswir1
                       int width, int height, int depth,
163 36cd9210 blueswir1
                       int machine_id)
164 e80cfcfc bellard
{
165 e80cfcfc bellard
    unsigned char tmp = 0;
166 66508601 blueswir1
    unsigned int i, j;
167 66508601 blueswir1
    uint32_t start, end;
168 e80cfcfc bellard
169 6f7e9aec bellard
    // Try to match PPC NVRAM
170 6f7e9aec bellard
    nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
171 6f7e9aec bellard
    nvram_set_lword(nvram,  0x10, 0x00000001); /* structure v1 */
172 6f7e9aec bellard
    // NVRAM_size, arch not applicable
173 ba3c64fb bellard
    m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
174 ba3c64fb bellard
    m48t59_write(nvram, 0x2E, 0);
175 819385c5 bellard
    m48t59_write(nvram, 0x2F, nographic & 0xff);
176 6f7e9aec bellard
    nvram_set_lword(nvram,  0x30, RAM_size);
177 819385c5 bellard
    m48t59_write(nvram, 0x34, boot_device & 0xff);
178 6f7e9aec bellard
    nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
179 6f7e9aec bellard
    nvram_set_lword(nvram,  0x3C, kernel_size);
180 b6f479d3 bellard
    if (cmdline) {
181 b6f479d3 bellard
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
182 6f7e9aec bellard
        nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
183 6f7e9aec bellard
        nvram_set_lword(nvram,  0x44, strlen(cmdline));
184 b6f479d3 bellard
    }
185 6f7e9aec bellard
    // initrd_image, initrd_size passed differently
186 6f7e9aec bellard
    nvram_set_word(nvram,   0x54, width);
187 6f7e9aec bellard
    nvram_set_word(nvram,   0x56, height);
188 6f7e9aec bellard
    nvram_set_word(nvram,   0x58, depth);
189 b6f479d3 bellard
190 66508601 blueswir1
    // OpenBIOS nvram variables
191 66508601 blueswir1
    // Variable partition
192 66508601 blueswir1
    start = 252;
193 66508601 blueswir1
    m48t59_write(nvram, start, 0x70);
194 66508601 blueswir1
    nvram_set_string(nvram, start + 4, "system", 12);
195 66508601 blueswir1
196 66508601 blueswir1
    end = start + 16;
197 66508601 blueswir1
    for (i = 0; i < nb_prom_envs; i++)
198 66508601 blueswir1
        end = nvram_set_var(nvram, end, prom_envs[i]);
199 66508601 blueswir1
200 66508601 blueswir1
    m48t59_write(nvram, end++ , 0);
201 66508601 blueswir1
    end = start + ((end - start + 15) & ~15);
202 66508601 blueswir1
    nvram_finish_partition(nvram, start, end);
203 66508601 blueswir1
204 66508601 blueswir1
    // free partition
205 66508601 blueswir1
    start = end;
206 66508601 blueswir1
    m48t59_write(nvram, start, 0x7f);
207 66508601 blueswir1
    nvram_set_string(nvram, start + 4, "free", 12);
208 66508601 blueswir1
209 66508601 blueswir1
    end = 0x1fd0;
210 66508601 blueswir1
    nvram_finish_partition(nvram, start, end);
211 66508601 blueswir1
212 6f7e9aec bellard
    // Sun4m specific use
213 66508601 blueswir1
    start = i = 0x1fd8;
214 819385c5 bellard
    m48t59_write(nvram, i++, 0x01);
215 36cd9210 blueswir1
    m48t59_write(nvram, i++, machine_id);
216 e80cfcfc bellard
    j = 0;
217 819385c5 bellard
    m48t59_write(nvram, i++, macaddr[j++]);
218 819385c5 bellard
    m48t59_write(nvram, i++, macaddr[j++]);
219 819385c5 bellard
    m48t59_write(nvram, i++, macaddr[j++]);
220 819385c5 bellard
    m48t59_write(nvram, i++, macaddr[j++]);
221 819385c5 bellard
    m48t59_write(nvram, i++, macaddr[j++]);
222 819385c5 bellard
    m48t59_write(nvram, i, macaddr[j]);
223 e80cfcfc bellard
224 e80cfcfc bellard
    /* Calculate checksum */
225 66508601 blueswir1
    for (i = start; i < start + 15; i++) {
226 66508601 blueswir1
        tmp ^= m48t59_read(nvram, i);
227 e80cfcfc bellard
    }
228 66508601 blueswir1
    m48t59_write(nvram, start + 15, tmp);
229 e80cfcfc bellard
}
230 e80cfcfc bellard
231 e80cfcfc bellard
static void *slavio_intctl;
232 e80cfcfc bellard
233 e80cfcfc bellard
void pic_info()
234 e80cfcfc bellard
{
235 e80cfcfc bellard
    slavio_pic_info(slavio_intctl);
236 e80cfcfc bellard
}
237 e80cfcfc bellard
238 e80cfcfc bellard
void irq_info()
239 e80cfcfc bellard
{
240 e80cfcfc bellard
    slavio_irq_info(slavio_intctl);
241 e80cfcfc bellard
}
242 e80cfcfc bellard
243 327ac2e7 blueswir1
void cpu_check_irqs(CPUState *env)
244 327ac2e7 blueswir1
{
245 327ac2e7 blueswir1
    if (env->pil_in && (env->interrupt_index == 0 ||
246 327ac2e7 blueswir1
                        (env->interrupt_index & ~15) == TT_EXTINT)) {
247 327ac2e7 blueswir1
        unsigned int i;
248 327ac2e7 blueswir1
249 327ac2e7 blueswir1
        for (i = 15; i > 0; i--) {
250 327ac2e7 blueswir1
            if (env->pil_in & (1 << i)) {
251 327ac2e7 blueswir1
                int old_interrupt = env->interrupt_index;
252 327ac2e7 blueswir1
253 327ac2e7 blueswir1
                env->interrupt_index = TT_EXTINT | i;
254 327ac2e7 blueswir1
                if (old_interrupt != env->interrupt_index)
255 327ac2e7 blueswir1
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
256 327ac2e7 blueswir1
                break;
257 327ac2e7 blueswir1
            }
258 327ac2e7 blueswir1
        }
259 327ac2e7 blueswir1
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
260 327ac2e7 blueswir1
        env->interrupt_index = 0;
261 327ac2e7 blueswir1
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
262 327ac2e7 blueswir1
    }
263 327ac2e7 blueswir1
}
264 327ac2e7 blueswir1
265 b3a23197 blueswir1
static void cpu_set_irq(void *opaque, int irq, int level)
266 b3a23197 blueswir1
{
267 b3a23197 blueswir1
    CPUState *env = opaque;
268 b3a23197 blueswir1
269 b3a23197 blueswir1
    if (level) {
270 b3a23197 blueswir1
        DPRINTF("Raise CPU IRQ %d\n", irq);
271 b3a23197 blueswir1
        env->halted = 0;
272 327ac2e7 blueswir1
        env->pil_in |= 1 << irq;
273 327ac2e7 blueswir1
        cpu_check_irqs(env);
274 b3a23197 blueswir1
    } else {
275 b3a23197 blueswir1
        DPRINTF("Lower CPU IRQ %d\n", irq);
276 327ac2e7 blueswir1
        env->pil_in &= ~(1 << irq);
277 327ac2e7 blueswir1
        cpu_check_irqs(env);
278 b3a23197 blueswir1
    }
279 b3a23197 blueswir1
}
280 b3a23197 blueswir1
281 b3a23197 blueswir1
static void dummy_cpu_set_irq(void *opaque, int irq, int level)
282 b3a23197 blueswir1
{
283 b3a23197 blueswir1
}
284 b3a23197 blueswir1
285 3475187d bellard
static void *slavio_misc;
286 3475187d bellard
287 3475187d bellard
void qemu_system_powerdown(void)
288 3475187d bellard
{
289 3475187d bellard
    slavio_set_power_fail(slavio_misc, 1);
290 3475187d bellard
}
291 3475187d bellard
292 c68ea704 bellard
static void main_cpu_reset(void *opaque)
293 c68ea704 bellard
{
294 c68ea704 bellard
    CPUState *env = opaque;
295 3d29fbef blueswir1
296 3d29fbef blueswir1
    cpu_reset(env);
297 3d29fbef blueswir1
    env->halted = 0;
298 3d29fbef blueswir1
}
299 3d29fbef blueswir1
300 3d29fbef blueswir1
static void secondary_cpu_reset(void *opaque)
301 3d29fbef blueswir1
{
302 3d29fbef blueswir1
    CPUState *env = opaque;
303 3d29fbef blueswir1
304 c68ea704 bellard
    cpu_reset(env);
305 3d29fbef blueswir1
    env->halted = 1;
306 c68ea704 bellard
}
307 c68ea704 bellard
308 b3ceef24 blueswir1
static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size,
309 b3ceef24 blueswir1
                           DisplayState *ds, const char *cpu_model)
310 36cd9210 blueswir1
311 420557e8 bellard
{
312 ba3c64fb bellard
    CPUState *env, *envs[MAX_CPUS];
313 713c45fa bellard
    unsigned int i;
314 b3ceef24 blueswir1
    void *iommu, *espdma, *ledma, *main_esp, *nvram;
315 62724a37 blueswir1
    const sparc_def_t *def;
316 b3a23197 blueswir1
    qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,
317 d7edfd27 blueswir1
        *espdma_irq, *ledma_irq;
318 2d069bab blueswir1
    qemu_irq *esp_reset, *le_reset;
319 420557e8 bellard
320 ba3c64fb bellard
    /* init CPUs */
321 62724a37 blueswir1
    sparc_find_by_name(cpu_model, &def);
322 62724a37 blueswir1
    if (def == NULL) {
323 62724a37 blueswir1
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
324 62724a37 blueswir1
        exit(1);
325 62724a37 blueswir1
    }
326 b3a23197 blueswir1
327 ba3c64fb bellard
    for(i = 0; i < smp_cpus; i++) {
328 ba3c64fb bellard
        env = cpu_init();
329 62724a37 blueswir1
        cpu_sparc_register(env, def);
330 ba3c64fb bellard
        envs[i] = env;
331 3d29fbef blueswir1
        if (i == 0) {
332 3d29fbef blueswir1
            qemu_register_reset(main_cpu_reset, env);
333 3d29fbef blueswir1
        } else {
334 3d29fbef blueswir1
            qemu_register_reset(secondary_cpu_reset, env);
335 ba3c64fb bellard
            env->halted = 1;
336 3d29fbef blueswir1
        }
337 ba3c64fb bellard
        register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
338 b3a23197 blueswir1
        cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);
339 ba3c64fb bellard
    }
340 b3a23197 blueswir1
341 b3a23197 blueswir1
    for (i = smp_cpus; i < MAX_CPUS; i++)
342 b3a23197 blueswir1
        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
343 b3a23197 blueswir1
344 420557e8 bellard
    /* allocate RAM */
345 b3ceef24 blueswir1
    cpu_register_physical_memory(0, RAM_size, 0);
346 420557e8 bellard
347 36cd9210 blueswir1
    iommu = iommu_init(hwdef->iommu_base);
348 36cd9210 blueswir1
    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
349 5dcb6b91 blueswir1
                                       hwdef->intctl_base + 0x10000ULL,
350 d537cf6c pbrook
                                       &hwdef->intbit_to_level[0],
351 d7edfd27 blueswir1
                                       &slavio_irq, &slavio_cpu_irq,
352 b3a23197 blueswir1
                                       cpu_irqs,
353 d7edfd27 blueswir1
                                       hwdef->clock_irq);
354 b3a23197 blueswir1
355 5aca8c3b blueswir1
    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
356 2d069bab blueswir1
                              iommu, &espdma_irq, &esp_reset);
357 2d069bab blueswir1
358 5aca8c3b blueswir1
    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
359 2d069bab blueswir1
                             slavio_irq[hwdef->le_irq], iommu, &ledma_irq,
360 2d069bab blueswir1
                             &le_reset);
361 ba3c64fb bellard
362 eee0b836 blueswir1
    if (graphic_depth != 8 && graphic_depth != 24) {
363 eee0b836 blueswir1
        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
364 eee0b836 blueswir1
        exit (1);
365 eee0b836 blueswir1
    }
366 b3ceef24 blueswir1
    tcx_init(ds, hwdef->tcx_base, phys_ram_base + RAM_size, RAM_size,
367 eee0b836 blueswir1
             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
368 dbe06e18 blueswir1
369 dbe06e18 blueswir1
    if (nd_table[0].model == NULL
370 dbe06e18 blueswir1
        || strcmp(nd_table[0].model, "lance") == 0) {
371 2d069bab blueswir1
        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
372 c4a7060c blueswir1
    } else if (strcmp(nd_table[0].model, "?") == 0) {
373 c4a7060c blueswir1
        fprintf(stderr, "qemu: Supported NICs: lance\n");
374 c4a7060c blueswir1
        exit (1);
375 dbe06e18 blueswir1
    } else {
376 dbe06e18 blueswir1
        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
377 dbe06e18 blueswir1
        exit (1);
378 a41b2ff2 pbrook
    }
379 dbe06e18 blueswir1
380 d537cf6c pbrook
    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
381 d537cf6c pbrook
                        hwdef->nvram_size, 8);
382 ba3c64fb bellard
    for (i = 0; i < MAX_CPUS; i++) {
383 5dcb6b91 blueswir1
        slavio_timer_init(hwdef->counter_base +
384 5dcb6b91 blueswir1
                          (target_phys_addr_t)(i * TARGET_PAGE_SIZE),
385 d7edfd27 blueswir1
                           slavio_cpu_irq[i], 0);
386 ba3c64fb bellard
    }
387 d7edfd27 blueswir1
    slavio_timer_init(hwdef->counter_base + 0x10000ULL,
388 d7edfd27 blueswir1
                      slavio_irq[hwdef->clock1_irq], 2);
389 d537cf6c pbrook
    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
390 b81b3b10 bellard
    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
391 b81b3b10 bellard
    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
392 d537cf6c pbrook
    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
393 d537cf6c pbrook
                       serial_hds[1], serial_hds[0]);
394 d537cf6c pbrook
    fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
395 2d069bab blueswir1
396 2d069bab blueswir1
    main_esp = esp_init(bs_table, hwdef->esp_base, espdma, *espdma_irq,
397 2d069bab blueswir1
                        esp_reset);
398 f1587550 ths
399 f1587550 ths
    for (i = 0; i < MAX_DISKS; i++) {
400 f1587550 ths
        if (bs_table[i]) {
401 f1587550 ths
            esp_scsi_attach(main_esp, bs_table[i], i);
402 f1587550 ths
        }
403 f1587550 ths
    }
404 f1587550 ths
405 5dcb6b91 blueswir1
    slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->power_base,
406 d537cf6c pbrook
                                   slavio_irq[hwdef->me_irq]);
407 5dcb6b91 blueswir1
    if (hwdef->cs_base != (target_phys_addr_t)-1)
408 803b3c7b blueswir1
        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
409 b3ceef24 blueswir1
410 b3ceef24 blueswir1
    return nvram;
411 36cd9210 blueswir1
}
412 36cd9210 blueswir1
413 b3ceef24 blueswir1
static void sun4m_load_kernel(long vram_size, int RAM_size, int boot_device,
414 36cd9210 blueswir1
                              const char *kernel_filename,
415 36cd9210 blueswir1
                              const char *kernel_cmdline,
416 36cd9210 blueswir1
                              const char *initrd_filename,
417 b3ceef24 blueswir1
                              int machine_id,
418 b3ceef24 blueswir1
                              void *nvram)
419 36cd9210 blueswir1
{
420 36cd9210 blueswir1
    int ret, linux_boot;
421 36cd9210 blueswir1
    char buf[1024];
422 36cd9210 blueswir1
    unsigned int i;
423 36cd9210 blueswir1
    long prom_offset, initrd_size, kernel_size;
424 36cd9210 blueswir1
425 36cd9210 blueswir1
    linux_boot = (kernel_filename != NULL);
426 420557e8 bellard
427 b3ceef24 blueswir1
    prom_offset = RAM_size + vram_size;
428 5fafdf24 ths
    cpu_register_physical_memory(PROM_ADDR,
429 5fafdf24 ths
                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
430 b3783731 bellard
                                 prom_offset | IO_MEM_ROM);
431 e80cfcfc bellard
432 0986ac3b bellard
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
433 74287114 ths
    ret = load_elf(buf, 0, NULL, NULL, NULL);
434 e80cfcfc bellard
    if (ret < 0) {
435 5fafdf24 ths
        fprintf(stderr, "qemu: could not load prom '%s'\n",
436 e80cfcfc bellard
                buf);
437 e80cfcfc bellard
        exit(1);
438 e80cfcfc bellard
    }
439 e80cfcfc bellard
440 6f7e9aec bellard
    kernel_size = 0;
441 e80cfcfc bellard
    if (linux_boot) {
442 74287114 ths
        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
443 6f7e9aec bellard
        if (kernel_size < 0)
444 6f7e9aec bellard
            kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
445 6f7e9aec bellard
        if (kernel_size < 0)
446 6f7e9aec bellard
            kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
447 6f7e9aec bellard
        if (kernel_size < 0) {
448 5fafdf24 ths
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
449 e80cfcfc bellard
                    kernel_filename);
450 e80cfcfc bellard
            exit(1);
451 420557e8 bellard
        }
452 713c45fa bellard
453 713c45fa bellard
        /* load initrd */
454 713c45fa bellard
        initrd_size = 0;
455 713c45fa bellard
        if (initrd_filename) {
456 713c45fa bellard
            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
457 713c45fa bellard
            if (initrd_size < 0) {
458 5fafdf24 ths
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
459 713c45fa bellard
                        initrd_filename);
460 713c45fa bellard
                exit(1);
461 713c45fa bellard
            }
462 713c45fa bellard
        }
463 713c45fa bellard
        if (initrd_size > 0) {
464 713c45fa bellard
            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
465 713c45fa bellard
                if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
466 713c45fa bellard
                    == 0x48647253) { // HdrS
467 713c45fa bellard
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
468 713c45fa bellard
                    stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
469 713c45fa bellard
                    break;
470 713c45fa bellard
                }
471 713c45fa bellard
            }
472 713c45fa bellard
        }
473 420557e8 bellard
    }
474 36cd9210 blueswir1
    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
475 b3ceef24 blueswir1
               boot_device, RAM_size, kernel_size, graphic_width,
476 36cd9210 blueswir1
               graphic_height, graphic_depth, machine_id);
477 36cd9210 blueswir1
}
478 36cd9210 blueswir1
479 36cd9210 blueswir1
static const struct hwdef hwdefs[] = {
480 36cd9210 blueswir1
    /* SS-5 */
481 36cd9210 blueswir1
    {
482 36cd9210 blueswir1
        .iommu_base   = 0x10000000,
483 36cd9210 blueswir1
        .tcx_base     = 0x50000000,
484 36cd9210 blueswir1
        .cs_base      = 0x6c000000,
485 384ccb5d blueswir1
        .slavio_base  = 0x70000000,
486 36cd9210 blueswir1
        .ms_kb_base   = 0x71000000,
487 36cd9210 blueswir1
        .serial_base  = 0x71100000,
488 36cd9210 blueswir1
        .nvram_base   = 0x71200000,
489 36cd9210 blueswir1
        .fd_base      = 0x71400000,
490 36cd9210 blueswir1
        .counter_base = 0x71d00000,
491 36cd9210 blueswir1
        .intctl_base  = 0x71e00000,
492 36cd9210 blueswir1
        .dma_base     = 0x78400000,
493 36cd9210 blueswir1
        .esp_base     = 0x78800000,
494 36cd9210 blueswir1
        .le_base      = 0x78c00000,
495 5dcb6b91 blueswir1
        .power_base   = 0x7a000000,
496 36cd9210 blueswir1
        .vram_size    = 0x00100000,
497 36cd9210 blueswir1
        .nvram_size   = 0x2000,
498 36cd9210 blueswir1
        .esp_irq = 18,
499 36cd9210 blueswir1
        .le_irq = 16,
500 36cd9210 blueswir1
        .clock_irq = 7,
501 36cd9210 blueswir1
        .clock1_irq = 19,
502 36cd9210 blueswir1
        .ms_kb_irq = 14,
503 36cd9210 blueswir1
        .ser_irq = 15,
504 36cd9210 blueswir1
        .fd_irq = 22,
505 36cd9210 blueswir1
        .me_irq = 30,
506 36cd9210 blueswir1
        .cs_irq = 5,
507 36cd9210 blueswir1
        .machine_id = 0x80,
508 e0353fe2 blueswir1
        .intbit_to_level = {
509 e0353fe2 blueswir1
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
510 e0353fe2 blueswir1
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
511 e0353fe2 blueswir1
        },
512 e0353fe2 blueswir1
    },
513 e0353fe2 blueswir1
    /* SS-10 */
514 e0353fe2 blueswir1
    {
515 5dcb6b91 blueswir1
        .iommu_base   = 0xfe0000000ULL,
516 5dcb6b91 blueswir1
        .tcx_base     = 0xe20000000ULL,
517 803b3c7b blueswir1
        .cs_base      = -1,
518 5dcb6b91 blueswir1
        .slavio_base  = 0xff0000000ULL,
519 5dcb6b91 blueswir1
        .ms_kb_base   = 0xff1000000ULL,
520 5dcb6b91 blueswir1
        .serial_base  = 0xff1100000ULL,
521 5dcb6b91 blueswir1
        .nvram_base   = 0xff1200000ULL,
522 5dcb6b91 blueswir1
        .fd_base      = 0xff1700000ULL,
523 5dcb6b91 blueswir1
        .counter_base = 0xff1300000ULL,
524 5dcb6b91 blueswir1
        .intctl_base  = 0xff1400000ULL,
525 5dcb6b91 blueswir1
        .dma_base     = 0xef0400000ULL,
526 5dcb6b91 blueswir1
        .esp_base     = 0xef0800000ULL,
527 5dcb6b91 blueswir1
        .le_base      = 0xef0c00000ULL,
528 5dcb6b91 blueswir1
        .power_base   = 0xefa000000ULL,
529 e0353fe2 blueswir1
        .vram_size    = 0x00100000,
530 e0353fe2 blueswir1
        .nvram_size   = 0x2000,
531 e0353fe2 blueswir1
        .esp_irq = 18,
532 e0353fe2 blueswir1
        .le_irq = 16,
533 e0353fe2 blueswir1
        .clock_irq = 7,
534 e0353fe2 blueswir1
        .clock1_irq = 19,
535 e0353fe2 blueswir1
        .ms_kb_irq = 14,
536 e0353fe2 blueswir1
        .ser_irq = 15,
537 e0353fe2 blueswir1
        .fd_irq = 22,
538 e0353fe2 blueswir1
        .me_irq = 30,
539 803b3c7b blueswir1
        .cs_irq = -1,
540 803b3c7b blueswir1
        .machine_id = 0x72,
541 e0353fe2 blueswir1
        .intbit_to_level = {
542 e0353fe2 blueswir1
            2, 3, 5, 7, 9, 11, 0, 14,        3, 5, 7, 9, 11, 13, 12, 12,
543 e0353fe2 blueswir1
            6, 0, 4, 10, 8, 0, 11, 0,        0, 0, 0, 0, 15, 0, 15, 0,
544 e0353fe2 blueswir1
        },
545 36cd9210 blueswir1
    },
546 36cd9210 blueswir1
};
547 36cd9210 blueswir1
548 b3ceef24 blueswir1
static void sun4m_common_init(int RAM_size, int boot_device, DisplayState *ds,
549 36cd9210 blueswir1
                              const char *kernel_filename, const char *kernel_cmdline,
550 36cd9210 blueswir1
                              const char *initrd_filename, const char *cpu_model,
551 4edebb0e blueswir1
                              unsigned int machine, int max_ram)
552 36cd9210 blueswir1
{
553 b3ceef24 blueswir1
    void *nvram;
554 b3ceef24 blueswir1
555 b3ceef24 blueswir1
    if ((unsigned int)RAM_size > (unsigned int)max_ram) {
556 4edebb0e blueswir1
        fprintf(stderr, "qemu: Too much memory for this machine: %d, maximum %d\n",
557 b3ceef24 blueswir1
                (unsigned int)RAM_size / (1024 * 1024),
558 5dcb6b91 blueswir1
                (unsigned int)max_ram / (1024 * 1024));
559 4edebb0e blueswir1
        exit(1);
560 4edebb0e blueswir1
    }
561 b3ceef24 blueswir1
    nvram = sun4m_hw_init(&hwdefs[machine], RAM_size, ds, cpu_model);
562 36cd9210 blueswir1
563 b3ceef24 blueswir1
    sun4m_load_kernel(hwdefs[machine].vram_size, RAM_size, boot_device,
564 36cd9210 blueswir1
                      kernel_filename, kernel_cmdline, initrd_filename,
565 b3ceef24 blueswir1
                      hwdefs[machine].machine_id, nvram);
566 36cd9210 blueswir1
}
567 36cd9210 blueswir1
568 36cd9210 blueswir1
/* SPARCstation 5 hardware initialisation */
569 b3ceef24 blueswir1
static void ss5_init(int RAM_size, int vga_ram_size, int boot_device,
570 36cd9210 blueswir1
                       DisplayState *ds, const char **fd_filename, int snapshot,
571 36cd9210 blueswir1
                       const char *kernel_filename, const char *kernel_cmdline,
572 36cd9210 blueswir1
                       const char *initrd_filename, const char *cpu_model)
573 36cd9210 blueswir1
{
574 36cd9210 blueswir1
    if (cpu_model == NULL)
575 36cd9210 blueswir1
        cpu_model = "Fujitsu MB86904";
576 b3ceef24 blueswir1
    sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
577 36cd9210 blueswir1
                      kernel_cmdline, initrd_filename, cpu_model,
578 4edebb0e blueswir1
                      0, 0x10000000);
579 420557e8 bellard
}
580 c0e564d5 bellard
581 e0353fe2 blueswir1
/* SPARCstation 10 hardware initialisation */
582 b3ceef24 blueswir1
static void ss10_init(int RAM_size, int vga_ram_size, int boot_device,
583 e0353fe2 blueswir1
                            DisplayState *ds, const char **fd_filename, int snapshot,
584 e0353fe2 blueswir1
                            const char *kernel_filename, const char *kernel_cmdline,
585 e0353fe2 blueswir1
                            const char *initrd_filename, const char *cpu_model)
586 e0353fe2 blueswir1
{
587 e0353fe2 blueswir1
    if (cpu_model == NULL)
588 e0353fe2 blueswir1
        cpu_model = "TI SuperSparc II";
589 b3ceef24 blueswir1
    sun4m_common_init(RAM_size, boot_device, ds, kernel_filename,
590 e0353fe2 blueswir1
                      kernel_cmdline, initrd_filename, cpu_model,
591 5dcb6b91 blueswir1
                      1, PROM_ADDR); // XXX prom overlap, actually first 4GB ok
592 e0353fe2 blueswir1
}
593 e0353fe2 blueswir1
594 36cd9210 blueswir1
QEMUMachine ss5_machine = {
595 36cd9210 blueswir1
    "SS-5",
596 36cd9210 blueswir1
    "Sun4m platform, SPARCstation 5",
597 36cd9210 blueswir1
    ss5_init,
598 c0e564d5 bellard
};
599 e0353fe2 blueswir1
600 e0353fe2 blueswir1
QEMUMachine ss10_machine = {
601 e0353fe2 blueswir1
    "SS-10",
602 e0353fe2 blueswir1
    "Sun4m platform, SPARCstation 10",
603 e0353fe2 blueswir1
    ss10_init,
604 e0353fe2 blueswir1
};