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 > > > >