From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LaI19-0005Ju-0z for qemu-devel@nongnu.org; Thu, 19 Feb 2009 18:09:19 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LaI17-0005IJ-DX for qemu-devel@nongnu.org; Thu, 19 Feb 2009 18:09:18 -0500 Received: from [199.232.76.173] (port=41364 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LaI17-0005IG-Al for qemu-devel@nongnu.org; Thu, 19 Feb 2009 18:09:17 -0500 Received: from mail-gx0-f175.google.com ([209.85.217.175]:47904) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LaI16-0000R4-Aw for qemu-devel@nongnu.org; Thu, 19 Feb 2009 18:09:17 -0500 Received: by gxk23 with SMTP id 23so2102127gxk.10 for ; Thu, 19 Feb 2009 15:09:15 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <1234864778-19099-2-git-send-email-yu.liu@freescale.com> References: <1234864778-19099-1-git-send-email-yu.liu@freescale.com> <1234864778-19099-2-git-send-email-yu.liu@freescale.com> Date: Thu, 19 Feb 2009 17:09:15 -0600 Message-ID: Subject: Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform. From: Paulev Content-Type: multipart/alternative; boundary=000e0cd4043405e4a704634da0e7 Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --000e0cd4043405e4a704634da0e7 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit How do I remove myself from the QEMU list? On Tue, Feb 17, 2009 at 3:59 AM, Liu Yu wrote: > MPIC and OpenPIC have very similar design. > So a lot of code can be reused. > > Modification mainly include: > 1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC. > 2. endianess swap. > MPIC has the same endianess as target, so no need to swap for MPIC. > 3. using different init functions and function pointers for reset and irq > raise. > > Haven't test OpenPIC. > > Signed-off-by: Liu Yu > --- > hw/openpic.c | 480 > +++++++++++++++++++++++++++++++++++++++++++++-------- > hw/ppc_mac.h | 13 -- > hw/ppc_newworld.c | 1 + > 3 files changed, 412 insertions(+), 82 deletions(-) > > diff --git a/hw/openpic.c b/hw/openpic.c > index 6dfb590..0f687e4 100644 > --- a/hw/openpic.c > +++ b/hw/openpic.c > @@ -35,6 +35,7 @@ > #include "hw.h" > #include "ppc_mac.h" > #include "pci.h" > +#include "openpic.h" > > //#define DEBUG_OPENPIC > > @@ -60,14 +61,10 @@ > > #define VID (0x00000000) > > -#define OPENPIC_LITTLE_ENDIAN 1 > -#define OPENPIC_BIG_ENDIAN 0 > - > #elif defined(USE_MPCxxx) > > #define MAX_CPU 2 > -#define MAX_IRQ 64 > -#define EXT_IRQ 48 > +#define MAX_IRQ 128 > #define MAX_DBL 0 > #define MAX_MBX 0 > #define MAX_TMR 4 > @@ -81,28 +78,55 @@ enum { > IRQ_IDE, > }; > > -#define OPENPIC_LITTLE_ENDIAN 1 > -#define OPENPIC_BIG_ENDIAN 0 > +/* OpenPIC */ > +#define OPENPIC_MAX_CPU 2 > +#define OPENPIC_MAX_IRQ 64 > +#define OPENPIC_EXT_IRQ 48 > +#define OPENPIC_MAX_TMR MAX_TMR > +#define OPENPIC_MAX_IPI MAX_IPI > > +/* Interrupt definitions */ > +#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional > IRQ */ > +#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */ > +#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */ > +#if OPENPIC_MAX_IPI > 0 > +#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First > IPI IRQ */ > +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * > OPENPIC_MAX_IPI)) /* First doorbell IRQ */ > #else > -#error "Please select which OpenPic implementation is to be emulated" > +#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First > doorbell IRQ */ > +#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First > mailbox IRQ */ > #endif > > -#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \ > - (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN) > -#define OPENPIC_SWAP > -#endif > +/* MPIC */ > +#define MPIC_MAX_CPU 1 > +#define MPIC_MAX_EXT 12 > +#define MPIC_MAX_INT 64 > +#define MPIC_MAX_MSG 4 > +#define MPIC_MAX_MSI 8 > +#define MPIC_MAX_TMR MAX_TMR > +#define MPIC_MAX_IPI MAX_IPI > +#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + > MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU)) > > /* Interrupt definitions */ > -#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */ > -#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */ > -#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */ > -#if MAX_IPI > 0 > -#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */ > -#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ > */ > +#define MPIC_EXT_IRQ 0 > +#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT) > +#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT) > +#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR) > +#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG) > +#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI) > + > +#define MPIC_MAP_SIZE 0x40000 > + > +enum mpic_ide_bits { > + IDR_EP = 0, > + IDR_CI0 = 1, > + IDR_CI1 = 2, > + IDR_P1 = 30, > + IDR_P0 = 31, > +}; > + > #else > -#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */ > -#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */ > +#error "Please select which OpenPic implementation is to be emulated" > #endif > > #define BF_WIDTH(_bits_) \ > @@ -157,6 +181,7 @@ enum IPVP_bits { > #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) > > typedef struct IRQ_dst_t { > + uint32_t tfrr; > uint32_t pctp; /* CPU current task priority */ > uint32_t pcsr; /* CPU sensitivity register */ > IRQ_queue_t raised; > @@ -200,8 +225,22 @@ typedef struct openpic_t { > #endif > /* IRQ out is used when in bypass mode (not implemented) */ > qemu_irq irq_out; > + int max_irq; > + int irq_ipi0; > + int irq_tim0; > + int need_swap; > + void (*reset) (void *); > + void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *); > } openpic_t; > > +static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val) > +{ > + if (opp->need_swap) > + return bswap32(val); > + > + return val; > +} > + > static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) > { > set_bit(q->queue, n_IRQ); > @@ -224,7 +263,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) > > next = -1; > priority = -1; > - for (i = 0; i < MAX_IRQ; i++) { > + for (i = 0; i < opp->max_irq; i++) { > if (IRQ_testbit(q, i)) { > DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", > i, IPVP_PRIORITY(opp->src[i].ipvp), priority); > @@ -286,7 +325,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, > int n_IRQ) > return; > } > DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ); > - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); > + opp->irq_raise(opp, n_CPU, src); > } > > /* update pic state because registers for n_IRQ have changed value */ > @@ -374,7 +413,7 @@ static void openpic_reset (void *opaque) > > opp->glbc = 0x80000000; > /* Initialise controller registers */ > - opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; > + opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | > VID; > opp->veni = VENI; > opp->pint = 0x00000000; > opp->spve = 0x000000FF; > @@ -382,7 +421,7 @@ static void openpic_reset (void *opaque) > /* ? */ > opp->micr = 0x00000000; > /* Initialise IRQ sources */ > - for (i = 0; i < MAX_IRQ; i++) { > + for (i = 0; i < opp->max_irq; i++) { > opp->src[i].ipvp = 0xA0000000; > opp->src[i].ide = 0x00000000; > } > @@ -544,16 +583,16 @@ static void openpic_gbl_write (void *opaque, uint32_t > addr, uint32_t val) > DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > if (addr & 0xF) > return; > -#if defined OPENPIC_SWAP > - val = bswap32(val); > +#if defined TARGET_WORDS_BIGENDIAN > + val = openpic_swap32(opp, val); > #endif > addr &= 0xFF; > switch (addr) { > case 0x00: /* FREP */ > break; > case 0x20: /* GLBC */ > - if (val & 0x80000000) > - openpic_reset(opp); > + if (val & 0x80000000 && opp->reset) > + opp->reset(opp); > opp->glbc = val & ~0x80000000; > break; > case 0x80: /* VENI */ > @@ -580,7 +619,7 @@ static void openpic_gbl_write (void *opaque, uint32_t > addr, uint32_t val) > { > int idx; > idx = (addr - 0xA0) >> 4; > - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val); > + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val); > } > break; > #endif > @@ -626,7 +665,7 @@ static uint32_t openpic_gbl_read (void *opaque, > uint32_t addr) > { > int idx; > idx = (addr - 0xA0) >> 4; > - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP); > + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP); > } > break; > #endif > @@ -640,8 +679,8 @@ static uint32_t openpic_gbl_read (void *opaque, > uint32_t addr) > break; > } > DPRINTF("%s: => %08x\n", __func__, retval); > -#if defined OPENPIC_SWAP > - retval = bswap32(retval); > +#if defined TARGET_WORDS_BIGENDIAN > + retval = openpic_swap32(opp, retval); > #endif > > return retval; > @@ -655,8 +694,8 @@ static void openpic_timer_write (void *opaque, uint32_t > addr, uint32_t val) > DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > if (addr & 0xF) > return; > -#if defined OPENPIC_SWAP > - val = bswap32(val); > +#if defined TARGET_WORDS_BIGENDIAN > + val = openpic_swap32(opp, val); > #endif > addr -= 0x1100; > addr &= 0xFFFF; > @@ -673,10 +712,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, IRQ_TIM0 + idx, IRQ_IPVP, val); > + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP, val); > break; > case 0x30: /* TIDE */ > - write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val); > + write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, val); > break; > } > } > @@ -703,15 +742,15 @@ static uint32_t openpic_timer_read (void *opaque, > uint32_t addr) > retval = opp->timers[idx].tibc; > break; > case 0x20: /* TIPV */ > - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP); > + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IPVP); > break; > case 0x30: /* TIDE */ > - retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE); > + retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE); > break; > } > DPRINTF("%s: => %08x\n", __func__, retval); > -#if defined OPENPIC_SWAP > - retval = bswap32(retval); > +#if defined TARGET_WORDS_BIGENDIAN > + retval = openpic_swap32(opp, retval); > #endif > > return retval; > @@ -725,8 +764,8 @@ static void openpic_src_write (void *opaque, uint32_t > addr, uint32_t val) > DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > if (addr & 0xF) > return; > -#if defined OPENPIC_SWAP > - val = tswap32(val); > +#if defined TARGET_WORDS_BIGENDIAN > + val = openpic_swap32(opp, val); > #endif > addr = addr & 0xFFF0; > idx = addr >> 5; > @@ -759,8 +798,8 @@ static uint32_t openpic_src_read (void *opaque, > uint32_t addr) > retval = read_IRQreg(opp, idx, IRQ_IPVP); > } > DPRINTF("%s: => %08x\n", __func__, retval); > -#if defined OPENPIC_SWAP > - retval = tswap32(retval); > +#if defined TARGET_WORDS_BIGENDIAN > + retval = openpic_swap32(opp, retval); > #endif > > return retval; > @@ -776,8 +815,8 @@ static void openpic_cpu_write (void *opaque, uint32_t > addr, uint32_t val) > DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > if (addr & 0xF) > return; > -#if defined OPENPIC_SWAP > - val = bswap32(val); > +#if defined TARGET_WORDS_BIGENDIAN > + val = openpic_swap32(opp, val); > #endif > addr &= 0x1FFF0; > idx = addr / 0x1000; > @@ -790,9 +829,9 @@ static void openpic_cpu_write (void *opaque, uint32_t > addr, uint32_t val) > case 0x60: > case 0x70: > idx = (addr - 0x40) >> 4; > - write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val); > - openpic_set_irq(opp, IRQ_IPI0 + idx, 1); > - openpic_set_irq(opp, IRQ_IPI0 + idx, 0); > + write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val); > + openpic_set_irq(opp, opp->irq_ipi0 + idx, 1); > + openpic_set_irq(opp, opp->irq_ipi0 + idx, 0); > break; > #endif > case 0x80: /* PCTP */ > @@ -819,7 +858,7 @@ static void openpic_cpu_write (void *opaque, uint32_t > addr, uint32_t val) > IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) { > DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", > idx, n_IRQ); > - qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]); > + opp->irq_raise(opp, idx, src); > } > break; > default: > @@ -889,15 +928,15 @@ static uint32_t openpic_cpu_read (void *opaque, > uint32_t addr) > case 0x40: /* IDE */ > case 0x50: > idx = (addr - 0x40) >> 4; > - retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE); > + retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE); > break; > #endif > default: > break; > } > DPRINTF("%s: => %08x\n", __func__, retval); > -#if defined OPENPIC_SWAP > - retval= bswap32(retval); > +#if defined TARGET_WORDS_BIGENDIAN > + retval = openpic_swap32(opp, retval); > #endif > > return retval; > @@ -989,7 +1028,7 @@ static void openpic_map(PCIDevice *pci_dev, int > region_num, > addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR); > /* Interrupt source registers */ > DPRINTF("Register OPENPIC src %08x => %08x\n", > - addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2)); > + addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + > 2)); > /* Per CPU registers */ > DPRINTF("Register OPENPIC dst %08x => %08x\n", > addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU); > @@ -1026,7 +1065,7 @@ static void openpic_save(QEMUFile* f, void *opaque) > qemu_put_be32s(f, &opp->spve); > qemu_put_be32s(f, &opp->tifr); > > - for (i = 0; i < MAX_IRQ; i++) { > + for (i = 0; i < opp->max_irq; i++) { > qemu_put_be32s(f, &opp->src[i].ipvp); > qemu_put_be32s(f, &opp->src[i].ide); > qemu_put_sbe32s(f, &opp->src[i].type); > @@ -1034,15 +1073,16 @@ static void openpic_save(QEMUFile* f, void *opaque) > qemu_put_sbe32s(f, &opp->src[i].pending); > } > > - for (i = 0; i < MAX_IRQ; i++) { > + qemu_put_sbe32s(f, &opp->nb_cpus); > + > + for (i = 0; i < opp->nb_cpus; i++) { > + qemu_put_be32s(f, &opp->dst[i].tfrr); > qemu_put_be32s(f, &opp->dst[i].pctp); > qemu_put_be32s(f, &opp->dst[i].pcsr); > openpic_save_IRQ_queue(f, &opp->dst[i].raised); > openpic_save_IRQ_queue(f, &opp->dst[i].servicing); > } > > - qemu_put_sbe32s(f, &opp->nb_cpus); > - > for (i = 0; i < MAX_TMR; i++) { > qemu_put_be32s(f, &opp->timers[i].ticc); > qemu_put_be32s(f, &opp->timers[i].tibc); > @@ -1092,7 +1132,7 @@ static int openpic_load(QEMUFile* f, void *opaque, > int version_id) > qemu_get_be32s(f, &opp->spve); > qemu_get_be32s(f, &opp->tifr); > > - for (i = 0; i < MAX_IRQ; i++) { > + for (i = 0; i < opp->max_irq; i++) { > qemu_get_be32s(f, &opp->src[i].ipvp); > qemu_get_be32s(f, &opp->src[i].ide); > qemu_get_sbe32s(f, &opp->src[i].type); > @@ -1100,15 +1140,16 @@ static int openpic_load(QEMUFile* f, void *opaque, > int version_id) > qemu_get_sbe32s(f, &opp->src[i].pending); > } > > - for (i = 0; i < MAX_IRQ; i++) { > + qemu_get_sbe32s(f, &opp->nb_cpus); > + > + for (i = 0; i < opp->nb_cpus; i++) { > + qemu_get_be32s(f, &opp->dst[i].tfrr); > qemu_get_be32s(f, &opp->dst[i].pctp); > qemu_get_be32s(f, &opp->dst[i].pcsr); > openpic_load_IRQ_queue(f, &opp->dst[i].raised); > openpic_load_IRQ_queue(f, &opp->dst[i].servicing); > } > > - qemu_get_sbe32s(f, &opp->nb_cpus); > - > for (i = 0; i < MAX_TMR; i++) { > qemu_get_be32s(f, &opp->timers[i].ticc); > qemu_get_be32s(f, &opp->timers[i].tibc); > @@ -1131,6 +1172,11 @@ static int openpic_load(QEMUFile* f, void *opaque, > int version_id) > return pci_device_load(&opp->pci_dev, f); > } > > +static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) > +{ > + qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); > +} > + > qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, > qemu_irq **irqs, qemu_irq irq_out) > { > @@ -1164,33 +1210,329 @@ qemu_irq *openpic_init (PCIBus *bus, int > *pmem_index, int nb_cpus, > > // isu_base &= 0xFFFC0000; > opp->nb_cpus = nb_cpus; > + opp->max_irq = OPENPIC_MAX_IRQ; > + opp->irq_ipi0 = OPENPIC_IRQ_IPI0; > + opp->irq_tim0 = OPENPIC_IRQ_TIM0; > /* Set IRQ types */ > - for (i = 0; i < EXT_IRQ; i++) { > + for (i = 0; i < OPENPIC_EXT_IRQ; i++) { > opp->src[i].type = IRQ_EXTERNAL; > } > - for (; i < IRQ_TIM0; i++) { > + for (; i < OPENPIC_IRQ_TIM0; i++) { > opp->src[i].type = IRQ_SPECIAL; > } > #if MAX_IPI > 0 > - m = IRQ_IPI0; > + m = OPENPIC_IRQ_IPI0; > #else > - m = IRQ_DBL0; > + m = OPENPIC_IRQ_DBL0; > #endif > for (; i < m; i++) { > opp->src[i].type = IRQ_TIMER; > } > - for (; i < MAX_IRQ; i++) { > + for (; i < OPENPIC_MAX_IRQ; i++) { > opp->src[i].type = IRQ_INTERNAL; > } > for (i = 0; i < nb_cpus; i++) > opp->dst[i].irqs = irqs[i]; > opp->irq_out = irq_out; > + opp->need_swap = 1; > > register_savevm("openpic", 0, 1, openpic_save, openpic_load, opp); > qemu_register_reset(openpic_reset, opp); > - openpic_reset(opp); > + > + opp->irq_raise = openpic_irq_raise; > + opp->reset = openpic_reset; > + > + opp->reset(opp); > if (pmem_index) > *pmem_index = opp->mem_index; > > - return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ); > + return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); > +} > + > +static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src) > +{ > + int n_ci = IDR_CI0 - n_CPU; > + DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__, > + n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci); > + if(test_bit(&src->ide, n_ci)) { > + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]); > + } > + else { > + qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]); > + } > +} > + > +static void mpic_reset (void *opaque) > +{ > + openpic_t *mpp = (openpic_t *)opaque; > + int i; > + > + mpp->glbc = 0x80000000; > + /* Initialise controller registers */ > + mpp->frep = 0x004f0002; > + mpp->veni = VENI; > + mpp->pint = 0x00000000; > + mpp->spve = 0x0000FFFF; > + /* Initialise IRQ sources */ > + for (i = 0; i < mpp->max_irq; i++) { > + mpp->src[i].ipvp = 0x80800000; > + mpp->src[i].ide = 0x00000001; > + } > + /* Initialise IRQ destinations */ > + for (i = 0; i < MAX_CPU; i++) { > + mpp->dst[i].pctp = 0x0000000F; > + mpp->dst[i].tfrr = 0x00000000; > + memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t)); > + mpp->dst[i].raised.next = -1; > + memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); > + mpp->dst[i].servicing.next = -1; > + } > + /* Initialise timers */ > + for (i = 0; i < MAX_TMR; i++) { > + mpp->timers[i].ticc = 0x00000000; > + mpp->timers[i].tibc = 0x80000000; > + } > + /* Go out of RESET state */ > + mpp->glbc = 0x00000000; > +} > + > +static void mpic_timer_write (void *opaque, uint32_t addr, uint32_t val) > +{ > + openpic_t *mpp = opaque; > + int idx, cpu; > + > + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > + if (addr & 0xF) > + return; > + addr &= 0xFFFF; > + cpu = addr >> 12; > + idx = (addr >> 6) & 0x3; > + switch (addr & 0x30) { > + case 0x00: /* gtccr */ > + break; > + case 0x10: /* gtbcr */ > + if ((mpp->timers[idx].ticc & 0x80000000) != 0 && > + (val & 0x80000000) == 0 && > + (mpp->timers[idx].tibc & 0x80000000) != 0) > + mpp->timers[idx].ticc &= ~0x80000000; > + mpp->timers[idx].tibc = val; > + break; > + case 0x20: /* GTIVPR */ > + write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, 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); > + break; > + } > +} > + > +static uint32_t mpic_timer_read (void *opaque, uint32_t addr) > +{ > + openpic_t *mpp = opaque; > + uint32_t retval; > + int idx, cpu; > + > + DPRINTF("%s: addr %08x\n", __func__, addr); > + retval = 0xFFFFFFFF; > + if (addr & 0xF) > + return retval; > + addr &= 0xFFFF; > + cpu = addr >> 12; > + idx = (addr >> 6) & 0x3; > + switch (addr & 0x30) { > + case 0x00: /* gtccr */ > + retval = mpp->timers[idx].ticc; > + break; > + case 0x10: /* gtbcr */ > + retval = mpp->timers[idx].tibc; > + break; > + case 0x20: /* TIPV */ > + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP); > + break; > + case 0x30: /* TIDR */ > + if ((addr &0xF0) == 0XF0) > + retval = mpp->dst[cpu].tfrr; > + else > + retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE); > + break; > + } > + DPRINTF("%s: => %08x\n", __func__, retval); > + > + return retval; > +} > + > +static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val) > +{ > + openpic_t *mpp = opaque; > + int idx; > + > + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); > + if (addr & 0xF) > + return; > + addr = addr & 0xFFF0; > + if (addr < 0x180) { > + idx = MPIC_EXT_IRQ; > + } else if (addr >= 0x200 && addr < 0xa00) { > + idx = MPIC_INT_IRQ; > + addr -= 0x200; > + } else if (addr >= 0x1600 && addr < 0x1700) { > + idx = MPIC_MSG_IRQ; > + addr -= 0x1600; > + } else if (addr >= 0x1C00 && addr < 0x1D00) { > + idx = MPIC_MSI_IRQ; > + addr -= 0x1C00; > + } else { > + return; > + } > + idx += addr >> 5; > + if (addr & 0x10) { > + /* EXDE / IFEDE / IEEDE */ > + write_IRQreg(mpp, idx, IRQ_IDE, val); > + } else { > + /* EXVP / IFEVP / IEEVP */ > + write_IRQreg(mpp, idx, IRQ_IPVP, val); > + } > +} > + > +static uint32_t mpic_src_read (void *opaque, uint32_t addr) > +{ > + openpic_t *mpp = opaque; > + uint32_t retval; > + int idx; > + > + DPRINTF("%s: addr %08x\n", __func__, addr); > + retval = 0xFFFFFFFF; > + if (addr & 0xF) > + return retval; > + addr = addr & 0xFFF0; > + if (addr < 0x180) { > + idx = MPIC_EXT_IRQ; > + } else if (addr >= 0x200 && addr < 0xa00) { > + idx = MPIC_INT_IRQ; > + addr -= 0x200; > + } else if (addr >= 0x1600 && addr < 0x1700) { > + idx = MPIC_MSG_IRQ; > + addr -= 0x1600; > + } else if (addr >= 0x1C00 && addr < 0x1D00) { > + idx = MPIC_MSI_IRQ; > + addr -= 0x1C00; > + } else { > + return retval; > + } > + idx += addr >> 5; > + if (addr & 0x10) { > + /* EXDE / IFEDE / IEEDE */ > + retval = read_IRQreg(mpp, idx, IRQ_IDE); > + } else { > + /* EXVP / IFEVP / IEEVP */ > + retval = read_IRQreg(mpp, idx, IRQ_IPVP); > + } > + DPRINTF("%s: => %08x\n", __func__, retval); > + > + return retval; > +} > + > +static void mpic_writel (void *opaque, > + target_phys_addr_t addr, uint32_t val) > +{ > + openpic_t *mpp = opaque; > + > + addr &= 0x3FFFF; > + DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val); > + if (addr < 0x10F0) { > + /* Global registers */ > + openpic_gbl_write(mpp, addr, val); > + } else if (addr < 0x10000) { > + /* Timers registers */ > + mpic_timer_write(mpp, addr, val); > + } else if (addr < 0x20000) { > + /* Source registers */ > + mpic_src_write(mpp, addr, val); > + } else if (addr < 0x30000){ > + /* CPU registers */ > + openpic_cpu_write(mpp, addr, val); > + } else { > + DPRINTF("wrong mpic write addr %p\n",addr); > + } > +} > + > +static uint32_t mpic_readl (void *opaque,target_phys_addr_t addr) > +{ > + openpic_t *mpp = opaque; > + uint32_t retval = 0; > + > + addr &= 0x3FFFF; > + DPRINTF("%s: offset %08x\n", __func__, (int)addr); > + if (addr < 0x10F0) { > + /* Global registers */ > + retval = openpic_gbl_read(mpp, addr); > + } else if (addr < 0x10000) { > + /* Timers registers */ > + retval = mpic_timer_read(mpp, addr); > + } else if (addr < 0x20000) { > + /* Source registers */ > + retval = mpic_src_read(mpp, addr); > + } else if (addr < 0x30000){ > + /* CPU registers */ > + retval = openpic_cpu_read(mpp, addr); > + } else { > + DPRINTF("wrong mpic read addr %p\n",addr); > + } > + > + return retval; > +} > + > +static CPUWriteMemoryFunc *mpic_write[] = { > + &openpic_buggy_write, > + &openpic_buggy_write, > + &mpic_writel, > +}; > + > +static CPUReadMemoryFunc *mpic_read[] = { > + &openpic_buggy_read, > + &openpic_buggy_read, > + &mpic_readl, > +}; > + > +qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus, > + qemu_irq **irqs, qemu_irq irq_out) > +{ > + openpic_t *mpp; > + int i; > + > + /* XXX: for now, only one CPU is supported */ > + if (nb_cpus != 1) > + return NULL; > + > + mpp = qemu_mallocz(sizeof(openpic_t)); > + > + mpp->mem_index = cpu_register_io_memory(0, mpic_read, mpic_write, > mpp); > + if (mpp->mem_index < 0) > + goto free; > + cpu_register_physical_memory(base, MPIC_MAP_SIZE, mpp->mem_index); > + > + mpp->nb_cpus = nb_cpus; > + mpp->max_irq = MPIC_MAX_IRQ; > + mpp->irq_ipi0 = MPIC_IPI_IRQ; > + mpp->irq_tim0 = MPIC_TMR_IRQ; > + > + for (i = 0; i < nb_cpus; i++) > + mpp->dst[i].irqs = irqs[i]; > + mpp->irq_out = irq_out; > + mpp->need_swap = 0; /* MPIC has the same endian as target */ > + > + mpp->irq_raise = mpic_irq_raise; > + mpp->reset = mpic_reset; > + > + register_savevm("mpic", 0, 1, openpic_save, openpic_load, mpp); > + mpp->reset(mpp); > + > + return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq); > + > +free: > + qemu_free(mpp); > + return NULL; > } > diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h > index 5851a5e..df148b2 100644 > --- a/hw/ppc_mac.h > +++ b/hw/ppc_mac.h > @@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus); > > extern ADBBusState adb_bus; > > -/* openpic.c */ > -/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output > */ > -enum { > - OPENPIC_OUTPUT_INT = 0, /* IRQ */ > - OPENPIC_OUTPUT_CINT, /* critical IRQ */ > - OPENPIC_OUTPUT_MCK, /* Machine check event */ > - OPENPIC_OUTPUT_DEBUG, /* Inconditional debug event */ > - OPENPIC_OUTPUT_RESET, /* Core reset event */ > - OPENPIC_OUTPUT_NB, > -}; > -qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus, > - qemu_irq **irqs, qemu_irq irq_out); > - > #endif /* !defined(__PPC_MAC_H__) */ > diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c > index 6f60e49..b285864 100644 > --- a/hw/ppc_newworld.c > +++ b/hw/ppc_newworld.c > @@ -34,6 +34,7 @@ > #include "boards.h" > #include "fw_cfg.h" > #include "escc.h" > +#include "openpic.h" > > #define MAX_IDE_BUS 2 > #define VGA_BIOS_SIZE 65536 > -- > 1.5.4 > > > > --000e0cd4043405e4a704634da0e7 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable How do I remove myself from the QEMU list?

On Tue, Feb 17, 2009 at 3:59 AM, Liu Yu <yu.liu@freescale.com> wrote:
=
MPIC and OpenPIC have very similar design.
So a lot of code can be reused.

Modification mainly include:
1. keep struct openpic_t to the maximum size of both MPIC and OpenPIC.
2. endianess swap.
  MPIC has the same endianess as target, so no need to swap for MPIC.=
3. using different init functions and function pointers for reset and irq r= aise.

Haven't test OpenPIC.

Signed-off-by: Liu Yu <yu.liu@fr= eescale.com>
---
 hw/openpic.c      |  480 ++++++++++++++++++++++++= +++++++++++++++++++++--------
 hw/ppc_mac.h      |   13 --
 hw/ppc_newworld.c |    1 +
 3 files changed, 412 insertions(+), 82 deletions(-)

diff --git a/hw/openpic.c b/hw/openpic.c
index 6dfb590..0f687e4 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -35,6 +35,7 @@
 #include "hw.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "openpic.h"

 //#define DEBUG_OPENPIC

@@ -60,14 +61,10 @@

 #define VID (0x00000000)

-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN    0
-
 #elif defined(USE_MPCxxx)

 #define MAX_CPU     2
-#define MAX_IRQ    64
-#define EXT_IRQ    48
+#define MAX_IRQ   128
 #define MAX_DBL     0
 #define MAX_MBX     0
 #define MAX_TMR     4
@@ -81,28 +78,55 @@ enum {
    IRQ_IDE,
 };

-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN    0
+/* OpenPIC */
+#define OPENPIC_MAX_CPU      2
+#define OPENPIC_MAX_IRQ     64
+#define OPENPIC_EXT_IRQ     48
+#define OPENPIC_MAX_TMR      MAX_TMR
+#define OPENPIC_MAX_IPI      MAX_IPI

+/* Interrupt definitions */
+#define OPENPIC_IRQ_FE     (OPENPIC_EXT_IRQ)     /* In= ternal functional IRQ */
+#define OPENPIC_IRQ_ERR    (OPENPIC_EXT_IRQ + 1) /* Error IRQ */=
+#define OPENPIC_IRQ_TIM0   (OPENPIC_EXT_IRQ + 2) /* First timer IRQ *= /
+#if OPENPIC_MAX_IPI > 0
+#define OPENPIC_IRQ_IPI0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* Fi= rst IPI IRQ */
+#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPE= NPIC_MAX_IPI)) /* First doorbell IRQ */
 #else
-#error "Please select which OpenPic implementation is to be emulated&= quot;
+#define OPENPIC_IRQ_DBL0   (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* Fi= rst doorbell IRQ */
+#define OPENPIC_IRQ_MBX0   (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* Fi= rst mailbox IRQ */
 #endif

-#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
-    (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN) -#define OPENPIC_SWAP
-#endif
+/* MPIC */
+#define MPIC_MAX_CPU      1
+#define MPIC_MAX_EXT     12
+#define MPIC_MAX_INT     64
+#define MPIC_MAX_MSG      4
+#define MPIC_MAX_MSI      8
+#define MPIC_MAX_TMR      MAX_TMR
+#define MPIC_MAX_IPI      MAX_IPI
+#define MPIC_MAX_IRQ     (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX= _TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))

 /* Interrupt definitions */
-#define IRQ_FE     (EXT_IRQ)     /* Internal functiona= l IRQ */
-#define IRQ_ERR    (EXT_IRQ + 1) /* Error IRQ */
-#define IRQ_TIM0   (EXT_IRQ + 2) /* First timer IRQ */
-#if MAX_IPI > 0
-#define IRQ_IPI0   (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
-#define IRQ_DBL0   (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell= IRQ */
+#define MPIC_EXT_IRQ      0
+#define MPIC_INT_IRQ      (MPIC_EXT_IRQ + MPIC_MAX_EXT)
+#define MPIC_TMR_IRQ      (MPIC_INT_IRQ + MPIC_MAX_INT)
+#define MPIC_MSG_IRQ      (MPIC_TMR_IRQ + MPIC_MAX_TMR)
+#define MPIC_MSI_IRQ      (MPIC_MSG_IRQ + MPIC_MAX_MSG)
+#define MPIC_IPI_IRQ      (MPIC_MSI_IRQ + MPIC_MAX_MSI)
+
+#define MPIC_MAP_SIZE     0x40000
+
+enum mpic_ide_bits {
+    IDR_EP     =3D 0,
+    IDR_CI0     =3D 1,
+    IDR_CI1     =3D 2,
+    IDR_P1     =3D 30,
+    IDR_P0     =3D 31,
+};
+
 #else
-#define IRQ_DBL0   (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
-#define IRQ_MBX0   (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
+#error "Please select which OpenPic implementation is to be emulated&= quot;
 #endif

 #define BF_WIDTH(_bits_) \
@@ -157,6 +181,7 @@ enum IPVP_bits {
 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK= )

 typedef struct IRQ_dst_t {
+    uint32_t tfrr;
    uint32_t pctp; /* CPU current task priority */
    uint32_t pcsr; /* CPU sensitivity register */
    IRQ_queue_t raised;
@@ -200,8 +225,22 @@ typedef struct openpic_t {
 #endif
    /* IRQ out is used when in bypass mode (not implemented) */<= br>     qemu_irq irq_out;
+    int max_irq;
+    int irq_ipi0;
+    int irq_tim0;
+    int need_swap;
+    void (*reset) (void *);
+    void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);  } openpic_t;

+static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
+{
+    if (opp->need_swap)
+        return bswap32(val);
+
+    return val;
+}
+
 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
 {
    set_bit(q->queue, n_IRQ);
@@ -224,7 +263,7 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)<= br>
    next =3D -1;
    priority =3D -1;
-    for (i =3D 0; i < MAX_IRQ; i++) {
+    for (i =3D 0; i < opp->max_irq; i++) {
       if (IRQ_testbit(q, i)) {
            DPRINTF("IRQ_check: irq %d = set ipvp_pr=3D%d pr=3D%d\n",
                    i, I= PVP_PRIORITY(opp->src[i].ipvp), priority);
@@ -286,7 +325,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, = int n_IRQ)
        return;
    }
    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n"= , n_CPU, n_IRQ);
-    qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+    opp->irq_raise(opp, n_CPU, src);
 }

 /* update pic state because registers for n_IRQ have changed value */=
@@ -374,7 +413,7 @@ static void openpic_reset (void *opaque)

    opp->glbc =3D 0x80000000;
    /* Initialise controller registers */
-    opp->frep =3D ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1= ) << 8) | VID;
+    opp->frep =3D ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX= _CPU - 1) << 8) | VID;
    opp->veni =3D VENI;
    opp->pint =3D 0x00000000;
    opp->spve =3D 0x000000FF;
