Commit da9b266bb8491fd41badfff8ae1772007602dcca
1 parent
dccfafc4
PREP machines have two IO mappings.
This patch adds support for non-contiguous IO map, which is used by OS/2. It also adds the missing legacy IO ports for the PREP PCI bridge and changes CPU PVR from 74x/75x to 604 to make OS/2 happy. (Jocelyn Mayer) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1381 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
125 additions
and
10 deletions
hw/pci.c
... | ... | @@ -694,6 +694,16 @@ PCIBus *pci_prep_init(void) |
694 | 694 | s = pci_register_bus(); |
695 | 695 | s->set_irq = prep_set_irq; |
696 | 696 | |
697 | + register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); | |
698 | + register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s); | |
699 | + | |
700 | + register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); | |
701 | + register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); | |
702 | + register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); | |
703 | + register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); | |
704 | + register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); | |
705 | + register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); | |
706 | + | |
697 | 707 | PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, |
698 | 708 | PPC_PCIIO_write, s); |
699 | 709 | cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); | ... | ... |
hw/ppc_prep.c
... | ... | @@ -249,6 +249,7 @@ typedef struct sysctrl_t { |
249 | 249 | uint8_t state; |
250 | 250 | uint8_t syscontrol; |
251 | 251 | uint8_t fake_io[2]; |
252 | + int contiguous_map; | |
252 | 253 | } sysctrl_t; |
253 | 254 | |
254 | 255 | enum { |
... | ... | @@ -328,10 +329,7 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val) |
328 | 329 | break; |
329 | 330 | case 0x0850: |
330 | 331 | /* I/O map type register */ |
331 | - if (!(val & 0x01)) { | |
332 | - printf("No support for non-continuous I/O map mode\n"); | |
333 | - abort(); | |
334 | - } | |
332 | + sysctrl->contiguous_map = val & 0x01; | |
335 | 333 | break; |
336 | 334 | default: |
337 | 335 | printf("ERROR: unaffected IO port write: %04lx => %02x\n", |
... | ... | @@ -375,6 +373,9 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr) |
375 | 373 | /* Motorola base module extended feature register */ |
376 | 374 | retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */ |
377 | 375 | break; |
376 | + case 0x0814: | |
377 | + /* L2 invalidate: don't care */ | |
378 | + break; | |
378 | 379 | case 0x0818: |
379 | 380 | /* Keylock */ |
380 | 381 | retval = 0x00; |
... | ... | @@ -391,7 +392,7 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr) |
391 | 392 | break; |
392 | 393 | case 0x0850: |
393 | 394 | /* I/O map type register */ |
394 | - retval = 0x01; | |
395 | + retval = sysctrl->contiguous_map; | |
395 | 396 | break; |
396 | 397 | default: |
397 | 398 | printf("ERROR: unaffected IO port: %04lx read\n", (long)addr); |
... | ... | @@ -402,6 +403,108 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr) |
402 | 403 | return retval; |
403 | 404 | } |
404 | 405 | |
406 | +static inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl, | |
407 | + target_phys_addr_t addr) | |
408 | +{ | |
409 | + if (sysctrl->contiguous_map == 0) { | |
410 | + /* 64 KB contiguous space for IOs */ | |
411 | + addr &= 0xFFFF; | |
412 | + } else { | |
413 | + /* 8 MB non-contiguous space for IOs */ | |
414 | + addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7); | |
415 | + } | |
416 | + | |
417 | + return addr; | |
418 | +} | |
419 | + | |
420 | +static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr, | |
421 | + uint32_t value) | |
422 | +{ | |
423 | + sysctrl_t *sysctrl = opaque; | |
424 | + | |
425 | + addr = prep_IO_address(sysctrl, addr); | |
426 | + cpu_outb(NULL, addr, value); | |
427 | +} | |
428 | + | |
429 | +static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr) | |
430 | +{ | |
431 | + sysctrl_t *sysctrl = opaque; | |
432 | + uint32_t ret; | |
433 | + | |
434 | + addr = prep_IO_address(sysctrl, addr); | |
435 | + ret = cpu_inb(NULL, addr); | |
436 | + | |
437 | + return ret; | |
438 | +} | |
439 | + | |
440 | +static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr, | |
441 | + uint32_t value) | |
442 | +{ | |
443 | + sysctrl_t *sysctrl = opaque; | |
444 | + | |
445 | + addr = prep_IO_address(sysctrl, addr); | |
446 | +#ifdef TARGET_WORDS_BIGENDIAN | |
447 | + value = bswap16(value); | |
448 | +#endif | |
449 | + PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value); | |
450 | + cpu_outw(NULL, addr, value); | |
451 | +} | |
452 | + | |
453 | +static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr) | |
454 | +{ | |
455 | + sysctrl_t *sysctrl = opaque; | |
456 | + uint32_t ret; | |
457 | + | |
458 | + addr = prep_IO_address(sysctrl, addr); | |
459 | + ret = cpu_inw(NULL, addr); | |
460 | +#ifdef TARGET_WORDS_BIGENDIAN | |
461 | + ret = bswap16(ret); | |
462 | +#endif | |
463 | + PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret); | |
464 | + | |
465 | + return ret; | |
466 | +} | |
467 | + | |
468 | +static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr, | |
469 | + uint32_t value) | |
470 | +{ | |
471 | + sysctrl_t *sysctrl = opaque; | |
472 | + | |
473 | + addr = prep_IO_address(sysctrl, addr); | |
474 | +#ifdef TARGET_WORDS_BIGENDIAN | |
475 | + value = bswap32(value); | |
476 | +#endif | |
477 | + PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value); | |
478 | + cpu_outl(NULL, addr, value); | |
479 | +} | |
480 | + | |
481 | +static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr) | |
482 | +{ | |
483 | + sysctrl_t *sysctrl = opaque; | |
484 | + uint32_t ret; | |
485 | + | |
486 | + addr = prep_IO_address(sysctrl, addr); | |
487 | + ret = cpu_inl(NULL, addr); | |
488 | +#ifdef TARGET_WORDS_BIGENDIAN | |
489 | + ret = bswap32(ret); | |
490 | +#endif | |
491 | + PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret); | |
492 | + | |
493 | + return ret; | |
494 | +} | |
495 | + | |
496 | +CPUWriteMemoryFunc *PPC_prep_io_write[] = { | |
497 | + &PPC_prep_io_writeb, | |
498 | + &PPC_prep_io_writew, | |
499 | + &PPC_prep_io_writel, | |
500 | +}; | |
501 | + | |
502 | +CPUReadMemoryFunc *PPC_prep_io_read[] = { | |
503 | + &PPC_prep_io_readb, | |
504 | + &PPC_prep_io_readw, | |
505 | + &PPC_prep_io_readl, | |
506 | +}; | |
507 | + | |
405 | 508 | extern CPUPPCState *global_env; |
406 | 509 | |
407 | 510 | #define NVRAM_SIZE 0x2000 |
... | ... | @@ -472,16 +575,18 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, |
472 | 575 | initrd_size = 0; |
473 | 576 | } |
474 | 577 | |
475 | - /* Register CPU as a 74x/75x */ | |
476 | - cpu_ppc_register(cpu_single_env, 0x00080000); | |
578 | + /* Register CPU as a 604 */ | |
579 | + cpu_ppc_register(cpu_single_env, 0x00040000); | |
477 | 580 | /* Set time-base frequency to 100 Mhz */ |
478 | 581 | cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL); |
479 | 582 | |
480 | 583 | isa_mem_base = 0xc0000000; |
481 | 584 | 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); | |
585 | + // pci_bus = i440fx_init(); | |
586 | + /* Register 8 MB of ISA IO space (needed for non-contiguous map) */ | |
587 | + PPC_io_memory = cpu_register_io_memory(0, PPC_prep_io_read, | |
588 | + PPC_prep_io_write, sysctrl); | |
589 | + cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory); | |
485 | 590 | |
486 | 591 | /* init basic PC hardware */ |
487 | 592 | vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, | ... | ... |