X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fslavio_intctl.c;h=5412228770af7921664feee694045a6166b2400c;hb=cd346349b45ef056f138a184f660b8c34c3213cc;hp=acde370e5c1e5d708d84dcb5d5dfc17039f3aeed;hpb=dd4131b39492bd91dc87d216e761ca4cf210fb67;p=qemu diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index acde370..5412228 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -1,8 +1,8 @@ /* * QEMU Sparc SLAVIO interrupt controller emulation - * + * * Copyright (c) 2003-2005 Fabrice Bellard - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -40,7 +40,7 @@ do { printf("IRQ: " fmt , ##args); } while (0) * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt * * There is a system master controller and one for each cpu. - * + * */ #define MAX_CPUS 16 @@ -84,7 +84,7 @@ static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr) ret = 0; break; } - DPRINTF("read cpu %d reg 0x%x = %x\n", addr, ret); + DPRINTF("read cpu %d reg 0x" TARGET_FMT_plx " = %x\n", cpu, addr, ret); return ret; } @@ -97,23 +97,24 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12; saddr = (addr & INTCTL_MAXADDR) >> 2; - DPRINTF("write cpu %d reg 0x%x = %x\n", cpu, addr, val); + DPRINTF("write cpu %d reg 0x" TARGET_FMT_plx " = %x\n", cpu, addr, val); switch (saddr) { case 1: // clear pending softints - if (val & 0x4000) - val |= 80000000; - val &= 0xfffe0000; - s->intreg_pending[cpu] &= ~val; - DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); - break; + if (val & 0x4000) + val |= 80000000; + val &= 0xfffe0000; + s->intreg_pending[cpu] &= ~val; + slavio_check_interrupts(s); + DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); + break; case 2: // set softint - val &= 0xfffe0000; - s->intreg_pending[cpu] |= val; + val &= 0xfffe0000; + s->intreg_pending[cpu] |= val; slavio_check_interrupts(s); - DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); - break; + DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); + break; default: - break; + break; } } @@ -150,7 +151,7 @@ static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr) ret = 0; break; } - DPRINTF("read system reg 0x%x = %x\n", addr, ret); + DPRINTF("read system reg 0x" TARGET_FMT_plx " = %x\n", addr, ret); return ret; } @@ -161,28 +162,30 @@ static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uin uint32_t saddr; saddr = (addr & INTCTLM_MASK) >> 2; - DPRINTF("write system reg 0x%x = %x\n", addr, val); + DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val); switch (saddr) { case 2: // clear (enable) - // Force clear unused bits - val &= ~0x4fb2007f; - s->intregm_disabled &= ~val; - DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); - slavio_check_interrupts(s); - break; + // Force clear unused bits + val &= ~0x4fb2007f; + s->intregm_disabled &= ~val; + DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); + slavio_check_interrupts(s); + break; case 3: // set (disable, clear pending) - // Force clear unused bits - val &= ~0x4fb2007f; - s->intregm_disabled |= val; - s->intregm_pending &= ~val; - DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); - break; + // Force clear unused bits + val &= ~0x4fb2007f; + s->intregm_disabled |= val; + s->intregm_pending &= ~val; + slavio_check_interrupts(s); + DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled); + break; case 4: - s->target_cpu = val & (MAX_CPUS - 1); - DPRINTF("Set master irq cpu %d\n", s->target_cpu); - break; + s->target_cpu = val & (MAX_CPUS - 1); + slavio_check_interrupts(s); + DPRINTF("Set master irq cpu %d\n", s->target_cpu); + break; default: - break; + break; } } @@ -204,7 +207,7 @@ void slavio_pic_info(void *opaque) int i; for (i = 0; i < MAX_CPUS; i++) { - term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]); + term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]); } term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled); } @@ -227,53 +230,36 @@ void slavio_irq_info(void *opaque) #endif } -static void raise_pil(SLAVIO_INTCTLState *s, unsigned int pil, - unsigned int cpu) -{ - qemu_irq irq; - unsigned int oldmax; - - irq = s->cpu_irqs[cpu][pil]; - -#ifdef DEBUG_IRQ_COUNT - s->irq_count[pil]++; -#endif - oldmax = s->pil_out[cpu]; - if (oldmax > 0 && oldmax != pil) - qemu_irq_lower(s->cpu_irqs[cpu][oldmax]); - s->pil_out[cpu] = pil; - if (pil > 0) - qemu_irq_raise(irq); - DPRINTF("cpu %d pil %d\n", cpu, pil); -} - static void slavio_check_interrupts(void *opaque) { SLAVIO_INTCTLState *s = opaque; - uint32_t pending = s->intregm_pending; - unsigned int i, j, max = 0; + uint32_t pending = s->intregm_pending, pil_pending; + unsigned int i, j; pending &= ~s->intregm_disabled; DPRINTF("pending %x disabled %x\n", pending, s->intregm_disabled); for (i = 0; i < MAX_CPUS; i++) { - max = 0; + pil_pending = 0; if (pending && !(s->intregm_disabled & 0x80000000) && (i == s->target_cpu)) { for (j = 0; j < 32; j++) { - if (pending & (1 << j)) { - if (max < s->intbit_to_level[j]) - max = s->intbit_to_level[j]; - } + if (pending & (1 << j)) + pil_pending |= 1 << s->intbit_to_level[j]; } } - for (j = 17; j < 32; j++) { - if (s->intreg_pending[i] & (1 << j)) { - if (max < j - 16) - max = j - 16; + pil_pending |= (s->intreg_pending[i] >> 16) & 0xfffe; + + for (j = 0; j < MAX_PILS; j++) { + if (pil_pending & (1 << j)) { + if (!(s->pil_out[i] & (1 << j))) + qemu_irq_raise(s->cpu_irqs[i][j]); + } else { + if (s->pil_out[i] & (1 << j)) + qemu_irq_lower(s->cpu_irqs[i][j]); } } - raise_pil(s, max, i); + s->pil_out[i] = pil_pending; } } @@ -291,6 +277,9 @@ static void slavio_set_irq(void *opaque, int irq, int level) level); if (pil > 0) { if (level) { +#ifdef DEBUG_IRQ_COUNT + s->irq_count[pil]++; +#endif s->intregm_pending |= mask; s->intreg_pending[s->target_cpu] |= 1 << pil; } else { @@ -319,9 +308,9 @@ static void slavio_intctl_save(QEMUFile *f, void *opaque) { SLAVIO_INTCTLState *s = opaque; int i; - + for (i = 0; i < MAX_CPUS; i++) { - qemu_put_be32s(f, &s->intreg_pending[i]); + qemu_put_be32s(f, &s->intreg_pending[i]); } qemu_put_be32s(f, &s->intregm_pending); qemu_put_be32s(f, &s->intregm_disabled); @@ -337,11 +326,12 @@ static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; for (i = 0; i < MAX_CPUS; i++) { - qemu_get_be32s(f, &s->intreg_pending[i]); + qemu_get_be32s(f, &s->intreg_pending[i]); } qemu_get_be32s(f, &s->intregm_pending); qemu_get_be32s(f, &s->intregm_disabled); qemu_get_be32s(f, &s->target_cpu); + slavio_check_interrupts(s); return 0; } @@ -351,11 +341,12 @@ static void slavio_intctl_reset(void *opaque) int i; for (i = 0; i < MAX_CPUS; i++) { - s->intreg_pending[i] = 0; + s->intreg_pending[i] = 0; } s->intregm_disabled = ~0xffb2007f; s->intregm_pending = 0; s->target_cpu = 0; + slavio_check_interrupts(s); } void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, @@ -372,8 +363,8 @@ void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, s->intbit_to_level = intbit_to_level; for (i = 0; i < MAX_CPUS; i++) { - slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s); - cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE, + slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s); + cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE, slavio_intctl_io_memory); s->cpu_irqs[i] = parent_irq[i]; }