[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 06/17] lm32: interrupt controller model
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH 06/17] lm32: interrupt controller model |
Date: |
Fri, 11 Feb 2011 23:49:59 +0200 |
On Fri, Feb 11, 2011 at 1:11 AM, Michael Walle <address@hidden> wrote:
> This patch adds the interrupt controller of the lm32. Because the PIC is
> accessed through special control registers and opcodes, there are callbacks
> from the lm32 translation code to this model.
>
> Signed-off-by: Michael Walle <address@hidden>
> ---
> hw/lm32_pic.c | 191
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/lm32_pic.h | 10 +++
> hw/lm32_pic_cpu.c | 37 ++++++++++
> trace-events | 9 +++
> 4 files changed, 247 insertions(+), 0 deletions(-)
> create mode 100644 hw/lm32_pic.c
> create mode 100644 hw/lm32_pic.h
> create mode 100644 hw/lm32_pic_cpu.c
>
> diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
> new file mode 100644
> index 0000000..dbef535
> --- /dev/null
> +++ b/hw/lm32_pic.c
> @@ -0,0 +1,191 @@
> +/*
> + * LatticeMico32 CPU interrupt controller logic.
> + *
> + * Copyright (c) 2010 Michael Walle <address@hidden>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <assert.h>
> +
> +#include "hw.h"
> +#include "pc.h"
> +#include "monitor.h"
> +#include "sysbus.h"
> +#include "trace.h"
> +#include "lm32_pic.h"
> +
> +struct LM32PicState {
> + SysBusDevice busdev;
> + qemu_irq parent_irq;
> + uint32_t im; /* interrupt mask */
> + uint32_t ip; /* interrupt pending */
> + uint32_t irq_state;
> +
> + /* statistics */
> + uint32_t stats_irq_count[32];
> +};
> +typedef struct LM32PicState LM32PicState;
> +
> +static LM32PicState *pic;
> +void pic_info(Monitor *mon)
> +{
> + if (pic == NULL) {
> + return;
> + }
> +
> + monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n",
> + pic->im, pic->ip, pic->irq_state);
> +}
> +
> +void irq_info(Monitor *mon)
> +{
> + int i;
> + uint32_t count;
> +
> + if (pic == NULL) {
> + return;
> + }
> +
> + monitor_printf(mon, "IRQ statistics:\n");
> + for (i = 0; i < 32; i++) {
> + count = pic->stats_irq_count[i];
> + if (count > 0) {
> + monitor_printf(mon, "%2d: %u\n", i, count);
> + }
> + }
> +}
> +
> +static void update_irq(LM32PicState *s)
> +{
> + s->ip |= s->irq_state;
> +
> + if (s->ip & s->im) {
> + trace_lm32_pic_raise_irq();
> + qemu_irq_raise(s->parent_irq);
> + } else {
> + trace_lm32_pic_lower_irq();
> + qemu_irq_lower(s->parent_irq);
> + }
> +}
> +
> +static void irq_handler(void *opaque, int irq, int level)
> +{
> + LM32PicState *s = opaque;
> +
> + assert(irq < 32);
> + trace_lm32_pic_interrupt(irq, level);
> +
> + if (level) {
> + s->irq_state |= (1 << irq);
> + s->stats_irq_count[irq]++;
> + } else {
> + s->irq_state &= ~(1 << irq);
> + }
> +
> + update_irq(s);
> +}
> +
> +void lm32_pic_set_im(CPUState *env, uint32_t im)
Again, this and the functions below should be reworked so that
CPUState is not passed to a device.
> +{
> + LM32PicState *s = env->pic_env;
> +
> + trace_lm32_pic_set_im(im);
> + s->im = im;
> +
> + update_irq(s);
> +}
> +
> +void lm32_pic_set_ip(CPUState *env, uint32_t ip)
> +{
> + LM32PicState *s = env->pic_env;
> +
> + trace_lm32_pic_set_ip(ip);
> +
> + /* ack interrupt */
> + s->ip &= ~ip;
> +
> + update_irq(s);
> +}
> +
> +uint32_t lm32_pic_get_im(CPUState *env)
> +{
> + LM32PicState *s = env->pic_env;
> +
> + trace_lm32_pic_get_im(s->im);
> + return s->im;
> +}
> +
> +uint32_t lm32_pic_get_ip(CPUState *env)
> +{
> + LM32PicState *s = env->pic_env;
> +
> + trace_lm32_pic_get_ip(s->ip);
> + return s->ip;
> +}
> +
> +static void pic_reset(void *opaque)
> +{
> + LM32PicState *s = opaque;
> + int i;
> +
> + s->im = 0;
> + s->ip = 0;
> + s->irq_state = 0;
> + for (i = 0; i < 32; i++) {
> + s->stats_irq_count[i] = 0;
> + }
> + qemu_irq_lower(s->parent_irq);
Remove.
> +}
> +
> +static int lm32_pic_init(SysBusDevice *dev)
> +{
> + LM32PicState *s = FROM_SYSBUS(typeof(*s), dev);
> +
> + qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
> + sysbus_init_irq(dev, &s->parent_irq);
> + qemu_register_reset(pic_reset, s);
qdev reset field
> +
> + pic = s;
> +
> + return 0;
> +}
> +
> +static const VMStateDescription vmstate_lm32_pic = {
> + .name = "lm32-pic",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .minimum_version_id_old = 1,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT32(im, LM32PicState),
> + VMSTATE_UINT32(ip, LM32PicState),
> + VMSTATE_UINT32(irq_state, LM32PicState),
> + VMSTATE_UINT32_ARRAY(stats_irq_count, LM32PicState, 32),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> +static SysBusDeviceInfo lm32_pic_info = {
> + .init = lm32_pic_init,
> + .qdev.name = "lm32-pic",
> + .qdev.size = sizeof(LM32PicState),
> + .qdev.vmsd = &vmstate_lm32_pic,
> +};
> +
> +static void lm32_pic_register(void)
> +{
> + sysbus_register_withprop(&lm32_pic_info);
> +}
> +
> +device_init(lm32_pic_register)
> diff --git a/hw/lm32_pic.h b/hw/lm32_pic.h
> new file mode 100644
> index 0000000..ce39ac7
> --- /dev/null
> +++ b/hw/lm32_pic.h
> @@ -0,0 +1,10 @@
> +#ifndef __LM32_PIC
QEMU_HW_LM32_PIC_H
> +#define __LM32_PIC
> +
> +#include "qemu-common.h"
> +
> +uint32_t lm32_pic_get_ip(CPUState *env);
> +uint32_t lm32_pic_get_im(CPUState *env);
> +void lm32_pic_set_ip(CPUState *env, uint32_t ip);
> +void lm32_pic_set_im(CPUState *env, uint32_t im);
> +#endif
> diff --git a/hw/lm32_pic_cpu.c b/hw/lm32_pic_cpu.c
> new file mode 100644
> index 0000000..8bbeccc
> --- /dev/null
> +++ b/hw/lm32_pic_cpu.c
> @@ -0,0 +1,37 @@
> +/*
> + * LatticeMico32 CPU interrupt wrapper logic.
> + *
> + * Copyright (c) 2010 Michael Walle <address@hidden>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see
> <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw.h"
> +
> +static void lm32_pic_cpu_handler(void *opaque, int irq, int level)
> +{
> + CPUState *env = (CPUState *)opaque;
Useless cast in C.
> +
> + if (level) {
> + cpu_interrupt(env, CPU_INTERRUPT_HARD);
> + } else {
> + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
> + }
> +}
> +
> +qemu_irq *lm32_pic_init_cpu(CPUState *env);
Belongs to a header.
> +qemu_irq *lm32_pic_init_cpu(CPUState *env)
> +{
> + return qemu_allocate_irqs(lm32_pic_cpu_handler, env, 1);
> +}
The whole file does not seem very useful. I'd merge this to board file instead.
> diff --git a/trace-events b/trace-events
> index e6138ea..557375e 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -254,3 +254,12 @@ disable spice_vmc_write(ssize_t out, int len) "spice
> wrottn %lu of requested %zd
> disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
> disable spice_vmc_register_interface(void *scd) "spice vmc registered
> interface %p"
> disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered
> interface %p"
> +
> +# hw/lm32_pic.c
> +disable lm32_pic_raise_irq(void) "Raise CPU interrupt"
> +disable lm32_pic_lower_irq(void) "Lower CPU interrupt"
> +disable lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d"
> +disable lm32_pic_set_im(uint32_t im) "im 0x%08x"
> +disable lm32_pic_set_ip(uint32_t ip) "ip 0x%08x"
> +disable lm32_pic_get_im(uint32_t im) "im 0x%08x"
> +disable lm32_pic_get_ip(uint32_t ip) "ip 0x%08x"
> --
> 1.7.2.3
>
>
>
- [Qemu-devel] [PATCH 07/17] lm32: juart model, (continued)
[Qemu-devel] [PATCH 06/17] lm32: interrupt controller model, Michael Walle, 2011/02/10
- Re: [Qemu-devel] [PATCH 06/17] lm32: interrupt controller model,
Blue Swirl <=
[Qemu-devel] [PATCH 13/17] lm32: EVR32 and uclinux BSP, Michael Walle, 2011/02/10
[Qemu-devel] [PATCH 12/17] lm32: support for creating device tree, Michael Walle, 2011/02/10
[Qemu-devel] [PATCH 17/17] MAINTAINERS: add LatticeMico32 maintainer, Michael Walle, 2011/02/10
[Qemu-devel] [PATCH 14/17] lm32: todo and documentation, Michael Walle, 2011/02/10