* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
#include "monitor/monitor.h"
#include "qemu/timer.h"
+#include "qemu/log.h"
#include "hw/isa/i8259_internal.h"
+#include "hw/intc/intc.h"
/* debug PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
+#define TYPE_I8259 "isa-i8259"
+#define PIC_CLASS(class) OBJECT_CLASS_CHECK(PICClass, (class), TYPE_I8259)
+#define PIC_GET_CLASS(obj) OBJECT_GET_CLASS(PICClass, (obj), TYPE_I8259)
+
+/**
+ * PICClass:
+ * @parent_realize: The parent's realizefn.
+ */
+typedef struct PICClass {
+ PICCommonClass parent_class;
+
+ DeviceRealize parent_realize;
+} PICClass;
+
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
#endif
#ifdef DEBUG_IRQ_LATENCY
if (level) {
- irq_time[irq_index] = qemu_get_clock_ns(vm_clock);
+ irq_time[irq_index] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
#endif
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
- (double)(qemu_get_clock_ns(vm_clock) -
- irq_time[irq]) * 1000000.0 / get_ticks_per_sec());
+ (double)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
+ irq_time[irq]) * 1000000.0 / NANOSECONDS_PER_SECOND);
#endif
DPRINTF("pic_interrupt: irq=%d\n", irq);
return intno;
pic_init_reset(s);
}
+static bool pic_get_statistics(InterruptStatsProvider *obj,
+ uint64_t **irq_counts, unsigned int *nb_irqs)
+{
+ PICCommonState *s = PIC_COMMON(obj);
+
+ if (s->master) {
+#ifdef DEBUG_IRQ_COUNT
+ *irq_counts = irq_count;
+ *nb_irqs = ARRAY_SIZE(irq_count);
+#else
+ return false;
+#endif
+ } else {
+ *irq_counts = NULL;
+ *nb_irqs = 0;
+ }
+ return true;
+}
+
+static void pic_print_info(InterruptStatsProvider *obj, Monitor *mon)
+{
+ PICCommonState *s = PIC_COMMON(obj);
+ monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
+ "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
+ s->master ? 0 : 1, s->irr, s->imr, s->isr, s->priority_add,
+ s->irq_base, s->read_reg_select, s->elcr,
+ s->special_fully_nested_mode);
+}
+
static void pic_ioport_write(void *opaque, hwaddr addr64,
uint64_t val64, unsigned size)
{
s->init4 = val & 1;
s->single_mode = val & 2;
if (val & 0x08) {
- hw_error("level sensitive irq not supported");
+ qemu_log_mask(LOG_UNIMP,
+ "i8259: level sensitive irq not supported\n");
}
} else if (val & 0x08) {
if (val & 0x04) {
ret = s->imr;
}
}
- DPRINTF("read: addr=0x%02x val=0x%02x\n", addr, ret);
+ DPRINTF("read: addr=0x%02" HWADDR_PRIx " val=0x%02x\n", addr, ret);
return ret;
}
},
};
-static void pic_init(PICCommonState *s)
+static void pic_realize(DeviceState *dev, Error **errp)
{
- DeviceState *dev = DEVICE(s);
+ PICCommonState *s = PIC_COMMON(dev);
+ PICClass *pc = PIC_GET_CLASS(dev);
- memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
- memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
+ memory_region_init_io(&s->base_io, OBJECT(s), &pic_base_ioport_ops, s,
+ "pic", 2);
+ memory_region_init_io(&s->elcr_io, OBJECT(s), &pic_elcr_ioport_ops, s,
+ "elcr", 1);
qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out));
qdev_init_gpio_in(dev, pic_set_irq, 8);
-}
-
-void pic_info(Monitor *mon, const QDict *qdict)
-{
- int i;
- PICCommonState *s;
-
- if (!isa_pic) {
- return;
- }
- for (i = 0; i < 2; i++) {
- s = i == 0 ? PIC_COMMON(isa_pic) : slave_pic;
- monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
- "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
- i, s->irr, s->imr, s->isr, s->priority_add,
- s->irq_base, s->read_reg_select, s->elcr,
- s->special_fully_nested_mode);
- }
-}
-void irq_info(Monitor *mon, const QDict *qdict)
-{
-#ifndef DEBUG_IRQ_COUNT
- monitor_printf(mon, "irq statistic code not compiled.\n");
-#else
- int i;
- int64_t count;
-
- monitor_printf(mon, "IRQ statistics:\n");
- for (i = 0; i < 16; i++) {
- count = irq_count[i];
- if (count > 0) {
- monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
- }
- }
-#endif
+ pc->parent_realize(dev, errp);
}
qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq)
{
qemu_irq *irq_set;
- ISADevice *dev;
+ DeviceState *dev;
+ ISADevice *isadev;
int i;
- irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
+ irq_set = g_new0(qemu_irq, ISA_NUM_IRQS);
- dev = i8259_init_chip("isa-i8259", bus, true);
+ isadev = i8259_init_chip(TYPE_I8259, bus, true);
+ dev = DEVICE(isadev);
- qdev_connect_gpio_out(&dev->qdev, 0, parent_irq);
+ qdev_connect_gpio_out(dev, 0, parent_irq);
for (i = 0 ; i < 8; i++) {
- irq_set[i] = qdev_get_gpio_in(&dev->qdev, i);
+ irq_set[i] = qdev_get_gpio_in(dev, i);
}
- isa_pic = &dev->qdev;
+ isa_pic = dev;
- dev = i8259_init_chip("isa-i8259", bus, false);
+ isadev = i8259_init_chip(TYPE_I8259, bus, false);
+ dev = DEVICE(isadev);
- qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]);
+ qdev_connect_gpio_out(dev, 0, irq_set[2]);
for (i = 0 ; i < 8; i++) {
- irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i);
+ irq_set[i + 8] = qdev_get_gpio_in(dev, i);
}
slave_pic = PIC_COMMON(dev);
static void i8259_class_init(ObjectClass *klass, void *data)
{
- PICCommonClass *k = PIC_COMMON_CLASS(klass);
+ PICClass *k = PIC_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
- k->init = pic_init;
+ k->parent_realize = dc->realize;
+ dc->realize = pic_realize;
dc->reset = pic_reset;
+ ic->get_statistics = pic_get_statistics;
+ ic->print_info = pic_print_info;
}
static const TypeInfo i8259_info = {
- .name = "isa-i8259",
+ .name = TYPE_I8259,
.instance_size = sizeof(PICCommonState),
.parent = TYPE_PIC_COMMON,
.class_init = i8259_class_init,
+ .class_size = sizeof(PICClass),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_INTERRUPT_STATS_PROVIDER },
+ { }
+ },
};
static void pic_register_types(void)