1/* ______ ___ ___ 2 * /\ _ \ /\_ \ /\_ \ 3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ 4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ 5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ 6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ 7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ 8 * /\____/ 9 * \_/__/ 10 * 11 * The djgpp interrupt wrappers used by the stuff in djirq.c. 12 * 13 * By Shawn Hargreaves. 14 * 15 * Thanks to Marcel de Kogel for identifying the problems Allegro was 16 * having with reentrant interrupts, and for suggesting this solution. 17 * 18 * See readme.txt for copyright information. 19 */ 20 21 22#include "../i386/asmdefs.inc" 23 24.text 25 26 27 28#define WRAPPER(x) ; \ 29FUNC(_irq_wrapper_##x) ; \ 30 pushw %ds /* save registers */ ; \ 31 pushw %es ; \ 32 pushw %fs ; \ 33 pushw %gs ; \ 34 pushal ; \ 35 ; \ 36 .byte 0x2e /* cs: override */ ; \ 37 movw GLOBL(__djgpp_ds_alias), %ax ; \ 38 movw %ax, %ds /* set up selectors */ ; \ 39 movw %ax, %es ; \ 40 movw %ax, %fs ; \ 41 movw %ax, %gs ; \ 42 ; \ 43 movl $IRQ_STACKS-1, %ecx /* look for a free stack */ ; \ 44 ; \ 45stack_search_loop_##x: ; \ 46 leal GLOBL(_irq_stack)(, %ecx, 4), %ebx ; \ 47 cmpl $0, (%ebx) ; \ 48 jnz found_stack_##x /* found one! */ ; \ 49 ; \ 50 decl %ecx ; \ 51 jge stack_search_loop_##x ; \ 52 ; \ 53 jmp get_out_##x /* oh shit.. */ ; \ 54 ; \ 55found_stack_##x: ; \ 56 movl %esp, %ecx /* old stack in ecx + dx */ ; \ 57 movw %ss, %dx ; \ 58 ; \ 59 movl (%ebx), %esp /* set up our stack */ ; \ 60 movw %ax, %ss ; \ 61 ; \ 62 movl $0, (%ebx) /* flag the stack is in use */ ; \ 63 ; \ 64 pushl %edx /* push old stack onto new */ ; \ 65 pushl %ecx ; \ 66 pushl %ebx ; \ 67 ; \ 68 cld /* clear the direction flag */ ; \ 69 ; \ 70 movl GLOBL(_irq_handler) + IRQ_HANDLER + IRQ_SIZE*x, %eax ; \ 71 call *%eax /* call the C handler */ ; \ 72 ; \ 73 cli ; \ 74 ; \ 75 popl %ebx /* restore the old stack */ ; \ 76 popl %ecx ; \ 77 popl %edx ; \ 78 movl %esp, (%ebx) ; \ 79 movw %dx, %ss ; \ 80 movl %ecx, %esp ; \ 81 ; \ 82 orl %eax, %eax /* check return value */ ; \ 83 jz get_out_##x ; \ 84 ; \ 85 popal /* chain to old handler */ ; \ 86 popw %gs ; \ 87 popw %fs ; \ 88 popw %es ; \ 89 popw %ds ; \ 90 ljmp *%cs:GLOBL(_irq_handler) + IRQ_OLDVEC + IRQ_SIZE*x ; \ 91 ; \ 92get_out_##x: ; \ 93 popal /* iret */ ; \ 94 popw %gs ; \ 95 popw %fs ; \ 96 popw %es ; \ 97 popw %ds ; \ 98 sti ; \ 99 iret 100 101 102 103WRAPPER(0); 104WRAPPER(1); 105WRAPPER(2); 106WRAPPER(3); 107WRAPPER(4); 108WRAPPER(5); 109WRAPPER(6); 110WRAPPER(7); 111 112 113FUNC(_irq_wrapper_0_end) 114 ret 115 116