@@ -382,7 +421,7 @@ static void openpic_reset (void *opaque)
    /* ? */
    opp->micr =3D 0x00000000;
    /* Initialise IRQ sources */
-    for (i =3D 0; i < MAX_IRQ; i++) {
+    for (i =3D 0; i < opp->max_irq; i++) {
       opp->src[i].ipvp =3D 0xA0000000;
       opp->src[i].ide  =3D 0x00000000;
    }
@@ -544,16 +583,16 @@ static void openpic_gbl_write (void *opaque, uint32_t= addr, uint32_t val)
    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
    if (addr & 0xF)
        return;
-#if defined OPENPIC_SWAP
-    val =3D bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+    val =3D openpic_swap32(opp, val);
 #endif
    addr &=3D 0xFF;
    switch (addr) {
    case 0x00: /* FREP */
        break;
    case 0x20: /* GLBC */
-        if (val & 0x80000000)
-            openpic_reset(opp);
+        if (val & 0x80000000 && opp->re= set)
+            opp->reset(opp);
        opp->glbc =3D val & ~0x80000000;
       break;
    case 0x80: /* VENI */
@@ -580,7 +619,7 @@ static void openpic_gbl_write (void *opaque, uint32_t a= ddr, uint32_t val)
        {
            int idx;
            idx =3D (addr - 0xA0) >> 4= ;
-            write_IRQreg(opp, IRQ_IPI0 + idx= , IRQ_IPVP, val);
+            write_IRQreg(opp, opp->irq_ip= i0 + idx, IRQ_IPVP, val);
        }
        break;
 #endif
@@ -626,7 +665,7 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_= t addr)
        {
            int idx;
            idx =3D (addr - 0xA0) >> 4= ;
-            retval =3D read_IRQreg(opp, IRQ_= IPI0 + idx, IRQ_IPVP);
+            retval =3D read_IRQreg(opp, opp-= >irq_ipi0 + idx, IRQ_IPVP);
        }
       break;
 #endif
@@ -640,8 +679,8 @@ static uint32_t openpic_gbl_read (void *opaque, uint32_= t addr)
        break;
    }
    DPRINTF("%s: =3D> %08x\n", __func__, retval); -#if defined OPENPIC_SWAP
