mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 10:34:58 -06:00
Merge remote-tracking branch 'upstream' into memory/batch
* upstream: (87 commits) target-alpha: Fix compilation errors for 32 bit hosts target-alpha: Add high-resolution access to wall clock and an alarm. target-alpha: Implement HALT IPR. target-alpha: Implement WAIT IPR. target-alpha: Add CLIPPER emulation. target-alpha: Add custom PALcode image for CLIPPER emulation. target-alpha: Honor icount for RPCC instruction. tcg/s390: Remove unused tcg_out_addi() tcg/ia64: Remove unused tcg_out_addi() ARM: fix segfault ppc64: Fix linker script pseries: Implement set-time-of-day RTAS function pseries: Refactor spapr irq allocation PPC: Clean up BookE timer code PPC: booke timers KVM: PPC: Use HIOR setting for -M pseries with PR KVM KVM: Update kernel headers KVM: Update kernel headers PPC: Fix heathrow PIC to use little endian MMIO PPC: Fix via-cuda memory registration ... Conflicts: hw/milkymist-uart.c hw/ppce500_mpc8544ds.c Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
commit
df2921d326
78 changed files with 3467 additions and 661 deletions
291
hw/openpic.c
291
hw/openpic.c
|
@ -2,6 +2,7 @@
|
|||
* OpenPIC emulation
|
||||
*
|
||||
* Copyright (c) 2004 Jocelyn Mayer
|
||||
* 2011 Alexander Graf
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -56,13 +57,13 @@
|
|||
#define MAX_MBX 4
|
||||
#define MAX_TMR 4
|
||||
#define VECTOR_BITS 8
|
||||
#define MAX_IPI 0
|
||||
#define MAX_IPI 4
|
||||
|
||||
#define VID (0x00000000)
|
||||
|
||||
#elif defined(USE_MPCxxx)
|
||||
|
||||
#define MAX_CPU 2
|
||||
#define MAX_CPU 15
|
||||
#define MAX_IRQ 128
|
||||
#define MAX_DBL 0
|
||||
#define MAX_MBX 0
|
||||
|
@ -127,14 +128,14 @@ enum {
|
|||
#define MPIC_MSI_REG_START 0x11C00
|
||||
#define MPIC_MSI_REG_SIZE 0x100
|
||||
#define MPIC_CPU_REG_START 0x20000
|
||||
#define MPIC_CPU_REG_SIZE 0x100
|
||||
#define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
|
||||
|
||||
enum mpic_ide_bits {
|
||||
IDR_EP = 0,
|
||||
IDR_CI0 = 1,
|
||||
IDR_CI1 = 2,
|
||||
IDR_P1 = 30,
|
||||
IDR_P0 = 31,
|
||||
IDR_EP = 31,
|
||||
IDR_CI0 = 30,
|
||||
IDR_CI1 = 29,
|
||||
IDR_P1 = 1,
|
||||
IDR_P0 = 0,
|
||||
};
|
||||
|
||||
#else
|
||||
|
@ -161,6 +162,16 @@ static inline int test_bit (uint32_t *field, int bit)
|
|||
return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
|
||||
}
|
||||
|
||||
static int get_current_cpu(void)
|
||||
{
|
||||
return cpu_single_env->cpu_index;
|
||||
}
|
||||
|
||||
static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
|
||||
int idx);
|
||||
static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val, int idx);
|
||||
|
||||
enum {
|
||||
IRQ_EXTERNAL = 0x01,
|
||||
IRQ_INTERNAL = 0x02,
|
||||
|
@ -465,46 +476,35 @@ static void openpic_reset (void *opaque)
|
|||
opp->glbc = 0x00000000;
|
||||
}
|
||||
|
||||
static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
|
||||
static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
|
||||
{
|
||||
uint32_t retval;
|
||||
|
||||
switch (reg) {
|
||||
case IRQ_IPVP:
|
||||
retval = opp->src[n_IRQ].ipvp;
|
||||
break;
|
||||
case IRQ_IDE:
|
||||
retval = opp->src[n_IRQ].ide;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return opp->src[n_IRQ].ide;
|
||||
}
|
||||
|
||||
static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
|
||||
uint32_t reg, uint32_t val)
|
||||
static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
|
||||
{
|
||||
return opp->src[n_IRQ].ipvp;
|
||||
}
|
||||
|
||||
static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
switch (reg) {
|
||||
case IRQ_IPVP:
|
||||
/* NOTE: not fully accurate for special IRQs, but simple and
|
||||
sufficient */
|
||||
/* ACTIVITY bit is read-only */
|
||||
opp->src[n_IRQ].ipvp =
|
||||
(opp->src[n_IRQ].ipvp & 0x40000000) |
|
||||
(val & 0x800F00FF);
|
||||
openpic_update_irq(opp, n_IRQ);
|
||||
DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
|
||||
n_IRQ, val, opp->src[n_IRQ].ipvp);
|
||||
break;
|
||||
case IRQ_IDE:
|
||||
tmp = val & 0xC0000000;
|
||||
tmp |= val & ((1 << MAX_CPU) - 1);
|
||||
opp->src[n_IRQ].ide = tmp;
|
||||
DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
|
||||
break;
|
||||
}
|
||||
tmp = val & 0xC0000000;
|
||||
tmp |= val & ((1ULL << MAX_CPU) - 1);
|
||||
opp->src[n_IRQ].ide = tmp;
|
||||
DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
|
||||
}
|
||||
|
||||
static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
|
||||
{
|
||||
/* NOTE: not fully accurate for special IRQs, but simple and sufficient */
|
||||
/* ACTIVITY bit is read-only */
|
||||
opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
|
||||
| (val & 0x800F00FF);
|
||||
openpic_update_irq(opp, n_IRQ);
|
||||
DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
|
||||
opp->src[n_IRQ].ipvp);
|
||||
}
|
||||
|
||||
#if 0 // Code provision for Intel model
|
||||
|
@ -516,10 +516,10 @@ static uint32_t read_doorbell_register (openpic_t *opp,
|
|||
|
||||
switch (offset) {
|
||||
case DBL_IPVP_OFFSET:
|
||||
retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
|
||||
break;
|
||||
case DBL_IDE_OFFSET:
|
||||
retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
|
||||
break;
|
||||
case DBL_DMR_OFFSET:
|
||||
retval = opp->doorbells[n_dbl].dmr;
|
||||
|
@ -534,10 +534,10 @@ static void write_doorbell_register (penpic_t *opp, int n_dbl,
|
|||
{
|
||||
switch (offset) {
|
||||
case DBL_IVPR_OFFSET:
|
||||
write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
|
||||
write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
|
||||
break;
|
||||
case DBL_IDE_OFFSET:
|
||||
write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
|
||||
write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
|
||||
break;
|
||||
case DBL_DMR_OFFSET:
|
||||
opp->doorbells[n_dbl].dmr = value;
|
||||
|
@ -557,10 +557,10 @@ static uint32_t read_mailbox_register (openpic_t *opp,
|
|||
retval = opp->mailboxes[n_mbx].mbr;
|
||||
break;
|
||||
case MBX_IVPR_OFFSET:
|
||||
retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
|
||||
break;
|
||||
case MBX_DMR_OFFSET:
|
||||
retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -575,10 +575,10 @@ static void write_mailbox_register (openpic_t *opp, int n_mbx,
|
|||
opp->mailboxes[n_mbx].mbr = value;
|
||||
break;
|
||||
case MBX_IVPR_OFFSET:
|
||||
write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
|
||||
write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
|
||||
break;
|
||||
case MBX_DMR_OFFSET:
|
||||
write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
|
||||
write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -594,18 +594,27 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v
|
|||
DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
|
||||
if (addr & 0xF)
|
||||
return;
|
||||
addr &= 0xFF;
|
||||
switch (addr) {
|
||||
case 0x00: /* FREP */
|
||||
case 0x40:
|
||||
case 0x50:
|
||||
case 0x60:
|
||||
case 0x70:
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
|
||||
break;
|
||||
case 0x20: /* GLBC */
|
||||
case 0x1000: /* FREP */
|
||||
break;
|
||||
case 0x1020: /* GLBC */
|
||||
if (val & 0x80000000 && opp->reset)
|
||||
opp->reset(opp);
|
||||
opp->glbc = val & ~0x80000000;
|
||||
break;
|
||||
case 0x80: /* VENI */
|
||||
case 0x1080: /* VENI */
|
||||
break;
|
||||
case 0x90: /* PINT */
|
||||
case 0x1090: /* PINT */
|
||||
for (idx = 0; idx < opp->nb_cpus; idx++) {
|
||||
if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
|
||||
DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
|
||||
|
@ -619,22 +628,20 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v
|
|||
}
|
||||
opp->pint = val;
|
||||
break;
|
||||
#if MAX_IPI > 0
|
||||
case 0xA0: /* IPI_IPVP */
|
||||
case 0xB0:
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
case 0x10A0: /* IPI_IPVP */
|
||||
case 0x10B0:
|
||||
case 0x10C0:
|
||||
case 0x10D0:
|
||||
{
|
||||
int idx;
|
||||
idx = (addr - 0xA0) >> 4;
|
||||
write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
|
||||
idx = (addr - 0x10A0) >> 4;
|
||||
write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 0xE0: /* SPVE */
|
||||
case 0x10E0: /* SPVE */
|
||||
opp->spve = val & 0x000000FF;
|
||||
break;
|
||||
case 0xF0: /* TIFR */
|
||||
case 0x10F0: /* TIFR */
|
||||
opp->tifr = val;
|
||||
break;
|
||||
default:
|
||||
|
@ -651,36 +658,43 @@ static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
|
|||
retval = 0xFFFFFFFF;
|
||||
if (addr & 0xF)
|
||||
return retval;
|
||||
addr &= 0xFF;
|
||||
switch (addr) {
|
||||
case 0x00: /* FREP */
|
||||
case 0x1000: /* FREP */
|
||||
retval = opp->frep;
|
||||
break;
|
||||
case 0x20: /* GLBC */
|
||||
case 0x1020: /* GLBC */
|
||||
retval = opp->glbc;
|
||||
break;
|
||||
case 0x80: /* VENI */
|
||||
case 0x1080: /* VENI */
|
||||
retval = opp->veni;
|
||||
break;
|
||||
case 0x90: /* PINT */
|
||||
case 0x1090: /* PINT */
|
||||
retval = 0x00000000;
|
||||
break;
|
||||
#if MAX_IPI > 0
|
||||
case 0xA0: /* IPI_IPVP */
|
||||
case 0x40:
|
||||
case 0x50:
|
||||
case 0x60:
|
||||
case 0x70:
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
|
||||
break;
|
||||
case 0x10A0: /* IPI_IPVP */
|
||||
case 0x10B0:
|
||||
case 0x10C0:
|
||||
case 0x10D0:
|
||||
{
|
||||
int idx;
|
||||
idx = (addr - 0xA0) >> 4;
|
||||
retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
|
||||
idx = (addr - 0x10A0) >> 4;
|
||||
retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 0xE0: /* SPVE */
|
||||
case 0x10E0: /* SPVE */
|
||||
retval = opp->spve;
|
||||
break;
|
||||
case 0xF0: /* TIFR */
|
||||
case 0x10F0: /* TIFR */
|
||||
retval = opp->tifr;
|
||||
break;
|
||||
default:
|
||||
|
@ -714,10 +728,10 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
|
|||
opp->timers[idx].tibc = val;
|
||||
break;
|
||||
case 0x20: /* TIVP */
|
||||
write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
|
||||
break;
|
||||
case 0x30: /* TIDE */
|
||||
write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -744,10 +758,10 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
|
|||
retval = opp->timers[idx].tibc;
|
||||
break;
|
||||
case 0x20: /* TIPV */
|
||||
retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
|
||||
break;
|
||||
case 0x30: /* TIDE */
|
||||
retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
|
||||
break;
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
|
@ -767,10 +781,10 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
|
|||
idx = addr >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg(opp, idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(opp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg(opp, idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(opp, idx, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,38 +802,40 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr)
|
|||
idx = addr >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg(opp, idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(opp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg(opp, idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(opp, idx);
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||
static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t val, int idx)
|
||||
{
|
||||
openpic_t *opp = opaque;
|
||||
IRQ_src_t *src;
|
||||
IRQ_dst_t *dst;
|
||||
int idx, s_IRQ, n_IRQ;
|
||||
int s_IRQ, n_IRQ;
|
||||
|
||||
DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
|
||||
DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
|
||||
addr, val);
|
||||
if (addr & 0xF)
|
||||
return;
|
||||
addr &= 0x1FFF0;
|
||||
idx = addr / 0x1000;
|
||||
dst = &opp->dst[idx];
|
||||
addr &= 0xFF0;
|
||||
switch (addr) {
|
||||
#if MAX_IPI > 0
|
||||
case 0x40: /* PIPD */
|
||||
case 0x40: /* IPIDR */
|
||||
case 0x50:
|
||||
case 0x60:
|
||||
case 0x70:
|
||||
idx = (addr - 0x40) >> 4;
|
||||
write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
|
||||
/* we use IDE as mask which CPUs to deliver the IPI to still. */
|
||||
write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
|
||||
opp->src[opp->irq_ipi0 + idx].ide | val);
|
||||
openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
|
||||
openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
|
||||
break;
|
||||
|
@ -856,20 +872,24 @@ static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t v
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
|
||||
static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
|
||||
{
|
||||
openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
|
||||
}
|
||||
|
||||
static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
|
||||
int idx)
|
||||
{
|
||||
openpic_t *opp = opaque;
|
||||
IRQ_src_t *src;
|
||||
IRQ_dst_t *dst;
|
||||
uint32_t retval;
|
||||
int idx, n_IRQ;
|
||||
int n_IRQ;
|
||||
|
||||
DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
|
||||
DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
|
||||
retval = 0xFFFFFFFF;
|
||||
if (addr & 0xF)
|
||||
return retval;
|
||||
addr &= 0x1FFF0;
|
||||
idx = addr / 0x1000;
|
||||
dst = &opp->dst[idx];
|
||||
addr &= 0xFF0;
|
||||
switch (addr) {
|
||||
|
@ -909,18 +929,22 @@ static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
|
|||
reset_bit(&src->ipvp, IPVP_ACTIVITY);
|
||||
src->pending = 0;
|
||||
}
|
||||
|
||||
if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
|
||||
src->ide &= ~(1 << idx);
|
||||
if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
|
||||
/* trigger on CPUs that didn't know about it yet */
|
||||
openpic_set_irq(opp, n_IRQ, 1);
|
||||
openpic_set_irq(opp, n_IRQ, 0);
|
||||
/* if all CPUs knew about it, set active bit again */
|
||||
set_bit(&src->ipvp, IPVP_ACTIVITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xB0: /* PEOI */
|
||||
retval = 0;
|
||||
break;
|
||||
#if MAX_IPI > 0
|
||||
case 0x40: /* IDE */
|
||||
case 0x50:
|
||||
idx = (addr - 0x40) >> 4;
|
||||
retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -929,6 +953,11 @@ static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
|
||||
}
|
||||
|
||||
static void openpic_buggy_write (void *opaque,
|
||||
target_phys_addr_t addr, uint32_t val)
|
||||
{
|
||||
|
@ -1247,7 +1276,7 @@ static void mpic_reset (void *opaque)
|
|||
|
||||
mpp->glbc = 0x80000000;
|
||||
/* Initialise controller registers */
|
||||
mpp->frep = 0x004f0002;
|
||||
mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
|
||||
mpp->veni = VENI;
|
||||
mpp->pint = 0x00000000;
|
||||
mpp->spve = 0x0000FFFF;
|
||||
|
@ -1256,6 +1285,10 @@ static void mpic_reset (void *opaque)
|
|||
mpp->src[i].ipvp = 0x80800000;
|
||||
mpp->src[i].ide = 0x00000001;
|
||||
}
|
||||
/* Set IDE for IPIs to 0 so we don't get spurious interrupts */
|
||||
for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
|
||||
mpp->src[i].ide = 0;
|
||||
}
|
||||
/* Initialise IRQ destinations */
|
||||
for (i = 0; i < MAX_CPU; i++) {
|
||||
mpp->dst[i].pctp = 0x0000000F;
|
||||
|
@ -1296,13 +1329,13 @@ static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t va
|
|||
mpp->timers[idx].tibc = val;
|
||||
break;
|
||||
case 0x20: /* GTIVPR */
|
||||
write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
|
||||
break;
|
||||
case 0x30: /* GTIDR & TFRR */
|
||||
if ((addr & 0xF0) == 0xF0)
|
||||
mpp->dst[cpu].tfrr = val;
|
||||
else
|
||||
write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1328,13 +1361,13 @@ static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
|
|||
retval = mpp->timers[idx].tibc;
|
||||
break;
|
||||
case 0x20: /* TIPV */
|
||||
retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
|
||||
break;
|
||||
case 0x30: /* TIDR */
|
||||
if ((addr &0xF0) == 0XF0)
|
||||
retval = mpp->dst[cpu].tfrr;
|
||||
else
|
||||
retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
|
||||
break;
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
|
@ -1357,10 +1390,10 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg(mpp, idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(mpp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg(mpp, idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(mpp, idx, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1381,10 +1414,10 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(mpp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(mpp, idx);
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
}
|
||||
|
@ -1407,10 +1440,10 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg(mpp, idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(mpp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg(mpp, idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(mpp, idx, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1431,10 +1464,10 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(mpp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(mpp, idx);
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
}
|
||||
|
@ -1457,10 +1490,10 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg(mpp, idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(mpp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg(mpp, idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(mpp, idx, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1481,10 +1514,10 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(mpp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(mpp, idx);
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
}
|
||||
|
@ -1507,10 +1540,10 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg(mpp, idx, IRQ_IDE, val);
|
||||
write_IRQreg_ide(mpp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg(mpp, idx, IRQ_IPVP, val);
|
||||
write_IRQreg_ipvp(mpp, idx, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1530,10 +1563,10 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
|
|||
idx += (addr & 0xFFF0) >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IDE);
|
||||
retval = read_IRQreg_ide(mpp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg(mpp, idx, IRQ_IPVP);
|
||||
retval = read_IRQreg_ipvp(mpp, idx);
|
||||
}
|
||||
DPRINTF("%s: => %08x\n", __func__, retval);
|
||||
}
|
||||
|
@ -1659,10 +1692,6 @@ qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
|
|||
{"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
|
||||
};
|
||||
|
||||
/* XXX: for now, only one CPU is supported */
|
||||
if (nb_cpus != 1)
|
||||
return NULL;
|
||||
|
||||
mpp = g_malloc0(sizeof(openpic_t));
|
||||
|
||||
memory_region_init(&mpp->mem, "mpic", 0x40000);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue