2 * This file is part of DZComm.
4 * Minor changes by Dim Zegebart (zager@post.comstar.ru) to run with Palantir
9 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
10 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
11 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
12 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
13 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
16 * By Shawn Hargreaves,
22 * Hardware interrupt wrapper functions. Unlike the _go32_dpmi_*
23 * functions, these can deal with reentrant interrupts.
25 * See readme.txt for copyright information.
30 #error This file should only be used by the djgpp version of Allegro
40 #include "asmdefs.inc"
44 #define STACK_SIZE 8*1024 /* 8k stack should be plenty */
47 static int irq_virgin = TRUE;
49 _IRQ_HANDLER _irq_handler[MAX_IRQS];
51 unsigned char *_irq_stack[IRQ_STACKS];
53 extern void _irq_wrapper_0(), _irq_wrapper_1(),
54 _irq_wrapper_2(), _irq_wrapper_3(),
55 _irq_wrapper_4(), _irq_wrapper_5(),
56 _irq_wrapper_6(), _irq_wrapper_7(),
57 _irq_wrapper_8(), _irq_wrapper_9(),
58 _irq_wrapper_10(), _irq_wrapper_11(),
59 _irq_wrapper_12(), _irq_wrapper_13(),
60 _irq_wrapper_14(), _irq_wrapper_15(),
66 * Installs a hardware interrupt handler for the specified irq, allocating
67 * an asm wrapper function which will save registers and handle the stack
68 * switching. The C function should return zero to exit the interrupt with
69 * an iret instruction, and non-zero to chain to the old handler.
71 int _install_irq(int num, int (*handler)())
76 if (irq_virgin) { /* first time we've been called? */
77 LOCK_VARIABLE(_irq_handler);
78 LOCK_VARIABLE(_irq_stack);
79 LOCK_FUNCTION(_irq_wrapper_0);
81 for (c=0; c<MAX_IRQS; c++) {
82 _irq_handler[c].handler = NULL;
83 _irq_handler[c].number = 0;
86 for (c=0; c<IRQ_STACKS; c++) {
87 _irq_stack[c] = malloc(STACK_SIZE);
89 _go32_dpmi_lock_data(_irq_stack[c], STACK_SIZE);
90 _irq_stack[c] += STACK_SIZE - 32; /* stacks grow downwards */
97 for (c=0; c<MAX_IRQS; c++) {
98 if (_irq_handler[c].handler == NULL) {
100 addr.selector = _my_cs();
103 case 0: addr.offset32 = (long)_irq_wrapper_0; break;
104 case 1: addr.offset32 = (long)_irq_wrapper_1; break;
105 case 2: addr.offset32 = (long)_irq_wrapper_2; break;
106 case 3: addr.offset32 = (long)_irq_wrapper_3; break;
107 case 4: addr.offset32 = (long)_irq_wrapper_4; break;
108 case 5: addr.offset32 = (long)_irq_wrapper_5; break;
109 case 6: addr.offset32 = (long)_irq_wrapper_6; break;
110 case 7: addr.offset32 = (long)_irq_wrapper_7; break;
111 case 8: addr.offset32 = (long)_irq_wrapper_8; break;
112 case 9: addr.offset32 = (long)_irq_wrapper_9; break;
113 case 10: addr.offset32 = (long)_irq_wrapper_10; break;
114 case 11: addr.offset32 = (long)_irq_wrapper_11; break;
115 case 12: addr.offset32 = (long)_irq_wrapper_12; break;
116 case 13: addr.offset32 = (long)_irq_wrapper_13; break;
117 case 14: addr.offset32 = (long)_irq_wrapper_14; break;
118 case 15: addr.offset32 = (long)_irq_wrapper_15; break;
123 _irq_handler[c].handler = handler;
124 _irq_handler[c].number = num;
126 __dpmi_get_protected_mode_interrupt_vector(num,
127 &_irq_handler[c].old_vector);
129 __dpmi_set_protected_mode_interrupt_vector(num, &addr);
141 * Removes a hardware interrupt handler, restoring the old vector.
143 void _remove_irq(int num)
147 for (c=0; c<MAX_IRQS; c++) {
148 if (_irq_handler[c].number == num) {
149 __dpmi_set_protected_mode_interrupt_vector(num,
150 &_irq_handler[c].old_vector);
151 _irq_handler[c].number = 0;
152 _irq_handler[c].handler = NULL;