/* * RM200 specific code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) * * i8259 parts ripped out of arch/mips/kernel/i8259.c
*/
/* * RM200 has an ISA and an EISA bus. The iSA bus is only used * for onboard devices and also has twi i8259 PICs. Since these * PICs are no accessible via inb/outb the following code uses * readb/writeb to access them
*/
/* * Careful! The 8259A is a fragile beast, it pretty * much _has_ to be done exactly like this (mask it * first, _then_ send the EOI, and the order of EOI * to the two 8259s is important!
*/ void sni_rm200_mask_and_ack_8259A(struct irq_data *d)
{ unsignedint irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE; unsignedlong flags;
irqmask = 1 << irq;
raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); /* * Lightweight spurious IRQ detection. We do not want * to overdo spurious IRQ handling - it's usually a sign * of hardware problems, so we only do the checks we can * do without slowing down good hardware unnecessarily. * * Note that IRQ7 and IRQ15 (the two spurious IRQs * usually resulting from the 8259A-1|2 PICs) occur * even if the IRQ is masked in the 8259A. Thus we * can check spurious 8259A IRQs without doing the * quite slow i8259A_irq_real() call for every IRQ. * This does not cover 100% of spurious interrupts, * but should be enough to warn the user that there * is something bad going on ...
*/ if (rm200_cached_irq_mask & irqmask) goto spurious_8259A_irq;
rm200_cached_irq_mask |= irqmask;
spurious_8259A_irq: /* * this is the slow path - should happen rarely.
*/ if (sni_rm200_i8259A_irq_real(irq)) /* * oops, the IRQ _is_ in service according to the * 8259A - not spurious, go handle it.
*/ goto handle_real_irq;
{ staticint spurious_irq_mask; /* * At this point we can be sure the IRQ is spurious, * let's ACK and report it. [once per IRQ]
*/ if (!(spurious_irq_mask & irqmask)) {
printk(KERN_DEBUG "spurious RM200 8259A interrupt: IRQ%d.\n", irq);
spurious_irq_mask |= irqmask;
}
atomic_inc(&irq_err_count); /* * Theoretically we do not have to handle this IRQ, * but in Linux this does not cause problems and is * simpler for us.
*/ goto handle_real_irq;
}
}
/* * Do the traditional i8259 interrupt polling thing. This is for the few * cases where no better interrupt acknowledge method is available and we * absolutely must touch the i8259.
*/ staticinlineint sni_rm200_i8259_irq(void)
{ int irq;
raw_spin_lock(&sni_rm200_i8259A_lock);
/* Perform an interrupt acknowledge cycle on controller 1. */
writeb(0x0C, rm200_pic_master + PIC_CMD); /* prepare for poll */
irq = readb(rm200_pic_master + PIC_CMD) & 7; if (irq == PIC_CASCADE_IR) { /* * Interrupt is cascaded so perform interrupt * acknowledge on controller 2.
*/
writeb(0x0C, rm200_pic_slave + PIC_CMD); /* prepare for poll */
irq = (readb(rm200_pic_slave + PIC_CMD) & 7) + 8;
}
if (unlikely(irq == 7)) { /* * This may be a spurious interrupt. * * Read the interrupt status register (ISR). If the most * significant bit is not set then there is no valid * interrupt.
*/
writeb(0x0B, rm200_pic_master + PIC_ISR); /* ISR register */ if (~readb(rm200_pic_master + PIC_ISR) & 0x80)
irq = -1;
}
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.