#include "hw.h"
#include "pc.h"
+#include "apic.h"
#include "qemu-timer.h"
#include "host-utils.h"
+#include "sysbus.h"
//#define DEBUG_IOAPIC
-#define IOAPIC_NUM_PINS 0x18
+#ifdef DEBUG_IOAPIC
+#define DPRINTF(fmt, ...) \
+ do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
#define IOAPIC_LVT_MASKED (1<<16)
#define IOAPIC_TRIGGER_EDGE 0
#define IOAPIC_DM_SIPI 0x5
#define IOAPIC_DM_EXTINT 0x7
+typedef struct IOAPICState IOAPICState;
+
struct IOAPICState {
+ SysBusDevice busdev;
uint8_t id;
uint8_t ioregsel;
}
}
-void ioapic_set_irq(void *opaque, int vector, int level)
+static void ioapic_set_irq(void *opaque, int vector, int level)
{
IOAPICState *s = opaque;
* to GSI 2. GSI maps to ioapic 1-1. This is not
* the cleanest way of doing it but it should work. */
+ DPRINTF("%s: %s vec %x\n", __func__, level? "raise" : "lower", vector);
if (vector == 0)
vector = 2;
}
}
-static uint32_t ioapic_mem_readl(void *opaque, a_target_phys_addr addr)
+static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
{
IOAPICState *s = opaque;
int index;
val = s->ioredtbl[index] & 0xffffffff;
}
}
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
-#endif
+ DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
}
return val;
}
-static void ioapic_mem_writel(void *opaque, a_target_phys_addr addr, uint32_t val)
+static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
IOAPICState *s = opaque;
int index;
s->ioregsel = val;
return;
} else if (addr == 0x10) {
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
-#endif
+ DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
switch (s->ioregsel) {
case 0x00:
s->id = (val >> 24) & 0xff;
}
};
-static void ioapic_reset(void *opaque)
+static void ioapic_reset(DeviceState *d)
{
- IOAPICState *s = opaque;
+ IOAPICState *s = DO_UPCAST(IOAPICState, busdev.qdev, d);
int i;
- memset(s, 0, sizeof(*s));
+ s->id = 0;
+ s->ioregsel = 0;
+ s->irr = 0;
for(i = 0; i < IOAPIC_NUM_PINS; i++)
s->ioredtbl[i] = 1 << 16; /* mask LVT */
}
ioapic_mem_writel,
};
-qemu_irq *ioapic_init(void)
+static int ioapic_init1(SysBusDevice *dev)
{
- IOAPICState *s;
- qemu_irq *irq;
+ IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
int io_memory;
- s = qemu_mallocz(sizeof(IOAPICState));
- ioapic_reset(s);
-
io_memory = cpu_register_io_memory(ioapic_mem_read,
- ioapic_mem_write, s);
- cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
+ ioapic_mem_write, s,
+ DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x1000, io_memory);
+
+ qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
+
+ return 0;
+}
- vmstate_register(0, &vmstate_ioapic, s);
- qemu_register_reset(ioapic_reset, s);
- irq = qemu_allocate_irqs(ioapic_set_irq, s, IOAPIC_NUM_PINS);
+static SysBusDeviceInfo ioapic_info = {
+ .init = ioapic_init1,
+ .qdev.name = "ioapic",
+ .qdev.size = sizeof(IOAPICState),
+ .qdev.vmsd = &vmstate_ioapic,
+ .qdev.reset = ioapic_reset,
+ .qdev.no_user = 1,
+};
- return irq;
+static void ioapic_register_devices(void)
+{
+ sysbus_register_withprop(&ioapic_info);
}
+
+device_init(ioapic_register_devices)