// SPDX-License-Identifier: GPL-2.0 /* * Interrupt request handling routines. On the * Sparc the IRQs are basically 'cast in stone' * and you are supposed to probe the prom's device * node trees to find out who's got which IRQ. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1995,2002 Pete A. Zaitcev (zaitcev@yahoo.com) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
*/
/* * Dave Redman (djhr@tadpole.co.uk) * * IRQ numbers.. These are no longer restricted to 15.. * * this is done to enable SBUS cards and onboard IO to be masked * correctly. using the interrupt level isn't good enough. * * For example: * A device interrupting at sbus level6 and the Floppy both come in * at IRQ11, but enabling and disabling them requires writing to * different bits in the SLAVIO/SEC. * * As a result of these changes sun4m machines could now support * directed CPU interrupts using the existing enable/disable irq code * with tweaks. * * Sun4d complicates things even further. IRQ numbers are arbitrary * 32-bit values in that case. Since this is similar to sparc64, * we adopt a virtual IRQ numbering scheme as is done there. * Virutal interrupt numbers are allocated by build_irq(). So NR_IRQS * just becomes a limit of how many interrupt sources we can handle in * a single system. Even fully loaded SS2000 machines top off at * about 32 interrupt sources or so, therefore a NR_IRQS value of 64 * is more than enough. * * We keep a map of per-PIL enable interrupts. These get wired * up via the irq_chip->startup() method which gets invoked by * the generic IRQ layer during request_irq().
*/
/* Table of allocated irqs. Unused entries has irq == 0 */ staticstruct irq_bucket irq_table[NR_IRQS]; /* Protect access to irq_table */ static DEFINE_SPINLOCK(irq_table_lock);
/* Map between the irq identifier used in hw to the irq_bucket. */ struct irq_bucket *irq_map[SUN4D_MAX_IRQ]; /* Protect access to irq_map */ static DEFINE_SPINLOCK(irq_map_lock);
/* Allocate a new irq from the irq_table */ unsignedint irq_alloc(unsignedint real_irq, unsignedint pil)
{ unsignedlong flags; unsignedint i;
spin_lock_irqsave(&irq_table_lock, flags); for (i = 1; i < NR_IRQS; i++) { if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil) goto found;
}
for (i = 1; i < NR_IRQS; i++) { if (!irq_table[i].irq) break;
}
if (i < NR_IRQS) {
irq_table[i].real_irq = real_irq;
irq_table[i].irq = i;
irq_table[i].pil = pil;
} else {
printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
i = 0;
}
found:
spin_unlock_irqrestore(&irq_table_lock, flags);
return i;
}
/* Based on a single pil handler_irq may need to call several * interrupt handlers. Use irq_map as entry to irq_table, * and let each entry in irq_table point to the next entry.
*/ void irq_link(unsignedint irq)
{ struct irq_bucket *p; unsignedlong flags; unsignedint pil;
/* Save for later use in floppy interrupt handler */
floppy_irq = irq;
cpu_irq = (irq & (NR_IRQS - 1));
/* Dork with trap table if we get this far. */ #define INSTANTIATE(table) \
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
SPARC_BRANCH((unsignedlong) floppy_hardint, \
(unsignedlong) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
INSTANTIATE(sparc_ttable)
#ifdefined CONFIG_SMP if (sparc_cpu_model != sparc_leon) { struct tt_entry *trap_table;
trap_table = &trapbase_cpu1[0];
INSTANTIATE(trap_table)
trap_table = &trapbase_cpu2[0];
INSTANTIATE(trap_table)
trap_table = &trapbase_cpu3[0];
INSTANTIATE(trap_table)
} #endif #undef INSTANTIATE /* * XXX Correct thing whould be to flush only I- and D-cache lines * which contain the handler in question. But as of time of the * writing we have no CPU-neutral interface to fine-grained flushes.
*/
flush_cache_all(); return 0;
}
EXPORT_SYMBOL(sparc_floppy_request_irq);
/* * These variables are used to access state from the assembler * interrupt handler, floppy_hardint, so we cannot put these in * the floppy driver image because that would not work in the * modular case.
*/ volatileunsignedchar *fdc_status;
EXPORT_SYMBOL(fdc_status);
/* Use the generic irq support to call floppy_interrupt * which was setup using request_irq() in sparc_floppy_request_irq(). * We only have one floppy interrupt so we do not need to check * for additional handlers being wired up by irq_link()
*/ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
{ struct pt_regs *old_regs;
/* djhr * This could probably be made indirect too and assigned in the CPU * bits of the code. That would be much nicer I think and would also * fit in with the idea of being able to tune your kernel for your machine * by removing unrequired machine and device support. *
*/
void __init init_IRQ(void)
{ switch (sparc_cpu_model) { case sun4m:
pcic_probe(); if (pcic_present())
sun4m_pci_init_IRQ(); else
sun4m_init_IRQ(); break;
case sun4d:
sun4d_init_IRQ(); break;
case sparc_leon:
leon_init_IRQ(); break;
default:
prom_printf("Cannot initialize IRQs on this Sun machine..."); break;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.