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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Carsten Langgaard, carstenl@mips.com
  3.  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
  4.  *
  5.  * ########################################################################
  6.  *
  7.  *  This program is free software; you can distribute it and/or modify it
  8.  *  under the terms of the GNU General Public License (Version 2) as
  9.  *  published by the Free Software Foundation.
  10.  *
  11.  *  This program is distributed in the hope it will be useful, but WITHOUT
  12.  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  *  for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License along
  17.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  18.  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  19.  *
  20.  * ########################################################################
  21.  *
  22.  * Routines for generic manipulation of the interrupts found on the MIPS
  23.  * Atlas board.
  24.  *
  25.  */
  26. #include <linux/config.h>
  27. #include <linux/init.h>
  28. #include <linux/sched.h>
  29. #include <linux/slab.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/kernel_stat.h>
  32. #include <asm/irq.h>
  33. #include <asm/mips-boards/atlas.h>
  34. #include <asm/mips-boards/atlasint.h>
  35. #include <asm/gdb-stub.h>
  36. struct atlas_ictrl_regs *atlas_hw0_icregs
  37. = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE;
  38. extern asmlinkage void mipsIRQ(void);
  39. extern void do_IRQ(int irq, struct pt_regs *regs);
  40. #if 0
  41. #define DEBUG_INT(x...) printk(x)
  42. #else
  43. #define DEBUG_INT(x...)
  44. #endif
  45. void disable_atlas_irq(unsigned int irq_nr)
  46. {
  47. atlas_hw0_icregs->intrsten = (1 << irq_nr);
  48. }
  49. void enable_atlas_irq(unsigned int irq_nr)
  50. {
  51. atlas_hw0_icregs->intseten = (1 << irq_nr);
  52. }
  53. static unsigned int startup_atlas_irq(unsigned int irq)
  54. {
  55. enable_atlas_irq(irq);
  56. return 0; /* never anything pending */
  57. }
  58. #define shutdown_atlas_irq disable_atlas_irq
  59. #define mask_and_ack_atlas_irq disable_atlas_irq
  60. static void end_atlas_irq(unsigned int irq)
  61. {
  62. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  63. enable_atlas_irq(irq);
  64. }
  65. static struct hw_interrupt_type atlas_irq_type = {
  66. "Atlas",
  67. startup_atlas_irq,
  68. shutdown_atlas_irq,
  69. enable_atlas_irq,
  70. disable_atlas_irq,
  71. mask_and_ack_atlas_irq,
  72. end_atlas_irq,
  73. NULL
  74. };
  75. static inline int ls1bit32(unsigned int x)
  76. {
  77. int b = 31, s;
  78. s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
  79. s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
  80. s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
  81. s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
  82. s =  1; if (x <<  1 == 0) s = 0; b -= s;
  83. return b;
  84. }
  85. void atlas_hw0_irqdispatch(struct pt_regs *regs)
  86. {
  87. struct irqaction *action;
  88. unsigned long int_status;
  89. int irq, cpu = smp_processor_id();
  90. int_status = atlas_hw0_icregs->intstatus;
  91. /* if int_status == 0, then the interrupt has already been cleared */
  92. if (int_status == 0)
  93. return;
  94. irq = ls1bit32(int_status);
  95. action = irq_desc[irq].action;
  96. DEBUG_INT("atlas_hw0_irqdispatch: irq=%dn", irq);
  97. /* if action == NULL, then we don't have a handler for the irq */
  98. if (action == NULL) {
  99. printk("No handler for hw0 irq: %in", irq);
  100. atomic_inc(&irq_err_count);
  101. return;
  102. }
  103. irq_enter(cpu, irq);
  104. kstat.irqs[0][irq]++;
  105. action->handler(irq, action->dev_id, regs);
  106. irq_exit(cpu, irq);
  107. return;
  108. }
  109. #ifdef CONFIG_REMOTE_DEBUG
  110. extern void breakpoint(void);
  111. extern int remote_debug;
  112. #endif
  113. void __init init_IRQ(void)
  114. {
  115. int i;
  116. /*
  117.  * Mask out all interrupt by writing "1" to all bit position in
  118.  * the interrupt reset reg.
  119.  */
  120. atlas_hw0_icregs->intrsten = 0xffffffff;
  121. /* Now safe to set the exception vector. */
  122. set_except_vector(0, mipsIRQ);
  123. for (i = 0; i <= ATLASINT_END; i++) {
  124. irq_desc[i].status = IRQ_DISABLED;
  125. irq_desc[i].action = 0;
  126. irq_desc[i].depth = 1;
  127. irq_desc[i].handler = &atlas_irq_type;
  128. }
  129. #ifdef CONFIG_REMOTE_DEBUG
  130. if (remote_debug) {
  131. set_debug_traps();
  132. breakpoint();
  133. }
  134. #endif
  135. }