|
|
1.1 ! root 1: #ifndef _ASM_IRQ_H ! 2: #define _ASM_IRQ_H ! 3: ! 4: /* ! 5: * linux/include/asm/irq.h ! 6: * ! 7: * (C) 1992, 1993 Linus Torvalds ! 8: * ! 9: * IRQ/IPI changes taken from work by Thomas Radke <[email protected]> ! 10: */ ! 11: ! 12: #include <linux/linkage.h> ! 13: #include <asm/segment.h> ! 14: ! 15: #define NR_IRQS 16 ! 16: ! 17: extern void disable_irq(unsigned int); ! 18: extern void enable_irq(unsigned int); ! 19: ! 20: #define __STR(x) #x ! 21: #define STR(x) __STR(x) ! 22: ! 23: #define SAVE_ALL \ ! 24: "cld\n\t" \ ! 25: "push %gs\n\t" \ ! 26: "push %fs\n\t" \ ! 27: "push %es\n\t" \ ! 28: "push %ds\n\t" \ ! 29: "pushl %eax\n\t" \ ! 30: "pushl %ebp\n\t" \ ! 31: "pushl %edi\n\t" \ ! 32: "pushl %esi\n\t" \ ! 33: "pushl %edx\n\t" \ ! 34: "pushl %ecx\n\t" \ ! 35: "pushl %ebx\n\t" \ ! 36: "movl $" STR(KERNEL_DS) ",%edx\n\t" \ ! 37: "mov %dx,%ds\n\t" \ ! 38: "mov %dx,%es\n\t" \ ! 39: "movl $" STR(USER_DS) ",%edx\n\t" \ ! 40: "mov %dx,%fs\n\t" \ ! 41: "movl $0,%edx\n\t" \ ! 42: "movl %edx,%db7\n\t" ! 43: ! 44: /* ! 45: * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, ! 46: * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't ! 47: * call the routines that do signal handling etc on return, and can have ! 48: * more relaxed register-saving etc. They are also atomic, and are thus ! 49: * suited for small, fast interrupts like the serial lines or the harddisk ! 50: * drivers, which don't actually need signal handling etc. ! 51: * ! 52: * Also note that we actually save only those registers that are used in ! 53: * C subroutines (%eax, %edx and %ecx), so if you do something weird, ! 54: * you're on your own. The only segments that are saved (not counting the ! 55: * automatic stack and code segment handling) are %ds and %es, and they ! 56: * point to kernel space. No messing around with %fs here. ! 57: */ ! 58: #define SAVE_MOST \ ! 59: "cld\n\t" \ ! 60: "push %es\n\t" \ ! 61: "push %ds\n\t" \ ! 62: "pushl %eax\n\t" \ ! 63: "pushl %edx\n\t" \ ! 64: "pushl %ecx\n\t" \ ! 65: "movl $" STR(KERNEL_DS) ",%edx\n\t" \ ! 66: "mov %dx,%ds\n\t" \ ! 67: "mov %dx,%es\n\t" ! 68: ! 69: #define RESTORE_MOST \ ! 70: "popl %ecx\n\t" \ ! 71: "popl %edx\n\t" \ ! 72: "popl %eax\n\t" \ ! 73: "pop %ds\n\t" \ ! 74: "pop %es\n\t" \ ! 75: "iret" ! 76: ! 77: /* ! 78: * The "inb" instructions are not needed, but seem to change the timings ! 79: * a bit - without them it seems that the harddisk driver won't work on ! 80: * all hardware. Arghh. ! 81: */ ! 82: #define ACK_FIRST(mask) \ ! 83: "inb $0x21,%al\n\t" \ ! 84: "jmp 1f\n" \ ! 85: "1:\tjmp 1f\n" \ ! 86: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \ ! 87: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ ! 88: "outb %al,$0x21\n\t" \ ! 89: "jmp 1f\n" \ ! 90: "1:\tjmp 1f\n" \ ! 91: "1:\tmovb $0x20,%al\n\t" \ ! 92: "outb %al,$0x20\n\t" ! 93: ! 94: #define ACK_SECOND(mask) \ ! 95: "inb $0xA1,%al\n\t" \ ! 96: "jmp 1f\n" \ ! 97: "1:\tjmp 1f\n" \ ! 98: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \ ! 99: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ ! 100: "outb %al,$0xA1\n\t" \ ! 101: "jmp 1f\n" \ ! 102: "1:\tjmp 1f\n" \ ! 103: "1:\tmovb $0x20,%al\n\t" \ ! 104: "outb %al,$0xA0\n\t" \ ! 105: "jmp 1f\n" \ ! 106: "1:\tjmp 1f\n" \ ! 107: "1:\toutb %al,$0x20\n\t" ! 108: ! 109: #define UNBLK_FIRST(mask) \ ! 110: "inb $0x21,%al\n\t" \ ! 111: "jmp 1f\n" \ ! 112: "1:\tjmp 1f\n" \ ! 113: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \ ! 114: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ ! 115: "outb %al,$0x21\n\t" ! 116: ! 117: #define UNBLK_SECOND(mask) \ ! 118: "inb $0xA1,%al\n\t" \ ! 119: "jmp 1f\n" \ ! 120: "1:\tjmp 1f\n" \ ! 121: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ ! 122: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ ! 123: "outb %al,$0xA1\n\t" ! 124: ! 125: #define IRQ_NAME2(nr) nr##_interrupt(void) ! 126: #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) ! 127: #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) ! 128: #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) ! 129: ! 130: #ifdef __SMP__ ! 131: ! 132: #ifndef __SMP_PROF__ ! 133: #define SMP_PROF_INT_SPINS ! 134: #define SMP_PROF_IPI_CNT ! 135: #else ! 136: #define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t" ! 137: #define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" ! 138: #endif ! 139: ! 140: #define GET_PROCESSOR_ID \ ! 141: "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \ ! 142: "movl 32(%edx), %eax\n\t" \ ! 143: "shrl $24,%eax\n\t" \ ! 144: "andb $0x0F,%al\n" ! 145: ! 146: #define ENTER_KERNEL \ ! 147: "pushl %eax\n\t" \ ! 148: "pushl %edx\n\t" \ ! 149: "pushfl\n\t" \ ! 150: "cli\n\t" \ ! 151: GET_PROCESSOR_ID \ ! 152: "1: " \ ! 153: "lock\n\t" \ ! 154: "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 155: "jnc 3f\n\t" \ ! 156: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \ ! 157: "je 4f\n\t" \ ! 158: "2: " \ ! 159: SMP_PROF_INT_SPINS \ ! 160: "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ ! 161: "jnc 5f\n\t" \ ! 162: "lock\n\t" \ ! 163: "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ ! 164: "jnc 5f\n\t" \ ! 165: "movl %cr3,%edx\n\t" \ ! 166: "movl %edx,%cr3\n" \ ! 167: "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 168: "jc 2b\n\t" \ ! 169: "jmp 1b\n\t" \ ! 170: "3: " \ ! 171: "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ ! 172: "4: " \ ! 173: "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ ! 174: "popfl\n\t" \ ! 175: "popl %edx\n\t" \ ! 176: "popl %eax\n\t" ! 177: ! 178: #define LEAVE_KERNEL \ ! 179: "pushfl\n\t" \ ! 180: "cli\n\t" \ ! 181: "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ ! 182: "jnz 1f\n\t" \ ! 183: "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ ! 184: "lock\n\t" \ ! 185: "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 186: "1: " \ ! 187: "popfl\n\t" ! 188: ! 189: ! 190: /* ! 191: * the syscall count inc is a gross hack because ret_from_syscall is used by both irq and ! 192: * syscall return paths (urghh). ! 193: */ ! 194: ! 195: #define BUILD_IRQ(chip,nr,mask) \ ! 196: asmlinkage void IRQ_NAME(nr); \ ! 197: asmlinkage void FAST_IRQ_NAME(nr); \ ! 198: asmlinkage void BAD_IRQ_NAME(nr); \ ! 199: __asm__( \ ! 200: "\n"__ALIGN_STR"\n" \ ! 201: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 202: "pushl $-"#nr"-2\n\t" \ ! 203: SAVE_ALL \ ! 204: ENTER_KERNEL \ ! 205: ACK_##chip(mask) \ ! 206: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 207: "sti\n\t" \ ! 208: "movl %esp,%ebx\n\t" \ ! 209: "pushl %ebx\n\t" \ ! 210: "pushl $" #nr "\n\t" \ ! 211: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 212: "addl $8,%esp\n\t" \ ! 213: "cli\n\t" \ ! 214: UNBLK_##chip(mask) \ ! 215: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 216: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 217: "jmp ret_from_sys_call\n" \ ! 218: "\n"__ALIGN_STR"\n" \ ! 219: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 220: SAVE_MOST \ ! 221: ENTER_KERNEL \ ! 222: ACK_##chip(mask) \ ! 223: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 224: "pushl $" #nr "\n\t" \ ! 225: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 226: "addl $4,%esp\n\t" \ ! 227: "cli\n\t" \ ! 228: UNBLK_##chip(mask) \ ! 229: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 230: LEAVE_KERNEL \ ! 231: RESTORE_MOST \ ! 232: "\n"__ALIGN_STR"\n" \ ! 233: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 234: SAVE_MOST \ ! 235: ENTER_KERNEL \ ! 236: ACK_##chip(mask) \ ! 237: LEAVE_KERNEL \ ! 238: RESTORE_MOST); ! 239: ! 240: ! 241: /* ! 242: * Message pass must be a fast IRQ.. ! 243: */ ! 244: ! 245: #define BUILD_MSGIRQ(chip,nr,mask) \ ! 246: asmlinkage void IRQ_NAME(nr); \ ! 247: asmlinkage void FAST_IRQ_NAME(nr); \ ! 248: asmlinkage void BAD_IRQ_NAME(nr); \ ! 249: __asm__( \ ! 250: "\n"__ALIGN_STR"\n" \ ! 251: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 252: "pushl $-"#nr"-2\n\t" \ ! 253: SAVE_ALL \ ! 254: ENTER_KERNEL \ ! 255: ACK_##chip(mask) \ ! 256: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 257: "sti\n\t" \ ! 258: "movl %esp,%ebx\n\t" \ ! 259: "pushl %ebx\n\t" \ ! 260: "pushl $" #nr "\n\t" \ ! 261: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 262: "addl $8,%esp\n\t" \ ! 263: "cli\n\t" \ ! 264: UNBLK_##chip(mask) \ ! 265: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 266: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 267: "jmp ret_from_sys_call\n" \ ! 268: "\n"__ALIGN_STR"\n" \ ! 269: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 270: SAVE_MOST \ ! 271: ACK_##chip(mask) \ ! 272: SMP_PROF_IPI_CNT \ ! 273: "pushl $" #nr "\n\t" \ ! 274: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 275: "addl $4,%esp\n\t" \ ! 276: "cli\n\t" \ ! 277: UNBLK_##chip(mask) \ ! 278: RESTORE_MOST \ ! 279: "\n"__ALIGN_STR"\n" \ ! 280: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 281: SAVE_MOST \ ! 282: ACK_##chip(mask) \ ! 283: RESTORE_MOST); ! 284: ! 285: #define BUILD_RESCHEDIRQ(nr) \ ! 286: asmlinkage void IRQ_NAME(nr); \ ! 287: __asm__( \ ! 288: "\n"__ALIGN_STR"\n" \ ! 289: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 290: "pushl $-"#nr"-2\n\t" \ ! 291: SAVE_ALL \ ! 292: ENTER_KERNEL \ ! 293: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 294: "sti\n\t" \ ! 295: "movl %esp,%ebx\n\t" \ ! 296: "pushl %ebx\n\t" \ ! 297: "pushl $" #nr "\n\t" \ ! 298: "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \ ! 299: "addl $8,%esp\n\t" \ ! 300: "cli\n\t" \ ! 301: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 302: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 303: "jmp ret_from_sys_call\n"); ! 304: #else ! 305: ! 306: #define BUILD_IRQ(chip,nr,mask) \ ! 307: asmlinkage void IRQ_NAME(nr); \ ! 308: asmlinkage void FAST_IRQ_NAME(nr); \ ! 309: asmlinkage void BAD_IRQ_NAME(nr); \ ! 310: __asm__( \ ! 311: "\n"__ALIGN_STR"\n" \ ! 312: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 313: "pushl $-"#nr"-2\n\t" \ ! 314: SAVE_ALL \ ! 315: ACK_##chip(mask) \ ! 316: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 317: "sti\n\t" \ ! 318: "movl %esp,%ebx\n\t" \ ! 319: "pushl %ebx\n\t" \ ! 320: "pushl $" #nr "\n\t" \ ! 321: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 322: "addl $8,%esp\n\t" \ ! 323: "cli\n\t" \ ! 324: UNBLK_##chip(mask) \ ! 325: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 326: "jmp ret_from_sys_call\n" \ ! 327: "\n"__ALIGN_STR"\n" \ ! 328: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 329: SAVE_MOST \ ! 330: ACK_##chip(mask) \ ! 331: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 332: "pushl $" #nr "\n\t" \ ! 333: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 334: "addl $4,%esp\n\t" \ ! 335: "cli\n\t" \ ! 336: UNBLK_##chip(mask) \ ! 337: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 338: RESTORE_MOST \ ! 339: "\n"__ALIGN_STR"\n" \ ! 340: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 341: SAVE_MOST \ ! 342: ACK_##chip(mask) \ ! 343: RESTORE_MOST); ! 344: ! 345: #endif ! 346: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.