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