]> git.proxmox.com Git - mirror_qemu.git/blame - hw/sun4m.c
Fix keyboard serial and mouse bugs
[mirror_qemu.git] / hw / sun4m.c
CommitLineData
420557e8
FB
1/*
2 * QEMU Sun4m System Emulator
3 *
b81b3b10 4 * Copyright (c) 2003-2005 Fabrice Bellard
420557e8
FB
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"
420557e8 25
36cd9210
BS
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
420557e8 41#define KERNEL_LOAD_ADDR 0x00004000
b6f479d3 42#define CMDLINE_ADDR 0x007ff000
713c45fa 43#define INITRD_LOAD_ADDR 0x00800000
b3783731 44#define PROM_SIZE_MAX (256 * 1024)
e80cfcfc 45#define PROM_ADDR 0xffd00000
0986ac3b 46#define PROM_FILENAME "openbios-sparc32"
b8174937 47
ba3c64fb 48#define MAX_CPUS 16
420557e8 49
36cd9210
BS
50struct 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
e0353fe2 62 uint32_t intbit_to_level[32];
36cd9210
BS
63};
64
420557e8
FB
65/* TSC handling */
66
67uint64_t cpu_get_tsc()
68{
69 return qemu_get_clock(vm_clock);
70}
71
6f7e9aec
FB
72int DMA_get_channel_mode (int nchan)
73{
74 return 0;
75}
76int DMA_read_memory (int nchan, void *buf, int pos, int size)
77{
78 return 0;
79}
80int DMA_write_memory (int nchan, void *buf, int pos, int size)
81{
82 return 0;
83}
84void DMA_hold_DREQ (int nchan) {}
85void DMA_release_DREQ (int nchan) {}
86void DMA_schedule(int nchan) {}
87void DMA_run (void) {}
88void DMA_init (int high_page_enable) {}
89void DMA_register_channel (int nchan,
90 DMA_transfer_handler transfer_handler,
91 void *opaque)
92{
93}
94
819385c5 95static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
6f7e9aec 96{
819385c5
FB
97 m48t59_write(nvram, addr++, (value >> 8) & 0xff);
98 m48t59_write(nvram, addr++, value & 0xff);
6f7e9aec
FB
99}
100
819385c5 101static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
6f7e9aec 102{
819385c5
FB
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);
6f7e9aec
FB
107}
108
819385c5 109static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
6f7e9aec
FB
110 const unsigned char *str, uint32_t max)
111{
112 unsigned int i;
113
114 for (i = 0; i < max && str[i] != '\0'; i++) {
819385c5 115 m48t59_write(nvram, addr + i, str[i]);
6f7e9aec 116 }
819385c5 117 m48t59_write(nvram, addr + max - 1, '\0');
6f7e9aec 118}
420557e8 119
819385c5 120static m48t59_t *nvram;
420557e8 121
6f7e9aec
FB
122extern int nographic;
123
819385c5 124static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
6f7e9aec
FB
125 int boot_device, uint32_t RAM_size,
126 uint32_t kernel_size,
36cd9210
BS
127 int width, int height, int depth,
128 int machine_id)
e80cfcfc
FB
129{
130 unsigned char tmp = 0;
131 int i, j;
132
6f7e9aec
FB
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
ba3c64fb
FB
137 m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
138 m48t59_write(nvram, 0x2E, 0);
819385c5 139 m48t59_write(nvram, 0x2F, nographic & 0xff);
6f7e9aec 140 nvram_set_lword(nvram, 0x30, RAM_size);
819385c5 141 m48t59_write(nvram, 0x34, boot_device & 0xff);
6f7e9aec
FB
142 nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
143 nvram_set_lword(nvram, 0x3C, kernel_size);
b6f479d3 144 if (cmdline) {
b6f479d3 145 strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
6f7e9aec
FB
146 nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
147 nvram_set_lword(nvram, 0x44, strlen(cmdline));
b6f479d3 148 }
6f7e9aec
FB
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);
b6f479d3 153
6f7e9aec 154 // Sun4m specific use
e80cfcfc 155 i = 0x1fd8;
819385c5 156 m48t59_write(nvram, i++, 0x01);
36cd9210 157 m48t59_write(nvram, i++, machine_id);
e80cfcfc 158 j = 0;
819385c5
FB
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]);
e80cfcfc
FB
165
166 /* Calculate checksum */
167 for (i = 0x1fd8; i < 0x1fe7; i++) {
819385c5 168 tmp ^= m48t59_read(nvram, i);
e80cfcfc 169 }
819385c5 170 m48t59_write(nvram, 0x1fe7, tmp);
e80cfcfc
FB
171}
172
173static void *slavio_intctl;
174
175void pic_info()
176{
177 slavio_pic_info(slavio_intctl);
178}
179
180void irq_info()
181{
182 slavio_irq_info(slavio_intctl);
183}
184
3475187d
FB
185static void *slavio_misc;
186
187void qemu_system_powerdown(void)
188{
189 slavio_set_power_fail(slavio_misc, 1);
190}
191
c68ea704
FB
192static void main_cpu_reset(void *opaque)
193{
194 CPUState *env = opaque;
195 cpu_reset(env);
196}
197
36cd9210
BS
198static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
199 DisplayState *ds, const char *cpu_model)
200
420557e8 201{
ba3c64fb 202 CPUState *env, *envs[MAX_CPUS];
713c45fa 203 unsigned int i;
67e999be 204 void *iommu, *dma, *main_esp, *main_lance = NULL;
62724a37 205 const sparc_def_t *def;
d537cf6c 206 qemu_irq *slavio_irq;
420557e8 207
ba3c64fb 208 /* init CPUs */
62724a37
BS
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 }
ba3c64fb
FB
214 for(i = 0; i < smp_cpus; i++) {
215 env = cpu_init();
62724a37 216 cpu_sparc_register(env, def);
ba3c64fb
FB
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 }
420557e8
FB
223 /* allocate RAM */
224 cpu_register_physical_memory(0, ram_size, 0);
420557e8 225
36cd9210
BS
226 iommu = iommu_init(hwdef->iommu_base);
227 slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
e0353fe2 228 hwdef->intctl_base + 0x10000,
d537cf6c
PB
229 &hwdef->intbit_to_level[0],
230 &slavio_irq);
ba3c64fb
FB
231 for(i = 0; i < smp_cpus; i++) {
232 slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
233 }
d537cf6c
PB
234 dma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
235 slavio_irq[hwdef->le_irq], iommu);
ba3c64fb 236
36cd9210
BS
237 tcx_init(ds, hwdef->tcx_base, phys_ram_base + ram_size, ram_size,
238 hwdef->vram_size, graphic_width, graphic_height);
a41b2ff2
PB
239 if (nd_table[0].vlan) {
240 if (nd_table[0].model == NULL
241 || strcmp(nd_table[0].model, "lance") == 0) {
d537cf6c
PB
242 main_lance = lance_init(&nd_table[0], hwdef->le_base, dma,
243 slavio_irq[hwdef->le_irq]);
a41b2ff2
PB
244 } else {
245 fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
246 exit (1);
247 }
248 }
d537cf6c
PB
249 nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
250 hwdef->nvram_size, 8);
ba3c64fb 251 for (i = 0; i < MAX_CPUS; i++) {
36cd9210 252 slavio_timer_init(hwdef->counter_base + i * TARGET_PAGE_SIZE,
52cc07d0 253 hwdef->clock_irq, 0, i, slavio_intctl);
ba3c64fb 254 }
36cd9210 255 slavio_timer_init(hwdef->counter_base + 0x10000, hwdef->clock1_irq, 2,
52cc07d0 256 (unsigned int)-1, slavio_intctl);
d537cf6c 257 slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
b81b3b10
FB
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
d537cf6c
PB
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);
36cd9210 263 main_esp = esp_init(bs_table, hwdef->esp_base, dma);
f1587550
TS
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
d537cf6c
PB
271 slavio_misc = slavio_misc_init(hwdef->slavio_base,
272 slavio_irq[hwdef->me_irq]);
803b3c7b
BS
273 if (hwdef->cs_base != (target_ulong)-1)
274 cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
67e999be 275 sparc32_dma_set_reset_data(dma, main_esp, main_lance);
36cd9210
BS
276}
277
278static 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);
420557e8 290
e80cfcfc 291 prom_offset = ram_size + vram_size;
b3783731
FB
292 cpu_register_physical_memory(PROM_ADDR,
293 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
294 prom_offset | IO_MEM_ROM);
e80cfcfc 295
0986ac3b 296 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
74287114 297 ret = load_elf(buf, 0, NULL, NULL, NULL);
e80cfcfc
FB
298 if (ret < 0) {
299 fprintf(stderr, "qemu: could not load prom '%s'\n",
300 buf);
301 exit(1);
302 }
e80cfcfc 303
6f7e9aec 304 kernel_size = 0;
e80cfcfc 305 if (linux_boot) {
74287114 306 kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
6f7e9aec
FB
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) {
420557e8 312 fprintf(stderr, "qemu: could not load kernel '%s'\n",
e80cfcfc
FB
313 kernel_filename);
314 exit(1);
420557e8 315 }
713c45fa
FB
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 }
420557e8 337 }
36cd9210
BS
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
343static 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,
e0353fe2
BS
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 */
e0353fe2 377 {
803b3c7b 378 .iommu_base = 0xe0000000, // XXX Actually at 0xfe0000000ULL (36 bits)
1c6e9070 379 .tcx_base = 0x20000000, // 0xe20000000ULL,
803b3c7b
BS
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,
e0353fe2
BS
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,
803b3c7b
BS
401 .cs_irq = -1,
402 .machine_id = 0x72,
e0353fe2
BS
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 },
36cd9210
BS
407 },
408};
409
410static 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 */
423static 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);
420557e8 433}
c0e564d5 434
e0353fe2
BS
435/* SPARCstation 10 hardware initialisation */
436static 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
36cd9210
BS
448QEMUMachine ss5_machine = {
449 "SS-5",
450 "Sun4m platform, SPARCstation 5",
451 ss5_init,
c0e564d5 452};
e0353fe2
BS
453
454QEMUMachine ss10_machine = {
455 "SS-10",
456 "Sun4m platform, SPARCstation 10",
457 ss10_init,
458};