/* * Activate a secondary processor. */ static void __init start_secondary(void *unused) { /* * Dont put anything before smp_callin(), SMP * booting is too fragile that we want to limit the * things done here to the most necessary things. */ cpu_init(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); setup_secondary_APIC_clock(); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); enable_NMI_through_LVT0(NULL); enable_8259A_irq(0); } enable_APIC_timer(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. */ local_flush_tlb(); cpu_set(smp_processor_id(), cpu_online_map); /* We can take interrupts now: we're officially "up". */ local_irq_enable(); wmb(); cpu_idle(); }
static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs) { struct irqServer * iServer; struct irqDescriptor *desc = &irq_desc[irq]; { unsigned int status; mask_and_ack_8259A(irq); status = desc->id_status & ~(IRQ_REPLAY | IRQ_WAITING); iServer = NULL; if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { iServer = desc->id_server; status |= IRQ_INPROGRESS; } desc->id_status = status; } /* Exit early if we had no action or it was disabled */ if (!iServer) return; handle_IRQ_event(irq, regs, iServer); { unsigned int status = desc->id_status & ~IRQ_INPROGRESS; desc->id_status = status; if (!(status & IRQ_DISABLED)) enable_8259A_irq(irq); } }
void keyboard_init() { kbdbuf.count = 0; kbdbuf.p_head = kbdbuf.p_tail = kbdbuf.buf; enable_8259A_irq(IRQ_KBD); }
void kbd_send_data(unsigned char data) { unsigned char status; disable_8259A_irq(1); /* disable interrupt */ kbd_write_output_w(data); status = kbd_wait_for_input(); if (status == KBD_REPLY_ACK) enable_8259A_irq(1); /* enable interrupt */ }
static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq) { TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENABLE, "irq=%d\n", irq); if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, "bad irq=%d\n", irq); panic("\n"); } enable_8259A_irq(irq); }
/* * Activate a secondary processor. */ void __init start_secondary(void) { /* * Dont put anything before smp_callin(), SMP * booting is too fragile that we want to limit the * things done here to the most necessary things. */ cpu_init(); smp_callin(); /* otherwise gcc will move up the smp_processor_id before the cpu_init */ barrier(); Dprintk("cpu %d: waiting for commence\n", smp_processor_id()); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); setup_secondary_APIC_clock(); Dprintk("cpu %d: enabling apic timer\n", smp_processor_id()); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); enable_NMI_through_LVT0(NULL); enable_8259A_irq(0); } enable_APIC_timer(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. */ local_flush_tlb(); Dprintk("cpu %d eSetting cpu_online_map\n", smp_processor_id()); cpu_set(smp_processor_id(), cpu_online_map); wmb(); cpu_idle(); }
/* * PIIX4-8259 master/virtual functions to handle interrupt requests * from legacy devices: floppy, parallel, serial, rtc. * * None of these get Cobalt APIC entries, neither do they have IDT * entries. These interrupts are purely virtual and distributed from * the 'master' interrupt source: CO_IRQ_8259. * * When the 8259 interrupts its handler figures out which of these * devices is interrupting and dispatches to its handler. * * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/ * enable_irq gets the right irq. This 'master' irq is never directly * manipulated by any driver. */ static irqreturn_t piix4_master_intr(int irq, void *dev_id) { int realirq; irq_desc_t *desc; unsigned long flags; spin_lock_irqsave(&i8259A_lock, flags); /* Find out what's interrupting in the PIIX4 master 8259 */ outb(0x0c, 0x20); /* OCW3 Poll command */ realirq = inb(0x20); /* * Bit 7 == 0 means invalid/spurious */ if (unlikely(!(realirq & 0x80))) goto out_unlock; realirq &= 7; if (unlikely(realirq == 2)) { outb(0x0c, 0xa0); realirq = inb(0xa0); if (unlikely(!(realirq & 0x80))) goto out_unlock; realirq = (realirq & 7) + 8; } /* mask and ack interrupt */ cached_irq_mask |= 1 << realirq; if (unlikely(realirq > 7)) { inb(0xa1); outb(cached_slave_mask, 0xa1); outb(0x60 + (realirq & 7), 0xa0); outb(0x60 + 2, 0x20); } else { inb(0x21); outb(cached_master_mask, 0x21); outb(0x60 + realirq, 0x20); } spin_unlock_irqrestore(&i8259A_lock, flags); desc = irq_desc + realirq; /* * handle this 'virtual interrupt' as a Cobalt one now. */ kstat_cpu(smp_processor_id()).irqs[realirq]++; if (likely(desc->action != NULL)) handle_IRQ_event(realirq, desc->action); if (!(desc->status & IRQ_DISABLED)) enable_8259A_irq(realirq); return IRQ_HANDLED; out_unlock: spin_unlock_irqrestore(&i8259A_lock, flags); return IRQ_NONE; }
static void end_i8259_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_8259A_irq(irq - I8259_IRQ_BASE); }
static void enable_i8259_irq(unsigned int irq) { enable_8259A_irq(irq - I8259_IRQ_BASE); }
static unsigned int startup_i8259_irq(unsigned int irq) { enable_8259A_irq(irq - I8259_IRQ_BASE); return 0; }