-    retval =3D bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+    retval =3D openpic_swap32(opp, retval);
 #endif

    return retval;
@@ -655,8 +694,8 @@ static void openpic_timer_write (void *opaque, uint32_t= addr, uint32_t val)
    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
    if (addr & 0xF)
        return;
-#if defined OPENPIC_SWAP
-    val =3D bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+    val =3D openpic_swap32(opp, val);
 #endif
    addr -=3D 0x1100;
    addr &=3D 0xFFFF;
@@ -673,10 +712,10 @@ static void openpic_timer_write (void *opaque, uint32= _t addr, uint32_t val)
       opp->timers[idx].tibc =3D val;
       break;
    case 0x20: /* TIVP */
-       write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val); +        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_= IPVP, val);
       break;
    case 0x30: /* TIDE */
-       write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
+        write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_= IDE, val);
       break;
    }
 }
@@ -703,15 +742,15 @@ static uint32_t openpic_timer_read (void *opaque, uin= t32_t addr)
       retval =3D opp->timers[idx].tibc;
       break;
    case 0x20: /* TIPV */
-       retval =3D read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP= );
+        retval =3D read_IRQreg(opp, opp->irq_tim0 += idx, IRQ_IPVP);
       break;
    case 0x30: /* TIDE */
-       retval =3D read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE)= ;
+        retval =3D read_IRQreg(opp, opp->irq_tim0 += idx, IRQ_IDE);
       break;
    }
    DPRINTF("%s: =3D> %08x\n", __func__, retval); -#if defined OPENPIC_SWAP
