#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
-#define MAX_PILS 16
+#define IVEC_MAX 0x30
#define TICK_MAX 0x7fffffffffffffffULL
return kernel_size;
}
-void cpu_check_irqs(CPUState *env)
+void cpu_check_irqs(CPUSPARCState *env)
{
uint32_t pil = env->pil_in |
(env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
+ /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
+ if (env->ivec_status & 0x20) {
+ return;
+ }
/* check if TM or SM in SOFTINT are set
setting these also causes interrupt 14 */
if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
int old_interrupt = env->interrupt_index;
int new_interrupt = TT_EXTINT | i;
- if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
+ if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
+ && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
"current %x >= pending %x\n",
env->tl, cpu_tsptr(env)->tt, new_interrupt);
}
}
-static void cpu_kick_irq(CPUState *env)
+static void cpu_kick_irq(CPUSPARCState *env)
{
env->halted = 0;
cpu_check_irqs(env);
qemu_cpu_kick(env);
}
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_ivec_irq(void *opaque, int irq, int level)
{
- CPUState *env = opaque;
+ CPUSPARCState *env = opaque;
if (level) {
- CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
- env->pil_in |= 1 << irq;
- cpu_kick_irq(env);
+ if (!(env->ivec_status & 0x20)) {
+ CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+ env->halted = 0;
+ env->interrupt_index = TT_IVEC;
+ env->ivec_status |= 0x20;
+ env->ivec_data[0] = (0x1f << 6) | irq;
+ env->ivec_data[1] = 0;
+ env->ivec_data[2] = 0;
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ }
} else {
- CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
- env->pil_in &= ~(1 << irq);
- cpu_check_irqs(env);
+ if (env->ivec_status & 0x20) {
+ CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+ env->ivec_status &= ~0x20;
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
}
}
typedef struct ResetData {
- CPUState *env;
+ CPUSPARCState *env;
uint64_t prom_addr;
} ResetData;
qemu_get_timer(f, s->qtimer);
}
-static CPUTimer* cpu_timer_create(const char* name, CPUState *env,
+static CPUTimer* cpu_timer_create(const char* name, CPUSPARCState *env,
QEMUBHFunc *cb, uint32_t frequency,
uint64_t disabled_mask)
{
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
- CPUState *env = s->env;
+ CPUSPARCState *env = s->env;
static unsigned int nr_resets;
- cpu_reset(env);
+ cpu_state_reset(env);
cpu_timer_reset(env->tick);
cpu_timer_reset(env->stick);
static void tick_irq(void *opaque)
{
- CPUState *env = opaque;
+ CPUSPARCState *env = opaque;
CPUTimer* timer = env->tick;
static void stick_irq(void *opaque)
{
- CPUState *env = opaque;
+ CPUSPARCState *env = opaque;
CPUTimer* timer = env->stick;
static void hstick_irq(void *opaque)
{
- CPUState *env = opaque;
+ CPUSPARCState *env = opaque;
CPUTimer* timer = env->hstick;
}
}
-static void dummy_isa_irq_handler(void *opaque, int n, int level)
+static void isa_irq_handler(void *opaque, int n, int level)
{
+ static const int isa_irq_to_ivec[16] = {
+ [1] = 0x29, /* keyboard */
+ [4] = 0x2b, /* serial */
+ [6] = 0x27, /* floppy */
+ [7] = 0x22, /* parallel */
+ [12] = 0x2a, /* mouse */
+ };
+ qemu_irq *irqs = opaque;
+ int ivec;
+
+ assert(n < 16);
+ ivec = isa_irq_to_ivec[n];
+ EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
+ if (ivec) {
+ qemu_set_irq(irqs[ivec], level);
+ }
}
/* EBUS (Eight bit bus) bridge */
static ISABus *
-pci_ebus_init(PCIBus *bus, int devfn)
+pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
{
qemu_irq *isa_irq;
PCIDevice *pci_dev;
pci_dev = pci_create_simple(bus, devfn, "ebus");
isa_bus = DO_UPCAST(ISABus, qbus,
qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
- isa_irq = qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16);
+ isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
isa_bus_irqs(isa_bus, isa_irq);
return isa_bus;
}
k->class_id = PCI_CLASS_BRIDGE_OTHER;
}
-static DeviceInfo ebus_info = {
- .name = "ebus",
- .size = sizeof(EbusState),
- .class_init = ebus_class_init,
+static TypeInfo ebus_info = {
+ .name = "ebus",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(EbusState),
+ .class_init = ebus_class_init,
};
-static void pci_ebus_register(void)
-{
- pci_qdev_register(&ebus_info);
-}
-
-device_init(pci_ebus_register);
-
typedef struct PROMState {
SysBusDevice busdev;
MemoryRegion prom;
return 0;
}
-static SysBusDeviceInfo prom_info = {
- .init = prom_init1,
- .qdev.name = "openprom",
- .qdev.size = sizeof(PROMState),
- .qdev.props = (Property[]) {
- {/* end of property list */}
- }
+static Property prom_properties[] = {
+ {/* end of property list */},
};
-static void prom_register_devices(void)
+static void prom_class_init(ObjectClass *klass, void *data)
{
- sysbus_register_withprop(&prom_info);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = prom_init1;
+ dc->props = prom_properties;
}
-device_init(prom_register_devices);
+static TypeInfo prom_info = {
+ .name = "openprom",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PROMState),
+ .class_init = prom_class_init,
+};
typedef struct RamDevice
sysbus_mmio_map(s, 0, addr);
}
-static SysBusDeviceInfo ram_info = {
- .init = ram_init1,
- .qdev.name = "memory",
- .qdev.size = sizeof(RamDevice),
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT64("size", RamDevice, size, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static Property ram_properties[] = {
+ DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+ DEFINE_PROP_END_OF_LIST(),
};
-static void ram_register_devices(void)
+static void ram_class_init(ObjectClass *klass, void *data)
{
- sysbus_register_withprop(&ram_info);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = ram_init1;
+ dc->props = ram_properties;
}
-device_init(ram_register_devices);
+static TypeInfo ram_info = {
+ .name = "memory",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(RamDevice),
+ .class_init = ram_class_init,
+};
-static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+static CPUSPARCState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
{
- CPUState *env;
+ CPUSPARCState *env;
ResetData *reset_info;
uint32_t tick_frequency = 100*1000000;
const char *initrd_filename, const char *cpu_model,
const struct hwdef *hwdef)
{
- CPUState *env;
+ CPUSPARCState *env;
M48t59State *nvram;
unsigned int i;
long initrd_size, kernel_size;
PCIBus *pci_bus, *pci_bus2, *pci_bus3;
ISABus *isa_bus;
- qemu_irq *irq;
+ qemu_irq *ivec_irqs, *pbm_irqs;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
DriveInfo *fd[MAX_FD];
void *fw_cfg;
prom_init(hwdef->prom_addr, bios_name);
-
- irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
- pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
- &pci_bus3);
+ ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX);
+ pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
+ &pci_bus3, &pbm_irqs);
pci_vga_init(pci_bus);
// XXX Should be pci_bus3
- isa_bus = pci_ebus_init(pci_bus, -1);
+ isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
i = 0;
if (hwdef->console_serial_base) {
.max_cpus = 1, // XXX for now
};
+static void sun4u_register_types(void)
+{
+ type_register_static(&ebus_info);
+ type_register_static(&prom_info);
+ type_register_static(&ram_info);
+}
+
static void sun4u_machine_init(void)
{
qemu_register_machine(&sun4u_machine);
qemu_register_machine(&niagara_machine);
}
+type_init(sun4u_register_types)
machine_init(sun4u_machine_init);