#include <linux/config.h>
      #include <linux/ptrace.h>
      #include <linux/errno.h>
      #include <linux/signal.h>
      #include <linux/sched.h>
      #include <linux/ioport.h>
      #include <linux/interrupt.h>
      #include <linux/timex.h>
      #include <linux/malloc.h>
      #include <linux/random.h>
      #include <linux/smp_lock.h>
      #include <linux/init.h>
      #include <linux/kernel_stat.h>
      
      #include <asm/system.h>
      #include <asm/io.h>
      #include <asm/irq.h>
      #include <asm/bitops.h>
      #include <asm/pgtable.h>
      #include <asm/delay.h>
      #include <asm/desc.h>
      
      #include <linux/irq.h>
      
      /*
       * Common place to define all x86 IRQ vectors
       *
       * This builds up the IRQ handler stubs using some ugly macros in irq.h
       *
       * These macros create the low-level assembly IRQ routines that save
       * register context and call do_IRQ(). do_IRQ() then does all the
       * operations that are needed to keep the AT (or SMP IOAPIC)
       * interrupt-controller happy.
       */
      
      BUILD_COMMON_IRQ()
      
      #define BI(x,y) \
      	BUILD_IRQ(x##y)
      
      #define BUILD_16_IRQS(x) \
      	BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
      	BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
      	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
      	BI(x,c) BI(x,d) BI(x,e) BI(x,f)
      
      /*
       * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
       * (these are usually mapped to vectors 0x20-0x2f)
       */
      BUILD_16_IRQS(0x0)
      
      #ifdef CONFIG_X86_IO_APIC
      /*
       * The IO-APIC gives us many more interrupt sources. Most of these 
       * are unused but an SMP system is supposed to have enough memory ...
       * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
       * across the spectrum, so we really want to be prepared to get all
       * of these. Plus, more powerful systems might have more than 64
       * IO-APIC registers.
       *
       * (these are usually mapped into the 0x30-0xff vector range)
       */
      		   BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
      BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
      BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
      BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
      #endif
      
      #undef BUILD_16_IRQS
      #undef BI
      
      
      /*
       * The following vectors are part of the Linux architecture, there
       * is no hardware IRQ pin equivalent for them, they are triggered
       * through the ICC by us (IPIs)
       */
      #ifdef CONFIG_SMP
      BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
      BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
      BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
      #endif
      
      /*
       * every pentium local APIC has two 'local interrupts', with a
       * soft-definable vector attached to both interrupts, one of
       * which is a timer interrupt, the other one is error counter
       * overflow. Linux uses the local APIC timer interrupt to get
       * a much simpler SMP time architecture:
       */
      #ifdef CONFIG_X86_LOCAL_APIC
      BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
      BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
      BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
      #endif
      
      #define IRQ(x,y) \
      	IRQ##x##y##_interrupt
      
      #define IRQLIST_16(x) \
      	IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
      	IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
      	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
      	IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
      
      void (*interrupt[NR_IRQS])(void) = {
      	IRQLIST_16(0x0),
      
      #ifdef CONFIG_X86_IO_APIC
      			 IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
      	IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
      	IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
      	IRQLIST_16(0xc), IRQLIST_16(0xd)
      #endif
      };
      
      #undef IRQ
      #undef IRQLIST_16
      
      /*
       * This is the 'legacy' 8259A Programmable Interrupt Controller,
       * present in the majority of PC/AT boxes.
       * plus some generic x86 specific things if generic specifics makes
       * any sense at all.
       * this file should become arch/i386/kernel/irq.c when the old irq.c
       * moves to arch independent land
       */
      
      spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
      
 132  static void end_8259A_irq (unsigned int irq)
      {
 134  	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
      		enable_8259A_irq(irq);
      }
      
      #define shutdown_8259A_irq	disable_8259A_irq
      
      void mask_and_ack_8259A(unsigned int);
      
 142  static unsigned int startup_8259A_irq(unsigned int irq)
      { 
      	enable_8259A_irq(irq);
 145  	return 0; /* never anything pending */
      }
      
      static struct hw_interrupt_type i8259A_irq_type = {
      	"XT-PIC",
      	startup_8259A_irq,
      	shutdown_8259A_irq,
      	enable_8259A_irq,
      	disable_8259A_irq,
      	mask_and_ack_8259A,
      	end_8259A_irq,
      	NULL
      };
      
      /*
       * 8259A PIC functions to handle ISA devices:
       */
      
      /*
       * This contains the irq mask for both 8259A irq controllers,
       */
      static unsigned int cached_irq_mask = 0xffff;
      
      #define __byte(x,y) 	(((unsigned char *)&(y))[x])
      #define cached_21	(__byte(0,cached_irq_mask))
      #define cached_A1	(__byte(1,cached_irq_mask))
      
      /*
       * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
       * boards the timer interrupt is not really connected to any IO-APIC pin,
       * it's fed to the master 8259A's IR0 line only.
       *
       * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
       * this 'mixed mode' IRQ handling costs nothing because it's only used
       * at IRQ setup time.
       */
      unsigned long io_apic_irqs;
      
 183  void disable_8259A_irq(unsigned int irq)
      {
      	unsigned int mask = 1 << irq;
      	unsigned long flags;
      
 188  	spin_lock_irqsave(&i8259A_lock, flags);
      	cached_irq_mask |= mask;
 190  	if (irq & 8)
      		outb(cached_A1,0xA1);
 192  	else
      		outb(cached_21,0x21);
 194  	spin_unlock_irqrestore(&i8259A_lock, flags);
      }
      
 197  void enable_8259A_irq(unsigned int irq)
      {
      	unsigned int mask = ~(1 << irq);
      	unsigned long flags;
      
 202  	spin_lock_irqsave(&i8259A_lock, flags);
      	cached_irq_mask &= mask;
 204  	if (irq & 8)
      		outb(cached_A1,0xA1);
 206  	else
      		outb(cached_21,0x21);
 208  	spin_unlock_irqrestore(&i8259A_lock, flags);
      }
      
 211  int i8259A_irq_pending(unsigned int irq)
      {
      	unsigned int mask = 1<<irq;
      	unsigned long flags;
      	int ret;
      
 217  	spin_lock_irqsave(&i8259A_lock, flags);
 218  	if (irq < 8)
      		ret = inb(0x20) & mask;
 220  	else
      		ret = inb(0xA0) & (mask >> 8);
 222  	spin_unlock_irqrestore(&i8259A_lock, flags);
      
 224  	return ret;
      }
      
 227  void make_8259A_irq(unsigned int irq)
      {
      	disable_irq_nosync(irq);
      	io_apic_irqs &= ~(1<<irq);
      	irq_desc[irq].handler = &i8259A_irq_type;
      	enable_irq(irq);
      }
      
      /*
       * This function assumes to be called rarely. Switching between
       * 8259A registers is slow.
       * This has to be protected by the irq controller spinlock
       * before being called.
       */
 241  static inline int i8259A_irq_real(unsigned int irq)
      {
      	int value;
      	int irqmask = 1<<irq;
      
 246  	if (irq < 8) {
      		outb(0x0B,0x20);		/* ISR register */
      		value = inb(0x20) & irqmask;
      		outb(0x0A,0x20);		/* back to the IRR register */
 250  		return value;
      	}
      	outb(0x0B,0xA0);		/* ISR register */
      	value = inb(0xA0) & (irqmask >> 8);
      	outb(0x0A,0xA0);		/* back to the IRR register */
 255  	return value;
      }
      
      /*
       * 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!
       */
 264  void mask_and_ack_8259A(unsigned int irq)
      {
      	unsigned int irqmask = 1 << irq;
      	unsigned long flags;
      
 269  	spin_lock_irqsave(&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 unnecesserily.
      	 *
      	 * 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 ...
      	 */
 285  	if (cached_irq_mask & irqmask)
 286  		goto spurious_8259A_irq;
      	cached_irq_mask |= irqmask;
      
      handle_real_irq:
 290  	if (irq & 8) {
      		inb(0xA1);		/* DUMMY - (do we need this?) */
      		outb(cached_A1,0xA1);
      		outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
      		outb(0x62,0x20);	/* 'Specific EOI' to master-IRQ2 */
 295  	} else {
      		inb(0x21);		/* DUMMY - (do we need this?) */
      		outb(cached_21,0x21);
      		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
      	}
 300  	spin_unlock_irqrestore(&i8259A_lock, flags);
 301  	return;
      
      spurious_8259A_irq:
      	/*
      	 * this is the slow path - should happen rarely.
      	 */
 307  	if (i8259A_irq_real(irq))
      		/*
      		 * oops, the IRQ _is_ in service according to the
      		 * 8259A - not spurious, go handle it.
      		 */
 312  		goto handle_real_irq;
      
      	{
      		static int spurious_irq_mask;
      		/*
      		 * At this point we can be sure the IRQ is spurious,
      		 * lets ACK and report it. [once per IRQ]
      		 */
 320  		if (!(spurious_irq_mask & irqmask)) {
      			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
      			spurious_irq_mask |= irqmask;
      		}
      		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.
      		 */
 330  		goto handle_real_irq;
      	}
      }
      
 334  void __init init_8259A(int auto_eoi)
      {
      	unsigned long flags;
      
 338  	spin_lock_irqsave(&i8259A_lock, flags);
      
      	outb(0xff, 0x21);	/* mask all of 8259A-1 */
      	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
      
      	/*
      	 * outb_p - this has to work on a wide range of PC hardware.
      	 */
      	outb_p(0x11, 0x20);	/* ICW1: select 8259A-1 init */
      	outb_p(0x20 + 0, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
      	outb_p(0x04, 0x21);	/* 8259A-1 (the master) has a slave on IR2 */
 349  	if (auto_eoi)
      		outb_p(0x03, 0x21);	/* master does Auto EOI */
 351  	else
      		outb_p(0x01, 0x21);	/* master expects normal EOI */
      
      	outb_p(0x11, 0xA0);	/* ICW1: select 8259A-2 init */
      	outb_p(0x20 + 8, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
      	outb_p(0x02, 0xA1);	/* 8259A-2 is a slave on master's IR2 */
      	outb_p(0x01, 0xA1);	/* (slave's support for AEOI in flat mode
      				    is to be investigated) */
      
 360  	if (auto_eoi)
      		/*
      		 * in AEOI mode we just have to mask the interrupt
      		 * when acking.
      		 */
      		i8259A_irq_type.ack = disable_8259A_irq;
 366  	else
      		i8259A_irq_type.ack = mask_and_ack_8259A;
      
      	udelay(100);		/* wait for 8259A to initialize */
      
      	outb(cached_21, 0x21);	/* restore master IRQ mask */
      	outb(cached_A1, 0xA1);	/* restore slave IRQ mask */
      
 374  	spin_unlock_irqrestore(&i8259A_lock, flags);
      }
      
      /*
       * Note that on a 486, we don't want to do a SIGFPE on an irq13
       * as the irq is unreliable, and exception 16 works correctly
       * (ie as explained in the intel literature). On a 386, you
       * can't use exception 16 due to bad IBM design, so we have to
       * rely on the less exact irq13.
       *
       * Careful.. Not only is IRQ13 unreliable, but it is also
       * leads to races. IBM designers who came up with it should
       * be shot.
       */
       
 389  static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
      {
      	extern void math_error(void *);
      	outb(0,0xF0);
 393  	if (ignore_irq13 || !boot_cpu_data.hard_math)
 394  		return;
      	math_error((void *)regs->eip);
      }
      
      /*
       * New motherboards sometimes make IRQ 13 be a PCI interrupt,
       * so allow interrupt sharing.
       */
      static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
      
      /*
       * IRQ2 is cascade interrupt to second interrupt controller
       */
      
      #ifndef CONFIG_VISWS
      static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
      #endif
      
      
 413  void __init init_ISA_irqs (void)
      {
      	int i;
      
      	init_8259A(0);
      
 419  	for (i = 0; i < NR_IRQS; i++) {
      		irq_desc[i].status = IRQ_DISABLED;
      		irq_desc[i].action = 0;
      		irq_desc[i].depth = 1;
      
 424  		if (i < 16) {
      			/*
      			 * 16 old-style INTA-cycle interrupts:
      			 */
      			irq_desc[i].handler = &i8259A_irq_type;
 429  		} else {
      			/*
      			 * 'high' PCI IRQs filled in on demand
      			 */
      			irq_desc[i].handler = &no_irq_type;
      		}
      	}
      }
      
 438  void __init init_IRQ(void)
      {
      	int i;
      
      #ifndef CONFIG_X86_VISWS_APIC
      	init_ISA_irqs();
      #else
      	init_VISWS_APIC_irqs();
      #endif
      	/*
      	 * Cover the whole vector space, no vector can escape
      	 * us. (some of these will be overridden and become
      	 * 'special' SMP interrupts)
      	 */
 452  	for (i = 0; i < NR_IRQS; i++) {
      		int vector = FIRST_EXTERNAL_VECTOR + i;
 454  		if (vector != SYSCALL_VECTOR) 
      			set_intr_gate(vector, interrupt[i]);
      	}
      
      #ifdef CONFIG_SMP
      	/*
      	 * IRQ0 must be given a fixed assignment and initialized,
      	 * because it's used before the IO-APIC is set up.
      	 */
      	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
      
      	/*
      	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
      	 * IPI, driven by wakeup.
      	 */
      	set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
      
      	/* IPI for invalidation */
      	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
      
      	/* IPI for generic function call */
      	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
      #endif	
      
      #ifdef CONFIG_X86_LOCAL_APIC
      	/* self generated IPI for local APIC timer */
      	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
      
      	/* IPI vectors for APIC spurious and error interrupts */
      	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
      	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
      #endif
      
      	/*
      	 * Set the clock to HZ Hz, we already have a valid
      	 * vector now:
      	 */
      	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
      	outb_p(LATCH & 0xff , 0x40);	/* LSB */
      	outb(LATCH >> 8 , 0x40);	/* MSB */
      
      #ifndef CONFIG_VISWS
      	setup_irq(2, &irq2);
      #endif
      
      	/*
      	 * External FPU? Set up irq13 if so, for
      	 * original braindamaged IBM FERR coupling.
      	 */
 503  	if (boot_cpu_data.hard_math && !cpu_has_fpu)
      		setup_irq(13, &irq13);
      }