-    retval =3D bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+    retval =3D openpic_swap32(opp, retval);
 #endif

    return retval;
@@ -725,8 +764,8 @@ static void openpic_src_write (void *opaque, uint32_t a= ddr, uint32_t val)
    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
    if (addr & 0xF)
        return;
-#if defined OPENPIC_SWAP
-    val =3D tswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+    val =3D openpic_swap32(opp, val);
 #endif
    addr =3D addr & 0xFFF0;
    idx =3D addr >> 5;
@@ -759,8 +798,8 @@ static uint32_t openpic_src_read (void *opaque, uint32_= t addr)
        retval =3D read_IRQreg(opp, idx, IRQ_IPVP);     }
    DPRINTF("%s: =3D> %08x\n", __func__, retval); -#if defined OPENPIC_SWAP
-    retval =3D tswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+    retval =3D openpic_swap32(opp, retval);
 #endif

    return retval;
@@ -776,8 +815,8 @@ static void openpic_cpu_write (void *opaque, uint32_t a= ddr, uint32_t val)
    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
    if (addr & 0xF)
        return;
-#if defined OPENPIC_SWAP
-    val =3D bswap32(val);
+#if defined TARGET_WORDS_BIGENDIAN
+    val =3D openpic_swap32(opp, val);
 #endif
    addr &=3D 0x1FFF0;
    idx =3D addr / 0x1000;
