/* * Acknowledge the IRQ using either the PCI host bridge's interrupt * acknowledge feature or poll. How i8259_init() is called determines * which is called. It should be noted that polling is broken on some * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
*/ unsignedint i8259_irq(void)
{ int irq; int lock = 0;
/* Either int-ack or poll for the IRQ */ if (pci_intack)
irq = readb(pci_intack); else {
raw_spin_lock(&i8259_lock);
lock = 1;
/* Perform an interrupt acknowledge cycle on controller 1. */
outb(0x0C, 0x20); /* prepare for poll */
irq = inb(0x20) & 7; if (irq == 2 ) { /* * Interrupt is cascaded so perform interrupt * acknowledge on controller 2.
*/
outb(0x0C, 0xA0); /* prepare for poll */
irq = (inb(0xA0) & 7) + 8;
}
}
if (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.
*/ if (!pci_intack)
outb(0x0B, 0x20); /* ISR register */ if(~inb(0x20) & 0x80)
irq = 0;
} elseif (irq == 0xff)
irq = 0;
if (lock)
raw_spin_unlock(&i8259_lock); return irq;
}
/* We block the internal cascade */ if (hw == 2)
irq_set_status_flags(virq, IRQ_NOREQUEST);
/* We use the level handler only for now, we might want to * be more cautious here but that works for now
*/
irq_set_status_flags(virq, IRQ_LEVEL);
irq_set_chip_and_handler(virq, &i8259_pic, handle_level_irq); return 0;
}
/** * i8259_init - Initialize the legacy controller * @node: device node of the legacy PIC (can be NULL, but then, it will match * all interrupts, so beware) * @intack_addr: PCI interrupt acknowledge (real) address which will return * the active irq from the 8259
*/ void i8259_init(struct device_node *node, unsignedlong intack_addr)
{ unsignedlong flags;
/* initialize the controller */
raw_spin_lock_irqsave(&i8259_lock, flags);
/* Mask all first */
outb(0xff, 0xA1);
outb(0xff, 0x21);
/* Set interrupt masks */
outb(cached_A1, 0xA1);
outb(cached_21, 0x21);
raw_spin_unlock_irqrestore(&i8259_lock, flags);
/* create a legacy host */
i8259_host = irq_domain_create_legacy(of_fwnode_handle(node), NR_IRQS_LEGACY, 0, 0,
&i8259_host_ops, NULL); if (i8259_host == NULL) {
printk(KERN_ERR "i8259: failed to allocate irq host !\n"); return;
}
/* reserve our resources */ /* XXX should we continue doing that ? it seems to cause problems * with further requesting of PCI IO resources for that range... * need to look into it.
*/
request_resource(&ioport_resource, &pic1_iores);
request_resource(&ioport_resource, &pic2_iores);
request_resource(&ioport_resource, &pic_edgectrl_iores);
if (intack_addr != 0)
pci_intack = ioremap(intack_addr, 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.