From: "Anthony.Appleyard" Organization: Materials Science Centre To: djgpp-workers AT delorie DOT com Date: Thu, 15 Jan 1998 16:42:50 GMT Subject: MCLSSAA2 : hooking interrupt 9 Reply-to: Anthony DOT Appleyard AT umist DOT ac DOT uk Message-ID: <4679C27AA@fs2.mt.umist.ac.uk> Precedence: bulk On Wed 14 Jan 1998 18:01:21 +0200 (IST) Eli Zaretskii wrote:- >> + enum{ /* numbers of the keys */ >> + k_esc = 1, ... > Why are these needed on a system-wide header? ... already has > definitions for all the PC keys ... add your definitions there, not to > . Now in . With thanks for the help and comments. >> + cli /* disable interrupts */ > I think this is both slow and unnecessary. Charles Sandmann agrees with > that, so I think this line should go away. If int (*_djgpp_kbd_callback)(int X) points to a user function, it will be called by the int09 hook routine and may take a while longer to run than the default routine alone. If so, if there are two keyboard events very close together (e.g. the user presses two keys at once), the second keypress may try to call the int09 routine for itself partway through the first keypress's int09 routine call. The effect of the `cli' only lasts until the next `popf'. I have put more pushes and pops around the call of *_djgpp_kbd_callback. >> + movw __go32_info_block+26,%ax >> + movw %ax,%fs /* FS = _dos_ds */ >> + .byte 0x64 /* use segment reg FS */ >> + movw 0417,%ax /* [0x417] [0x418] are shift status */ > I already asked why do you need to do this when the original handler code > already loads the _dos_ds selector into DS, two lines after you call the > callback code. Moving that line higher is all you need to do, no? The original handler code runs in conventional memory mode by changing DS to _dos_ds and restoring it afterwards. _calldjgpp_kbd_callback calls the user function *__djgpp_kbd_callback and thus needs DS to be as for normal running. >> Herewith a .TXH file for it, say call it djgppkbh.txh :- > This needs more work in the markup. Below is a somewhat changed version > which shows what you missed. Some noteworthy comments: Points taken. Thank you for letting me take up your time. > In this case, you haven't locked the code and the data, and it would surely > crash, since it is called from within an interrupt handler. (Neither did you > mention this in the description.) In my ventures so far into writing interrupt matter (using _go32_dpmi_allocate_real_mode_callback_retf and _go32_dpmi_chain_protected_mode_interrupt_vector), I got away without locking, probably because the areas of store involved were small and often used and thus DPMI likely happened to keep them always in RAM anyway. > One thing which is definitely not right is that GCC assumes SS == DS, which > is incorrect in the interrupt handler, so the callback code should take care > of that also. I now save all possibe registers (segment and otherwise) before calling the user function and restore them afterwards. The software does not alter DS until after the user function has been called. Herewith DIFF files for:- include\keys.h include\sys\exceptn.h src\libc\go32\exceptn.s and a new .TXH file ================================================================== *** exceptn.h Mon Dec 4 22:39:44 1995 --- exceptn2.h Thu Jan 15 15:40:52 1998 *************** *** 27,32 **** --- 27,33 ---- #define __djgpp_exception_state (*__djgpp_exception_state_ptr) #endif + extern int (*_djgpp_kbd_callback)(int X); extern unsigned short __djgpp_our_DS; extern unsigned short __djgpp_app_DS; /* Data selector invalidated by HW ints */ extern unsigned short __djgpp_ds_alias; /* Data selector always valid */ ================================================================== *** exceptn.s Mon Jan 12 14:54:06 1998 --- exceptn2.s Thu Jan 15 14:28:24 1998 *************** *** 284,292 **** --- 284,335 ---- iret .align 4 + .global __djgpp_kbd_callback + __djgpp_kbd_callback: .int 0 /* int (*_djgpp_kbd_callback)(int X); */ + /* If not 0, the interrupt 9 hook routine will call this function with:- */ + /* X &255 == keyboard event */ + /* (X>> 8)&255 == keyboard shift status as if from (AH=2, int 16h) */ + /* (X>>16)&255 == keyboard extended shift status as if from (AH=12h, int 16h) */ + _calldjgpp_kbd_callback: + xorl %eax,%eax /* must return 0 if no function */ + pushl %ebx /* save EBX */ + movl __djgpp_kbd_callback,%ebx + testl %ebx,%ebx /* if zero, there is no function */ + je no_user_hdlr + cli /* disable interrupts until popf */ + pushw %fs + movw __go32_info_block+26,%ax + movw %ax,%fs /* FS = _dos_ds */ + .byte 0x64 /* use segment reg FS */ + movw 0417,%ax /* [0x417] [0x418] are shift status */ + sall $8,%eax /* move EAX one byte up */ + inb $0x60,%al /* read keyboard event into AL */ + pushw %ds /* save everything */ + pushw %es + pushw %gs + pushal + pushl %eax /* parameter for call */ + call *%ebx /* call the user function */ + testl %eax,%eax /* the flags will survive the pops & the ret */ + popal /* restore everything */ + popw %gs + popw %es + popw %ds + popw %fs + no_user_hdlr: + popl %ebx + ret + .global ___djgpp_kbd_hdlr ___djgpp_kbd_hdlr: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + je call_default_fn /* nonzero, no default handling of the event */ + movb $0x20,%al /* EOI the interrupt */ + outb %al,$0x020 + popl %eax + iret + call_default_fn: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ *************** *** 317,322 **** --- 360,372 ---- .global ___djgpp_kbd_hdlr_pc98 ___djgpp_kbd_hdlr_pc98: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + je call_default /* nonzero, no default handling of the event */ + movb $0x20,%al /* EOI the interrupt */ + outb %al,$0x020 + popl %eax + iret + call_default: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ ================================================================== *** keys.h Mon Aug 12 21:58:02 1996 --- keys2.h Thu Jan 15 10:11:40 1998 *************** *** 250,255 **** --- 250,367 ---- #define K_Control_EInsert 0x292 #define K_Control_EDelete 0x293 + /* Raw values of keyboard key-press events. Add 128 to get key-release values */ + + #define k_esc 0x01 + #define k_1 0x02 + #define k_2 0x03 + #define k_3 0x04 + #define k_4 0x05 + #define k_5 0x06 + #define k_6 0x07 + #define k_7 0x08 + #define k_8 0x09 + #define k_9 0x0A + #define k_0 0x0B + #define k_1rof0 0x0C + #define k_2rof0 0x0D + #define k_backspace 0x0E + #define k_tab 0x0F + #define k_Q 0x10 + #define k_W 0x11 + #define k_E 0x12 + #define k_R 0x13 + #define k_T 0x14 + #define k_Y 0x15 + #define k_U 0x16 + #define k_I 0x17 + #define k_O 0x18 + #define k_P 0x19 + #define k_1rofP 0x1A + #define k_2rofP 0x1B + #define k_enter 0x1C + #define k_lctrl 0x1D + #define k_A 0x1E + #define k_S 0x1F + #define k_D 0x20 + #define k_F 0x21 + #define k_G 0x22 + #define k_H 0x23 + #define k_J 0x24 + #define k_K 0x25 + #define k_L 0x26 + #define k_1rofL 0x27 + #define k_2rofL 0x28 + #define k_1lof1 0x29 + #define k_lshift 0x2A + #define k_3rofL 0x2B + #define k_Z 0x2C + #define k_X 0x2D + #define k_C 0x2E + #define k_V 0x2F + #define k_B 0x30 + #define k_N 0x31 + #define k_M 0x32 + #define k_1rofM 0x33 + #define k_2rofM 0x34 + #define k_3rofM 0x35 + #define k_rshift 0x36 + #define k_padstar 0x37 + #define k_lalt 0x38 + #define k_space 0x39 + #define k_capslock 0x3A + #define k_F1 0x3B + #define k_F2 0x3C + #define k_F3 0x3D + #define k_F4 0x3E + #define k_F5 0x3F + #define k_F6 0x40 + #define k_F7 0x41 + #define k_F8 0x42 + #define k_F9 0x43 + #define k_F10 0x44 + #define k_numlock 0x45 + #define k_scrolllock 0x46 + #define k_pad7 0x47 + #define k_pad8 0x48 + #define k_pad9 0x49 + #define k_padminus 0x4A + #define k_pad4 0x4B + #define k_pad5 0x4C + #define k_pad6 0x4D + #define k_padplus 0x4E + #define k_pad1 0x4F + #define k_pad2 0x50 + #define k_pad3 0x51 + #define k_pad0 0x52 + #define k_paddot 0x53 + #define k_sysreq 0x54 + #define k_1lofZ 0x56 + #define k_F11 0x57 + #define k_F12 0x58 + + /* Keyboard events that return 0xe0 and then the code modulo 256 */ + + #define k_padenter 0x11c + #define k_rctrl 0x11d + #define k_numshift 0x12a + #define k_padslash 0x135 + #define k_prtscr 0x137 + #define k_ralt 0x138 + #define k_home 0x147 + #define k_uparrow 0x148 + #define k_pageup 0x149 + #define k_leftarrow 0x14b + #define k_rightarrow 0x14d + #define k_end 0x14f + #define k_downarrow 0x150 + #define k_pagedown 0x151 + #define k_insert 0x152 + #define k_delete 0x153 + #define k_lwin 0x15b + #define k_rwin 0x15c + #define k_menu 0x15d + #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */