i8259.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <linux/linkage.h>
  2. #include <linux/config.h>
  3. #include <linux/ptrace.h>
  4. #include <linux/errno.h>
  5. #include <linux/signal.h>
  6. #include <linux/sched.h>
  7. #include <linux/ioport.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/timex.h>
  10. #include <linux/slab.h>
  11. #include <linux/random.h>
  12. #include <linux/smp_lock.h>
  13. #include <linux/init.h>
  14. #include <linux/kernel_stat.h>
  15. #include <asm/atomic.h>
  16. #include <asm/system.h>
  17. #include <asm/io.h>
  18. #include <asm/irq.h>
  19. #include <asm/hw_irq.h>
  20. #include <asm/bitops.h>
  21. #include <asm/pgtable.h>
  22. #include <asm/delay.h>
  23. #include <asm/desc.h>
  24. #include <asm/apic.h>
  25. #include <linux/irq.h>
  26. /* When we have things working, we can switch to always use
  27.    IOAPIC. --pavel */
  28. /*
  29.  * Common place to define all x86 IRQ vectors
  30.  *
  31.  * This builds up the IRQ handler stubs using some ugly macros in irq.h
  32.  *
  33.  * These macros create the low-level assembly IRQ routines that save
  34.  * register context and call do_IRQ(). do_IRQ() then does all the
  35.  * operations that are needed to keep the AT (or SMP IOAPIC)
  36.  * interrupt-controller happy.
  37.  */
  38. BUILD_COMMON_IRQ()
  39. #define BI(x,y) 
  40. BUILD_IRQ(x##y)
  41. #define BUILD_16_IRQS(x) 
  42. BI(x,0) BI(x,1) BI(x,2) BI(x,3) 
  43. BI(x,4) BI(x,5) BI(x,6) BI(x,7) 
  44. BI(x,8) BI(x,9) BI(x,a) BI(x,b) 
  45. BI(x,c) BI(x,d) BI(x,e) BI(x,f)
  46. /*
  47.  * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
  48.  * (these are usually mapped to vectors 0x20-0x2f)
  49.  */
  50. BUILD_16_IRQS(0x0)
  51. #ifdef CONFIG_X86_IO_APIC
  52. /*
  53.  * The IO-APIC gives us many more interrupt sources. Most of these
  54.  * are unused but an SMP system is supposed to have enough memory ...
  55.  * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
  56.  * across the spectrum, so we really want to be prepared to get all
  57.  * of these. Plus, more powerful systems might have more than 64
  58.  * IO-APIC registers.
  59.  *
  60.  * (these are usually mapped into the 0x30-0xff vector range)
  61.  */
  62.    BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
  63. BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
  64. BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
  65. BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
  66. #endif
  67. #undef BUILD_16_IRQS
  68. #undef BI
  69. /*
  70.  * The following vectors are part of the Linux architecture, there
  71.  * is no hardware IRQ pin equivalent for them, they are triggered
  72.  * through the ICC by us (IPIs)
  73.  */
  74. #ifdef CONFIG_SMP
  75. BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR);
  76. BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR);
  77. BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR);
  78. #endif
  79. #ifdef CONFIG_X86_LOCAL_APIC
  80. BUILD_SMP_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR);
  81. BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR);
  82. BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR);
  83. #endif
  84. #define IRQ(x,y) 
  85. IRQ##x##y##_interrupt
  86. #define IRQLIST_16(x) 
  87. IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), 
  88. IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), 
  89. IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), 
  90. IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
  91. void (*interrupt[NR_IRQS])(void) = {
  92. IRQLIST_16(0x0),
  93. #ifdef CONFIG_X86_IO_APIC
  94.  IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
  95. IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
  96. IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
  97. IRQLIST_16(0xc), IRQLIST_16(0xd)
  98. #endif
  99. };
  100. #undef IRQ
  101. #undef IRQLIST_16
  102. /*
  103.  * This is the 'legacy' 8259A Programmable Interrupt Controller,
  104.  * present in the majority of PC/AT boxes.
  105.  * plus some generic x86 specific things if generic specifics makes
  106.  * any sense at all.
  107.  * this file should become arch/i386/kernel/irq.c when the old irq.c
  108.  * moves to arch independent land
  109.  */
  110. spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
  111. static void end_8259A_irq (unsigned int irq)
  112. {
  113. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  114. enable_8259A_irq(irq);
  115. }
  116. #define shutdown_8259A_irq disable_8259A_irq
  117.  void mask_and_ack_8259A(unsigned int);
  118. static unsigned int startup_8259A_irq(unsigned int irq)
  119. {
  120. enable_8259A_irq(irq);
  121. return 0; /* never anything pending */
  122. }
  123. static struct hw_interrupt_type i8259A_irq_type = {
  124. "XT-PIC",
  125. startup_8259A_irq,
  126. shutdown_8259A_irq,
  127. enable_8259A_irq,
  128. disable_8259A_irq,
  129. mask_and_ack_8259A,
  130. end_8259A_irq,
  131. NULL
  132. };
  133. /*
  134.  * 8259A PIC functions to handle ISA devices:
  135.  */
  136. /*
  137.  * This contains the irq mask for both 8259A irq controllers,
  138.  */
  139. static unsigned int cached_irq_mask = 0xffff;
  140. #define __byte(x,y) (((unsigned char *)&(y))[x])
  141. #define cached_21 (__byte(0,cached_irq_mask))
  142. #define cached_A1 (__byte(1,cached_irq_mask))
  143. /*
  144.  * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
  145.  * boards the timer interrupt is not really connected to any IO-APIC pin,
  146.  * it's fed to the master 8259A's IR0 line only.
  147.  *
  148.  * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
  149.  * this 'mixed mode' IRQ handling costs nothing because it's only used
  150.  * at IRQ setup time.
  151.  */
  152. unsigned long io_apic_irqs;
  153. void disable_8259A_irq(unsigned int irq)
  154. {
  155. unsigned int mask = 1 << irq;
  156. unsigned long flags;
  157. spin_lock_irqsave(&i8259A_lock, flags);
  158. cached_irq_mask |= mask;
  159. if (irq & 8)
  160. outb(cached_A1,0xA1);
  161. else
  162. outb(cached_21,0x21);
  163. spin_unlock_irqrestore(&i8259A_lock, flags);
  164. }
  165. void enable_8259A_irq(unsigned int irq)
  166. {
  167. unsigned int mask = ~(1 << irq);
  168. unsigned long flags;
  169. spin_lock_irqsave(&i8259A_lock, flags);
  170. cached_irq_mask &= mask;
  171. if (irq & 8)
  172. outb(cached_A1,0xA1);
  173. else
  174. outb(cached_21,0x21);
  175. spin_unlock_irqrestore(&i8259A_lock, flags);
  176. }
  177. int i8259A_irq_pending(unsigned int irq)
  178. {
  179. unsigned int mask = 1<<irq;
  180. unsigned long flags;
  181. int ret;
  182. spin_lock_irqsave(&i8259A_lock, flags);
  183. if (irq < 8)
  184. ret = inb(0x20) & mask;
  185. else
  186. ret = inb(0xA0) & (mask >> 8);
  187. spin_unlock_irqrestore(&i8259A_lock, flags);
  188. return ret;
  189. }
  190. void make_8259A_irq(unsigned int irq)
  191. {
  192. disable_irq_nosync(irq);
  193. io_apic_irqs &= ~(1<<irq);
  194. irq_desc[irq].handler = &i8259A_irq_type;
  195. enable_irq(irq);
  196. }
  197. /*
  198.  * This function assumes to be called rarely. Switching between
  199.  * 8259A registers is slow.
  200.  * This has to be protected by the irq controller spinlock
  201.  * before being called.
  202.  */
  203. static inline int i8259A_irq_real(unsigned int irq)
  204. {
  205. int value;
  206. int irqmask = 1<<irq;
  207. if (irq < 8) {
  208. outb(0x0B,0x20); /* ISR register */
  209. value = inb(0x20) & irqmask;
  210. outb(0x0A,0x20); /* back to the IRR register */
  211. return value;
  212. }
  213. outb(0x0B,0xA0); /* ISR register */
  214. value = inb(0xA0) & (irqmask >> 8);
  215. outb(0x0A,0xA0); /* back to the IRR register */
  216. return value;
  217. }
  218. /*
  219.  * Careful! The 8259A is a fragile beast, it pretty
  220.  * much _has_ to be done exactly like this (mask it
  221.  * first, _then_ send the EOI, and the order of EOI
  222.  * to the two 8259s is important!
  223.  */
  224. void mask_and_ack_8259A(unsigned int irq)
  225. {
  226. unsigned int irqmask = 1 << irq;
  227. unsigned long flags;
  228. spin_lock_irqsave(&i8259A_lock, flags);
  229. /*
  230.  * Lightweight spurious IRQ detection. We do not want
  231.  * to overdo spurious IRQ handling - it's usually a sign
  232.  * of hardware problems, so we only do the checks we can
  233.  * do without slowing down good hardware unnecesserily.
  234.  *
  235.  * Note that IRQ7 and IRQ15 (the two spurious IRQs
  236.  * usually resulting from the 8259A-1|2 PICs) occur
  237.  * even if the IRQ is masked in the 8259A. Thus we
  238.  * can check spurious 8259A IRQs without doing the
  239.  * quite slow i8259A_irq_real() call for every IRQ.
  240.  * This does not cover 100% of spurious interrupts,
  241.  * but should be enough to warn the user that there
  242.  * is something bad going on ...
  243.  */
  244. if (cached_irq_mask & irqmask)
  245. goto spurious_8259A_irq;
  246. cached_irq_mask |= irqmask;
  247. handle_real_irq:
  248. if (irq & 8) {
  249. inb(0xA1); /* DUMMY - (do we need this?) */
  250. outb(cached_A1,0xA1);
  251. outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
  252. outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
  253. } else {
  254. inb(0x21); /* DUMMY - (do we need this?) */
  255. outb(cached_21,0x21);
  256. outb(0x60+irq,0x20); /* 'Specific EOI' to master */
  257. }
  258. spin_unlock_irqrestore(&i8259A_lock, flags);
  259. return;
  260. spurious_8259A_irq:
  261. /*
  262.  * this is the slow path - should happen rarely.
  263.  */
  264. if (i8259A_irq_real(irq))
  265. /*
  266.  * oops, the IRQ _is_ in service according to the
  267.  * 8259A - not spurious, go handle it.
  268.  */
  269. goto handle_real_irq;
  270. {
  271. static int spurious_irq_mask;
  272. /*
  273.  * At this point we can be sure the IRQ is spurious,
  274.  * lets ACK and report it. [once per IRQ]
  275.  */
  276. if (!(spurious_irq_mask & irqmask)) {
  277. printk("spurious 8259A interrupt: IRQ%d.n", irq);
  278. spurious_irq_mask |= irqmask;
  279. }
  280. atomic_inc(&irq_err_count);
  281. /*
  282.  * Theoretically we do not have to handle this IRQ,
  283.  * but in Linux this does not cause problems and is
  284.  * simpler for us.
  285.  */
  286. goto handle_real_irq;
  287. }
  288. }
  289. void __init init_8259A(int auto_eoi)
  290. {
  291. unsigned long flags;
  292. spin_lock_irqsave(&i8259A_lock, flags);
  293. outb(0xff, 0x21); /* mask all of 8259A-1 */
  294. outb(0xff, 0xA1); /* mask all of 8259A-2 */
  295. /*
  296.  * outb_p - this has to work on a wide range of PC hardware.
  297.  */
  298. outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
  299. outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
  300. outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
  301. if (auto_eoi)
  302. outb_p(0x03, 0x21); /* master does Auto EOI */
  303. else
  304. outb_p(0x01, 0x21); /* master expects normal EOI */
  305. outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
  306. outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
  307. outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
  308. outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
  309.     is to be investigated) */
  310. if (auto_eoi)
  311. /*
  312.  * in AEOI mode we just have to mask the interrupt
  313.  * when acking.
  314.  */
  315. i8259A_irq_type.ack = disable_8259A_irq;
  316. else
  317. i8259A_irq_type.ack = mask_and_ack_8259A;
  318. udelay(100); /* wait for 8259A to initialize */
  319. outb(cached_21, 0x21); /* restore master IRQ mask */
  320. outb(cached_A1, 0xA1); /* restore slave IRQ mask */
  321. spin_unlock_irqrestore(&i8259A_lock, flags);
  322. }
  323. /*
  324.  * IRQ2 is cascade interrupt to second interrupt controller
  325.  */
  326. static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
  327. void __init init_ISA_irqs (void)
  328. {
  329. int i;
  330. #ifdef CONFIG_X86_LOCAL_APIC
  331. init_bsp_APIC();
  332. #endif
  333. init_8259A(0);
  334. for (i = 0; i < NR_IRQS; i++) {
  335. irq_desc[i].status = IRQ_DISABLED;
  336. irq_desc[i].action = 0;
  337. irq_desc[i].depth = 1;
  338. if (i < 16) {
  339. /*
  340.  * 16 old-style INTA-cycle interrupts:
  341.  */
  342. irq_desc[i].handler = &i8259A_irq_type;
  343. } else {
  344. /*
  345.  * 'high' PCI IRQs filled in on demand
  346.  */
  347. irq_desc[i].handler = &no_irq_type;
  348. }
  349. }
  350. }
  351. void __init init_IRQ(void)
  352. {
  353. int i;
  354. #ifndef CONFIG_X86_VISWS_APIC
  355. init_ISA_irqs();
  356. #else
  357. init_VISWS_APIC_irqs();
  358. #endif
  359. /*
  360.  * Cover the whole vector space, no vector can escape
  361.  * us. (some of these will be overridden and become
  362.  * 'special' SMP interrupts)
  363.  */
  364. for (i = 0; i < NR_IRQS; i++) {
  365. int vector = FIRST_EXTERNAL_VECTOR + i;
  366. if (vector != IA32_SYSCALL_VECTOR && vector != KDBENTER_VECTOR) {
  367. set_intr_gate(vector, interrupt[i]);
  368. }
  369. }
  370. #ifdef CONFIG_SMP
  371. /*
  372.  * IRQ0 must be given a fixed assignment and initialized,
  373.  * because it's used before the IO-APIC is set up.
  374.  */
  375. set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
  376. /*
  377.  * The reschedule interrupt is a CPU-to-CPU reschedule-helper
  378.  * IPI, driven by wakeup.
  379.  */
  380. set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
  381. /* IPI for invalidation */
  382. set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
  383. /* IPI for generic function call */
  384. set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
  385. #endif
  386. #ifdef CONFIG_X86_LOCAL_APIC
  387. /* self generated IPI for local APIC timer */
  388. set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
  389. /* IPI vectors for APIC spurious and error interrupts */
  390. set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
  391. set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
  392. #endif
  393. #ifndef CONFIG_VISWS
  394. setup_irq(2, &irq2);
  395. #endif
  396. }