Moved input stuff to arch subdirs, as in d1x.
[btb/d2x.git] / arch / dos / comm / irqwrap.S
1 /*
2  * This file is part of DZComm.
3  * Version : 0.6
4  * Minor changes by Dim Zegebart (zager@post.comstar.ru) to run with Palantir
5  */
6
7 /*         ______   ___    ___
8  *        /\  _  \ /\_ \  /\_ \
9  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
10  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
11  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
12  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
13  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
14  *                                           /\____/
15  *                                           \_/__/
16  *      By Shawn Hargreaves,
17  *      1 Salisbury Road,
18  *      Market Drayton,
19  *      Shropshire,
20  *      England, TF9 1AJ.
21  *
22  *      The hardware interrupt wrappers used by the stuff in irq.c.
23  *
24  *      Thanks to Marcel de Kogel for identifying the problems Allegro was
25  *      having with reentrant interrupts, and for suggesting this solution.
26  *
27  *      See readme.txt for copyright information.
28  */
29
30
31 #ifndef DJGPP
32 #error This file should only be used by the djgpp version of Allegro
33 #endif
34
35 #include "asmdefs.inc"
36
37 .text
38
39
40
41 #define WRAPPER(x)                                                         ; \
42 .globl __irq_wrapper_##x                                                   ; \
43    .align 4                                                                ; \
44 __irq_wrapper_##x:                                                         ; \
45    pushw %ds                              /* save registers */             ; \
46    pushw %es                                                               ; \
47    pushw %fs                                                               ; \
48    pushw %gs                                                               ; \
49    pushal                                                                  ; \
50                                                                            ; \
51    .byte 0x2e                             /* cs: override */               ; \
52    movw ___djgpp_ds_alias, %ax                                             ; \
53    movw %ax, %ds                          /* set up selectors */           ; \
54    movw %ax, %es                                                           ; \
55    movw %ax, %fs                                                           ; \
56    movw %ax, %gs                                                           ; \
57                                                                            ; \
58    movl $IRQ_STACKS-1, %ecx               /* look for a free stack */      ; \
59                                                                            ; \
60 stack_search_loop_##x:                                                     ; \
61    leal __irq_stack(, %ecx, 4), %ebx                                       ; \
62    cmpl $0, (%ebx)                                                         ; \
63    jnz found_stack_##x                    /* found one! */                 ; \
64                                                                            ; \
65    decl %ecx                                                               ; \
66    jge stack_search_loop_##x                                               ; \
67                                                                            ; \
68    jmp get_out_##x                        /* oh shit.. */                  ; \
69                                                                            ; \
70 found_stack_##x:                                                           ; \
71    movl %esp, %ecx                        /* old stack in ecx + dx */      ; \
72    movw %ss, %dx                                                           ; \
73                                                                            ; \
74    movl (%ebx), %esp                      /* set up our stack */           ; \
75    movw %ax, %ss                                                           ; \
76                                                                            ; \
77    movl $0, (%ebx)                        /* flag the stack is in use */   ; \
78                                                                            ; \
79    pushl %edx                             /* push old stack onto new */    ; \
80    pushl %ecx                                                              ; \
81    pushl %ebx                                                              ; \
82                                                                            ; \
83    cld                                    /* clear the direction flag */   ; \
84                                                                            ; \
85    movl __irq_handler + IRQ_HANDLER + IRQ_SIZE*x, %eax                     ; \
86    call *%eax                             /* call the C handler */         ; \
87                                                                            ; \
88    popl %ebx                              /* restore the old stack */      ; \
89    popl %ecx                                                               ; \
90    popl %edx                                                               ; \
91    movl %esp, (%ebx)                                                       ; \
92    movw %dx, %ss                                                           ; \
93    movl %ecx, %esp                                                         ; \
94                                                                            ; \
95    orl %eax, %eax                         /* check return value */         ; \
96    jz get_out_##x                                                          ; \
97                                                                            ; \
98    popal                                  /* chain to old handler */       ; \
99    popw %gs                                                                ; \
100    popw %fs                                                                ; \
101    popw %es                                                                ; \
102    popw %ds                                                                ; \
103    ljmp %cs:__irq_handler + IRQ_OLDVEC + IRQ_SIZE*x                        ; \
104                                                                            ; \
105 get_out_##x:                                                               ; \
106    popal                                  /* iret */                       ; \
107    popw %gs                                                                ; \
108    popw %fs                                                                ; \
109    popw %es                                                                ; \
110    popw %ds                                                                ; \
111    sti                                                                     ; \
112    iret
113
114
115
116 WRAPPER(0);
117 WRAPPER(1);
118 WRAPPER(2);
119 WRAPPER(3);
120 WRAPPER(4);
121 WRAPPER(5);
122 WRAPPER(6);
123 WRAPPER(7);
124 WRAPPER(8);
125 WRAPPER(9);
126 WRAPPER(10);
127 WRAPPER(11);
128 WRAPPER(12);
129 WRAPPER(13);
130 WRAPPER(14);
131 WRAPPER(15);
132
133
134 .globl __irq_wrapper_0_end
135    .align 4
136 __irq_wrapper_0_end:
137    ret
138