On Mon, Sep 10, 2012 at 12:20 AM, <crwu...@gmail.com> wrote: > From: Chris Wulff <crwu...@gmail.com> > > Signed-off-by: Chris Wulff <crwu...@gmail.com> > --- > hw/Makefile.objs | 5 ++ > hw/altera.h | 34 ++++++++ > hw/altera_timer.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++ > hw/altera_uart.c | 218 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/altera_vic.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ > hw/nios2.h | 46 +++++++++++ > hw/nios2_pic_cpu.c | 48 ++++++++++++ > 7 files changed, 744 insertions(+) > create mode 100644 hw/altera.h > create mode 100644 hw/altera_timer.c > create mode 100644 hw/altera_uart.c > create mode 100644 hw/altera_vic.c > create mode 100644 hw/nios2.h > create mode 100644 hw/nios2_pic_cpu.c > > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index 6dfebd2..59dd2d5 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -67,6 +67,11 @@ hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o > hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o > hw-obj-$(CONFIG_XILINX_AXI) += stream.o > > +# Altera devices > +hw-obj-$(CONFIG_ALTERA) += altera_vic.o > +hw-obj-$(CONFIG_ALTERA) += altera_uart.o > +hw-obj-$(CONFIG_ALTERA) += altera_timer.o > + > # PKUnity SoC devices > hw-obj-$(CONFIG_PUV3) += puv3_intc.o > hw-obj-$(CONFIG_PUV3) += puv3_ost.o > diff --git a/hw/altera.h b/hw/altera.h > new file mode 100644 > index 0000000..b25366e > --- /dev/null > +++ b/hw/altera.h > @@ -0,0 +1,34 @@ > +/* > + * Altera Nios II device instantiation header. > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + > +/* timer */ > +static inline DeviceState *altera_timer_create(target_phys_addr_t base, > + qemu_irq irq, int freq) > +{ > + DeviceState *dev; > + > + dev = qdev_create(NULL, "altera,timer"); > + qdev_prop_set_uint32(dev, "frequency", freq); > + qdev_init_nofail(dev); > + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); > + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); > + return dev; > +} > + > diff --git a/hw/altera_timer.c b/hw/altera_timer.c > new file mode 100644 > index 0000000..e490da5 > --- /dev/null > +++ b/hw/altera_timer.c > @@ -0,0 +1,198 @@ > +/* > + * QEMU model of the Altera timer. > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + > +#include "sysbus.h" > +#include "sysemu.h" > +#include "ptimer.h" > + > +#define R_STATUS 0 > +#define R_CONTROL 1 > +#define R_PERIODL 2 > +#define R_PERIODH 3 > +#define R_SNAPL 4 > +#define R_SNAPH 5 > +#define R_MAX 6 > + > +#define STATUS_TO 0x0001 > +#define STATUS_RUN 0x0002 > + > +#define CONTROL_ITO 0x0001 > +#define CONTROL_CONT 0x0002 > +#define CONTROL_START 0x0004 > +#define CONTROL_STOP 0x0008 > + > +struct altera_timer {
CamelCase > + SysBusDevice busdev; > + MemoryRegion mmio; > + qemu_irq irq; > + uint32_t freq_hz; > + QEMUBH *bh; > + ptimer_state *ptimer; > + uint32_t regs[R_MAX]; > +}; > + > +static uint64_t timer_read(void *opaque, target_phys_addr_t addr, > + unsigned int size) > +{ > + struct altera_timer *t = opaque; > + uint32_t r = 0; uint32_t does not match uint64_t for function return value. > + > + addr >>= 2; > + addr &= 0x7; > + switch (addr) { > + case R_STATUS: > + r = t->regs[R_STATUS]; > + break; > + > + default: > + if (addr < ARRAY_SIZE(t->regs)) { > + r = t->regs[addr]; > + } > + break; > + } > + > + qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & > CONTROL_ITO); It would be better to set the IRQ only if the state has changed. > + > + return r; > +} > + > +static void timer_start(struct altera_timer *t) > +{ > + ptimer_stop(t->ptimer); > + ptimer_set_count(t->ptimer, (t->regs[R_PERIODH]<<16) | > t->regs[R_PERIODL]); > + ptimer_run(t->ptimer, 1); > +} > + > +static void timer_write(void *opaque, target_phys_addr_t addr, > + uint64_t val64, unsigned int size) > +{ > + struct altera_timer *t = opaque; > + uint32_t value = val64; > + uint32_t count = 0; > + > + addr >>= 2; > + addr &= 0x7; > + switch (addr) { > + case R_STATUS: > + /* Writing zero clears the timeout */ > + t->regs[R_STATUS] &= ~STATUS_TO; > + break; > + > + case R_CONTROL: > + t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT); > + if ((value & CONTROL_START) && > + ((t->regs[R_STATUS] & STATUS_RUN) == 0)) { > + timer_start(t); > + } > + if ((value & CONTROL_STOP) && (t->regs[R_STATUS] & STATUS_RUN)) { > + ptimer_stop(t->ptimer); > + } > + break; > + > + case R_PERIODL: > + case R_PERIODH: > + t->regs[addr] = value & 0xFFFF; > + if (t->regs[R_STATUS] & STATUS_RUN) { > + timer_start(t); > + } > + break; > + > + case R_SNAPL: > + case R_SNAPH: > + count = ptimer_get_count(t->ptimer); > + t->regs[R_SNAPL] = count & 0xFFFF; > + t->regs[R_SNAPH] = (count>>16) & 0xFFFF; > + break; > + > + default: > + if (addr < ARRAY_SIZE(t->regs)) { > + t->regs[addr] = value; > + } > + break; > + } > + > + qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & > CONTROL_ITO); > +} > + > +static const MemoryRegionOps timer_ops = { > + .read = timer_read, > + .write = timer_write, > + .endianness = DEVICE_NATIVE_ENDIAN, Native endian cases should be rare, you should fix it to LE or BE. > + .valid = { > + .min_access_size = 1, > + .max_access_size = 4 > + } > +}; > + > +static void timer_hit(void *opaque) > +{ > + struct altera_timer *t = opaque; > + t->regs[R_STATUS] |= STATUS_TO; > + > + if (t->regs[R_CONTROL] & CONTROL_CONT) { > + timer_start(t); > + } > + qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & > CONTROL_ITO); > +} > + > +static int altera_timer_init(SysBusDevice *dev) > +{ > + struct altera_timer *t = FROM_SYSBUS(typeof(*t), dev); > + > + sysbus_init_irq(dev, &t->irq); > + > + t->bh = qemu_bh_new(timer_hit, t); > + t->ptimer = ptimer_init(t->bh); > + ptimer_set_freq(t->ptimer, t->freq_hz); > + > + memory_region_init_io(&t->mmio, &timer_ops, t, "altera,timer", > + R_MAX * sizeof(uint32_t)); > + sysbus_init_mmio(dev, &t->mmio); > + return 0; > +} > + > +static Property altera_timer_properties[] = { > + DEFINE_PROP_UINT32("frequency", struct altera_timer, freq_hz, 0), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void altera_timer_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); > + > + k->init = altera_timer_init; > + dc->props = altera_timer_properties; > +} > + > +static TypeInfo altera_timer_info = { const > + .name = "altera,timer", > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(struct altera_timer), > + .class_init = altera_timer_class_init, > +}; > + > +static void altera_timer_register(void) > +{ > + type_register_static(&altera_timer_info); > +} > + > +type_init(altera_timer_register) > + newline > diff --git a/hw/altera_uart.c b/hw/altera_uart.c > new file mode 100644 > index 0000000..e32651e > --- /dev/null > +++ b/hw/altera_uart.c > @@ -0,0 +1,218 @@ > +/* > + * QEMU model of the Altera uart. > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + > +#include "sysbus.h" > +#include "qemu-char.h" > + > +#define R_RXDATA 0 > +#define R_TXDATA 1 > +#define R_STATUS 2 > +#define R_CONTROL 3 > +#define R_DIVISOR 4 > +#define R_ENDOFPACKET 5 > +#define R_MAX 6 > + > +#define STATUS_PE 0x0001 > +#define STATUS_FE 0x0002 > +#define STATUS_BRK 0x0004 > +#define STATUS_ROE 0x0008 > +#define STATUS_TOE 0x0010 > +#define STATUS_TMT 0x0020 > +#define STATUS_TRDY 0x0040 > +#define STATUS_RRDY 0x0080 > +#define STATUS_E 0x0100 > +#define STATUS_DTCS 0x0400 > +#define STATUS_CTS 0x0800 > +#define STATUS_EOP 0x1000 > + > +#define CONTROL_IPE 0x0001 > +#define CONTROL_IFE 0x0002 > +#define CONTROL_IBRK 0x0004 > +#define CONTROL_IROE 0x0008 > +#define CONTROL_ITOE 0x0010 > +#define CONTROL_ITMT 0x0020 > +#define CONTROL_ITRDY 0x0040 > +#define CONTROL_IRRDY 0x0080 > +#define CONTROL_IE 0x0100 > +#define CONTROL_TBRK 0x0200 > +#define CONTROL_IDTCS 0x0400 > +#define CONTROL_RTS 0x0800 > +#define CONTROL_IEOP 0x1000 > + > +struct altera_uart { > + SysBusDevice busdev; > + MemoryRegion mmio; > + CharDriverState *chr; > + qemu_irq irq; > + > + uint32_t regs[R_MAX]; > +}; > + > +static void uart_update_irq(struct altera_uart *s) > +{ > + unsigned int irq; > + > + irq = (s->regs[R_STATUS] & s->regs[R_CONTROL] & > + (STATUS_PE | STATUS_FE | STATUS_BRK | STATUS_ROE | STATUS_TOE | > + STATUS_TMT | STATUS_TRDY | STATUS_RRDY | STATUS_E | STATUS_DTCS)); > + irq = (irq == 0) ? 0 : 1; > + qemu_set_irq(s->irq, irq); > +} > + > +static uint64_t uart_read(void *opaque, target_phys_addr_t addr, > + unsigned int size) > +{ > + struct altera_uart *s = opaque; > + uint32_t r = 0; > + addr >>= 2; > + addr &= 0x7; > + switch (addr) { > + case R_RXDATA: > + r = s->regs[R_RXDATA]; > + s->regs[R_STATUS] &= ~STATUS_RRDY; > + uart_update_irq(s); > + break; > + > + case R_STATUS: > + r = s->regs[R_STATUS]; > + s->regs[R_STATUS] &= ~(STATUS_PE | STATUS_FE | STATUS_BRK | > + STATUS_ROE | STATUS_TOE | STATUS_E | > + STATUS_DTCS); > + uart_update_irq(s); > + break; > + > + default: > + if (addr < ARRAY_SIZE(s->regs)) { > + r = s->regs[addr]; > + } > + break; > + } > + > + return r; > +} > + > +static void uart_write(void *opaque, target_phys_addr_t addr, > + uint64_t val64, unsigned int size) > +{ > + struct altera_uart *s = opaque; > + uint32_t value = val64; > + unsigned char ch = value; > + > + addr >>= 2; > + addr &= 0x7; > + > + switch (addr) { > + case R_TXDATA: > + if (s->chr) { > + qemu_chr_fe_write(s->chr, &ch, 1); > + } > + > + s->regs[addr] = value; > + break; > + > + case R_RXDATA: > + case R_STATUS: > + /* No writeable bits */ > + break; > + > + default: > + s->regs[addr] = value; > + break; > + } > + uart_update_irq(s); > +} > + > +static void uart_rx(void *opaque, const uint8_t *buf, int size) > +{ > + struct altera_uart *s = opaque; > + > + s->regs[R_RXDATA] = *buf; > + s->regs[R_STATUS] |= STATUS_RRDY; > + > + uart_update_irq(s); > +} > + > +static int uart_can_rx(void *opaque) > +{ > + struct altera_uart *s = opaque; > + return ((s->regs[R_STATUS] & STATUS_RRDY) == 0); > +} > + > +static void uart_event(void *opaque, int event) > +{ > +} > + > +static const MemoryRegionOps uart_ops = { > + .read = uart_read, > + .write = uart_write, > + .endianness = DEVICE_NATIVE_ENDIAN, > + .valid = { > + .min_access_size = 1, > + .max_access_size = 4 > + } > +}; > + > +static int altera_uart_init(SysBusDevice *dev) > +{ > + struct altera_uart *s = FROM_SYSBUS(typeof(*s), dev); > + > + s->regs[R_STATUS] = STATUS_TMT | STATUS_TRDY; /* Always ready to tx */ > + > + sysbus_init_irq(dev, &s->irq); > + > + memory_region_init_io(&s->mmio, &uart_ops, s, > + "altera,uart", R_MAX * sizeof(uint32_t)); > + sysbus_init_mmio(dev, &s->mmio); > + > + s->chr = qemu_char_get_next_serial(); > + if (s->chr) { > + qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s); > + } > + > + return 0; > +} > + > +static Property altera_uart_properties[] = { > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void altera_uart_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); > + > + k->init = altera_uart_init; > + dc->props = altera_uart_properties; > +} > + > +static TypeInfo altera_uart_info = { > + .name = "altera,uart", > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(struct altera_uart), > + .class_init = altera_uart_class_init, > +}; > + > +static void altera_uart_register(void) > +{ > + type_register_static(&altera_uart_info); > +} > + > +type_init(altera_uart_register) > + > diff --git a/hw/altera_vic.c b/hw/altera_vic.c > new file mode 100644 > index 0000000..43a2b68 > --- /dev/null > +++ b/hw/altera_vic.c > @@ -0,0 +1,195 @@ > +/* > + * QEMU Altera Vectored Interrupt Controller. > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + > +#include "sysbus.h" > +#include "hw.h" > + > +#define R_INT_CONFIG_0 0 > +#define R_INT_ENABLE 32 > +#define R_INT_ENABLE_SET 33 > +#define R_INT_ENABLE_CLR 34 > +#define R_INT_PENDING 35 > +#define R_INT_RAW_STATUS 36 > +#define R_SW_INTERRUPT 37 > +#define R_SW_INTERRUPT_SET 38 > +#define R_SW_INTERRUPT_CLR 39 > +#define R_VIC_CONFIG 40 > +#define R_VIC_STATUS 41 > +#define R_VEC_TBL_BASE 42 > +#define R_VEC_TBL_ADDR 43 > +#define R_MAX 44 > + > +struct altera_vic { > + SysBusDevice busdev; > + MemoryRegion mmio; > + qemu_irq parent_irq; > + > + /* Runtime control registers. */ > + uint32_t regs[R_MAX]; > +}; > + > +static void update_irq(struct altera_vic *pv) > +{ > + uint32_t i; > + pv->regs[R_INT_PENDING] = (pv->regs[R_INT_RAW_STATUS] | > + pv->regs[R_SW_INTERRUPT]) & > + pv->regs[R_INT_ENABLE]; > + > + for (i = 0; i < 32; i++) { > + if (pv->regs[R_INT_PENDING] & (1 << i)) { > + break; > + } > + } > + if (i == 32) { > + pv->regs[R_VEC_TBL_ADDR] = 0; > + pv->regs[R_VIC_STATUS] = 0; > + qemu_irq_lower(pv->parent_irq); > + } else { > + pv->regs[R_VEC_TBL_ADDR] = pv->regs[R_VEC_TBL_BASE] + > + i*(4 << (pv->regs[R_VIC_CONFIG] & 7)); Spaces around '*'. > + pv->regs[R_VIC_STATUS] = 0x80000000 | i; > + qemu_irq_raise(pv->parent_irq); > + } > +} > + > +static uint64_t pic_read(void *opaque, target_phys_addr_t addr, > + unsigned int size) > +{ > + struct altera_vic *pv = opaque; > + uint32_t r = 0; > + > + addr >>= 2; > + if (addr < R_MAX) { > + r = pv->regs[addr]; > + } > + > + return r; > +} > + > +static void pic_write(void *opaque, target_phys_addr_t addr, > + uint64_t val64, unsigned int size) > +{ > + struct altera_vic *pv = opaque; > + uint32_t value = val64; > + > + addr >>= 2; > + if (addr < R_INT_ENABLE) { > + /* R_INT_CONFIG_XX */ > + pv->regs[addr] = value & 0x00001FFF; > + } else { > + switch (addr) { > + case R_INT_PENDING: > + case R_INT_RAW_STATUS: > + case R_VIC_STATUS: > + case R_VEC_TBL_ADDR: > + /* read only */ > + break; > + > + case R_INT_ENABLE_SET: > + pv->regs[R_INT_ENABLE] |= value; > + break; > + > + case R_SW_INTERRUPT_SET: > + pv->regs[R_SW_INTERRUPT] |= value; > + break; > + > + case R_INT_ENABLE_CLR: > + pv->regs[R_INT_ENABLE] &= ~value; > + break; > + > + case R_SW_INTERRUPT_CLR: > + pv->regs[R_SW_INTERRUPT] &= ~value; > + break; > + > + case R_VIC_CONFIG: > + pv->regs[addr] = value & 0x0000000F; > + break; > + > + default: > + if (addr < ARRAY_SIZE(pv->regs)) { > + pv->regs[addr] = value; > + } > + break; > + } > + } > + update_irq(pv); > +} > + > +static const MemoryRegionOps pic_ops = { > + .read = pic_read, > + .write = pic_write, > + .endianness = DEVICE_NATIVE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 4 > + } > +}; > + > +static void irq_handler(void *opaque, int irq, int level) > +{ > + struct altera_vic *pv = opaque; > + > + pv->regs[R_INT_RAW_STATUS] &= ~(1 << irq); > + pv->regs[R_INT_RAW_STATUS] |= level << irq; > + > + update_irq(pv); > +} > + > +static int altera_vic_init(SysBusDevice *dev) > +{ > + struct altera_vic *pv = FROM_SYSBUS(typeof(*pv), dev); > + > + qdev_init_gpio_in(&dev->qdev, irq_handler, 32); > + sysbus_init_irq(dev, &pv->parent_irq); > + > + memset(pv->regs, 0, sizeof(uint32_t) * R_MAX); > + memory_region_init_io(&pv->mmio, &pic_ops, pv, > + "altera,vic", R_MAX * sizeof(uint32_t)); > + sysbus_init_mmio(dev, &pv->mmio); > + return 0; > +} > + > +static Property altera_vic_properties[] = { > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void altera_vic_class_init(ObjectClass *klass, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(klass); > + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); > + > + k->init = altera_vic_init; > + dc->props = altera_vic_properties; > +} > + > +static TypeInfo altera_vic_info = { > + .name = "altera,vic", > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(struct altera_vic), > + .class_init = altera_vic_class_init, > +}; > + > +static void altera_vic_register(void) > +{ > + type_register_static(&altera_vic_info); > +} > + > +type_init(altera_vic_register) > + > diff --git a/hw/nios2.h b/hw/nios2.h > new file mode 100644 > index 0000000..a4af154 > --- /dev/null > +++ b/hw/nios2.h > @@ -0,0 +1,46 @@ > +/* > + * Altera Nios II CPU interrupt controllers > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + Missing duplicate include protection #ifdeffery. > +#include "sysbus.h" > + > +qemu_irq *nios2_pic_init_cpu(CPUNios2State *env); > + > +static inline DeviceState * > +altera_vic_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr) > +{ > + DeviceState *dev; > + > + dev = qdev_create(NULL, "altera,vic"); > + qdev_init_nofail(dev); > + sysbus_mmio_map(sysbus_from_qdev(dev), 0, base); > + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); > + return dev; > +} > + > +static inline DeviceState * > +altera_iic_create(qemu_irq irq, int kind_of_intr) > +{ > + DeviceState *dev; > + > + dev = qdev_create(NULL, "altera,iic"); > + qdev_init_nofail(dev); > + sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq); > + return dev; > +} > diff --git a/hw/nios2_pic_cpu.c b/hw/nios2_pic_cpu.c > new file mode 100644 > index 0000000..c89b4ae > --- /dev/null > +++ b/hw/nios2_pic_cpu.c > @@ -0,0 +1,48 @@ > +/* > + * QEMU Altera Nios II CPU interrupt wrapper logic. > + * > + * Copyright (c) 2012 Chris Wulff <crwu...@gmail.com> > + * > + * 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.1 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/lgpl-2.1.html> > + */ > + > +#include "hw.h" > +#include "pc.h" > +#include "nios2.h" > + > +void pic_info(Monitor *mon) > +{ > +} > + > +void irq_info(Monitor *mon) > +{ > +} > + > +static void nios2_pic_cpu_handler(void *opaque, int irq, int level) > +{ > + CPUNios2State *env = (CPUNios2State *)opaque; Useless cast in C. > + int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; > + > + if (level) { > + cpu_interrupt(env, type); > + } else { > + cpu_reset_interrupt(env, type); > + } > +} > + > +qemu_irq *nios2_pic_init_cpu(CPUNios2State *env) > +{ > + return qemu_allocate_irqs(nios2_pic_cpu_handler, env, 2); > +} > -- > 1.7.9.5 > >