@@ -790,9 +829,9 @@ static void openpic_cpu_write (void *opaque, uint32_t a= ddr, uint32_t val)
    case 0x60:
    case 0x70:
        idx =3D (addr - 0x40) >> 4;
-        write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val= );
-        openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
-        openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
+        write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_= IDE, val);
+        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1= );
+        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0= );
        break;
 #endif
    case 0x80: /* PCTP */
@@ -819,7 +858,7 @@ static void openpic_cpu_write (void *opaque, uint32_t a= ddr, uint32_t val)
             IPVP_PRIORITY(src->ipvp= ) > dst->servicing.priority)) {
            DPRINTF("Raise OpenPIC INT = output cpu %d irq %d\n",
                    idx,= n_IRQ);
-            qemu_irq_raise(dst->irqs[OPEN= PIC_OUTPUT_INT]);
+            opp->irq_raise(opp, idx, src)= ;
        }
       break;
    default:
@@ -889,15 +928,15 @@ static uint32_t openpic_cpu_read (void *opaque, uint3= 2_t addr)
    case 0x40: /* IDE */
    case 0x50:
        idx =3D (addr - 0x40) >> 4;
-        retval =3D read_IRQreg(opp, IRQ_IPI0 + idx, IR= Q_IDE);
+        retval =3D read_IRQreg(opp, opp->irq_ipi0 += idx, IRQ_IDE);
        break;
 #endif
    default:
        break;
    }
    DPRINTF("%s: =3D> %08x\n", __func__, retval); -#if defined OPENPIC_SWAP
