From fb6e86f3883d46c6832b12f40b51a4605e6e8860 Mon Sep 17 00:00:00 2001 From: Kenneth J Davis Date: Sun, 20 Nov 2005 16:57:35 +0000 Subject: [PATCH] assembly glue to wrap misc interrupts with C handler git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/branches/UNSTABLE@1155 6ac86273-5f31-0410-b378-82cca8765d1b --- kernel/intwrap.asm | 161 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 kernel/intwrap.asm diff --git a/kernel/intwrap.asm b/kernel/intwrap.asm new file mode 100644 index 0000000..6c642a5 --- /dev/null +++ b/kernel/intwrap.asm @@ -0,0 +1,161 @@ +; +; File: +; intwrap.asm +; Description: +; support for hooking misc interrupts +; BIOS disk interrupt support code +; warm boot support code +; +; Copyright (c) 2005 +; Pasquale J. Villani +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation; either version +; 2, or (at your option) any later version. +; +; DOS-C is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +; the GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public +; License along with DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; + + %include "segs.inc" + %include "stacks.inc" + +segment HMA_TEXT + extern _DGROUP_ + + ; defined in kernel.asm + extern _UserInt13 ; actual BIOS int13 disk handler used by kernel + extern _BIOSInt19 ; original int19 (reboot) + + +; receives int 13h request, invokes original handler, +; but passes to C routine in inthndr.c on error +; this lets successful calls proceed with minimal overhead +; while allowing us to handle errors, store disk change, ... + + global reloc_call_int13_handler +reloc_call_int13_handler: + cli ; disable other interrupts for now + stc ; force error unless BIOS clears + push dx ; store BIOS drive # for error handling usage + + push ds ; get segment of kernel DATA + mov ds, [cs:_DGROUP_] + pushf ; simulate int call so returns back here (flags+cs:ip on stack) + call far [ds:_UserInt13] + pop ds ; restore ds + + jc int13err ; test if error, if not return to caller + +int13iret: + inc sp ; clean up stack + inc sp + sti ; ensure int's are renabled + retf 2 ; return to caller leaving flags asis + +int13err: + pushf ; don't mess up flags + + cmp ah, 06h ; disk changed + je int13wrap + + ; add check for other errors here, such as DMA issues + + popf + jmp int13iret ; pass error asis back to user + + +int13wrap: +%IF XCPU < 186 + push ax ; preserve registers, setup stack frame + push bp + mov bp, sp + mov ax, 13h ; want to push 0x13 onto stack + xchg ax, [bp+2] ; so restore pushed ax value and put 0x13 on stack + pop bp ; clean up stack frame (leaving just 0x13 pushed on stack) +%ELSE + push 13h ; the 186+ way to push a constant on the stack +%ENDIF + + ; at this point stack has initial flags, called cs,ip, initial dx, + ; flags returned from int13 call, and value 13h + ; fall through to intWrapCall to invoke C handler + + +; assumes interrupt # and single word param already pushed on stack +; pushes all registers on stack +; calls C handler +; restores registers (replacing value if changed by C code) +; pops int# and param off stack +; returns via iret +intWrapCall: + ; set up register frame + push ax + push cx + push dx + push bx + push bp + push si + push di + push ds + push es + + cld + + Protect386Registers ; ensure 386+ registers possibly modified by kernel safe + + mov ds,[cs:_DGROUP_] + push ds ; mov es, ds + pop es + extern _intXX_filter + call _intXX_filter + + Restore386Registers + + pop es + pop ds + pop di + pop si + pop bp + pop bx + pop dx + pop cx + pop ax + + add sp, 2 ; pop int# off stack + popf ; restore flags + inc sp ; pop param off stack (without altering flags) + inc sp + retf 2 ; iret but ignore pushed flags + + + +#if 0 +; receives int 19h request, resets various int values, +; clears hma if in use, and finally invokes original handler, + + global reloc_call_int19_handler +reloc_call_int19_handler: + + mov ds, [cs:_DGROUP_] + lds ax,[_BIOSInt19] ; iret calls original handler, doesn't return + add sp, 4 ; so pop callers return address off stack + push ds ; and replace with address of original handler + push ax + push ax ; param, ignored + pushf ; flags, ignored + mov ax, 19h ; handler for int 19h + push ax + jmp intWrapCall +#endif