提交 e9df014c 编写于 作者: J j_mayer

Implement embedded IRQ controller for PowerPC 6xx/740 & 750.

Fix PowerPC external interrupt input handling and lowering.
Fix OpenPIC output pins management.
Fix multiples bugs in OpenPIC IRQ management.
Fix OpenPIC CPU(s) reset function.
Fix Mac99 machine to properly route OpenPIC outputs to the PowerPC input pins.
Fix PREP machine to properly route i8259 output to the PowerPC external
  interrupt pin.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2647 c046a42c-6fe2-441c-8c8c-71466251a162
上级 682c4f15
...@@ -467,16 +467,14 @@ int cpu_exec(CPUState *env1) ...@@ -467,16 +467,14 @@ int cpu_exec(CPUState *env1)
} }
#endif #endif
if (interrupt_request & CPU_INTERRUPT_HARD) { if (interrupt_request & CPU_INTERRUPT_HARD) {
if (ppc_hw_interrupt(env) == 1) { ppc_hw_interrupt(env);
/* Some exception was raised */ if (env->pending_interrupts == 0)
if (env->pending_interrupts == 0) env->interrupt_request &= ~CPU_INTERRUPT_HARD;
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#if defined(__sparc__) && !defined(HOST_SOLARIS) #if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0; tmp_T0 = 0;
#else #else
T0 = 0; T0 = 0;
#endif #endif
}
} }
#elif defined(TARGET_MIPS) #elif defined(TARGET_MIPS)
if ((interrupt_request & CPU_INTERRUPT_HARD) && if ((interrupt_request & CPU_INTERRUPT_HARD) &&
......
...@@ -159,18 +159,18 @@ typedef struct IRQ_dst_t { ...@@ -159,18 +159,18 @@ typedef struct IRQ_dst_t {
uint32_t pcsr; /* CPU sensitivity register */ uint32_t pcsr; /* CPU sensitivity register */
IRQ_queue_t raised; IRQ_queue_t raised;
IRQ_queue_t servicing; IRQ_queue_t servicing;
CPUState *env; qemu_irq *irqs;
} IRQ_dst_t; } IRQ_dst_t;
typedef struct openpic_t { typedef struct openpic_t {
PCIDevice pci_dev; PCIDevice pci_dev;
SetIRQFunc *set_irq;
int mem_index; int mem_index;
/* Global registers */ /* Global registers */
uint32_t frep; /* Feature reporting register */ uint32_t frep; /* Feature reporting register */
uint32_t glbc; /* Global configuration register */ uint32_t glbc; /* Global configuration register */
uint32_t micr; /* MPIC interrupt configuration register */ uint32_t micr; /* MPIC interrupt configuration register */
uint32_t veni; /* Vendor identification register */ uint32_t veni; /* Vendor identification register */
uint32_t pint; /* Processor initialization register */
uint32_t spve; /* Spurious vector register */ uint32_t spve; /* Spurious vector register */
uint32_t tifr; /* Timer frequency reporting register */ uint32_t tifr; /* Timer frequency reporting register */
/* Source registers */ /* Source registers */
...@@ -196,6 +196,8 @@ typedef struct openpic_t { ...@@ -196,6 +196,8 @@ typedef struct openpic_t {
uint32_t mbr; /* Mailbox register */ uint32_t mbr; /* Mailbox register */
} mailboxes[MAX_MAILBOXES]; } mailboxes[MAX_MAILBOXES];
#endif #endif
/* IRQ out is used when in bypass mode (not implemented) */
qemu_irq irq_out;
} openpic_t; } openpic_t;
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
...@@ -255,19 +257,34 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) ...@@ -255,19 +257,34 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
priority = IPVP_PRIORITY(src->ipvp); priority = IPVP_PRIORITY(src->ipvp);
if (priority <= dst->pctp) { if (priority <= dst->pctp) {
/* Too low priority */ /* Too low priority */
DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
__func__, n_IRQ, n_CPU);
return; return;
} }
if (IRQ_testbit(&dst->raised, n_IRQ)) { if (IRQ_testbit(&dst->raised, n_IRQ)) {
/* Interrupt miss */ /* Interrupt miss */
DPRINTF("%s: IRQ %d was missed on CPU %d\n",
__func__, n_IRQ, n_CPU);
return; return;
} }
set_bit(&src->ipvp, IPVP_ACTIVITY); set_bit(&src->ipvp, IPVP_ACTIVITY);
IRQ_setbit(&dst->raised, n_IRQ); IRQ_setbit(&dst->raised, n_IRQ);
if (priority > dst->raised.priority) { if (priority < dst->raised.priority) {
IRQ_get_next(opp, &dst->raised); /* An higher priority IRQ is already raised */
DPRINTF("Raise CPU IRQ fn %p env %p\n", opp->set_irq, dst->env); DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
opp->set_irq(dst->env, OPENPIC_EVT_INT, 1); __func__, n_IRQ, dst->raised.next, n_CPU);
return;
}
IRQ_get_next(opp, &dst->raised);
if (IRQ_get_next(opp, &dst->servicing) != -1 &&
priority < dst->servicing.priority) {
DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
__func__, n_IRQ, dst->servicing.next, n_CPU);
/* Already servicing a higher priority IRQ */
return;
} }
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
} }
/* update pic state because registers for n_IRQ have changed value */ /* update pic state because registers for n_IRQ have changed value */
...@@ -280,27 +297,34 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) ...@@ -280,27 +297,34 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
if (!src->pending) { if (!src->pending) {
/* no irq pending */ /* no irq pending */
DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
return; return;
} }
if (test_bit(&src->ipvp, IPVP_MASK)) { if (test_bit(&src->ipvp, IPVP_MASK)) {
/* Interrupt source is disabled */ /* Interrupt source is disabled */
DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
return; return;
} }
if (IPVP_PRIORITY(src->ipvp) == 0) { if (IPVP_PRIORITY(src->ipvp) == 0) {
/* Priority set to zero */ /* Priority set to zero */
DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
return; return;
} }
if (test_bit(&src->ipvp, IPVP_ACTIVITY)) { if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
/* IRQ already active */ /* IRQ already active */
DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
return; return;
} }
if (src->ide == 0x00000000) { if (src->ide == 0x00000000) {
/* No target */ /* No target */
DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
return; return;
} }
if (!test_bit(&src->ipvp, IPVP_MODE) || if (src->ide == (1 << src->last_cpu)) {
src->ide == (1 << src->last_cpu)) { /* Only one CPU is allowed to receive this IRQ */
IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
} else if (!test_bit(&src->ipvp, IPVP_MODE)) {
/* Directed delivery mode */ /* Directed delivery mode */
for (i = 0; i < opp->nb_cpus; i++) { for (i = 0; i < opp->nb_cpus; i++) {
if (test_bit(&src->ide, i)) if (test_bit(&src->ide, i))
...@@ -308,9 +332,8 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ) ...@@ -308,9 +332,8 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
} }
} else { } else {
/* Distributed delivery mode */ /* Distributed delivery mode */
/* XXX: incorrect code */ for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
for (i = src->last_cpu; i < src->last_cpu; i++) { if (i == opp->nb_cpus)
if (i == MAX_IRQ)
i = 0; i = 0;
if (test_bit(&src->ide, i)) { if (test_bit(&src->ide, i)) {
IRQ_local_pipe(opp, i, n_IRQ); IRQ_local_pipe(opp, i, n_IRQ);
...@@ -350,6 +373,7 @@ static void openpic_reset (openpic_t *opp) ...@@ -350,6 +373,7 @@ static void openpic_reset (openpic_t *opp)
/* Initialise controller registers */ /* Initialise controller registers */
opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
opp->veni = VENI; opp->veni = VENI;
opp->pint = 0x00000000;
opp->spve = 0x000000FF; opp->spve = 0x000000FF;
opp->tifr = 0x003F7A00; opp->tifr = 0x003F7A00;
/* ? */ /* ? */
...@@ -360,7 +384,7 @@ static void openpic_reset (openpic_t *opp) ...@@ -360,7 +384,7 @@ static void openpic_reset (openpic_t *opp)
opp->src[i].ide = 0x00000000; opp->src[i].ide = 0x00000000;
} }
/* Initialise IRQ destinations */ /* Initialise IRQ destinations */
for (i = 0; i < opp->nb_cpus; i++) { for (i = 0; i < MAX_CPU; i++) {
opp->dst[i].pctp = 0x0000000F; opp->dst[i].pctp = 0x0000000F;
opp->dst[i].pcsr = 0x00000000; opp->dst[i].pcsr = 0x00000000;
memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t)); memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
...@@ -511,6 +535,8 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx, ...@@ -511,6 +535,8 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx,
static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
{ {
openpic_t *opp = opaque; openpic_t *opp = opaque;
IRQ_dst_t *dst;
int idx;
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF) if (addr & 0xF)
...@@ -530,11 +556,18 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) ...@@ -530,11 +556,18 @@ static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
case 0x80: /* VENI */ case 0x80: /* VENI */
break; break;
case 0x90: /* PINT */ case 0x90: /* PINT */
/* XXX: Should be able to reset any CPU */ for (idx = 0; idx < opp->nb_cpus; idx++) {
if (val & 1) { if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
DPRINTF("Reset CPU IRQ\n"); DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
// opp->set_irq(dst->env, OPENPIC_EVT_RESET, 1); dst = &opp->dst[idx];
qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
} else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
dst = &opp->dst[idx];
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
}
} }
opp->pint = val;
break; break;
#if MAX_IPI > 0 #if MAX_IPI > 0
case 0xA0: /* IPI_IPVP */ case 0xA0: /* IPI_IPVP */
...@@ -735,7 +768,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) ...@@ -735,7 +768,7 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
openpic_t *opp = opaque; openpic_t *opp = opaque;
IRQ_src_t *src; IRQ_src_t *src;
IRQ_dst_t *dst; IRQ_dst_t *dst;
int idx, n_IRQ; int idx, s_IRQ, n_IRQ;
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF) if (addr & 0xF)
...@@ -770,21 +803,21 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) ...@@ -770,21 +803,21 @@ static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
break; break;
case 0xB0: /* PEOI */ case 0xB0: /* PEOI */
DPRINTF("PEOI\n"); DPRINTF("PEOI\n");
n_IRQ = IRQ_get_next(opp, &dst->servicing); s_IRQ = IRQ_get_next(opp, &dst->servicing);
IRQ_resetbit(&dst->servicing, n_IRQ); IRQ_resetbit(&dst->servicing, s_IRQ);
dst->servicing.next = -1; dst->servicing.next = -1;
src = &opp->src[n_IRQ];
/* Set up next servicing IRQ */ /* Set up next servicing IRQ */
IRQ_get_next(opp, &dst->servicing); s_IRQ = IRQ_get_next(opp, &dst->servicing);
/* Check queued interrupts. */ /* Check queued interrupts. */
n_IRQ = IRQ_get_next(opp, &dst->raised); n_IRQ = IRQ_get_next(opp, &dst->raised);
if (n_IRQ != -1) { src = &opp->src[n_IRQ];
src = &opp->src[n_IRQ]; if (n_IRQ != -1 &&
if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) { (s_IRQ == -1 ||
DPRINTF("Raise CPU IRQ\n"); IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
opp->set_irq(dst->env, OPENPIC_EVT_INT, 1); DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
} idx, n_IRQ);
} qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
}
break; break;
default: default:
break; break;
...@@ -815,11 +848,13 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) ...@@ -815,11 +848,13 @@ static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
retval = idx; retval = idx;
break; break;
case 0xA0: /* PIAC */ case 0xA0: /* PIAC */
DPRINTF("Lower OpenPIC INT output\n");
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
n_IRQ = IRQ_get_next(opp, &dst->raised); n_IRQ = IRQ_get_next(opp, &dst->raised);
DPRINTF("PIAC: irq=%d\n", n_IRQ); DPRINTF("PIAC: irq=%d\n", n_IRQ);
if (n_IRQ == -1) { if (n_IRQ == -1) {
/* No more interrupt pending */ /* No more interrupt pending */
retval = opp->spve; retval = IPVP_VECTOR(opp->spve);
} else { } else {
src = &opp->src[n_IRQ]; src = &opp->src[n_IRQ];
if (!test_bit(&src->ipvp, IPVP_ACTIVITY) || if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
...@@ -964,8 +999,8 @@ static void openpic_map(PCIDevice *pci_dev, int region_num, ...@@ -964,8 +999,8 @@ static void openpic_map(PCIDevice *pci_dev, int region_num,
#endif #endif
} }
qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq, qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
int *pmem_index, int nb_cpus, CPUState **envp) qemu_irq **irqs, qemu_irq irq_out)
{ {
openpic_t *opp; openpic_t *opp;
uint8_t *pci_conf; uint8_t *pci_conf;
...@@ -995,7 +1030,6 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq, ...@@ -995,7 +1030,6 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
} else { } else {
opp = qemu_mallocz(sizeof(openpic_t)); opp = qemu_mallocz(sizeof(openpic_t));
} }
opp->set_irq = set_irq;
opp->mem_index = cpu_register_io_memory(0, openpic_read, opp->mem_index = cpu_register_io_memory(0, openpic_read,
openpic_write, opp); openpic_write, opp);
...@@ -1020,9 +1054,11 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq, ...@@ -1020,9 +1054,11 @@ qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq,
opp->src[i].type = IRQ_INTERNAL; opp->src[i].type = IRQ_INTERNAL;
} }
for (i = 0; i < nb_cpus; i++) for (i = 0; i < nb_cpus; i++)
opp->dst[i].env = envp[i]; opp->dst[i].irqs = irqs[i];
opp->irq_out = irq_out;
openpic_reset(opp); openpic_reset(opp);
if (pmem_index) if (pmem_index)
*pmem_index = opp->mem_index; *pmem_index = opp->mem_index;
return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ); return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
} }
/* /*
* QEMU generic PPC hardware System Emulator * QEMU generic PowerPC hardware System Emulator
* *
* Copyright (c) 2003-2007 Jocelyn Mayer * Copyright (c) 2003-2007 Jocelyn Mayer
* *
...@@ -24,18 +24,13 @@ ...@@ -24,18 +24,13 @@
#include "vl.h" #include "vl.h"
#include "m48t59.h" #include "m48t59.h"
//#define PPC_DEBUG_IRQ
extern FILE *logfile; extern FILE *logfile;
extern int loglevel; extern int loglevel;
/*****************************************************************************/ void ppc_set_irq (CPUState *env, int n_IRQ, int level)
/* PowerPC internal fake IRQ controller
* used to manage multiple sources hardware events
*/
static void ppc_set_irq (void *opaque, int n_IRQ, int level)
{ {
CPUState *env;
env = opaque;
if (level) { if (level) {
env->pending_interrupts |= 1 << n_IRQ; env->pending_interrupts |= 1 << n_IRQ;
cpu_interrupt(env, CPU_INTERRUPT_HARD); cpu_interrupt(env, CPU_INTERRUPT_HARD);
...@@ -44,49 +39,104 @@ static void ppc_set_irq (void *opaque, int n_IRQ, int level) ...@@ -44,49 +39,104 @@ static void ppc_set_irq (void *opaque, int n_IRQ, int level)
if (env->pending_interrupts == 0) if (env->pending_interrupts == 0)
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
} }
#if 0 #if defined(PPC_DEBUG_IRQ)
printf("%s: %p n_IRQ %d level %d => pending %08x req %08x\n", __func__, printf("%s: %p n_IRQ %d level %d => pending %08x req %08x\n", __func__,
env, n_IRQ, level, env->pending_interrupts, env->interrupt_request); env, n_IRQ, level, env->pending_interrupts, env->interrupt_request);
#endif #endif
} }
void cpu_ppc_irq_init_cpu(CPUState *env) /* PowerPC 6xx / 7xx internal IRQ controller */
static void ppc6xx_set_irq (void *opaque, int pin, int level)
{ {
qemu_irq *qi; CPUState *env = opaque;
int i; int cur_level;
qi = qemu_allocate_irqs(ppc_set_irq, env, 32); #if defined(PPC_DEBUG_IRQ)
for (i = 0; i < 32; i++) { printf("%s: env %p pin %d level %d\n", __func__, env, pin, level);
env->irq[i] = qi[i]; #endif
cur_level = (env->irq_input_state >> pin) & 1;
/* Don't generate spurious events */
if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0) || 0) {
switch (pin) {
case PPC_INPUT_INT:
/* Level sensitive - asserted high */
#if defined(PPC_DEBUG_IRQ)
printf("%s: set the external IRQ state to %d\n", __func__, level);
#endif
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
break;
case PPC_INPUT_SMI:
/* Level sensitive - active high */
#if defined(PPC_DEBUG_IRQ)
printf("%s: set the SMI IRQ state to %d\n", __func__, level);
#endif
ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
break;
case PPC_INPUT_MCP:
/* Negative edge sensitive */
/* XXX: TODO: actual reaction may depends on HID0 status
* 603/604/740/750: check HID0[EMCP]
*/
if (cur_level == 1 && level == 0) {
#if defined(PPC_DEBUG_IRQ)
printf("%s: raise machine check state\n", __func__);
#endif
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
}
break;
case PPC_INPUT_CKSTP_IN:
/* Level sensitive - active low */
/* XXX: TODO: relay the signal to CKSTP_OUT pin */
if (level) {
#if defined(PPC_DEBUG_IRQ)
printf("%s: stop the CPU\n", __func__);
#endif
env->halted = 1;
} else {
#if defined(PPC_DEBUG_IRQ)
printf("%s: restart the CPU\n", __func__);
#endif
env->halted = 0;
}
break;
case PPC_INPUT_HRESET:
/* Level sensitive - active low */
if (level) {
#if 0 // XXX: TOFIX
#if defined(PPC_DEBUG_IRQ)
printf("%s: reset the CPU\n", __func__);
#endif
cpu_reset(env);
#endif
}
break;
case PPC_INPUT_SRESET:
#if defined(PPC_DEBUG_IRQ)
printf("%s: set the RESET IRQ state to %d\n", __func__, level);
#endif
ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
break;
default:
/* Unknown pin - do nothing */
#if defined(PPC_DEBUG_IRQ)
printf("%s: unknown IRQ pin %d\n", __func__, pin);
#endif
return;
}
if (level)
env->irq_input_state |= 1 << pin;
else
env->irq_input_state &= ~(1 << pin);
} }
} }
/* External IRQ callback from OpenPIC IRQ controller */ void ppc6xx_irq_init (CPUState *env)
void ppc_openpic_irq (void *opaque, int n_IRQ, int level)
{ {
switch (n_IRQ) { env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
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 */ /* PowerPC time base and decrementer emulation */
//#define DEBUG_TB //#define DEBUG_TB
struct ppc_tb_t { struct ppc_tb_t {
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
*/ */
#include "vl.h" #include "vl.h"
/* SMP is not enabled, for now */
#define MAX_CPUS 1
#define BIOS_FILENAME "ppc_rom.bin" #define BIOS_FILENAME "ppc_rom.bin"
#define VGABIOS_FILENAME "video.x" #define VGABIOS_FILENAME "video.x"
#define NVRAM_SIZE 0x2000 #define NVRAM_SIZE 0x2000
...@@ -296,9 +299,9 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, ...@@ -296,9 +299,9 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
const char *cpu_model, const char *cpu_model,
int is_heathrow) int is_heathrow)
{ {
CPUState *env; CPUState *env, *envs[MAX_CPUS];
char buf[1024]; char buf[1024];
qemu_irq *pic; qemu_irq *pic, **openpic_irqs;
m48t59_t *nvram; m48t59_t *nvram;
int unin_memory; int unin_memory;
int linux_boot, i; int linux_boot, i;
...@@ -329,13 +332,13 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, ...@@ -329,13 +332,13 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
if (def == NULL) { if (def == NULL) {
cpu_abort(env, "Unable to find PowerPC CPU definition\n"); cpu_abort(env, "Unable to find PowerPC CPU definition\n");
} }
cpu_ppc_register(env, def); for (i = 0; i < smp_cpus; i++) {
cpu_ppc_irq_init_cpu(env); cpu_ppc_register(env, def);
/* Set time-base frequency to 100 Mhz */
/* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); env->osi_call = vga_osi_call;
envs[i] = env;
env->osi_call = vga_osi_call; }
/* allocate RAM */ /* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
...@@ -458,7 +461,26 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device, ...@@ -458,7 +461,26 @@ static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL); unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory); cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
pic = openpic_init(NULL, &ppc_openpic_irq, &openpic_mem_index, 1, &env); openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
openpic_irqs[0] =
qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
for (i = 0; i < smp_cpus; i++) {
/* Mac99 IRQ connection between OpenPIC outputs pins
* and PowerPC input pins
*/
openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
openpic_irqs[i][OPENPIC_OUTPUT_INT] =
((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
((qemu_irq *)env->irq_inputs)[PPC_INPUT_INT];
openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
((qemu_irq *)env->irq_inputs)[PPC_INPUT_MCP];
openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Not connected ? */
openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
((qemu_irq *)env->irq_inputs)[PPC_INPUT_HRESET]; /* Check this */
}
pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
openpic_irqs, NULL);
pci_bus = pci_pmac_init(pic); pci_bus = pci_pmac_init(pic);
/* init basic PC hardware */ /* init basic PC hardware */
pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
......
...@@ -548,7 +548,6 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, ...@@ -548,7 +548,6 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
cpu_abort(env, "Unable to find PowerPC CPU definition\n"); cpu_abort(env, "Unable to find PowerPC CPU definition\n");
} }
cpu_ppc_register(env, def); cpu_ppc_register(env, def);
cpu_ppc_irq_init_cpu(env);
/* Set time-base frequency to 100 Mhz */ /* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
...@@ -599,7 +598,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, ...@@ -599,7 +598,7 @@ static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
} }
isa_mem_base = 0xc0000000; isa_mem_base = 0xc0000000;
i8259 = i8259_init(first_cpu->irq[PPC_INTERRUPT_EXT]); i8259 = i8259_init(first_cpu->irq_inputs[PPC_INPUT_INT]);
pci_bus = pci_prep_init(i8259); pci_bus = pci_prep_init(i8259);
// pci_bus = i440fx_init(); // pci_bus = i440fx_init();
/* Register 8 MB of ISA IO space (needed for non-contiguous map) */ /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
......
...@@ -758,7 +758,13 @@ struct CPUPPCState { ...@@ -758,7 +758,13 @@ struct CPUPPCState {
int error_code; int error_code;
int interrupt_request; int interrupt_request;
uint32_t pending_interrupts; uint32_t pending_interrupts;
void *irq[32]; #if !defined(CONFIG_USER_ONLY)
/* This is the IRQ controller, which is implementation dependant
* and only relevant when emulating a complete machine.
*/
uint32_t irq_input_state;
void **irq_inputs;
#endif
/* Those resources are used only during code translation */ /* Those resources are used only during code translation */
/* Next instruction pointer */ /* Next instruction pointer */
...@@ -801,6 +807,7 @@ int cpu_ppc_signal_handler(int host_signum, void *pinfo, ...@@ -801,6 +807,7 @@ int cpu_ppc_signal_handler(int host_signum, void *pinfo,
void *puc); void *puc);
void do_interrupt (CPUPPCState *env); void do_interrupt (CPUPPCState *env);
void ppc_hw_interrupt (CPUPPCState *env);
void cpu_loop_exit(void); void cpu_loop_exit(void);
void dump_stack (CPUPPCState *env); void dump_stack (CPUPPCState *env);
...@@ -1303,16 +1310,35 @@ enum { ...@@ -1303,16 +1310,35 @@ enum {
/* Hardware interruption sources: /* Hardware interruption sources:
* all those exception can be raised simulteaneously * all those exception can be raised simulteaneously
*/ */
/* Input pins definitions */
enum {
/* 6xx bus input pins */
PPC_INPUT_HRESET = 0,
PPC_INPUT_SRESET = 1,
PPC_INPUT_CKSTP_IN = 2,
PPC_INPUT_MCP = 3,
PPC_INPUT_SMI = 4,
PPC_INPUT_INT = 5,
/* Embedded PowerPC input pins */
PPC_INPUT_CINT = 6,
PPC_INPUT_NB,
};
/* Hardware exceptions definitions */
enum { enum {
PPC_INTERRUPT_RESET = 0, /* Reset / critical input */ /* External hardware exception sources */
PPC_INTERRUPT_MCK = 1, /* Machine check exception */ PPC_INTERRUPT_RESET = 0, /* Reset exception */
PPC_INTERRUPT_EXT = 2, /* External interrupt */ PPC_INTERRUPT_MCK = 1, /* Machine check exception */
PPC_INTERRUPT_DECR = 3, /* Decrementer exception */ PPC_INTERRUPT_EXT = 2, /* External interrupt */
PPC_INTERRUPT_HDECR = 4, /* Hypervisor decrementer exception */ PPC_INTERRUPT_SMI = 3, /* System management interrupt */
PPC_INTERRUPT_PIT = 5, /* Programmable inteval timer interrupt */ PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */
PPC_INTERRUPT_FIT = 6, /* Fixed interval timer interrupt */ PPC_INTERRUPT_DEBUG = 5, /* External debug exception */
PPC_INTERRUPT_WDT = 7, /* Watchdog timer interrupt */ /* Internal hardware exception sources */
PPC_INTERRUPT_DEBUG = 8, /* External debug exception */ PPC_INTERRUPT_DECR = 6, /* Decrementer exception */
PPC_INTERRUPT_HDECR = 7, /* Hypervisor decrementer exception */
PPC_INTERRUPT_PIT = 8, /* Programmable inteval timer interrupt */
PPC_INTERRUPT_FIT = 9, /* Fixed interval timer interrupt */
PPC_INTERRUPT_WDT = 10, /* Watchdog timer interrupt */
}; };
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -1358,11 +1358,9 @@ void do_interrupt (CPUState *env) ...@@ -1358,11 +1358,9 @@ void do_interrupt (CPUState *env)
env->exception_index = -1; env->exception_index = -1;
} }
int ppc_hw_interrupt (CPUState *env) void ppc_hw_interrupt (CPUState *env)
{ {
env->exception_index = -1; env->exception_index = -1;
return 0;
} }
#else /* defined (CONFIG_USER_ONLY) */ #else /* defined (CONFIG_USER_ONLY) */
static void dump_syscall(CPUState *env) static void dump_syscall(CPUState *env)
...@@ -1927,7 +1925,7 @@ void do_interrupt (CPUState *env) ...@@ -1927,7 +1925,7 @@ void do_interrupt (CPUState *env)
env->exception_index = EXCP_NONE; env->exception_index = EXCP_NONE;
} }
int ppc_hw_interrupt (CPUState *env) void ppc_hw_interrupt (CPUPPCState *env)
{ {
int raised = 0; int raised = 0;
...@@ -1940,6 +1938,9 @@ int ppc_hw_interrupt (CPUState *env) ...@@ -1940,6 +1938,9 @@ int ppc_hw_interrupt (CPUState *env)
/* Raise it */ /* Raise it */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
/* External reset / critical input */ /* External reset / critical input */
/* XXX: critical input should be handled another way.
* This code is not correct !
*/
env->exception_index = EXCP_RESET; env->exception_index = EXCP_RESET;
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
raised = 1; raised = 1;
...@@ -1984,7 +1985,12 @@ int ppc_hw_interrupt (CPUState *env) ...@@ -1984,7 +1985,12 @@ int ppc_hw_interrupt (CPUState *env)
/* External interrupt */ /* External interrupt */
} else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
env->exception_index = EXCP_EXTERNAL; env->exception_index = EXCP_EXTERNAL;
/* Taking an external interrupt does not clear the external
* interrupt status
*/
#if 0
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT); env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
#endif
raised = 1; raised = 1;
} }
#if 0 // TODO #if 0 // TODO
...@@ -1999,7 +2005,5 @@ int ppc_hw_interrupt (CPUState *env) ...@@ -1999,7 +2005,5 @@ int ppc_hw_interrupt (CPUState *env)
env->error_code = 0; env->error_code = 0;
do_interrupt(env); do_interrupt(env);
} }
return raised;
} }
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
...@@ -35,6 +35,18 @@ struct ppc_def_t { ...@@ -35,6 +35,18 @@ struct ppc_def_t {
uint64_t msr_mask; uint64_t msr_mask;
}; };
/* For user-mode emulation, we don't emulate any IRQ controller */
#if defined(CONFIG_USER_ONLY)
#define PPC_IRQ_INIT_FN(name) \
static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \
{ \
}
#else
#define PPC_IRQ_INIT_FN(name) \
void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
#endif
PPC_IRQ_INIT_FN(6xx);
/* Generic callbacks: /* Generic callbacks:
* do nothing but store/retrieve spr value * do nothing but store/retrieve spr value
*/ */
...@@ -1865,6 +1877,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1865,6 +1877,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
case CPU_PPC_403GA: /* 403 GA family */ case CPU_PPC_403GA: /* 403 GA family */
...@@ -1879,6 +1892,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1879,6 +1892,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
case CPU_PPC_405CR: /* 405 GP/CR family */ case CPU_PPC_405CR: /* 405 GP/CR family */
...@@ -1895,6 +1909,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1895,6 +1909,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
case CPU_PPC_NPE405H: /* NPe405 H family */ case CPU_PPC_NPE405H: /* NPe405 H family */
...@@ -1909,6 +1924,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1909,6 +1924,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
#if defined (TODO) #if defined (TODO)
...@@ -1940,6 +1956,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1940,6 +1956,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
case CPU_PPC_440EP: /* 440 EP family */ case CPU_PPC_440EP: /* 440 EP family */
...@@ -1959,6 +1976,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1959,6 +1976,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
/* Embedded PowerPC from Freescale */ /* Embedded PowerPC from Freescale */
...@@ -1994,6 +2012,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -1994,6 +2012,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_tlb = 64; env->nb_tlb = 64;
env->nb_ways = 1; env->nb_ways = 1;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
#if defined (TODO) #if defined (TODO)
...@@ -2038,6 +2057,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2038,6 +2057,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
env->nb_ways = 2; env->nb_ways = 2;
env->id_tlbs = 0; env->id_tlbs = 0;
env->id_tlbs = 0; env->id_tlbs = 0;
/* XXX: TODO: allocate internal IRQ controller */
break; break;
case CPU_PPC_602: /* PowerPC 602 */ case CPU_PPC_602: /* PowerPC 602 */
...@@ -2060,6 +2080,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2060,6 +2080,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_603: /* PowerPC 603 */ case CPU_PPC_603: /* PowerPC 603 */
...@@ -2087,6 +2109,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2087,6 +2109,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_G2: /* PowerPC G2 family */ case CPU_PPC_G2: /* PowerPC G2 family */
...@@ -2123,6 +2147,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2123,6 +2147,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_604: /* PowerPC 604 */ case CPU_PPC_604: /* PowerPC 604 */
...@@ -2146,6 +2172,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2146,6 +2172,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_74x: /* PowerPC 740 / 750 */ case CPU_PPC_74x: /* PowerPC 740 / 750 */
...@@ -2178,6 +2206,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2178,6 +2206,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_750FX10: /* IBM PowerPC 750 FX */ case CPU_PPC_750FX10: /* IBM PowerPC 750 FX */
...@@ -2213,6 +2243,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2213,6 +2243,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
case CPU_PPC_755_10: /* PowerPC 755 */ case CPU_PPC_755_10: /* PowerPC 755 */
...@@ -2257,6 +2289,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2257,6 +2289,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic, &spr_read_generic, &spr_write_generic,
0x00000000); 0x00000000);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
break; break;
#if defined (TODO) #if defined (TODO)
...@@ -2326,6 +2360,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def) ...@@ -2326,6 +2360,7 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
default: default:
gen_spr_generic(env); gen_spr_generic(env);
/* XXX: TODO: allocate internal IRQ controller */
break; break;
} }
if (env->nb_BATs == -1) if (env->nb_BATs == -1)
......
...@@ -854,16 +854,17 @@ void i440fx_init_memory_mappings(PCIDevice *d); ...@@ -854,16 +854,17 @@ void i440fx_init_memory_mappings(PCIDevice *d);
int piix4_init(PCIBus *bus, int devfn); int piix4_init(PCIBus *bus, int devfn);
/* openpic.c */ /* openpic.c */
/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
enum { enum {
OPENPIC_EVT_INT = 0, /* IRQ */ OPENPIC_OUTPUT_INT = 0, /* IRQ */
OPENPIC_EVT_CINT, /* critical IRQ */ OPENPIC_OUTPUT_CINT, /* critical IRQ */
OPENPIC_EVT_MCK, /* Machine check event */ OPENPIC_OUTPUT_MCK, /* Machine check event */
OPENPIC_EVT_DEBUG, /* Inconditional debug event */ OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */
OPENPIC_EVT_RESET, /* Core reset event */ OPENPIC_OUTPUT_RESET, /* Core reset event */
OPENPIC_OUTPUT_NB,
}; };
qemu_irq *openpic_init (PCIBus *bus, SetIRQFunc *set_irq, qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
int *pmem_index, int nb_cpus, qemu_irq **irqs, qemu_irq irq_out);
struct CPUState **envp);
/* heathrow_pic.c */ /* heathrow_pic.c */
qemu_irq *heathrow_pic_init(int *pmem_index); qemu_irq *heathrow_pic_init(int *pmem_index);
...@@ -1145,9 +1146,6 @@ extern QEMUMachine shix_machine; ...@@ -1145,9 +1146,6 @@ extern QEMUMachine shix_machine;
#ifdef TARGET_PPC #ifdef TARGET_PPC
/* PowerPC hardware exceptions management helpers */ /* PowerPC hardware exceptions management helpers */
void cpu_ppc_irq_init_cpu(CPUState *env);
void ppc_openpic_irq (void *opaque, int n_IRQ, int level);
int ppc_hw_interrupt (CPUState *env);
ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq); ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
#endif #endif
void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册