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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1992 Linus Torvalds
  7.  * Copyright (C) 1994 - 2000 Ralf Baechle
  8.  */
  9. #include <linux/delay.h>
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/kernel.h>
  13. #include <linux/spinlock.h>
  14. #include <asm/io.h>
  15. #include <asm/sni.h>
  16. spinlock_t pciasic_lock = SPIN_LOCK_UNLOCKED;
  17. extern asmlinkage void sni_rm200_pci_handle_int(void);
  18. extern void do_IRQ(int irq, struct pt_regs *regs);
  19. static void enable_pciasic_irq(unsigned int irq);
  20. static unsigned int startup_pciasic_irq(unsigned int irq)
  21. {
  22. enable_pciasic_irq(irq);
  23. return 0; /* never anything pending */
  24. }
  25. #define shutdown_pciasic_irq disable_pciasic_irq
  26. void disable_pciasic_irq(unsigned int irq)
  27. {
  28. unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
  29. unsigned long flags;
  30. spin_lock_irqsave(&pciasic_lock, flags);
  31. *(volatile u8 *) PCIMT_IRQSEL &= mask;
  32. spin_unlock_irqrestore(&pciasic_lock, flags);
  33. }
  34. static void enable_pciasic_irq(unsigned int irq)
  35. {
  36. unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
  37. unsigned long flags;
  38. spin_lock_irqsave(&pciasic_lock, flags);
  39. *(volatile u8 *) PCIMT_IRQSEL |= mask;
  40. spin_unlock_irqrestore(&pciasic_lock, flags);
  41. }
  42. #define mask_and_ack_pciasic_irq disable_pciasic_irq
  43. static void end_pciasic_irq(unsigned int irq)
  44. {
  45. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  46. enable_pciasic_irq(irq);
  47. }
  48. static struct hw_interrupt_type pciasic_irq_type = {
  49. "PCIASIC",
  50. startup_pciasic_irq,
  51. shutdown_pciasic_irq,
  52. enable_pciasic_irq,
  53. disable_pciasic_irq,
  54. mask_and_ack_pciasic_irq,
  55. end_pciasic_irq,
  56. NULL
  57. };
  58. /*
  59.  * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
  60.  * button interrupts.  Later ...
  61.  */
  62. void pciasic_hwint0(struct pt_regs *regs)
  63. {
  64. panic("Received int0 but no handler yet ...");
  65. }
  66. /* This interrupt was used for the com1 console on the first prototypes.  */
  67. void pciasic_hwint2(struct pt_regs *regs)
  68. {
  69. /* I think this shouldn't happen on production machines.  */
  70. panic("hwint2 and no handler yet");
  71. }
  72. /* hwint5 is the r4k count / compare interrupt  */
  73. void pciasic_hwint5(struct pt_regs *regs)
  74. {
  75. panic("hwint5 and no handler yet");
  76. }
  77. static inline int ls1bit8(unsigned int x)
  78. {
  79. int b = 8, s;
  80. x <<= 24;
  81. s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
  82. s = 2; if ((x & 0x03) == 0) s = 0; b -= s; x <<= s;
  83. s = 1; if ((x & 0x01) == 0) s = 0; b -= s;
  84. return b;
  85. }
  86. /*
  87.  * hwint 1 deals with EISA and SCSI interrupts,
  88.  * hwint 3 should deal with the PCI A - D interrupts,
  89.  * hwint 4 is used for only the onboard PCnet 32.
  90.  */
  91. void pciasic_hwint134(struct pt_regs *regs)
  92. {
  93. u8 pend = *(volatile char *)PCIMT_CSITPEND;
  94. int irq;
  95. irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
  96. if (irq == PCIMT_IRQ_EISA) {
  97. pend = *(volatile char *)PCIMT_INT_ACKNOWLEDGE;
  98. if (!(pend ^ 0xff))
  99. return;
  100. }
  101. do_IRQ(irq, regs);
  102. return;
  103. }
  104. void __init init_pciasic(void)
  105. {
  106. unsigned long flags;
  107. spin_lock_irqsave(&pciasic_lock, flags);
  108. * (volatile u8 *) PCIMT_IRQSEL =
  109. IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
  110. spin_unlock_irqrestore(&pciasic_lock, flags);
  111. }
  112. /*
  113.  * On systems with i8259-style interrupt controllers we assume for
  114.  * driver compatibility reasons interrupts 0 - 15 to be the i8295
  115.  * interrupts even if the hardware uses a different interrupt numbering.
  116.  */
  117. void __init init_IRQ (void)
  118. {
  119. int i;
  120. set_except_vector(0, sni_rm200_pci_handle_int);
  121. init_generic_irq();
  122. init_i8259_irqs(); /* Integrated i8259  */
  123. init_pciasic();
  124. /* Actually we've got more interrupts to handle ...  */
  125. for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
  126. irq_desc[i].status     = IRQ_DISABLED;
  127. irq_desc[i].action     = 0;
  128. irq_desc[i].depth      = 1;
  129. irq_desc[i].handler    = &pciasic_irq_type;
  130. }
  131. }