aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/openpic.c15
-rw-r--r--hw/ppc.c54
-rw-r--r--hw/ppc_chrp.c12
-rw-r--r--hw/ppc_prep.c18
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);
diff --git a/hw/ppc.c b/hw/ppc.c
index c910cb9..04242ac 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -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) {