qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paulev <paulev@gmail.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform.
Date: Thu, 19 Feb 2009 17:09:15 -0600	[thread overview]
Message-ID: <f94f89aa0902191509v4ec53a38w2c3ad916aa0402e0@mail.gmail.com> (raw)
In-Reply-To: <1234864778-19099-2-git-send-email-yu.liu@freescale.com>

[-- Attachment #1: Type: text/plain, Size: 27159 bytes --]

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
> raise.
>
> Haven't test OpenPIC.
>
> Signed-off-by: Liu Yu <yu.liu@freescale.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)     /* 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
>
>
>
>

[-- Attachment #2: Type: text/html, Size: 40006 bytes --]

  parent reply	other threads:[~2009-02-19 23:09 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-17  9:59 [Qemu-devel] powerpc/kvm: Add MPC8544DS board support Liu Yu
2009-02-17  9:59 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu
2009-02-17  9:59   ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Liu Yu
2009-02-17  9:59     ` [Qemu-devel] [PATCH 3/5] kvm/powerpc: Add irq support for E500 core Liu Yu
2009-02-17  9:59       ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Liu Yu
2009-02-17  9:59         ` [Qemu-devel] [PATCH 5/5] kvm/powerpc: flat device tree files for MPC8544DS Liu Yu
2009-02-17 15:28         ` [Qemu-devel] [PATCH 4/5] kvm/powerpc: Add MPC8544DS board support Blue Swirl
2009-02-18  7:01           ` Liu Yu-B13201
2009-02-17 15:09     ` [Qemu-devel] [PATCH 2/5] kvm/powerpc: Add freescale pci controller's support Blue Swirl
2009-02-17 16:08       ` M. Warner Losh
2009-02-17 16:23         ` M. Warner Losh
2009-02-17 17:41           ` Jamie Lokier
2009-02-18  6:04       ` Liu Yu-B13201
2009-02-17 14:55   ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Blue Swirl
2009-02-18  7:17     ` Liu Yu-B13201
2009-02-19 22:41     ` Aurelien Jarno
2009-02-20 17:20       ` Blue Swirl
2009-02-19 23:09   ` Paulev [this message]
  -- strict thread matches above, loose matches on Subject: below --
2009-02-26 10:35 [Qemu-devel] [PATCH v4 0/5] powerpc/kvm: Add MPC8544DS board support Liu Yu
2009-02-26 10:35 ` [Qemu-devel] [PATCH 1/5] kvm/powerpc: Enable MPIC for E500 platform Liu Yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f94f89aa0902191509v4ec53a38w2c3ad916aa0402e0@mail.gmail.com \
    --to=paulev@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).