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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file COPYING in the main directory of this archive
  6.  * for more details.
  7.  *
  8.  * 07/03/96: Timer initialization, and thus mach_sched_init(),
  9.  *           removed from request_irq() and moved to init_time().
  10.  *           We should therefore consider renaming our add_isr() and
  11.  *           remove_isr() to request_irq() and free_irq()
  12.  *           respectively, so they are compliant with the other
  13.  *           architectures.                                     /Jes
  14.  * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
  15.  *           Removed irq list support, if any machine needs an irq server
  16.  *           it must implement this itself (as it's already done), instead
  17.  *           only default handler are used with mach_default_handler.
  18.  *           request_irq got some flags different from other architectures:
  19.  *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
  20.  *                               can be replaced without this flag)
  21.  *           - IRQ_FLG_LOCK : handler can't be replaced
  22.  *           There are other machine depending flags, see there
  23.  *           If you want to replace a default handler you should know what
  24.  *           you're doing, since it might handle different other irq sources
  25.  *           which must be served                               /Roman Zippel
  26.  */
  27. #include <linux/config.h>
  28. #include <linux/types.h>
  29. #include <linux/sched.h>
  30. #include <linux/kernel_stat.h>
  31. #include <linux/errno.h>
  32. #include <linux/init.h>
  33. #include <asm/setup.h>
  34. #include <asm/system.h>
  35. #include <asm/irq.h>
  36. #include <asm/traps.h>
  37. #include <asm/page.h>
  38. #include <asm/machdep.h>
  39. #ifdef CONFIG_Q40
  40. #include <asm/q40ints.h>
  41. #endif
  42. /* table for system interrupt handlers */
  43. static irq_handler_t irq_list[SYS_IRQS];
  44. static const char *default_names[SYS_IRQS] = {
  45. "spurious int", "int1 handler", "int2 handler", "int3 handler",
  46. "int4 handler", "int5 handler", "int6 handler", "int7 handler"
  47. };
  48. /* The number of spurious interrupts */
  49. volatile unsigned int num_spurious;
  50. #define NUM_IRQ_NODES 100
  51. static irq_node_t nodes[NUM_IRQ_NODES];
  52. static void dummy_enable_irq(unsigned int irq);
  53. static void dummy_disable_irq(unsigned int irq);
  54. static int dummy_request_irq(unsigned int irq,
  55. void (*handler) (int, void *, struct pt_regs *),
  56. unsigned long flags, const char *devname, void *dev_id);
  57. static void dummy_free_irq(unsigned int irq, void *dev_id);
  58. void (*enable_irq) (unsigned int) = dummy_enable_irq;
  59. void (*disable_irq) (unsigned int) = dummy_disable_irq;
  60. int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
  61.                       unsigned long, const char *, void *) = dummy_request_irq;
  62. void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
  63. void init_irq_proc(void);
  64. /*
  65.  * void init_IRQ(void)
  66.  *
  67.  * Parameters: None
  68.  *
  69.  * Returns: Nothing
  70.  *
  71.  * This function should be called during kernel startup to initialize
  72.  * the IRQ handling routines.
  73.  */
  74. void __init init_IRQ(void)
  75. {
  76. int i;
  77. for (i = 0; i < SYS_IRQS; i++) {
  78. if (mach_default_handler)
  79. irq_list[i].handler = (*mach_default_handler)[i];
  80. irq_list[i].flags   = 0;
  81. irq_list[i].dev_id  = NULL;
  82. irq_list[i].devname = default_names[i];
  83. }
  84. for (i = 0; i < NUM_IRQ_NODES; i++)
  85. nodes[i].handler = NULL;
  86. mach_init_IRQ ();
  87. }
  88. irq_node_t *new_irq_node(void)
  89. {
  90. irq_node_t *node;
  91. short i;
  92. for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
  93. if (!node->handler)
  94. return node;
  95. printk ("new_irq_node: out of nodesn");
  96. return NULL;
  97. }
  98. /*
  99.  * We will keep these functions until I have convinced Linus to move
  100.  * the declaration of them from include/linux/sched.h to
  101.  * include/asm/irq.h.
  102.  */
  103. int request_irq(unsigned int irq,
  104. void (*handler) (int, void *, struct pt_regs *),
  105. unsigned long flags, const char *devname, void *dev_id)
  106. {
  107. return mach_request_irq(irq, handler, flags, devname, dev_id);
  108. }
  109. void free_irq(unsigned int irq, void *dev_id)
  110. {
  111. mach_free_irq(irq, dev_id);
  112. }
  113. int sys_request_irq(unsigned int irq, 
  114.                     void (*handler)(int, void *, struct pt_regs *), 
  115.                     unsigned long flags, const char *devname, void *dev_id)
  116. {
  117. if (irq < IRQ1 || irq > IRQ7) {
  118. printk("%s: Incorrect IRQ %d from %sn",
  119.        __FUNCTION__, irq, devname);
  120. return -ENXIO;
  121. }
  122. #if 0
  123. if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
  124. if (irq_list[irq].flags & IRQ_FLG_LOCK) {
  125. printk("%s: IRQ %d from %s is not replaceablen",
  126.        __FUNCTION__, irq, irq_list[irq].devname);
  127. return -EBUSY;
  128. }
  129. if (!(flags & IRQ_FLG_REPLACE)) {
  130. printk("%s: %s can't replace IRQ %d from %sn",
  131.        __FUNCTION__, devname, irq, irq_list[irq].devname);
  132. return -EBUSY;
  133. }
  134. }
  135. #endif
  136. irq_list[irq].handler = handler;
  137. irq_list[irq].flags   = flags;
  138. irq_list[irq].dev_id  = dev_id;
  139. irq_list[irq].devname = devname;
  140. return 0;
  141. }
  142. void sys_free_irq(unsigned int irq, void *dev_id)
  143. {
  144. if (irq < IRQ1 || irq > IRQ7) {
  145. printk("%s: Incorrect IRQ %dn", __FUNCTION__, irq);
  146. return;
  147. }
  148. if (irq_list[irq].dev_id != dev_id)
  149. printk("%s: Removing probably wrong IRQ %d from %sn",
  150.        __FUNCTION__, irq, irq_list[irq].devname);
  151. irq_list[irq].handler = (*mach_default_handler)[irq];
  152. irq_list[irq].flags   = 0;
  153. irq_list[irq].dev_id  = NULL;
  154. irq_list[irq].devname = default_names[irq];
  155. }
  156. /*
  157.  * Do we need these probe functions on the m68k?
  158.  *
  159.  *  ... may be useful with ISA devices
  160.  */
  161. unsigned long probe_irq_on (void)
  162. {
  163. #ifdef CONFIG_Q40
  164. if (MACH_IS_Q40)
  165. return q40_probe_irq_on();
  166. #endif
  167. return 0;
  168. }
  169. int probe_irq_off (unsigned long irqs)
  170. {
  171. #ifdef CONFIG_Q40
  172. if (MACH_IS_Q40)
  173. return q40_probe_irq_off(irqs);
  174. #endif
  175. return 0;
  176. }
  177. static void dummy_enable_irq(unsigned int irq)
  178. {
  179. printk("calling uninitialized enable_irq()n");
  180. }
  181. static void dummy_disable_irq(unsigned int irq)
  182. {
  183. printk("calling uninitialized disable_irq()n");
  184. }
  185. static int dummy_request_irq(unsigned int irq,
  186. void (*handler) (int, void *, struct pt_regs *),
  187. unsigned long flags, const char *devname, void *dev_id)
  188. {
  189. printk("calling uninitialized request_irq()n");
  190. return 0;
  191. }
  192. static void dummy_free_irq(unsigned int irq, void *dev_id)
  193. {
  194. printk("calling uninitialized disable_irq()n");
  195. }
  196. asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
  197. {
  198. if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
  199. vec -= VEC_SPUR;
  200. kstat.irqs[0][vec]++;
  201. irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
  202. } else {
  203. if (mach_process_int)
  204. mach_process_int(vec, fp);
  205. else
  206. panic("Can't process interrupt vector %ldn", vec);
  207. return;
  208. }
  209. }
  210. int get_irq_list(char *buf)
  211. {
  212. int i, len = 0;
  213. /* autovector interrupts */
  214. if (mach_default_handler) {
  215. for (i = 0; i < SYS_IRQS; i++) {
  216. len += sprintf(buf+len, "auto %2d: %10u ", i,
  217.                i ? kstat.irqs[0][i] : num_spurious);
  218. len += sprintf(buf+len, "  ");
  219. len += sprintf(buf+len, "%sn", irq_list[i].devname);
  220. }
  221. }
  222. len += mach_get_irq_list(buf+len);
  223. return len;
  224. }
  225. void init_irq_proc(void)
  226. {
  227. /* Insert /proc/irq driver here */
  228. }