| /* |
| * PC/HW routine collection v1.3 for DOS/DJGPP |
| * |
| * Copyright (C) 2002 - Daniel Borca |
| * Email : dborca@yahoo.com |
| * Web : http://www.geocities.com/dborca |
| */ |
| |
| |
| .file "pc_irq.S" |
| |
| .text |
| |
| #define IRQ_STACK_SIZE 16384 |
| |
| #define IRQ_WRAPPER_LEN (__irq_wrapper_1-__irq_wrapper_0) |
| #define IRQ_OLD (__irq_old_0-__irq_wrapper_0) |
| #define IRQ_HOOK (__irq_hook_0-__irq_wrapper_0) |
| #define IRQ_STACK (__irq_stack_0-__irq_wrapper_0) |
| |
| .balign 4 |
| common: |
| movw $0x0400, %ax |
| int $0x31 |
| |
| movl %ss:8(%ebp), %ebx |
| cmpl $15, %ebx |
| jbe 0f |
| fail: |
| orl $-1, %eax |
| popl %edi |
| popl %ebx |
| leave |
| ret |
| |
| 0: |
| movl %ebx, %edi |
| imull $IRQ_WRAPPER_LEN, %edi |
| addl $__irq_wrapper_0, %edi |
| |
| cmpb $7, %bl |
| jbe 1f |
| movb %dl, %dh |
| subb $8, %dh |
| 1: |
| addb %dh, %bl |
| ret |
| |
| .balign 4 |
| .global _pc_install_irq |
| _pc_install_irq: |
| pushl %ebp |
| movl %esp, %ebp |
| pushl %ebx |
| pushl %edi |
| |
| call common |
| |
| cmpl $0, IRQ_HOOK(%edi) |
| jne fail |
| |
| pushl $IRQ_WRAPPER_LEN |
| pushl %edi |
| call __go32_dpmi_lock_code |
| addl $8, %esp |
| testl %eax, %eax |
| jnz fail |
| |
| pushl $IRQ_STACK_SIZE |
| call _pc_malloc |
| popl %edx |
| testl %eax, %eax |
| jz fail |
| addl %edx, %eax |
| movl %eax, IRQ_STACK(%edi) |
| |
| movl ___djgpp_ds_alias, %eax |
| movl %eax, IRQ_STACK+4(%edi) |
| |
| movl %ss:12(%ebp), %eax |
| movl %eax, IRQ_HOOK(%edi) |
| |
| movw $0x0204, %ax |
| int $0x31 |
| movl %edx, IRQ_OLD(%edi) |
| movw %cx, IRQ_OLD+4(%edi) |
| movw $0x0205, %ax |
| movl %edi, %edx |
| movl %cs, %ecx |
| int $0x31 |
| |
| done: |
| xorl %eax, %eax |
| popl %edi |
| popl %ebx |
| leave |
| ret |
| |
| .balign 4 |
| .global _pc_remove_irq |
| _pc_remove_irq: |
| pushl %ebp |
| movl %esp, %ebp |
| pushl %ebx |
| pushl %edi |
| |
| call common |
| |
| cmpl $0, IRQ_HOOK(%edi) |
| je fail |
| |
| movl $0, IRQ_HOOK(%edi) |
| |
| movw $0x0205, %ax |
| movl IRQ_OLD(%edi), %edx |
| movl IRQ_OLD+4(%edi), %ecx |
| int $0x31 |
| |
| movl IRQ_STACK(%edi), %eax |
| subl $IRQ_STACK_SIZE, %eax |
| pushl %eax |
| call _free |
| popl %eax |
| |
| jmp done |
| |
| #define WRAPPER(x) ; \ |
| .balign 4 ; \ |
| __irq_wrapper_##x: ; \ |
| pushal ; \ |
| pushl %ds ; \ |
| pushl %es ; \ |
| pushl %fs ; \ |
| pushl %gs ; \ |
| movl %ss, %ebx ; \ |
| movl %esp, %esi ; \ |
| lss %cs:__irq_stack_##x, %esp ; \ |
| pushl %ss ; \ |
| pushl %ss ; \ |
| popl %es ; \ |
| popl %ds ; \ |
| movl ___djgpp_dos_sel, %fs ; \ |
| pushl %fs ; \ |
| popl %gs ; \ |
| call *__irq_hook_##x ; \ |
| movl %ebx, %ss ; \ |
| movl %esi, %esp ; \ |
| testl %eax, %eax ; \ |
| popl %gs ; \ |
| popl %fs ; \ |
| popl %es ; \ |
| popl %ds ; \ |
| popal ; \ |
| jz __irq_ignore_##x ; \ |
| __irq_bypass_##x: ; \ |
| ljmp *%cs:__irq_old_##x ; \ |
| __irq_ignore_##x: ; \ |
| iret ; \ |
| .balign 4 ; \ |
| __irq_old_##x: ; \ |
| .long 0, 0 ; \ |
| __irq_hook_##x: ; \ |
| .long 0 ; \ |
| __irq_stack_##x: ; \ |
| .long 0, 0 |
| |
| WRAPPER(0); |
| WRAPPER(1); |
| WRAPPER(2); |
| WRAPPER(3); |
| WRAPPER(4); |
| WRAPPER(5); |
| WRAPPER(6); |
| WRAPPER(7); |
| WRAPPER(8); |
| WRAPPER(9); |
| WRAPPER(10); |
| WRAPPER(11); |
| WRAPPER(12); |
| WRAPPER(13); |
| WRAPPER(14); |
| WRAPPER(15); |