ia64/xen-unstable

view tools/ioemu/hw/ppc_prep.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children f7b43e5c42b9
line source
1 /*
2 * QEMU PPC PREP hardware System Emulator
3 *
4 * Copyright (c) 2003-2004 Jocelyn Mayer
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"
26 //#define HARD_DEBUG_PPC_IO
27 //#define DEBUG_PPC_IO
29 #define BIOS_FILENAME "ppc_rom.bin"
30 #define KERNEL_LOAD_ADDR 0x01000000
31 #define INITRD_LOAD_ADDR 0x01800000
33 extern int loglevel;
34 extern FILE *logfile;
36 #if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
37 #define DEBUG_PPC_IO
38 #endif
40 #if defined (HARD_DEBUG_PPC_IO)
41 #define PPC_IO_DPRINTF(fmt, args...) \
42 do { \
43 if (loglevel & CPU_LOG_IOPORT) { \
44 fprintf(logfile, "%s: " fmt, __func__ , ##args); \
45 } else { \
46 printf("%s : " fmt, __func__ , ##args); \
47 } \
48 } while (0)
49 #elif defined (DEBUG_PPC_IO)
50 #define PPC_IO_DPRINTF(fmt, args...) \
51 do { \
52 if (loglevel & CPU_LOG_IOPORT) { \
53 fprintf(logfile, "%s: " fmt, __func__ , ##args); \
54 } \
55 } while (0)
56 #else
57 #define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
58 #endif
60 /* Constants for devices init */
61 static const int ide_iobase[2] = { 0x1f0, 0x170 };
62 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
63 static const int ide_irq[2] = { 13, 13 };
65 #define NE2000_NB_MAX 6
67 static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
68 static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
70 //static PITState *pit;
72 /* ISA IO ports bridge */
73 #define PPC_IO_BASE 0x80000000
75 /* Speaker port 0x61 */
76 int speaker_data_on;
77 int dummy_refresh_clock;
79 static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
80 {
81 #if 0
82 speaker_data_on = (val >> 1) & 1;
83 pit_set_gate(pit, 2, val & 1);
84 #endif
85 }
87 static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
88 {
89 #if 0
90 int out;
91 out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
92 dummy_refresh_clock ^= 1;
93 return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
94 (dummy_refresh_clock << 4);
95 #endif
96 return 0;
97 }
99 /* PCI intack register */
100 /* Read-only register (?) */
101 static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
102 {
103 // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
104 }
106 static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
107 {
108 uint32_t retval = 0;
110 if (addr == 0xBFFFFFF0)
111 retval = pic_intack_read(NULL);
112 // printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
114 return retval;
115 }
117 static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
118 {
119 return _PPC_intack_read(addr);
120 }
122 static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
123 {
124 #ifdef TARGET_WORDS_BIGENDIAN
125 return bswap16(_PPC_intack_read(addr));
126 #else
127 return _PPC_intack_read(addr);
128 #endif
129 }
131 static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
132 {
133 #ifdef TARGET_WORDS_BIGENDIAN
134 return bswap32(_PPC_intack_read(addr));
135 #else
136 return _PPC_intack_read(addr);
137 #endif
138 }
140 static CPUWriteMemoryFunc *PPC_intack_write[] = {
141 &_PPC_intack_write,
142 &_PPC_intack_write,
143 &_PPC_intack_write,
144 };
146 static CPUReadMemoryFunc *PPC_intack_read[] = {
147 &PPC_intack_readb,
148 &PPC_intack_readw,
149 &PPC_intack_readl,
150 };
152 /* PowerPC control and status registers */
153 #if 0 // Not used
154 static struct {
155 /* IDs */
156 uint32_t veni_devi;
157 uint32_t revi;
158 /* Control and status */
159 uint32_t gcsr;
160 uint32_t xcfr;
161 uint32_t ct32;
162 uint32_t mcsr;
163 /* General purpose registers */
164 uint32_t gprg[6];
165 /* Exceptions */
166 uint32_t feen;
167 uint32_t fest;
168 uint32_t fema;
169 uint32_t fecl;
170 uint32_t eeen;
171 uint32_t eest;
172 uint32_t eecl;
173 uint32_t eeint;
174 uint32_t eemck0;
175 uint32_t eemck1;
176 /* Error diagnostic */
177 } XCSR;
179 static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
180 {
181 printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
182 }
184 static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
185 {
186 #ifdef TARGET_WORDS_BIGENDIAN
187 value = bswap16(value);
188 #endif
189 printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
190 }
192 static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
193 {
194 #ifdef TARGET_WORDS_BIGENDIAN
195 value = bswap32(value);
196 #endif
197 printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
198 }
200 static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
201 {
202 uint32_t retval = 0;
204 printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
206 return retval;
207 }
209 static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
210 {
211 uint32_t retval = 0;
213 printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
214 #ifdef TARGET_WORDS_BIGENDIAN
215 retval = bswap16(retval);
216 #endif
218 return retval;
219 }
221 static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
222 {
223 uint32_t retval = 0;
225 printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
226 #ifdef TARGET_WORDS_BIGENDIAN
227 retval = bswap32(retval);
228 #endif
230 return retval;
231 }
233 static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
234 &PPC_XCSR_writeb,
235 &PPC_XCSR_writew,
236 &PPC_XCSR_writel,
237 };
239 static CPUReadMemoryFunc *PPC_XCSR_read[] = {
240 &PPC_XCSR_readb,
241 &PPC_XCSR_readw,
242 &PPC_XCSR_readl,
243 };
244 #endif
246 /* Fake super-io ports for PREP platform (Intel 82378ZB) */
247 typedef struct sysctrl_t {
248 m48t59_t *nvram;
249 uint8_t state;
250 uint8_t syscontrol;
251 uint8_t fake_io[2];
252 } sysctrl_t;
254 enum {
255 STATE_HARDFILE = 0x01,
256 };
258 static sysctrl_t *sysctrl;
260 static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
261 {
262 sysctrl_t *sysctrl = opaque;
264 PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
265 sysctrl->fake_io[addr - 0x0398] = val;
266 }
268 static uint32_t PREP_io_read (void *opaque, uint32_t addr)
269 {
270 sysctrl_t *sysctrl = opaque;
272 PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
273 sysctrl->fake_io[addr - 0x0398]);
274 return sysctrl->fake_io[addr - 0x0398];
275 }
277 static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
278 {
279 sysctrl_t *sysctrl = opaque;
281 PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
282 switch (addr) {
283 case 0x0092:
284 /* Special port 92 */
285 /* Check soft reset asked */
286 if (val & 0x01) {
287 // cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET);
288 }
289 /* Check LE mode */
290 if (val & 0x02) {
291 printf("Little Endian mode isn't supported (yet ?)\n");
292 abort();
293 }
294 break;
295 case 0x0800:
296 /* Motorola CPU configuration register : read-only */
297 break;
298 case 0x0802:
299 /* Motorola base module feature register : read-only */
300 break;
301 case 0x0803:
302 /* Motorola base module status register : read-only */
303 break;
304 case 0x0808:
305 /* Hardfile light register */
306 if (val & 1)
307 sysctrl->state |= STATE_HARDFILE;
308 else
309 sysctrl->state &= ~STATE_HARDFILE;
310 break;
311 case 0x0810:
312 /* Password protect 1 register */
313 if (sysctrl->nvram != NULL)
314 m48t59_toggle_lock(sysctrl->nvram, 1);
315 break;
316 case 0x0812:
317 /* Password protect 2 register */
318 if (sysctrl->nvram != NULL)
319 m48t59_toggle_lock(sysctrl->nvram, 2);
320 break;
321 case 0x0814:
322 /* L2 invalidate register */
323 // tlb_flush(cpu_single_env, 1);
324 break;
325 case 0x081C:
326 /* system control register */
327 sysctrl->syscontrol = val & 0x0F;
328 break;
329 case 0x0850:
330 /* I/O map type register */
331 if (!(val & 0x01)) {
332 printf("No support for non-continuous I/O map mode\n");
333 abort();
334 }
335 break;
336 default:
337 printf("ERROR: unaffected IO port write: %04lx => %02x\n",
338 (long)addr, val);
339 break;
340 }
341 }
343 static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
344 {
345 sysctrl_t *sysctrl = opaque;
346 uint32_t retval = 0xFF;
348 switch (addr) {
349 case 0x0092:
350 /* Special port 92 */
351 retval = 0x00;
352 break;
353 case 0x0800:
354 /* Motorola CPU configuration register */
355 retval = 0xEF; /* MPC750 */
356 break;
357 case 0x0802:
358 /* Motorola Base module feature register */
359 retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
360 break;
361 case 0x0803:
362 /* Motorola base module status register */
363 retval = 0xE0; /* Standard MPC750 */
364 break;
365 case 0x080C:
366 /* Equipment present register:
367 * no L2 cache
368 * no upgrade processor
369 * no cards in PCI slots
370 * SCSI fuse is bad
371 */
372 retval = 0x3C;
373 break;
374 case 0x0810:
375 /* Motorola base module extended feature register */
376 retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
377 break;
378 case 0x0818:
379 /* Keylock */
380 retval = 0x00;
381 break;
382 case 0x081C:
383 /* system control register
384 * 7 - 6 / 1 - 0: L2 cache enable
385 */
386 retval = sysctrl->syscontrol;
387 break;
388 case 0x0823:
389 /* */
390 retval = 0x03; /* no L2 cache */
391 break;
392 case 0x0850:
393 /* I/O map type register */
394 retval = 0x01;
395 break;
396 default:
397 printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
398 break;
399 }
400 PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
402 return retval;
403 }
405 extern CPUPPCState *global_env;
407 #define NVRAM_SIZE 0x2000
409 /* PowerPC PREP hardware initialisation */
410 void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
411 DisplayState *ds, const char **fd_filename, int snapshot,
412 const char *kernel_filename, const char *kernel_cmdline,
413 const char *initrd_filename)
414 {
415 char buf[1024];
416 m48t59_t *nvram;
417 int PPC_io_memory;
418 int ret, linux_boot, i, nb_nics1;
419 unsigned long bios_offset;
420 uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
421 PCIBus *pci_bus;
423 sysctrl = qemu_mallocz(sizeof(sysctrl_t));
424 if (sysctrl == NULL)
425 return;
427 linux_boot = (kernel_filename != NULL);
429 /* allocate RAM */
430 cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
432 /* allocate and load BIOS */
433 bios_offset = ram_size + vga_ram_size;
434 snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
435 ret = load_image(buf, phys_ram_base + bios_offset);
436 if (ret != BIOS_SIZE) {
437 fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
438 exit(1);
439 }
440 cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
441 BIOS_SIZE, bios_offset | IO_MEM_ROM);
442 cpu_single_env->nip = 0xfffffffc;
444 if (linux_boot) {
445 kernel_base = KERNEL_LOAD_ADDR;
446 /* now we can load the kernel */
447 kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
448 if (kernel_size < 0) {
449 fprintf(stderr, "qemu: could not load kernel '%s'\n",
450 kernel_filename);
451 exit(1);
452 }
453 /* load initrd */
454 if (initrd_filename) {
455 initrd_base = INITRD_LOAD_ADDR;
456 initrd_size = load_image(initrd_filename,
457 phys_ram_base + initrd_base);
458 if (initrd_size < 0) {
459 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
460 initrd_filename);
461 exit(1);
462 }
463 } else {
464 initrd_base = 0;
465 initrd_size = 0;
466 }
467 boot_device = 'm';
468 } else {
469 kernel_base = 0;
470 kernel_size = 0;
471 initrd_base = 0;
472 initrd_size = 0;
473 }
475 /* Register CPU as a 74x/75x */
476 cpu_ppc_register(cpu_single_env, 0x00080000);
477 /* Set time-base frequency to 100 Mhz */
478 cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
480 isa_mem_base = 0xc0000000;
481 pci_bus = pci_prep_init();
482 /* Register 64 KB of ISA IO space */
483 PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
484 cpu_register_physical_memory(0x80000000, 0x00010000, PPC_io_memory);
486 /* init basic PC hardware */
487 vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
488 vga_ram_size);
489 rtc_init(0x70, 8);
490 // openpic = openpic_init(0x00000000, 0xF0000000, 1);
491 // pic_init(openpic);
492 pic_init();
493 // pit = pit_init(0x40, 0);
495 serial_init(0x3f8, 4, serial_hds[0]);
496 nb_nics1 = nb_nics;
497 if (nb_nics1 > NE2000_NB_MAX)
498 nb_nics1 = NE2000_NB_MAX;
499 for(i = 0; i < nb_nics1; i++) {
500 isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
501 }
503 for(i = 0; i < 2; i++) {
504 isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
505 bs_table[2 * i], bs_table[2 * i + 1]);
506 }
507 kbd_init();
508 DMA_init(1);
509 // AUD_init();
510 // SB16_init();
512 fdctrl_init(6, 2, 0, 0x3f0, fd_table);
514 /* Register speaker port */
515 register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
516 register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
517 /* Register fake IO ports for PREP */
518 register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
519 register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
520 /* System control ports */
521 register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
522 register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
523 register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
524 register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
525 /* PCI intack location */
526 PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
527 PPC_intack_write, NULL);
528 cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
529 /* PowerPC control and status register group */
530 #if 0
531 PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
532 cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
533 #endif
535 nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE);
536 if (nvram == NULL)
537 return;
538 sysctrl->nvram = nvram;
540 /* Initialise NVRAM */
541 PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
542 kernel_base, kernel_size,
543 kernel_cmdline,
544 initrd_base, initrd_size,
545 /* XXX: need an option to load a NVRAM image */
546 0,
547 graphic_width, graphic_height, graphic_depth);
548 }