irq.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

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