~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-i386/hw_irq.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.