-    retval=3D bswap32(retval);
+#if defined TARGET_WORDS_BIGENDIAN
+    retval =3D openpic_swap32(opp, retval);
 #endif

    return retval;
@@ -989,7 +1028,7 @@ static void openpic_map(PCIDevice *pci_dev, int region= _num,
            addr + 0x1100, addr + 0x1100 + 0= x40 * MAX_TMR);
    /* Interrupt source registers */
    DPRINTF("Register OPENPIC src   %08x =3D> %08x\= n",
-            addr + 0x10000, addr + 0x10000 += 0x20 * (EXT_IRQ + 2));
+            addr + 0x10000, addr + 0x10000 += 0x20 * (OPENPIC_EXT_IRQ + 2));
    /* Per CPU registers */
    DPRINTF("Register OPENPIC dst   %08x =3D> %08x\= n",
            addr + 0x20000, addr + 0x20000 += 0x1000 * MAX_CPU);
@@ -1026,7 +1065,7 @@ static void openpic_save(QEMUFile* f, void *opaque)     qemu_put_be32s(f, &opp->spve);
    qemu_put_be32s(f, &opp->tifr);

-    for (i =3D 0; i < MAX_IRQ; i++) {
+    for (i =3D 0; i < opp->max_irq; i++) {
        qemu_put_be32s(f, &opp->src[i].ipvp);         qemu_put_be32s(f, &opp->src[i].ide);         qemu_put_sbe32s(f, &opp->src[i].type);<= br> @@ -1034,15 +1073,16 @@ static void openpic_save(QEMUFile* f, void *opaque)=
        qemu_put_sbe32s(f, &opp->src[i].pending= );
    }

-    for (i =3D 0; i < MAX_IRQ; i++) {
+    qemu_put_sbe32s(f, &opp->nb_cpus);
+
+    for (i =3D 0; i < opp->nb_cpus; i++) {
+        qemu_put_be32s(f, &opp->dst[i].tfrr);         qemu_put_be32s(f, &opp->dst[i].pctp);         qemu_put_be32s(f, &opp->dst[i].pcsr);         openpic_save_IRQ_queue(f, &opp->dst[i].= raised);
        openpic_save_IRQ_queue(f, &opp->dst[i].= servicing);
    }

-    qemu_put_sbe32s(f, &opp->nb_cpus);
-
    for (i =3D 0; i < MAX_TMR; i++) {
        qemu_put_be32s(f, &opp->timers[i].ticc)= ;
        qemu_put_be32s(f, &opp->timers[i].tibc)= ;
@@ -1092,7 +1132,7 @@ static int openpic_load(QEMUFile* f, void *opaque, in= t version_id)
    qemu_get_be32s(f, &opp->spve);
    qemu_get_be32s(f, &opp->tifr);

-    for (i =3D 0; i < MAX_IRQ; i++) {
+    for (i =3D 0; i < opp->max_irq; i++) {
        qemu_get_be32s(f, &opp->src[i].ipvp);         qemu_get_be32s(f, &opp->src[i].ide);         qemu_get_sbe32s(f, &opp->src[i].type);<= br> @@ -1100,15 +1140,16 @@ static int openpic_load(QEMUFile* f, void *opaque, = int version_id)
        qemu_get_sbe32s(f, &opp->src[i].pending= );
    }

-    for (i =3D 0; i < MAX_IRQ; i++) {
+    qemu_get_sbe32s(f, &opp->nb_cpus);
+
+    for (i =3D 0; i < opp->nb_cpus; i++) {
+        qemu_get_be32s(f, &opp->dst[i].tfrr);         qemu_get_be32s(f, &opp->dst[i].pctp);         qemu_get_be32s(f, &opp->dst[i].pcsr);         openpic_load_IRQ_queue(f, &opp->dst[i].= raised);
        openpic_load_IRQ_queue(f, &opp->dst[i].= servicing);
    }

-    qemu_get_sbe32s(f, &opp->nb_cpus);
-
    for (i =3D 0; i < MAX_TMR; i++) {
        qemu_get_be32s(f, &opp->timers[i].ticc)= ;
        qemu_get_be32s(f, &opp->timers[i].tibc)= ;
@@ -1131,6 +1172,11 @@ static int openpic_load(QEMUFile* f, void *opaque, i= nt version_id)
    return pci_device_load(&opp->pci_dev, f);
 }

+static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src) +{
+    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);=
+}
+
 qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,                     &nbs= p;   qemu_irq **irqs, qemu_irq irq_out)
 {
@@ -1164,33 +1210,329 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_ind= ex, int nb_cpus,

    //    isu_base &=3D 0xFFFC0000;
    opp->nb_cpus =3D nb_cpus;
+    opp->max_irq =3D OPENPIC_MAX_IRQ;
+    opp->irq_ipi0 =3D OPENPIC_IRQ_IPI0;
+    opp->irq_tim0 =3D OPENPIC_IRQ_TIM0;
    /* Set IRQ types */
-    for (i =3D 0; i < EXT_IRQ; i++) {
+    for (i =3D 0; i < OPENPIC_EXT_IRQ; i++) {
        opp->src[i].type =3D IRQ_EXTERNAL;
    }
-    for (; i < IRQ_TIM0; i++) {
+    for (; i < OPENPIC_IRQ_TIM0; i++) {
        opp->src[i].type =3D IRQ_SPECIAL;
    }
 #if MAX_IPI > 0
-    m =3D IRQ_IPI0;
+    m =3D OPENPIC_IRQ_IPI0;
 #else
-    m =3D IRQ_DBL0;
+    m =3D OPENPIC_IRQ_DBL0;
 #endif
    for (; i < m; i++) {
        opp->src[i].type =3D IRQ_TIMER;
    }
-    for (; i < MAX_IRQ; i++) {
+    for (; i < OPENPIC_MAX_IRQ; i++) {
        opp->src[i].type =3D IRQ_INTERNAL;
    }
    for (i =3D 0; i < nb_cpus; i++)
        opp->dst[i].irqs =3D irqs[i];
    opp->irq_out =3D irq_out;
+    opp->need_swap =3D 1;

    register_savevm("openpic", 0, 1, openpic_save, ope= npic_load, opp);
    qemu_register_reset(openpic_reset, opp);
-    openpic_reset(opp);
+
+    opp->irq_raise =3D openpic_irq_raise;
+    opp->reset =3D openpic_reset;
+
+    opp->reset(opp);
    if (pmem_index)
        *pmem_index =3D opp->mem_index;

-    return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ); +    return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_= irq);
+}
+
+static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
+{
+    int n_ci =3D IDR_CI0 - n_CPU;
+    DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n&quo= t;, __func__,
+                    n_CP= U, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
+    if(test_bit(&src->ide, n_ci)) {
+        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC= _OUTPUT_CINT]);
+    }
+    else {
+        qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC= _OUTPUT_INT]);
+    }
+}
+
+static void mpic_reset (void *opaque)
+{
+    openpic_t *mpp =3D (openpic_t *)opaque;
+    int i;
+
+    mpp->glbc =3D 0x80000000;
+    /* Initialise controller registers */
+    mpp->frep =3D 0x004f0002;
+    mpp->veni =3D VENI;
+    mpp->pint =3D 0x00000000;
+    mpp->spve =3D 0x0000FFFF;
+    /* Initialise IRQ sources */
+    for (i =3D 0; i < mpp->max_irq; i++) {
+        mpp->src[i].ipvp =3D 0x80800000;
+        mpp->src[i].ide  =3D 0x00000001;
+    }
+    /* Initialise IRQ destinations */
+    for (i =3D 0; i < MAX_CPU; i++) {
+        mpp->dst[i].pctp      =3D 0x= 0000000F;
+        mpp->dst[i].tfrr      =3D 0x= 00000000;
+        memset(&mpp->dst[i].raised, 0, sizeof(I= RQ_queue_t));
+        mpp->dst[i].raised.next =3D -1;
+        memset(&mpp->dst[i].servicing, 0, sizeo= f(IRQ_queue_t));
+        mpp->dst[i].servicing.next =3D -1;
+    }
+    /* Initialise timers */
+    for (i =3D 0; i < MAX_TMR; i++) {
+        mpp->timers[i].ticc =3D 0x00000000;
+        mpp->timers[i].tibc =3D 0x80000000;
+    }
+    /* Go out of RESET state */
+    mpp->glbc =3D 0x00000000;
+}
+
+static void mpic_timer_write (void *opaque, uint32_t addr, uint32_t val) +{
+    openpic_t *mpp =3D opaque;
+    int idx, cpu;
+
+    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
+    if (addr & 0xF)
+        return;
+    addr &=3D 0xFFFF;
+    cpu =3D addr >> 12;
+    idx =3D (addr >> 6) & 0x3;
+    switch (addr & 0x30) {
+    case 0x00: /* gtccr */
+        break;
+    case 0x10: /* gtbcr */
+        if ((mpp->timers[idx].ticc & 0x80000000= ) !=3D 0 &&
+            (val & 0x80000000) =3D=3D 0 = &&
+            (mpp->timers[idx].tibc & = 0x80000000) !=3D 0)
+            mpp->timers[idx].ticc &= =3D ~0x80000000;
+        mpp->timers[idx].tibc =3D val;
+        break;
+    case 0x20: /* GTIVPR */
+        write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP= , val);
+        break;
+    case 0x30: /* GTIDR & TFRR */
+        if ((addr & 0xF0) =3D=3D 0xF0)
+            mpp->dst[cpu].tfrr =3D val; +        else
+            write_IRQreg(mpp, MPIC_TMR_IRQ += idx, IRQ_IDE, val);
+        break;
+    }
+}
+
+static uint32_t mpic_timer_read (void *opaque, uint32_t addr)
+{
+    openpic_t *mpp =3D opaque;
+    uint32_t retval;
+    int idx, cpu;
+
+    DPRINTF("%s: addr %08x\n", __func__, addr);
+    retval =3D 0xFFFFFFFF;
+    if (addr & 0xF)
+        return retval;
+    addr &=3D 0xFFFF;
+    cpu =3D addr >> 12;
+    idx =3D (addr >> 6) & 0x3;
+    switch (addr & 0x30) {
+    case 0x00: /* gtccr */
+        retval =3D mpp->timers[idx].ticc;
+        break;
+    case 0x10: /* gtbcr */
+        retval =3D mpp->timers[idx].tibc;
+        break;
+    case 0x20: /* TIPV */
+        retval =3D read_IRQreg(mpp, MPIC_TMR_IRQ + idx= , IRQ_IPVP);
+        break;
+    case 0x30: /* TIDR */
+        if ((addr &0xF0) =3D=3D 0XF0)
+            retval =3D mpp->dst[cpu].tfrr= ;
+        else
+            retval =3D read_IRQreg(mpp, MPIC= _TMR_IRQ + idx, IRQ_IDE);
+        break;
+    }
+    DPRINTF("%s: =3D> %08x\n", __func__, retval); +
+    return retval;
+}
+
+static void mpic_src_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    openpic_t *mpp =3D opaque;
+    int idx;
+
+    DPRINTF("%s: addr %08x <=3D %08x\n", __func__, = addr, val);
+    if (addr & 0xF)
+        return;
+    addr =3D addr & 0xFFF0;
+    if (addr < 0x180) {
+        idx =3D MPIC_EXT_IRQ;
+    } else if (addr >=3D 0x200 && addr < 0xa00) {<= br> +        idx =3D MPIC_INT_IRQ;
+        addr -=3D 0x200;
+    } else if (addr >=3D 0x1600 && addr < 0x1700) = {
+        idx =3D MPIC_MSG_IRQ;
+        addr -=3D 0x1600;
+    } else if (addr >=3D 0x1C00 && addr < 0x1D00) = {
+        idx =3D MPIC_MSI_IRQ;
+        addr -=3D 0x1C00;
+    } else {
+        return;
+    }
+    idx +=3D addr >> 5;
+    if (addr & 0x10) {
+        /* EXDE / IFEDE / IEEDE */
+        write_IRQreg(mpp, idx, IRQ_IDE, val);
+    } else {
+        /* EXVP / IFEVP / IEEVP */
+        write_IRQreg(mpp, idx, IRQ_IPVP, val);
+    }
+}
+
+static uint32_t mpic_src_read (void *opaque, uint32_t addr)
+{
+    openpic_t *mpp =3D opaque;
+    uint32_t retval;
+    int idx;
+
+    DPRINTF("%s: addr %08x\n", __func__, addr);
+    retval =3D 0xFFFFFFFF;
+    if (addr & 0xF)
+        return retval;
+    addr =3D addr & 0xFFF0;
+    if (addr < 0x180) {
+        idx =3D MPIC_EXT_IRQ;
+    } else if (addr >=3D 0x200 && addr < 0xa00) {<= br> +        idx =3D MPIC_INT_IRQ;
+        addr -=3D 0x200;
+    } else if (addr >=3D 0x1600 && addr < 0x1700) = {
+        idx =3D MPIC_MSG_IRQ;
+        addr -=3D 0x1600;
+    } else if (addr >=3D 0x1C00 && addr < 0x1D00) = {
+        idx =3D MPIC_MSI_IRQ;
+        addr -=3D 0x1C00;
+    } else {
+        return retval;
+    }
+    idx +=3D addr >> 5;
+    if (addr & 0x10) {
+        /* EXDE / IFEDE / IEEDE */
+        retval =3D read_IRQreg(mpp, idx, IRQ_IDE);
+    } else {
+        /* EXVP / IFEVP / IEEVP */
+        retval =3D read_IRQreg(mpp, idx, IRQ_IPVP); +    }
+    DPRINTF("%s: =3D> %08x\n", __func__, retval); +
+    return retval;
+}
+
+static void mpic_writel (void *opaque,
+                     &nb= sp;      target_phys_addr_t addr, uint32_t val)
+{
+    openpic_t *mpp =3D opaque;
+
+    addr &=3D 0x3FFFF;
+    DPRINTF("%s: offset %08x val: %08x\n", __func__, (= int)addr, val);
+    if (addr < 0x10F0) {
+        /* Global registers */
+        openpic_gbl_write(mpp, addr, val);
+    } else if (addr < 0x10000) {
+        /* Timers registers */
+        mpic_timer_write(mpp, addr, val);
+    } else if (addr < 0x20000) {
+        /* Source registers */
+        mpic_src_write(mpp, addr, val);
+    } else if (addr < 0x30000){
+        /* CPU registers */
+        openpic_cpu_write(mpp, addr, val);
+    } else {
+        DPRINTF("wrong mpic write addr %p\n"= ,addr);
+    }
+}
+
+static uint32_t mpic_readl (void *opaque,target_phys_addr_t addr)
+{
+    openpic_t *mpp =3D opaque;
+    uint32_t retval =3D 0;
+
+    addr &=3D 0x3FFFF;
+    DPRINTF("%s: offset %08x\n", __func__, (int)addr);=
+    if (addr < 0x10F0) {
+        /* Global registers */
+        retval =3D openpic_gbl_read(mpp, addr);
+    } else if (addr < 0x10000) {
+        /* Timers registers */
+        retval =3D mpic_timer_read(mpp, addr);
+    } else if (addr < 0x20000) {
+        /* Source registers */
+        retval =3D mpic_src_read(mpp, addr);
+    } else if (addr < 0x30000){
+        /* CPU registers */
+        retval =3D openpic_cpu_read(mpp, addr);
+    } else {
+        DPRINTF("wrong mpic read addr %p\n",= addr);
+    }
+
+    return retval;
+}
+
+static CPUWriteMemoryFunc *mpic_write[] =3D {
+    &openpic_buggy_write,
+    &openpic_buggy_write,
+    &mpic_writel,
+};
+
+static CPUReadMemoryFunc *mpic_read[] =3D {
+    &openpic_buggy_read,
+    &openpic_buggy_read,
+    &mpic_readl,
+};
+
+qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
+                     &nb= sp;  qemu_irq **irqs, qemu_irq irq_out)
+{
+    openpic_t *mpp;
+    int i;
+
+    /* XXX: for now, only one CPU is supported */
+    if (nb_cpus !=3D 1)
+        return NULL;
+
+    mpp =3D qemu_mallocz(sizeof(openpic_t));
+
+    mpp->mem_index =3D cpu_register_io_memory(0, mpic_read, m= pic_write, mpp);
+    if (mpp->mem_index < 0)
+        goto free;
+    cpu_register_physical_memory(base, MPIC_MAP_SIZE, mpp->me= m_index);
+
+    mpp->nb_cpus =3D nb_cpus;
+    mpp->max_irq =3D MPIC_MAX_IRQ;
+    mpp->irq_ipi0 =3D MPIC_IPI_IRQ;
+    mpp->irq_tim0 =3D MPIC_TMR_IRQ;
+
+    for (i =3D 0; i < nb_cpus; i++)
+        mpp->dst[i].irqs =3D irqs[i];
+    mpp->irq_out =3D irq_out;
+    mpp->need_swap =3D 0;    /* MPIC has the same e= ndian as target */
+
+    mpp->irq_raise =3D mpic_irq_raise;
+    mpp->reset =3D mpic_reset;
+
+    register_savevm("mpic", 0, 1, openpic_save, openpi= c_load,  mpp);
+    mpp->reset(mpp);
+
+    return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_= irq);
+
+free:
+    qemu_free(mpp);
+    return NULL;
 }
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 5851a5e..df148b2 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -112,17 +112,4 @@ void adb_mouse_init(ADBBusState *bus);

 extern ADBBusState adb_bus;

-/* openpic.c */
-/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output = */
-enum {
-    OPENPIC_OUTPUT_INT =3D 0, /* IRQ        =               */
-    OPENPIC_OUTPUT_CINT,    /* critical IRQ   &nb= sp;          */
-    OPENPIC_OUTPUT_MCK,     /* Machine check event &nb= sp;     */
-    OPENPIC_OUTPUT_DEBUG,   /* Inconditional debug event */=
-    OPENPIC_OUTPUT_RESET,   /* Core reset event   &nbs= p;      */
-    OPENPIC_OUTPUT_NB,
-};
-qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
-                     &nb= sp;  qemu_irq **irqs, qemu_irq irq_out);
-
 #endif /* !defined(__PPC_MAC_H__) */
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 6f60e49..b285864 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -34,6 +34,7 @@
 #include "boards.h"
 #include "fw_cfg.h"
 #include "escc.h"
+#include "openpic.h"

 #define MAX_IDE_BUS 2
 #define VGA_BIOS_SIZE 65536
--
1.5.4




--000e0cd4043405e4a704634da0e7--