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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef _ASM_HW_IRQ_H
  2. #define _ASM_HW_IRQ_H
  3. /*
  4.  * linux/include/asm/hw_irq.h
  5.  *
  6.  * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar
  7.  *
  8.  * moved some of the old arch/i386/kernel/irq.h to here. VY
  9.  *
  10.  * IRQ/IPI changes taken from work by Thomas Radke
  11.  * <tomsoft@informatik.tu-chemnitz.de>
  12.  */
  13. #include <linux/config.h>
  14. #include <asm/atomic.h>
  15. #include <asm/irq.h>
  16. /*
  17.  * IDT vectors usable for external interrupt sources start
  18.  * at 0x20:
  19.  */
  20. #define FIRST_EXTERNAL_VECTOR 0x20
  21. #define SYSCALL_VECTOR 0x80
  22. /*
  23.  * Vectors 0x20-0x2f are used for ISA interrupts.
  24.  */
  25. /*
  26.  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
  27.  *
  28.  *  some of the following vectors are 'rare', they are merged
  29.  *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
  30.  *  TLB, reschedule and local APIC vectors are performance-critical.
  31.  *
  32.  *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
  33.  */
  34. #define SPURIOUS_APIC_VECTOR 0xff
  35. #define ERROR_APIC_VECTOR 0xfe
  36. #define INVALIDATE_TLB_VECTOR 0xfd
  37. #define RESCHEDULE_VECTOR 0xfc
  38. #define CALL_FUNCTION_VECTOR 0xfb
  39. /*
  40.  * Local APIC timer IRQ vector is on a different priority level,
  41.  * to work around the 'lost local interrupt if more than 2 IRQ
  42.  * sources per level' errata.
  43.  */
  44. #define LOCAL_TIMER_VECTOR 0xef
  45. /*
  46.  * First APIC vector available to drivers: (vectors 0x30-0xee)
  47.  * we start at 0x31 to spread out vectors evenly between priority
  48.  * levels. (0x80 is the syscall vector)
  49.  */
  50. #define FIRST_DEVICE_VECTOR 0x31
  51. #define FIRST_SYSTEM_VECTOR 0xef
  52. extern int irq_vector[NR_IRQS];
  53. #define IO_APIC_VECTOR(irq) irq_vector[irq]
  54. /*
  55.  * Various low-level irq details needed by irq.c, process.c,
  56.  * time.c, io_apic.c and smp.c
  57.  *
  58.  * Interrupt entry/exit code at both C and assembly level
  59.  */
  60. extern void mask_irq(unsigned int irq);
  61. extern void unmask_irq(unsigned int irq);
  62. extern void disable_8259A_irq(unsigned int irq);
  63. extern void enable_8259A_irq(unsigned int irq);
  64. extern int i8259A_irq_pending(unsigned int irq);
  65. extern void make_8259A_irq(unsigned int irq);
  66. extern void init_8259A(int aeoi);
  67. extern void FASTCALL(send_IPI_self(int vector));
  68. extern void init_VISWS_APIC_irqs(void);
  69. extern void setup_IO_APIC(void);
  70. extern void disable_IO_APIC(void);
  71. extern void print_IO_APIC(void);
  72. extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
  73. extern void send_IPI(int dest, int vector);
  74. extern unsigned long io_apic_irqs;
  75. extern atomic_t irq_err_count;
  76. extern atomic_t irq_mis_count;
  77. extern char _stext, _etext;
  78. #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
  79. #define __STR(x) #x
  80. #define STR(x) __STR(x)
  81. #define SAVE_ALL 
  82. "cldnt" 
  83. "pushl %esnt" 
  84. "pushl %dsnt" 
  85. "pushl %eaxnt" 
  86. "pushl %ebpnt" 
  87. "pushl %edint" 
  88. "pushl %esint" 
  89. "pushl %edxnt" 
  90. "pushl %ecxnt" 
  91. "pushl %ebxnt" 
  92. "movl $" STR(__KERNEL_DS) ",%edxnt" 
  93. "movl %edx,%dsnt" 
  94. "movl %edx,%esnt"
  95. #define IRQ_NAME2(nr) nr##_interrupt(void)
  96. #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
  97. #define GET_CURRENT 
  98. "movl %esp, %ebxnt" 
  99. "andl $-8192, %ebxnt"
  100. /*
  101.  * SMP has a few special interrupts for IPI messages
  102.  */
  103. /* there is a second layer of macro just to get the symbolic
  104.    name for the vector evaluated. This change is for RTLinux */
  105. #define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
  106. #define XBUILD_SMP_INTERRUPT(x,v)
  107. asmlinkage void x(void); 
  108. asmlinkage void call_##x(void); 
  109. __asm__( 
  110. "n"__ALIGN_STR"n" 
  111. SYMBOL_NAME_STR(x) ":nt" 
  112. "pushl $"#v"-256nt" 
  113. SAVE_ALL 
  114. SYMBOL_NAME_STR(call_##x)":nt" 
  115. "call "SYMBOL_NAME_STR(smp_##x)"nt" 
  116. "jmp ret_from_intrn");
  117. #define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v)
  118. #define XBUILD_SMP_TIMER_INTERRUPT(x,v) 
  119. asmlinkage void x(struct pt_regs * regs); 
  120. asmlinkage void call_##x(void); 
  121. __asm__( 
  122. "n"__ALIGN_STR"n" 
  123. SYMBOL_NAME_STR(x) ":nt" 
  124. "pushl $"#v"-256nt" 
  125. SAVE_ALL 
  126. "movl %esp,%eaxnt" 
  127. "pushl %eaxnt" 
  128. SYMBOL_NAME_STR(call_##x)":nt" 
  129. "call "SYMBOL_NAME_STR(smp_##x)"nt" 
  130. "addl $4,%espnt" 
  131. "jmp ret_from_intrn");
  132. #define BUILD_COMMON_IRQ() 
  133. asmlinkage void call_do_IRQ(void); 
  134. __asm__( 
  135. "n" __ALIGN_STR"n" 
  136. "common_interrupt:nt" 
  137. SAVE_ALL 
  138. SYMBOL_NAME_STR(call_do_IRQ)":nt" 
  139. "call " SYMBOL_NAME_STR(do_IRQ) "nt" 
  140. "jmp ret_from_intrn");
  141. /* 
  142.  * subtle. orig_eax is used by the signal code to distinct between
  143.  * system calls and interrupted 'random user-space'. Thus we have
  144.  * to put a negative value into orig_eax here. (the problem is that
  145.  * both system calls and IRQs want to have small integer numbers in
  146.  * orig_eax, and the syscall code has won the optimization conflict ;)
  147.  *
  148.  * Subtle as a pigs ear.  VY
  149.  */
  150. #define BUILD_IRQ(nr) 
  151. asmlinkage void IRQ_NAME(nr); 
  152. __asm__( 
  153. "n"__ALIGN_STR"n" 
  154. SYMBOL_NAME_STR(IRQ) #nr "_interrupt:nt" 
  155. "pushl $"#nr"-256nt" 
  156. "jmp common_interrupt");
  157. extern unsigned long prof_cpu_mask;
  158. extern unsigned int * prof_buffer;
  159. extern unsigned long prof_len;
  160. extern unsigned long prof_shift;
  161. /*
  162.  * x86 profiling function, SMP safe. We might want to do this in
  163.  * assembly totally?
  164.  */
  165. static inline void x86_do_profile (unsigned long eip)
  166. {
  167. if (!prof_buffer)
  168. return;
  169. /*
  170.  * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
  171.  * (default is all CPUs.)
  172.  */
  173. if (!((1<<smp_processor_id()) & prof_cpu_mask))
  174. return;
  175. eip -= (unsigned long) &_stext;
  176. eip >>= prof_shift;
  177. /*
  178.  * Don't ignore out-of-bounds EIP values silently,
  179.  * put them into the last histogram slot, so if
  180.  * present, they will show up as a sharp peak.
  181.  */
  182. if (eip > prof_len-1)
  183. eip = prof_len-1;
  184. atomic_inc((atomic_t *)&prof_buffer[eip]);
  185. }
  186. #ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */
  187. static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
  188. if (IO_APIC_IRQ(i))
  189. send_IPI_self(IO_APIC_VECTOR(i));
  190. }
  191. #else
  192. static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
  193. #endif
  194. #endif /* _ASM_HW_IRQ_H */