diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/openpic.c | 15 | ||||
-rw-r--r-- | hw/ppc.c | 54 | ||||
-rw-r--r-- | hw/ppc_chrp.c | 12 | ||||
-rw-r--r-- | hw/ppc_prep.c | 18 |
4 files changed, 75 insertions, 24 deletions
diff --git a/hw/openpic.c b/hw/openpic.c index 3177337..7565b1d 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -164,6 +164,7 @@ typedef struct IRQ_dst_t { struct openpic_t { PCIDevice pci_dev; + SetIRQFunc *set_irq; int mem_index; /* Global registers */ uint32_t frep; /* Feature reporting register */ @@ -264,8 +265,8 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) IRQ_setbit(&dst->raised, n_IRQ); if (priority > dst->raised.priority) { IRQ_get_next(opp, &dst->raised); - DPRINTF("Raise CPU IRQ\n"); - cpu_interrupt(dst->env, CPU_INTERRUPT_HARD); + DPRINTF("Raise CPU IRQ fn %p env %p\n", opp->set_irq, dst->env); + opp->set_irq(dst->env, OPENPIC_EVT_INT, 1); } } @@ -532,7 +533,7 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) /* XXX: Should be able to reset any CPU */ if (val & 1) { DPRINTF("Reset CPU IRQ\n"); - // cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET); + // opp->set_irq(dst->env, OPENPIC_EVT_RESET, 1); } break; #if MAX_IPI > 0 @@ -781,7 +782,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) src = &opp->src[n_IRQ]; if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) { DPRINTF("Raise CPU IRQ\n"); - cpu_interrupt(dst->env, CPU_INTERRUPT_HARD); + opp->set_irq(dst->env, OPENPIC_EVT_INT, 1); } } break; @@ -963,8 +964,8 @@ static void openpic_map(PCIDevice *pci_dev, int region_num, #endif } -openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, - CPUPPCState **envp) +openpic_t *openpic_init (PCIBus *bus, SetIRQFunc *set_irq, + int *pmem_index, int nb_cpus, CPUPPCState **envp) { openpic_t *opp; uint8_t *pci_conf; @@ -994,7 +995,7 @@ openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, } else { opp = qemu_mallocz(sizeof(openpic_t)); } - + opp->set_irq = set_irq; opp->mem_index = cpu_register_io_memory(0, openpic_read, openpic_write, opp); @@ -24,6 +24,57 @@ #include "vl.h" #include "m48t59.h" +extern FILE *logfile; +extern int loglevel; + +/*****************************************************************************/ +/* PowerPC internal fake IRQ controller + * used to manage multiple sources hardware events + */ +/* XXX: should be protected */ +void ppc_set_irq (void *opaque, int n_IRQ, int level) +{ + CPUState *env; + + env = opaque; + if (level) { + env->pending_interrupts |= 1 << n_IRQ; + cpu_interrupt(env, CPU_INTERRUPT_HARD); + } else { + env->pending_interrupts &= ~(1 << n_IRQ); + if (env->pending_interrupts == 0) + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); + } +#if 0 + printf("%s: %p n_IRQ %d level %d => pending %08x req %08x\n", __func__, + env, n_IRQ, level, env->pending_interrupts, env->interrupt_request); +#endif +} + +/* External IRQ callback from OpenPIC IRQ controller */ +void ppc_openpic_irq (void *opaque, int n_IRQ, int level) +{ + switch (n_IRQ) { + case OPENPIC_EVT_INT: + n_IRQ = PPC_INTERRUPT_EXT; + break; + case OPENPIC_EVT_CINT: + /* On PowerPC BookE, critical input use vector 0 */ + n_IRQ = PPC_INTERRUPT_RESET; + break; + case OPENPIC_EVT_MCK: + n_IRQ = PPC_INTERRUPT_MCK; + break; + case OPENPIC_EVT_DEBUG: + n_IRQ = PPC_INTERRUPT_DEBUG; + break; + case OPENPIC_EVT_RESET: + qemu_system_reset_request(); + return; + } + ppc_set_irq(opaque, n_IRQ, level); +} + /*****************************************************************************/ /* PPC time base and decrementer emulation */ //#define DEBUG_TB @@ -35,6 +86,7 @@ struct ppc_tb_t { /* Decrementer management */ uint64_t decr_next; /* Tick for next decr interrupt */ struct QEMUTimer *decr_timer; + void *opaque; }; static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env) @@ -131,7 +183,7 @@ static inline void cpu_ppc_decr_excp (CPUState *env) #ifdef DEBUG_TB printf("raise decrementer exception\n"); #endif - cpu_interrupt(env, CPU_INTERRUPT_TIMER); + ppc_set_irq(env, PPC_INTERRUPT_DECR, 1); } static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr, diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c index b1199e2..e9d6670 100644 --- a/hw/ppc_chrp.c +++ b/hw/ppc_chrp.c @@ -1,7 +1,7 @@ /* * QEMU PPC CHRP/PMAC hardware System Emulator * - * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2004-2007 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -449,21 +449,21 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, } macio_init(pci_bus, 0x0017); - + nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE, 59); - + arch_name = "HEATHROW"; } else { isa_mem_base = 0x80000000; - + /* Register 8 MB of ISA IO space */ isa_mmio_init(0xf2000000, 0x00800000); - + /* UniN init */ unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL); cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory); - pic = openpic_init(NULL, &openpic_mem_index, 1, &env); + pic = openpic_init(NULL, &ppc_openpic_irq, &openpic_mem_index, 1, &env); set_irq = openpic_set_irq; pci_bus = pci_pmac_init(pic); /* init basic PC hardware */ diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index 32a3e52..d504b1c 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -1,7 +1,7 @@ /* * QEMU PPC PREP hardware System Emulator * - * Copyright (c) 2003-2004 Jocelyn Mayer + * Copyright (c) 2003-2007 Jocelyn Mayer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -84,29 +84,27 @@ static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) #endif } -static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) +static uint32_t speaker_ioport_read (void *opaque, uint32_t addr) { #if 0 int out; out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); dummy_refresh_clock ^= 1; return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | - (dummy_refresh_clock << 4); + (dummy_refresh_clock << 4); #endif return 0; } -static void pic_irq_request(void *opaque, int level) +static void pic_irq_request (void *opaque, int level) { - if (level) - cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD); - else - cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD); + ppc_set_irq(opaque, PPC_INTERRUPT_EXT, level); } /* PCI intack register */ /* Read-only register (?) */ -static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value) +static void _PPC_intack_write (void *opaque, + target_phys_addr_t addr, uint32_t value) { // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value); } @@ -294,7 +292,7 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val) /* Special port 92 */ /* Check soft reset asked */ if (val & 0x01) { - // cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET); + // cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET); } /* Check LE mode */ if (val & 0x02) { |